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

【经验分享】HAL库 STM32CubeMX教程八---定时器输入捕获

[复制链接]
STMCU小助手 发布时间:2022-3-25 10:29
前言:
' R0 u" Y1 O1 q* F% b/ z1 ^& ]本系列教程将外设原理,HAL库与STM32CubeMX结合在一起讲解,使您可以更快速的学会各个模块的使用
; @+ {+ T7 {/ p4 H- m$ w* s! ^% i2 [& U1 A  E
1 i% x! }8 O* X
所用工具:4 ~1 M' ]# L! g8 U4 N. b
: ]3 P9 a( H1 k
1、芯片: STM32F407ZET6/STM32F103ZET63 V9 k7 N# y& i4 d0 W: K

# E; j) _# L# T. j& @0 |( v2、STM32CubeMx软件
0 h. _* I+ p' g& O1 w( I$ \- Q
! ?# |$ T8 m5 ~9 D3、IDE: MDK-Keil软件, G1 _8 {7 `! Z% s% @4 q

( A2 o5 C4 o, o1 f! N$ G4、STM32F1xx/STM32F4xxHAL库 % N$ c1 `0 G2 m. m7 h

0 G2 P$ @: r& z6 g知识概括:
; T- U7 P- g" E0 `3 _) v
1 F* [( N. X4 a' r+ l- t通过本篇博客您将学到:  u! R' l4 l9 w; C/ E

) w7 i% K: _; zSMT32定时器输入捕获9 h7 E0 B6 S2 M# y

6 c+ X  n! X9 Z 测量PWM频率和占空比
8 q3 F& q; K- q2 v+ P& q0 D. y6 P8 E) q6 j2 [; h
- u" j8 j0 b5 Q0 m) L# Z
输入捕获5 _4 d1 J3 s2 s, X
输入捕获概念
# |: E4 n( s+ w# \) s3 A& Z输入捕获模式可以用来测量脉冲宽度或者测量频率。STM32的定时器,除了TIM6、TIM7,其他的定时器都有输入捕获的功能。- A8 k, J: P4 ~
: r$ @, j" T/ u4 T: _$ E6 ]2 U
输入捕获的工作原理2 N0 w: M. K6 ]2 q, F

6 ?( l' @* Y$ v 20190813094532466.png " _3 p6 {0 m$ a: d7 d: g. n
①先设置输入捕获为上升沿检测,
) l, x  Q1 Z7 p; W5 P. @% y: L. H3 f0 @- |" j' A" ]' R4 W
②记录发生上升沿时TIMx_CNT(计数器)的值
7 a, J+ n2 r1 d6 n& r  j3 q5 n( b) d: @+ a$ E0 n+ U* j
③配置捕获信号为下降沿捕获,当下降沿到来的时候发生捕获1 W7 H1 Y" y/ W+ S9 m0 y: B, C
2 t' \7 W3 v  O0 u; u6 o+ W2 @
④记录此时的TIMx_CN(计数器)T的值9 r; A5 }4 _* P% B6 m7 }# H0 D

  S; i; q( d! l" z; Z⑤前后两次TIMx_CNT(计数器)的值之差就是高电平的脉宽。同时根据TIM的计数频率,我们就能知道高电平脉宽的准确时间。" m3 b& A: `" M0 G& f
1 n* E3 X9 S4 B/ N

( r$ ~' W, z( _' H( K简单说:& E5 Z- W' K( ]% @
! P- G. }% v$ _* h) m9 ?( m( M
当你设置的捕获开始的时候,cpu会将计数寄存器的值复制到捕获比较寄存器中并开始计数,当再次捕捉到电平变化时,这是计数寄存器中的值减去刚才复制的值就是这段电平的持续时间,你可以设置上升沿捕获、下降沿捕获、或者上升沿下降沿都捕获,6 C# o; C* n( l
7 y: ~* m+ R* V: R1 H1 ~

  g; O9 M9 J3 x, k+ H输入捕获的工作流程(对应CubeMx的四个选项)
  w; {( J1 |8 G4 a0 @: m2 M8 r: m; J
20180419215648175.png
. m" r  _$ c# V) R; [/ K7 b; _8 R# @* f0 x3 D& Q
设置输入捕获滤波器

) E5 U! P$ v9 C% h$ L. {0 oSTM32在很多功能中都提供了滤波器,滤波器的功能简单来说就是多次检测视为一次有效,达到滤波效果,& z) c1 U, J, [4 ^$ V/ `% `& h

* m& d+ v/ i8 F$ o& w数字滤波器由一个事件计数器组成,假设我们是检测高电平,滤波N次,那么记录到N个事件后计数器会产生一个输出的跳变。也就是说连续N次采样检测,如果都是高电平,则说明这是一个有效的电平信号,这样便可以过滤掉那些因为某些而干扰产生的一些信号        0 Y( u% e  ^' v! ?! `

2 J% F' M. O  H: H1 B( u2 f2 Z输入捕获滤波器IC1F[3:0],这个用于设置采样频率和数字滤波器长度。其中:fCK_INT是定时器的输入频率,fDTS是根据TIMx_CR1的CKD[1:0]的设置来确定的。
0 d) M5 U3 Q  t8 I( R; r+ ]
: ?9 z$ I5 O3 Q# w- s$ `设置输入捕获极性2 f; C3 d1 J/ P5 P9 v
& z' |% c4 g& z; t
设置具体为那种
捕获事件- l/ [& j& b, A. p
5 @, w, g9 D- S5 F6 ~) {
可以设置上升沿捕获、下降沿捕获、或者上升沿下降沿都捕获- |/ q0 N. ]8 F  S/ a3 p- _

