你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【经验分享】STM32G4 嵌入式---模块配置---TIM_Output_Compare

[复制链接]
STMCU小助手 发布时间:2022-7-7 16:00
前言: j9 b/ Z0 C8 x* `& _% y  D
定时器输出比较模式(翻转模式)。, M$ `5 q. N& ?6 w: q+ o
对于输出PWM波,在十一届考了个输出不同频率的可调占空比的PWM波。
& b' m5 h1 Q0 }: K2 i* h对于此,用新板子的话可以采用TIM3、TIM17输出。(建议用新板子准备此题仍然用输出比较模式)/ j0 r9 o$ q/ R  b1 R; J
但是考点并不在这,考的是定时器的输出比较模式。
; H4 k' c! [& r2 ?4 }% T
' Z+ Y. o: N* x& O9 u* J- BTIM_Output_Compare& D4 z2 |4 k6 R% b3 Y: a! y
1.TIM_Output_Compare原理

" k2 y1 c5 O0 f& D对于输出比较的使用,资料还是比较少,我也是查了参考手册。
6 `% P1 J, a6 \) M) R可能有的地方理解有问题,欢迎指出,谢谢。& h6 o7 Z# _8 R* e0 Z2 h$ E

" \- a! P; \& R) [1.定时器通道的工作模式
! m& M7 Z8 s2 f/ [7 dA.输入捕获
  V2 Q; a1 T' d& g1 I( mB.输出比较
' E* g" |" i0 _# I& C2 f8 FC.PWM 生成(边缘或中间对齐模式). i" X5 e/ M2 |& d& P8 g2 `! d! W
D.单脉冲模式输出
; i* b9 y' d  o( S: j2 I/ P& \0 R( t& \  c
2.输出比较模式简介
  F5 ]0 U" h. e8 S此功能用于控制输出波形,或指示已经过某一时间段。% z4 D! u: y4 M
