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

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

[复制链接]
STMCU小助手 发布时间:2022-7-7 16:00
前言
: R4 G; N" s; y  d2 I定时器输出比较模式(翻转模式)。& t% O# r* k* Y7 s* q. K2 A
对于输出PWM波,在十一届考了个输出不同频率的可调占空比的PWM波。; b9 U' D2 ?( |2 w- U
对于此,用新板子的话可以采用TIM3、TIM17输出。(建议用新板子准备此题仍然用输出比较模式)9 Z5 o: A( O" [& O7 H
但是考点并不在这,考的是定时器的输出比较模式。, K7 V3 T: z$ A6 P
# Q: p' ^: m% L% d
TIM_Output_Compare
: E0 @5 W5 u# ^( @: h' y1.TIM_Output_Compare原理

% H! }/ r; {0 i$ B对于输出比较的使用,资料还是比较少,我也是查了参考手册。
* J+ `1 A4 `8 A+ B可能有的地方理解有问题,欢迎指出,谢谢。
/ }) h7 v8 p7 }+ c6 G6 |) c9 F- J6 f# E% j/ i
1.定时器通道的工作模式" D5 Z; ]& |+ c; Q4 {5 ^* Y4 }2 ?
A.输入捕获: M( }- ~/ h) H1 q& H/ }0 M
B.输出比较4 R3 e/ q3 Y/ `" f) ^' {+ q
C.PWM 生成(边缘或中间对齐模式)
' v8 ?& U  N' ?3 s& w# `, ~D.单脉冲模式输出5 \1 V9 H& x% V2 ~1 X: }
" r7 S( s! K9 y* [/ s# ]
2.输出比较模式简介/ r/ S% K8 c) @9 {3 `* T2 A, X. V
此功能用于控制输出波形,或指示已经过某一时间段。% i) `, p6 P8 G
在输出比较模式下,更新事件 UEV 对 OCxREF 和 OCx 输出毫无影响。同步的精度可以达! U2 Q- {. m: @$ @( x5 w1 q) q/ G" K
到计数器的一个计数周期。
/ f. E3 {& }9 e5 k可通过软件随时更新 TIMx_CCRx 寄存器以控制输出波形,前提是未使能预加载寄存器
5 a8 o+ t6 b# Q! ?/ I9 `, e(OCxPE=“0”,否则仅当发生下一个更新事件 UEV 时,才会更新 TIMx_CCRx 影子寄存( M/ v+ b3 |& v+ R$ b
器)。' x% c; S- w% E
Z){LHL9C45S0XCS8S]}NPOR.png
8 c9 }3 A4 R: M1 y( _# L5 a; j6 R* C; o
通过上述介绍,可以这样理解,在TIMx的CCRx写入一个值,如果TIMx的CNT与它匹配(相同),会产生电平翻转,如果开启了中断,就会产生中断。& p% D6 [- c' i, T

8 s4 H4 C' X. E3 w5 H" h3.如何输出不同频率的方波% b' D" F9 B3 o* m
取计数周期为200的定时器(计数值从0到200 - 1循环),频率设为f = 80MHz/200/x。(主要看实例,可能文字描述不到位)$ H5 ?& x; H6 R, B7 E$ N- `  F1 m- b
记输出PWM1,计数周期为100,频率即2f。: e6 F' e: S+ J
记输出PWM2,计数周期为50,频率即4f。3 o3 |, y6 X. c) [
则令TIMx_CCR1 = 100 * 0.5 = 50,TIMx_CCR2 = 50 * 0.5 = 25。4 s( }) q: L% v# k# M* ^: D0 H$ N
当发生中断时,若是通道1,则将比较值加50,CCR1 += 50,若是通道2,则将比较值加 25, CCR2 += 25。! s4 s8 L2 t$ r3 e" ^
则可以得到如下方波。  U) [" s4 I& i+ V
( u8 V5 m; Z3 N0 u/ Z
DAVFA%`9HV)Z9`KS1]9V{98.png ) @/ [9 r. L  {0 o$ p/ O$ a
- q9 F/ }. W5 C8 Q
通道2类似,读者可以自己画图检验; D% y9 \# V- u2 j" u
  O' V$ e7 N. e# E( j
4.如何输出不同频率的可调占空比的PWM波

% T$ ?: \/ Z2 o取计数周期为TIMx_Preiod的定时器(计数值从0到TIMx_Preiod - 1循环),频率设为f = 80MHz/TIMx_Preiod/x。(主要看实例,可能文字描述不到位)7 D  M. C. X* E, G  q
记输出PWM1,计数周期为T1。6 x4 G! a, F# ?7 t0 W8 |2 y
记输出PWM2,计数周期为T2。
5 T' w5 ?) z0 b1 J' Q则令初始值TIMx_CCR1 = T1 * PA6_Duty ,TIMx_CCR2 = T2 * PA7_Duty 。(此处是百分比)- n2 F1 N- O3 s8 O' ]6 j; @8 M" n
当发生中断时,
0 l4 X$ c. V0 S1 k/ E(若计数周期值为0XFFFF时)6 Z* j, [- I- c# j  d
若是通道1,则将比较值CCR1 += T1PA6_Duty ;下一次CCR1 += T1(1 - PA6_Duty);以此循环0 p5 d& z. J' m6 w. o$ u, q
若是通道2,则将比较值CCR2 += T2PA7_Duty ;下一次CCR2 += T2(1 - PA7_Duty);以此循环
9 i3 E3 B$ V# X3 f(由于CCRx的值一直加下去,会溢出,所以不用担心计数器达不到比较寄存器的值)' Y9 v3 d3 k  y  B. L8 B7 u% ]
(若计数周期值不为0XFFFF时)
! {, ?& A' r0 o3 e2 d" n8 L9 |若是通道1,
; X5 |( V1 Q9 H) U则将比较值CCR1 += T1PA6_Duty ;CCR1 %= TIMx_Period;
$ y) Y' O/ ~1 i1 ]6 h  |. @9 w7 v$ F" {下一次CCR1 += T1(1 - PA6_Duty);CCR1 %= TIMx_Period;以此循环* h8 u; c7 k: U" `! c
若是通道2,! Q9 z4 ^, K' r( C7 B+ d
则将比较值CCR2 += T2PA7_Duty ;CCR2 %= TIMx_Period;
+ p* ]* I1 ?9 S% X$ c; _- n下一次CCR2 += T2(1 - PA7_Duty);CCR2 %= TIMx_Period;以此循环0 {4 `0 t4 G+ F& Z: `% Z) M1 l# u
& Z( R9 o) e! X4 u+ s
则可以得到如下PWM波。
) l& n4 h, Q1 X" |4 c# D' g; b% G9 a! z2 O! a, A( p3 A6 @
{%~3JJSWRH24UVPFLJRF.png
. N- `, }3 d+ D( x6 y7 }
4 j/ B; Z) ]2 j1 I8 G6 _5.实例(1Hz和2Hz的方波)(由于细节过多,所以在下一节给出可调占空比的实例)3 @( f. k" E7 `) ]
取计数周期为10000的定时器(计数值从0到10000- 1循环),频率设为1Hz = 80MHz/10000/8000。
& t% [4 D: x7 o" T( o6 p$ a8 I! `记输出PWM1,计数周期为10000,f = 1Hz。
) j2 _% n  @9 c) h- j/ y记输出PWM2,计数周期为5000,f = 2Hz。
& u' N) Z3 i. X: a6 x+ Y则令初始值TIMx_CCR1 = 10000* 0.5 ,TIMx_CCR2 = 5000* 0.5 。
3 L9 b- |- U* X8 c. ^: }" [4 f& I4 m当发生中断时,
, b  i$ K3 K1 v9 r% H2 y若是通道1,则将比较值CCR1 += 5000;CCR1 %= 10000;
3 M( D1 o0 C: v' q- B: b6 {若是通道2,则将比较值CCR2 += 5000;CCR2 %= 10000;
- a+ r* p* c4 ~' F& E" K' J" G7 T4 e! a# Y( M
(如果读者还是不能理解,可以画个波形看看哦)2 J9 m4 k) o# n' p/ N8 {4 K
9 y. S" s6 J( V! C
2.Cubemx实现TIM的配置
# H1 }# o. \/ T& E由于在做这个实验的时候身边没有示波器,所以采用上升沿和下降沿个数来判断是否成功。
$ P( \: J2 d* P6 N& p: J所以我们采用了串口(9600)和LCD帮助测试
  D8 ^0 q" z9 d0 i) ^TIM3配置如下:, c4 A+ l) h; b7 ?: s2 I

5 N( s- N* O4 q3 u 2021022314525275.png
* J* Q& J' ?2 k$ a3 h% v* A  H9 a5 c0 h( x9 U9 `$ V* d* X$ ^
1_8_4HG@KV]%E`(CH%XA@WB.png
2 m) i) y2 ]* p% k
) N+ x7 x2 V; c# g0 z9 K
& J' a1 T) a  l7 F! O! i0 k( t开启定时器中断
( }: A7 D  Z( h
  p4 C9 I  ?% q, G X%)~U6X$YG}3]OP}7OT05NJ.png
  A3 t$ S/ m4 g/ C5 u
, ]2 \% E5 O: Q% ^# f3.生成工程
2 g+ {6 T: V3 X+ W' Q+ z. P& w- P1.开启定时器中断

2 R! H9 \7 ~2 p- c" W% Z) b3 a7 K# [# y/ }  _1 [5 z# X
ZW001I%X)M}0[_OO6QYV$NM.png ' }/ ~* Z& v& x
9 P+ N3 c. M2 Y6 M
  1.         LCD_Init();
    : [% m8 d0 j# O
  2.         LCD_Clear(White);9 j  V3 f0 Y9 \/ {6 r* r% a
  3.         LCD_SetTextColor(Red);$ o: ^3 M9 G4 U5 @
  4.         
    ' j3 L+ ^$ C) K3 p" v7 s
  5.         HAL_TIM_OC_Start_IT(&htim3,TIM_CHANNEL_1);
    7 t9 Y6 P, y1 |3 f: Y& x
  6.         HAL_TIM_OC_Start_IT(&htim3,TIM_CHANNEL_2);//合并在一起有bug,我在调车的时候用编码电机也遇到过
    & d, [# w7 x2 M
  7.         TIM3->CNT = 0;
复制代码
  1.                 sprintf((char *)str, "num1 : %d", num1);. V; b; _5 H4 ~% y! y! I( ?
  2.                 LCD_DisplayStringLine(Line1, str);4 C. E4 G4 R: E0 U; h" G
  3.                 sprintf((char *)str, "num2 : %d", num2);1 _$ R/ H/ q6 I+ b1 [. T
  4.                 LCD_DisplayStringLine(Line3, str);
    - e5 Z; W2 R' u1 h: z
  5.                 7 K/ J& J; C# l6 q' [' u4 I: S
  6.                 sprintf((char *)str, "CNT : %d", TIM3->CNT);
    $ c4 S  u* `) Z0 O% w  a# {7 _7 w
  7.                 LCD_DisplayStringLine(Line7, str);8 ?- @8 }5 M- G# i. z4 y1 ^7 A' y
  8.                 sprintf((char *)str, "CCR1: %d", TIM3->CCR1);
    1 v5 q* o. c& F
  9.                 LCD_DisplayStringLine(Line8, str);
    5 w0 ~; \1 Y) e3 a
  10.                 sprintf((char *)str, "CCR2: %d", TIM3->CCR2);
