前言% h/ d6 ]* Q6 O
N% }! h' i# z) R* w
一、测量PWM频率和占空比原理
. C3 I5 N. P% @6 ^1 QSTM32G4上有两个信号发生器,接入引脚PA15和PB4用于生成PWM波1 z( p. @6 N7 ]3 `
9 Y" X0 G5 ~) g, N! O/ {6 E* s
# {# B w7 b* o! p: g6 q* {1 P! ?* d
使用的是定时器2的通道1和定时器3的通道16 }4 i5 T& m: S
" `2 s; O+ i7 B+ a5 \
" j% ?4 v# X5 A+ G
0 C- d9 l6 J' o/ ]% d9 ^8 |3 N
测量占空比和频率使用 PWM 输入模式,该模式是输入捕获的特例,使用通道 1 和通道 2。== PWM 输入模式需要占用两个捕获寄存器==) [) a. f3 i: m! F% G `9 I
% f* C( S S, n% r' S
) p$ m( ]4 e, r: j: A
当使用 PWM 输入模式的时候,因为一个输入通道(TIx)会占用两个捕获通道(ICx),所以一个定时器在使用 PWM 输入的时候最多只能使用两个输入通道(TIx),PWM 信号由输入通道 TI1 进入,因为是 PWM 输入模式的缘故,信号会被分为两路,一路是 TI1FP1,另外一路是 TI2FP2,一路是周期,另一路是占空比
9 a+ I* t# K( n4 x/ g% v' j! \( E2 H X% m4 x9 K
$ ~/ _* t8 |" I" Z
1 V& l! N4 p, u定时器从模式选择复位Reset模式: 使用内部时钟作为时钟源,TI1/2外部有效信号复位计数器。CH1触发输入上升沿有效时,先将计算器的值,移动到CCR比较寄存器中,然后计数器复位到默认值0(注意事件发生的顺序)7 y! |6 Z- {5 V7 p) M/ b: R6 Z
3 B2 Y5 S' N7 R6 H' L+ ]0 U
; z+ p' |3 U# }, M) R
0 E( v1 \$ z7 C0 a$ E( Z% g所以,当PWM信号由TI1进入**,配置TI1FP1为触发信号,上升沿捕获**,当上升沿的时候IC1,先将计算器的值移动到CCR中,然后计数器CNT清零,到了下降沿的时候,IC2捕获,此时计数器CNT的值被锁存到捕获寄存器CCR2中;到了下一个上升沿的时候,IC1捕获,计数器CNT的值被锁存到捕获寄存器CCR1中,然后又恢复到0, 其中CCR2测量的是脉宽,CCR1测量的是周期所以,占空比 = CCR2 / CCR1, s) H1 z4 w$ b; i4 ` O
* t) D! W! o+ Z& |0 d1 G# a
详细原理:输入捕获原理
% z6 J5 b" o' S7 T0 s$ B& K* m, p, t, |
所以,通道1设置为上升沿捕获,通道2设置为下降沿捕获$ H. k- p- u5 v! B
(其实通道2也可以设置为上升沿捕获,见参考文章)+ |5 a9 l+ {) ~, I, I8 z' b' l
$ `' K" Q: F3 L, W6 A: f
1Mhz计数cnt到65535需要的时间为0.065536s,因为两个上升沿之间的时间间隔最大为0.0014s(fmax=22.4khz),在这个时间段内,Cnt不能溢出,所以,直接记录捕获比较寄存器的数值即可计算频率,无需考虑溢出问题,也不用自动重装载
' c s. n- X1 G- G8 |8 d" [& G% O! T" i7 }8 U5 b
二、STM32CubeMX配置
) {9 V+ _& u# a2 z' L(1)配置定时器2 / 3的模式,时钟来源,触发源,使能通道1/2% i; v, E+ ?( P' `/ P: |7 E
2 p1 S: i4 \# D I& i2 T/ {
( t* C! P' C; P; g( ~& X- K% ?, O! H( f8 K" O, ?6 X* j
(2)配置计数器,通道1/2的基本参数7 o, F$ ] Z! x% z$ A# }
( F: U( _4 v0 Q& V) H, T/ k% `
& w; f2 X& Y; q- N( ?1 I, P; K& j+ y8 T
8 H, T- z8 \. [1 K(3)定时器引脚配置# g$ z2 i( y" ]! W
9 [$ L8 l" r% P+ `. }
2 B6 _+ Z: F' r' j
: o% e# F0 }0 `% N1 X' j% D(4)定时器中断优先级配置: P4 z7 T. D9 ]
0 D6 j$ k9 D, o
& O8 H6 |, o: B3 w+ B% T( ^
2 N; Q- p. S. w. g: h: y
三、部分源码
) c5 Y9 u- x1 z% T- void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)+ T }" p1 [2 g3 F9 C2 D. D
- {
6 @; b- ^5 Y% V# N. J- ?+ T - if(htim->Instance == TIM3) // 定时器判断" W/ x+ R- `2 J" Z1 H$ {6 H
- {
2 d6 x6 I; g( |. I7 j - if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1) // 通道1
$ j7 _$ Q0 b. Z1 j6 |; \" G9 L - {
4 {! _0 x3 q7 L - PWM1_T_Count = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1)+1; // f = 1e6/PWM1_T_Count1 v% |( k. q, Z, R# p4 z
- PWM1_Duty = (float)PWM1_D_Count / PWM1_T_Count; // 占空比 u3 f w; ^5 R
- }
# ^* u8 O! W& b - else if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2) // 通道2" o# K u; a/ _' b) I8 x- Z
- {, C. z5 A* v( Q- r
- PWM1_D_Count = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_2)+1;
- v/ G9 A, o. Y/ q. O( j - } R" C7 h0 f, {4 E
- }1 P B' G# ?) J2 p* q
- 7 w6 `0 o2 ?& r! n
-
. ^7 p; r) ~; S+ f - if(htim->Instance == TIM2)
& B: n$ H6 V2 m. i! V6 s - {
. _' y. h J& y( e - if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1)
& l! e7 |0 v0 E4 T; ? O/ p - {! k. k$ y5 i- h1 ~
- PWM2_T_Count = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1)+1;
" n% j0 W( D) \2 g4 P: V - PWM2_Duty = (float)PWM2_D_Count / PWM1_T_Count ; // 占空比
# G7 V$ D% }; `* ~3 x - }) \. b. D* a* P. p
- else if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2) // 通道2
8 J% G$ Y' F# U; Z1 V3 j% Z - {
0 U9 O# H* m! }1 p" H5 o - PWM2_D_Count = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_2)+1;" s. j4 i, Y! ~8 I& r& u* b" G! U5 f
- }
2 G9 s7 L/ F" ` M - }
, v' ?; z% A* M* c3 W- p - }
3 t w) V" n" F$ m) c. m/ C5 J
复制代码
/ G$ _" V. s7 r; \8 O测得结果:
8 s. a; w) }; r8 U* O5 G5 Z
) N' K; V* y+ U+ w. c# Q4 ?$ MPWM1 output = 710hz-22.4khz PB43 }$ K s2 H$ {! T4 g
PWM2 output = 630hz-22.0khz PA150 i( R& P! n0 g3 V
Tmax = 0.001410437235543s 最长周期! L. w7 b! J0 x
- I; R, ]9 y) l+ A9 l9 E
3 a6 X. ?5 V( r* Z; ?: P& m: w" S) s V, G" H3 j) Y3 o
|