在输出比较模式下,更新事件 UEV 对 OCxREF 和 OCx 输出毫无影响。同步的精度可以达
' q7 Z. @: L6 x, n6 w3 |; A到计数器的一个计数周期。
# @' _# H6 M5 @; h$ V可通过软件随时更新 TIMx_CCRx 寄存器以控制输出波形,前提是未使能预加载寄存器
- `; t, i/ H' w1 w(OCxPE=“0”,否则仅当发生下一个更新事件 UEV 时,才会更新 TIMx_CCRx 影子寄存* K" l& a6 B- ~. n
器)。) L) {4 x7 \5 G2 v* d
Z){LHL9C45S0XCS8S]}NPOR.png
# i6 l& d1 Q' G/ g% K: k) m3 U% B$ `7 \9 z6 `* C9 B
通过上述介绍,可以这样理解,在TIMx的CCRx写入一个值,如果TIMx的CNT与它匹配(相同),会产生电平翻转,如果开启了中断,就会产生中断。
) C0 ]5 a, }1 @6 e, y
: v: O% G& S( e1 ]3 J, _, S1 p3.如何输出不同频率的方波
+ d" x( Q" t: C  x( H取计数周期为200的定时器(计数值从0到200 - 1循环),频率设为f = 80MHz/200/x。(主要看实例,可能文字描述不到位)
3 L1 K9 I+ a: P+ E0 t) A记输出PWM1,计数周期为100,频率即2f。
6 w& e3 v% T0 B* U0 }记输出PWM2,计数周期为50,频率即4f。
2 n1 c5 Y  \6 U1 [5 N! u则令TIMx_CCR1 = 100 * 0.5 = 50,TIMx_CCR2 = 50 * 0.5 = 25。+ L$ O5 r/ u& u& H4 E/ e" _
当发生中断时,若是通道1,则将比较值加50,CCR1 += 50,若是通道2,则将比较值加 25, CCR2 += 25。7 h% b/ D' e6 M& a
则可以得到如下方波。
9 o* `1 f+ V+ r2 g8 N# W
5 U# e2 B0 d8 t4 a7 o DAVFA%`9HV)Z9`KS1]9V{98.png
/ G* D3 Y( I/ c/ S
1 C$ @8 }2 G2 v通道2类似,读者可以自己画图检验
4 f0 [3 x6 D3 S, d
' i2 q# ?1 q/ I4.如何输出不同频率的可调占空比的PWM波

7 D. q$ ^* W+ P# A( i/ d取计数周期为TIMx_Preiod的定时器(计数值从0到TIMx_Preiod - 1循环),频率设为f = 80MHz/TIMx_Preiod/x。(主要看实例,可能文字描述不到位)
. _: \! A' g/ s' o# r. H/ q$ o记输出PWM1,计数周期为T1。& p8 \, w7 p* _6 V/ P+ `& f
记输出PWM2,计数周期为T2。
, E+ }  m( G, ]1 z则令初始值TIMx_CCR1 = T1 * PA6_Duty ,TIMx_CCR2 = T2 * PA7_Duty 。(此处是百分比)
6 m* T9 c$ t+ e: ]当发生中断时,
0 \7 J, S9 W; G+ x" o$ ?(若计数周期值为0XFFFF时)
/ ]2 G& f2 l" n# ?4 X: g, d: S若是通道1,则将比较值CCR1 += T1PA6_Duty ;下一次CCR1 += T1(1 - PA6_Duty);以此循环' _! J0 c! V4 c) k
若是通道2,则将比较值CCR2 += T2PA7_Duty ;下一次CCR2 += T2(1 - PA7_Duty);以此循环
2 t  P. D. {5 r" g(由于CCRx的值一直加下去,会溢出,所以不用担心计数器达不到比较寄存器的值)
0 F% m- O" d$ V- Q% {5 ~- u(若计数周期值不为0XFFFF时)
" p( x! w# F3 N' G! a/ ?4 H若是通道1,
% o; J# [" r- c则将比较值CCR1 += T1PA6_Duty ;CCR1 %= TIMx_Period;
4 u! [" Z, B% U8 C% b, O# O+ R下一次CCR1 += T1(1 - PA6_Duty);CCR1 %= TIMx_Period;以此循环5 `+ @- ^6 G& D0 `0 _" B' w1 z
若是通道2,. |4 s! g" i" n5 g* O
则将比较值CCR2 += T2PA7_Duty ;CCR2 %= TIMx_Period;
. e. I7 d2 }8 y+ z下一次CCR2 += T2(1 - PA7_Duty);CCR2 %= TIMx_Period;以此循环
& m$ k1 N7 ^" S
& @' ^) j* C9 g7 U' Q则可以得到如下PWM波。
) j# ?0 O) x) F' Y& {
8 q& {2 K) Z+ @* X0 |% M {%~3JJSWRH24UVPFLJRF.png
/ I8 _# f7 [, j% O" l
$ G  H) k( r; P5 e6 s5.实例(1Hz和2Hz的方波)(由于细节过多,所以在下一节给出可调占空比的实例)
$ Y7 W1 ]0 ~6 H: v2 q+ C取计数周期为10000的定时器(计数值从0到10000- 1循环),频率设为1Hz = 80MHz/10000/8000。
7 ]; _% X/ @2 K) m2 G记输出PWM1,计数周期为10000,f = 1Hz。7 J$ }' _% [' ^2 r/ t, ~
记输出PWM2,计数周期为5000,f = 2Hz。/ Z. l0 ~0 Z) ?; B/ y, `# {' [
则令初始值TIMx_CCR1 = 10000* 0.5 ,TIMx_CCR2 = 5000* 0.5 。5 T2 T: R" k, ?  }
当发生中断时,
- O4 p$ c+ c' d$ E; u( k若是通道1,则将比较值CCR1 += 5000;CCR1 %= 10000;
$ i! O5 D9 P* G6 m7 D5 v若是通道2,则将比较值CCR2 += 5000;CCR2 %= 10000;# u" ]1 _& Q. e1 X6 J7 |  M
# }1 C0 }; I% E7 v
(如果读者还是不能理解,可以画个波形看看哦)
+ i" @- h2 [: v) \- {# L+ I6 P9 }9 z& T! e
2.Cubemx实现TIM的配置! A, d' Y6 j* ^1 w" s9 {/ T% `
由于在做这个实验的时候身边没有示波器,所以采用上升沿和下降沿个数来判断是否成功。
8 c! o1 R, q/ Y0 T5 E所以我们采用了串口(9600)和LCD帮助测试& k/ I; i' g7 b: Y- M
TIM3配置如下:8 L" @% T0 B/ t5 U. B* j
7 e, \. A  y1 X3 R7 C# u, O
2021022314525275.png 7 Y1 P$ Y. O$ d8 Q8 ~, x! s