0 K5 B  s- w, b2 Y9 w: z& t设置输入捕获映射关系
; z3 a4 ~5 h" USTM32为了更好的优化使用,TIMx_CH1通道1捕捉到的信号可以传输到IC1,TIMx_CH1捕捉到的信号也可以连接到IC2,TIMx_CH2捕捉到的信号也可以连接到IC2,也可以连接到IC2
9 k7 E+ P6 D* h3 `# h
  u' m* W3 ]4 K: r 20190813111456218.png
& o5 B, _* F- ]4 P- Q% {* W$ P+ A9 S, b. j" M" ~
; Z% B+ r- V3 j  u% r- k
设置输入捕获分频器
/ Z) @# T1 v8 l设置每N个事件触发一次捕获,可以设置为1/2/4/8次检测到电平变化才触发捕获
+ {+ l0 S! D" S! s) z& G# U- K; x4 D& R- |5 g5 B; Q  R+ O" F+ ?1 e
溢出时间计算:$ W/ \+ F3 o% m
aHR0cHM6Ly9pbWFnZXMyMDE4LmNuYmxvZ3MuY29tL2Jsb2cvMTIwNzU3Ni8yMDE4MDUvMTIwNzU3Ni0y.png 6 B5 \8 Z" ~3 H, ~

7 e8 A. @; b. S+ e7 a( bt1时刻检测到高电平,发生中断,在中断里将计数值置0,开始记溢出次数N,
4 R: A* F9 q1 c0 N9 P8 j' R3 F0 k5 }8 e1 s8 @
其中每计数0xFFFF次溢出一次,直到t2时刻跳变回低电平,. N* H1 p5 ]5 G: u4 {

) B  D" f0 |" ^3 f4 s+ B2 J获取最后一次溢出时到t2时刻的计数值TIM5CH1_CAPTURE_VAL
, Z- K$ j: z8 e) b9 c) N9 m4 V: l0 d2 v! e- ]3 H) S5 O
则  高电平时间 = 溢出次数*65535+TIM5CH1_CAPTURE_VAL     us ;根据定时器初始化时的频率即可计算出溢出总次数所占用的时间,即为高电平时间。& F) s$ J( q( _/ \
& n- Q4 v( a( X$ J6 J% v
如果计数器值为 32 bit   那么最大为0xFFFFFFFF      ' f6 J4 Q) m% E5 o3 _$ F0 S8 x" }/ c

" n5 j$ ~$ y. z$ o: u; {- B( k) q高电平时间:
# |" |' t) z0 @$ [4 W7 ^4 X7 W* R, t8 ^4 M( S
20190813172958716.png 5 c' ?, {. b8 C8 p8 S/ F
* P& s7 G* a9 a/ s8 k, s* A
! v. h/ b5 s( u  @. A
输入捕获的工作框图
. d4 ?% a- o7 R- R. q' b: b
& h) C& X& P: K# @; P  T 20180419213733338.png / J  M/ o0 Y% |: z& ?# N
8 [: g3 H+ M5 |( |! P( q
  {1 a& J* B) x& Y1 T
工程创建% Z8 {( w: j2 e, i, c) ?" W
设置RCC
6 w1 ~1 j$ ?- u4 v
1 C8 b9 r0 F! H, Z2 D; y- m( }0 w8 I( f
设置高速外部时钟HSE 选择外部时钟源8 R# `; Y' ~) Z( h6 V