复制代码
; l) ~$ @2 p+ c% y  J: a$ d
以上都是初始化和测试显示函数,不需要多讲6 p" ~/ ~4 i) j, K% ?2 x

* Q8 {, C  S" u: m- `* O+ h2.更改HAL库TIM的中断总函数! ^7 o; v, j& i; B
由于输出比较的真的比较少,而且对于用HAL做的资料,本人就没找到。。。
$ T! g- v; I1 V0 b# Q' }/ t% f所以查了原子提供的参考手册,然后也是被HAL库的集成度坑了。
5 s" k3 [! L7 I% S8 n4 F首先对于中断标志位:
" v+ E  Y/ }# u6 `% @( D9 A
# ]9 g, T. F3 B5 @- p KQ~`KI6}X$~1O8M`OVG5C.png 2 ^7 z& o/ f- Q& v% @- b: }) g
! v3 G8 e3 P  Z+ N) ]8 V
TIMx_SR寄存器,第1.2位保存的通道1、2的捕获和比较中断标志,上面说的很清楚,当在输出比较模式下,计数值和比较值匹配时,该位会置1。
1 {2 X& y9 C$ `3 ?, x* N$ V( d$ J7 C% \$ \
3、中断服务函数
# D) q; }7 e- h, I; _HAL库不熟悉的情况下,本人建议可以记一些比较常用的的寄存器,比如CCRx,SR,CNT等等,以免找不到想要找的函数。
; a1 b$ p" e- x* B$ L
8 X- o/ |0 ^9 H9 X' s7 d EN`BUM5FT84%SB6T67DBGFW.png
4 Q( P/ {* F, l: X; y  _7 `, W) F$ z0 n% P; ]! |
  1. void HAL_TIM_OC_DelayElapsedCallback(TIM_HandleTypeDef *htim)
    9 W, C2 ]4 G6 X5 d9 B  G9 N
  2. {
    6 q5 L1 ~- h1 \  |
  3.         if((TIM3->DIER & (0x1 << 1)) && (TIM3->DIER & (0x1 << 2)))
    9 ^) G9 d1 z6 j& r
  4.         {
    7 Q7 b! I+ u* p
  5.                 if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1)//(TIM3->SR & (0x1 << 1))
    0 ?- ^' m; G4 G/ }. ?
  6.                 {
    % ^% S  |( A% h1 s( Q* @
  7.                         sprintf((char *)arr, "CNT: %d, CCR1: %d\r\n", TIM3->CNT,TIM3->CCR1);3 c+ [$ v/ V, y9 B3 w
  8.                         HAL_UART_Transmit(&huart1, arr,sizeof(arr),50);
    8 k4 `3 r7 C7 a2 c
  9.                         TIM3->CCR1 = TIM3->CCR1 + 5000;3 Z3 \9 d( v( F9 ]3 i; B3 W  G' J3 t
  10.                         TIM3->CCR1 = TIM3->CCR1 % 10000;8 \+ @) P* W0 y( c. `
  11.                         num1++;
    8 h7 W, h4 x1 g) p1 x) Y0 ]; f7 B9 G: K
  12.                 }& D% ^4 R8 f8 x& C# l
  13.                
    : o( y  w. w  H+ x( K! `9 K
  14.                 if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2)//(TIM3->SR & (0x1 << 2))
    * |9 c& W- L- p3 m
  15.                 {
    / h9 z; G, e9 ?; G/ q
  16.                         sprintf((char *)arr, "CNT: %d, CCR2: %d \r\n", TIM3->CNT,TIM3->CCR2);
    6 x6 `# m9 E- c$ w/ S
  17.                         HAL_UART_Transmit(&huart1, arr,sizeof(arr),50);* ~: t- K% ^8 ~7 Q
  18.                         TIM3->CCR2 = TIM3->CCR2 + 2500;
    - c# {- D5 ~( n, w. l/ `1 a0 V
  19.                         TIM3->CCR2 = TIM3->CCR2 % 10000;
    + X0 w$ y3 q/ H) u4 X
  20.                         num2++;
    & M! G* O/ ^3 v4 a9 I  p
  21.                 }& P; B* p7 h& q2 \
  22. ' f! `3 {: }5 Y- `8 Y& ^2 [
  23. }
复制代码

/ |; [# n' T, {* Q: R: J0 n# n% c对于外条件判断,是因为本人在测试标志位的时候,打印过SR寄存器的显示值。3、4通道未开启中断,但是默认值是1,如果有操作不当可能使用的3、4的中断处理代码,会使程序卡死。所以外条件判断是判断1、2通道是否开启允许中断。
& t9 u2 b! i+ P; R0 c7 |代码测试:5 ^, x* D% t9 w$ V8 M2 z! _2 Q
6 w. m4 C; z* \+ k- ]( D3 }
R14~5JTLHG%$DI`2Z{B{C[J.png # `. ?$ k3 |: p$ s

! q7 ~8 Y, r6 N' \2 k, V/ B UKGHE0_KK0K_$J6GW]YYB2P.png ) {! Q' W# d1 O" N- u5 G8 a
+ R! m; n3 |  ?6 k: f9 W
串口接收到的CNT值大于CCRx值是正常的,因为代码运行需要时间,产生了中断就表示有匹配。
: V9 y, q/ W7 n! y" V图2可以看到2通道粗略是1通道的两倍,即1Hz和2Hz的方波。) Y+ [6 x7 p# C" }

. ?8 D3 C8 Z' D& Q( P
" U6 T* ?. D4 L7 R5 m6 |9 r& {; `& ?# L
收藏 评论0 发布时间:2022-7-7 16:00

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版