5 }3 |) G3 k! s8 `- S0 N3 i 1_8_4HG@KV]%E`(CH%XA@WB.png
4 L$ r! @1 T+ {; ]3 v
( F6 K* B2 ?, H% \6 H  J
' N- v& \% Q# h( ~开启定时器中断* I5 q6 O, M: j& }# Q+ g0 z

" f: }3 g: W1 o( [+ t8 I, g X%)~U6X$YG}3]OP}7OT05NJ.png 7 c. \$ j8 z4 b; l& d5 _+ N0 j

9 N# f" |( w8 r* [4 N3.生成工程; K  ^% D3 O8 f! S  e! |
1.开启定时器中断

& |( K, I9 s8 j3 i$ {. Q# P4 s. P5 d, |8 K! M
ZW001I%X)M}0[_OO6QYV$NM.png
+ y* R1 \& Z2 P, x" k, b2 R
$ J/ M8 ^8 @4 G  }& P0 x. [
  1.         LCD_Init();# C. n& n+ k, b  K# c1 F
  2.         LCD_Clear(White);. r) u; A" U' Y' h: G# ?& _$ ^! P
  3.         LCD_SetTextColor(Red);$ B3 ]% R! m) h  m5 O6 C, l
  4.         
    4 H5 @1 p; m6 l. S+ N; V, f
  5.         HAL_TIM_OC_Start_IT(&htim3,TIM_CHANNEL_1);  I& _/ k$ |# e4 y0 n! c
  6.         HAL_TIM_OC_Start_IT(&htim3,TIM_CHANNEL_2);//合并在一起有bug,我在调车的时候用编码电机也遇到过! X* V% |" O0 q
  7.         TIM3->CNT = 0;