1 f. d+ R5 P  W 20190810145615696.png
: M9 Q9 z" a9 T# @) L6 |
% L4 s( j9 {3 I/ f2设置时钟$ B: w& R* |! W8 |, }
3 V. k/ M- }+ Z# z9 y6 g  E7 v: `
2019081117400555.png / ^/ p" g3 B. I1 F( I  y/ Q  V) m1 w3 q  v
, S. K' f  l! a- N/ y; x4 w7 l+ D
我的是  外部晶振为8MHz . |% v- G' a% `6 Y
1选择外部时钟HSE 8MHz   
, g3 _* M+ B5 s0 J: ?2PLL锁相环倍频72倍9 f- u7 }0 n7 A9 k
3系统时钟来源选择为PLL
3 i8 G+ T% p% S' l% {4设置APB1分频器为 /2
) d; S  }8 j5 C# y& D5 这时候定时器的时钟频率为72Mhz, T; j9 `$ x; Z, X  J6 g  _

. |2 L0 U9 R5 I6 x6 F$ C3定时器配置/ Q; j2 T$ I1 {$ h* \; l$ h- J

. K/ V4 T6 S- _: O 20190813120324793.png 5 v' x8 l5 E+ l9 E+ U- E
# Y# x5 _. M5 G/ [$ W6 c5 w
这里我们选择TIM5的通道1# f. p; l3 i6 }8 A$ v

# H+ q9 m$ ?- r+ S/ u  ~0 T/ {$ z& ^预分频系数为71   计数时钟频率就是 72MHz/(71+1) = 1MHz        此时1us计数一次4 u2 _# e2 o+ T% G" F0 W
自动加载值设置为32bit最大值  0xFFFFFFFF          7 m( r" W+ B; o6 ^
上升沿捕获' Q( F: c' Q8 R; x( T; I2 {
不分频
4 o" |3 ?0 K! M! X滤波值为8! L4 t* {- l& `* @% S- F- D+ A% g, e

( ?* G2 s( @+ \3 B- X同时在NVIC一栏使能TIM5的中断9 x& y1 s/ o  j; H: W% n: H
$ X3 x( U1 Q! K& s
对应引脚设置下拉电阻,保证没有信号输入的时候电平稳定
5 m1 i4 y& e5 f: `1 M. t4 V8 A9 r: a! V
20190813152340197.png
- s: F- P) w8 _" H2 g% l0 d: E" O3 M: @2 B
4项目文件设置
9 u, R3 f# N: O+ [5 Q8 ?; x/ t/ A
+ d3 s% i0 L8 o# Z$ l 20190811193124463.png
0 G6 w3 P3 o, J' c2 j8 M1 h
4 @% l! W0 f, ^. Y: H1 设置项目名称+ S& n* V, a7 X$ V0 M+ {* v! G* i3 J
2 设置存储路径
$ O# [- v5 w5 \* m& j3 选择所用IDE
0 V" V* |# P: Z& M8 n* ~/ j9 t1 O) l- A6 l
2019080921100765.png & M2 V6 P, q* q9 ~* w- E/ S
0 b5 j. n+ x4 B( a
5创建工程文件
, a: k$ ~7 l6 `; [! c- H: N5 b) V" `+ [1 |1 p4 }' r* o7 d1 `  }
然后点击GENERATE CODE  创建工程
+ g( Y' }6 F* g+ B' k
$ A( M% l: H& M( m. w7 E& ?; g1 b配置下载工具
& f1 H# b9 t! P新建的工程所有配置都是默认的  我们需要自行选择下载模式,勾选上下载后复位运行; Q% \: b+ {- Q) D6 p

4 X$ h" K0 U4 j6 f5 W$ I0 N 20190809172359875.png $ [+ x9 L! x$ r5 l6 i% L! ~

8 [! L; C' x  r5 t+ W* i例程实现:
; o' X# U1 R, F' N! T, ?定义变量:
  1. /* USER CODE BEGIN 0 */- D9 E4 D; [0 \' y. i" ~9 e
  2.     uint32_t capture_Buf[3] = {0};   //存放计数值
    6 d8 g) f+ b/ x6 `; J9 P. d
  3.     uint8_t capture_Cnt = 0;    //状态标志位
    # f3 A; `; F* b+ n" u$ {7 T1 H
  4.     uint32_t high_time;   //高电平时间  i9 f1 I* p$ z5 w6 _
  5. /* USER CODE END 0 */
复制代码
9 P. D8 `  p  C& S5 Q) v7 F1 `
在 while(1)中的用户代码区 3,写入TIM2 CH1通道的输入捕获控制和数据处理
( o' z6 Q, x4 r4 s# N
( j5 o' x7 b4 Z8 r( \. ^4 b2 k
  1. while (1)
    , Y$ b# h. a1 ]- v( c1 |
  2. {
    ) |0 L: s8 c* ]
  3.     /* USER CODE END WHILE */
    " D% A* i" N. M& ^
  4. : G" T! v' H$ b) n4 X* f
  5.     /* USER CODE BEGIN 3 */5 U: S. Y* }6 r& u9 g( e; ?# ?) q, V
  6.   switch (capture_Cnt){
    , q: E% T* x7 [  K) O
  7.         case 0:
    - i& Q/ c1 T, R0 P' u9 j) ~
  8.                 capture_Cnt++;) a* ?! P# a) h$ P# {1 T# m
  9.                 __HAL_TIM_SET_CAPTUREPOLARITY(&htim5, TIM_CHANNEL_1, TIM_INPUTCHANNELPOLARITY_RISING);
    , z, S; d: n, g4 \1 R- w
  10.                 HAL_TIM_IC_Start_IT(&htim5, TIM_CHANNEL_1);        //启动输入捕获       或者: __HAL_TIM_ENABLE(&htim5);( G+ E$ k/ M$ Z$ B( \2 ?9 \1 y
  11.                 break;
    ! z! k% Z9 i& M) `
  12.         case 3:
    3 N7 h, A0 a4 |( z% i
  13.                 high_time = capture_Buf[1]- capture_Buf[0];    //高电平时间  b0 H( o( ?+ S; E$ D/ i
  14.                 HAL_UART_Transmit(&huart1, (uint8_t *)high_time, 1, 0xffff);   //发送高电平时间
    4 h7 J! I: ^( S; I
  15.                                 
    % u5 ~1 v& ?& ?. u( ~! }
  16.                                 
    : ]7 Y4 r, n' [: y+ [4 D4 N( B
  17.                 HAL_Delay(1000);   //延时1S! i5 u1 D6 Q$ w% U; o" \  ~1 |" Z9 X
  18.                 capture_Cnt = 0;  //清空标志位
    ( n2 K7 o8 Q# R! q
  19.                 break;5 Q0 u0 v$ o8 j
  20.                                 
    : F9 p# I+ N) }. `5 f8 w
  21.         }
    ) j. s! T/ w: R6 N
  22. }. x: Q" \/ q6 F: P4 p6 S- l3 d
  23. /* USER CODE END 3 */
复制代码

5 H" I! M2 x4 {7 H$ q在main函数下方添加中断回调函数:* t( \& K4 W& ^6 n% R5 a* ~: H: G
9 z; R( g, O6 v; g% R% r" X
  1. /* USER CODE BEGIN 4 */
    8 @2 a/ \6 Y) `6 u" i8 l+ Q
  2. void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
    1 O4 H5 ?( m8 x) Q, s8 U/ l
  3. {. {( i" I9 A( I) I, L( J4 ~  k) Z
  4.         
    # F7 J! q  v5 l! L! |
  5.         if(TIM5 == htim->Instance)+ |. Z0 w* O8 U
  6.         {; ?! t$ q4 {( E, ^2 I6 d
  7.                 switch(capture_Cnt){
    - M. O" V9 Z: J9 m/ b
  8.                         case 1:
    * w5 B. i7 g& c: M' h8 d) t( ]
  9.                                 capture_Buf[0] = HAL_TIM_ReadCapturedValue(&htim5,TIM_CHANNEL_1);//获取当前的捕获值.
    ; W: U7 C( m0 i6 q2 G& Q
  10.                                 __HAL_TIM_SET_CAPTUREPOLARITY(&htim5,TIM_CHANNEL_1,TIM_ICPOLARITY_FALLING);  //设置为下降沿捕获8 Y8 V. ^+ q! p# T1 a
  11.                                 capture_Cnt++;, N8 ^9 S1 E+ X3 s
  12.                                 break;
    0 [/ k5 U% @0 i6 I: w
  13.                         case 2:
    1 A( w* l& o  I( j
  14.                                 capture_Buf[1] = HAL_TIM_ReadCapturedValue(&htim5,TIM_CHANNEL_1);//获取当前的捕获值.7 [4 O; X# o' f1 d9 u$ `6 S$ r
  15.                                 HAL_TIM_IC_Stop_IT(&htim5,TIM_CHANNEL_1); //停止捕获   或者: __HAL_TIM_DISABLE(&htim5);. G$ I* l5 h( y1 _  U& A0 T
  16.                                 capture_Cnt++;    + q4 H2 D! b8 f& K3 ]% N5 r
  17.                 }3 c  Y8 j$ B) V5 U% X
  18.         
    ) B/ w$ V8 g, |
  19.         }0 Y5 v3 |, P& S$ B' M$ n
  20.         & I$ }6 i& a2 s5 H0 n
  21. }
    - e' A" p2 V7 |1 Z! f' A
  22. /* USER CODE END 4 */! J9 v, ~$ `. {# x: `
复制代码
8 L0 Z# G) E& L: v8 P# U' T
具体流程:# r" o2 p& j1 \! h: o, _

) u, [' R' ?, R0 l3 b1.设置TIM5 CH1为输入捕获功能;  
% @9 U, L& R: k) j% V) g5 E, k+ o" }/ v3 b
2.设置上升沿捕获;
& q8 l% S$ ~; X9 d  H/ t. k' Q, g3 w9 P) \3 w4 m
3.使能TIM2 CH1捕获功能;  
# a$ f% W3 F( q; h' |2 k: M' _6 h8 e& n" O" z. [
4.捕获到上升沿后,定时器当前计数值存入capture_buf[0],改为捕获下降沿;   0 a1 z& s* C8 P
# E; Q! y, D' k" ]' l  k# {3 C
5.捕获到下降沿后,定时器当前计数值存入存入capture_buf[1],关闭TIM2 CH1捕获功能;  capture_Cnt=3;
6 J8 w2 c( v1 B5 h% w! L/ _
) l: v; E" K0 \! G+ S6.  高电平时间: capture_buf[1] - capture_buf[0]        发送到上位机  重新启动输入捕获5 L. A0 u/ L% b