复制代码
  1.                 sprintf((char *)str, "num1 : %d", num1);7 B5 h; p0 V9 h$ v9 ?" I
  2.                 LCD_DisplayStringLine(Line1, str);
    ' I& [8 q! L$ D8 o4 ?) G6 U* Z
  3.                 sprintf((char *)str, "num2 : %d", num2);
    , W0 L: B8 v3 Y9 L6 ]7 \
  4.                 LCD_DisplayStringLine(Line3, str);5 h5 n- f; s9 r/ U. V1 D! v" I
  5.                
    $ S3 }: k' Y9 v) D) K
  6.                 sprintf((char *)str, "CNT : %d", TIM3->CNT);( _: |3 v0 d4 Y) j
  7.                 LCD_DisplayStringLine(Line7, str);7 F: Y8 Z, G9 b) c2 [1 {0 _
  8.                 sprintf((char *)str, "CCR1: %d", TIM3->CCR1);1 ]9 i& x8 h; T: M0 L! B4 u6 [% I
  9.                 LCD_DisplayStringLine(Line8, str);
    ( X( u4 e2 s5 n- t  x. v
  10.                 sprintf((char *)str, "CCR2: %d", TIM3->CCR2);
复制代码

* c7 e' z* H- s, a  _以上都是初始化和测试显示函数,不需要多讲
# b- r5 O, ]# a( {0 M/ p5 J
% L4 p, y) m" {' ]$ f5 B2.更改HAL库TIM的中断总函数
- Q4 a7 w. w: P" ]由于输出比较的真的比较少,而且对于用HAL做的资料,本人就没找到。。。( A9 X; ]6 H5 [) A7 `/ q8 @2 \
所以查了原子提供的参考手册,然后也是被HAL库的集成度坑了。: |" z4 {# o3 q- h
首先对于中断标志位:
- F+ b7 {( g: r; t% Q) N; I* x! u: W
KQ~`KI6}X$~1O8M`OVG5C.png
1 `! M; D8 `+ ^8 J
: S  R* {7 K$ b5 U% GTIMx_SR寄存器,第1.2位保存的通道1、2的捕获和比较中断标志,上面说的很清楚,当在输出比较模式下,计数值和比较值匹配时,该位会置1。% q5 d3 Z, ?$ c2 {8 e( W. f- E+ M
. R8 d9 Q5 `  ]5 `4 g
3、中断服务函数& X; z4 H9 [8 P) x' [+ f
HAL库不熟悉的情况下,本人建议可以记一些比较常用的的寄存器,比如CCRx,SR,CNT等等,以免找不到想要找的函数。( V7 ^: A/ \2 q6 i% A
4 W) k* U% Z0 W9 L( k( Z
EN`BUM5FT84%SB6T67DBGFW.png
0 f' _5 x% D' b) z: d: Y3 V9 V5 n$ {+ O6 {7 E' G2 C* K/ ^9 j
  1. void HAL_TIM_OC_DelayElapsedCallback(TIM_HandleTypeDef *htim)
    7 \5 m; t3 c! ]' g6 b4 k
  2. {
    % u2 H3 `0 q/ `, @5 B8 }2 P
  3.         if((TIM3->DIER & (0x1 << 1)) && (TIM3->DIER & (0x1 << 2)))" Y1 z4 a, s$ _
  4.         {& G, t7 ?; U. h. ?5 i8 G3 U- `: }
  5.                 if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1)//(TIM3->SR & (0x1 << 1))! I$ L3 J" g/ m& f- H' Z
  6.                 {' B# t& Y$ f! V( z) D7 \
  7.                         sprintf((char *)arr, "CNT: %d, CCR1: %d\r\n", TIM3->CNT,TIM3->CCR1);% S& j  ~, G3 e3 N' X
  8.                         HAL_UART_Transmit(&huart1, arr,sizeof(arr),50);" A! n) ?5 Z, D7 Z- y) D! d
  9.                         TIM3->CCR1 = TIM3->CCR1 + 5000;
    ) s) O* g8 V0 L  D# d0 s
  10.                         TIM3->CCR1 = TIM3->CCR1 % 10000;
    6 f. U2 k* c% X5 A5 o8 K  w5 F: K
  11.                         num1++;
    8 ?9 c( u3 |6 u  G
  12.                 }5 U) ^# g1 H1 p1 E' I- ]
  13.                 ! T: l3 Y0 l5 \# ~: B: K( @0 Q6 I- T
  14.                 if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2)//(TIM3->SR & (0x1 << 2))" e/ W! v7 Z; ?
  15.                 {
    " f! T7 T; L8 _$ {3 m" V% a7 Y
  16.                         sprintf((char *)arr, "CNT: %d, CCR2: %d \r\n", TIM3->CNT,TIM3->CCR2);
    ' g: \- z& Z. d& q. {! w  w
  17.                         HAL_UART_Transmit(&huart1, arr,sizeof(arr),50);) b4 c0 x" E( G" o. S4 s9 Q* r
  18.                         TIM3->CCR2 = TIM3->CCR2 + 2500;
      d/ s, W5 A! g& q
  19.                         TIM3->CCR2 = TIM3->CCR2 % 10000;
    ) G* R- I: A! }) e/ x5 f2 }
  20.                         num2++;
    4 `- q- W. H+ g6 s5 F
  21.                 }( f. R3 _: K- ?. x

  22. ) R9 Y, w) L" ^+ b# r
  23. }
复制代码

$ I! c+ |2 n9 B) o% u% `( ~; y' r对于外条件判断,是因为本人在测试标志位的时候,打印过SR寄存器的显示值。3、4通道未开启中断,但是默认值是1,如果有操作不当可能使用的3、4的中断处理代码,会使程序卡死。所以外条件判断是判断1、2通道是否开启允许中断。
: h( `& G/ J: V7 }% c8 `% _: y% b# J代码测试:! p5 w5 Z0 _, [4 i! \$ e2 y

- ?3 U+ s# P1 L8 F R14~5JTLHG%$DI`2Z{B{C[J.png
" i# m  ?, t8 Q8 U. ~, l' [  B+ o
UKGHE0_KK0K_$J6GW]YYB2P.png
1 [& t% W& Y/ C- }  ?. u& W: f+ w. p+ ?' B; L% f4 b
串口接收到的CNT值大于CCRx值是正常的,因为代码运行需要时间,产生了中断就表示有匹配。# l) `5 Y/ U. l4 [4 V4 C
图2可以看到2通道粗略是1通道的两倍,即1Hz和2Hz的方波。
' z  o4 R/ Y+ b4 S. I) U8 Q7 F5 _& P9 \
) ?# k: |" w( Y
& L6 e8 n; E! L7 S0 b$ L
赞 收藏 评论0 发布时间:2022-7-7 16:00

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版