% Z1 ^9 a6 K" c3 x3 ]8 ~* C2 e$ ^  \& q% X2 P
__HAL_TIM_SET_COUNTER(&TIM5_Handler,0);   //设置计数寄存器的值变为0
. y* I: R8 F: t
! o  G* H* J2 B$ CHAL_TIM_PWM_Start()              函数用于使能定时器某一通道的PWM输出。# B# O+ X2 a$ E8 I" o9 G% |
& y* m0 o) Z6 ]; h: _0 m# F! n
HAL_TIM_IC_Start_IT()                  函数用于使能定时器某一通道的输入捕获功能,并使能相应的中断
9 M. q6 ]1 x! v; x2 g& T* w
' C) N+ T( O; }4 b0 V1 P6 p/ ^HAL_TIM_IC_Stop_IT()                 函数和开启功能相反,是关闭定时器某一通道的输入捕获功能和相应中断3 R2 d" G# R$ v# ?6 N2 Z7 a' B  z

  ]0 n6 Y0 u, D2 @0 B__HAL_TIM_SET_CAPTUREPOLARITY
不是函数,而是底层操作的一个宏定义. _7 F( i# u. S* e4 N
. b# z, a4 v. o/ v
在stm32f4xx_hal_tim.h文件中可以找到。其作用是修改定时器某一通道的输入捕获极性. d1 @% r* x6 A' Y  a, s

) k1 ]# I; G+ n. j) f0 V7 y 20190813171232499.png : j. Y. I2 F# d* I! p; O, r% [

& d" C  F! L  J; r  X0 ^其中有两个函数,第一个为清除清除原来的捕获极性,第二个为设置通道捕捉极性
& Y" ~/ @7 X9 k5 p0 |7 \
+ E+ u0 K5 \4 s$ d/ Z等价于:
/ |( \% W: O; A3 j, U0 v; w3 K. M1 m) Y8 u, N/ O$ S: m' M) G; J
  1. TIM_RESET_CAPTUREPOLARITY(&TIM5_Handler,TIM_CHANNEL_1);   //一定要先清除原来的捕获极性!!
    / M# Q& t% d: t  d0 n+ j  S
  2. TIM_SET_CAPTUREPOLARITY(&TIM5_Handler,TIM_CHANNEL_1,TIM_ICPOLARITY_FALLING);//定时器5通道1设置为下降沿捕获(重设捕获极性)
复制代码
2 W1 r$ Q( L' ]+ M" S
在修改定时器某一通道的输入捕获极性时,一定要先清除该通道之前捕获极性/ T$ r) V3 L' T3 s4 U7 V

" J; b5 t: D0 \2 w$ i  A__HAL_TIM_GET_COMPARE也是一个宏定义。   w! P5 ^3 D9 ]5 v$ d- b( R
在stm32f4xx_hal_tim.h文件中可以找到。其作用是获取定时器某一通道的捕获/比较寄存器值- B$ T! R4 o/ b$ E( t6 [! a

3 `7 O. p- U  I" J$ I6 P3 W 20190813171323391.png 1 P0 J% C1 Z* O! ^* d  @0 ?5 P

, M, _  B8 |. Y等价于 :  HAL_TIM_ReadCapturedValue(&htim5,TIM_CHANNEL_1);
) p& O8 Z' Z/ t+ \
% I5 L3 n* {3 T5 X; @* c9 Y! S  两者都是直接读取对应CCRx寄存器的值
7 i  \0 V9 b/ _9 Z! e
  \" G' H# v" G% ^$ {( W. p
9 N, v0 Z' }: I3 i9 ~  ^' \; R5 Y
% i2 [- a; c/ h* L7 Y4 Z
赞 收藏 评论0 发布时间:2022-3-25 10:29

举报

0个回答

所属标签

相似技术帖

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