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

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

[复制链接]
STMCU小助手 发布时间:2022-3-25 10:29
前言:
/ @( C! b$ O! i+ j; {本系列教程将外设原理,HAL库与STM32CubeMX结合在一起讲解,使您可以更快速的学会各个模块的使用
& d+ |+ E( M! k- j  N9 X
2 k3 f7 J! Y& ]  }5 Z
9 D3 l4 t6 }* I. v% Z. G8 _所用工具:, k7 d  ~4 R1 U2 a$ j
0 y( [5 h! k0 r( Q
1、芯片: STM32F407ZET6/STM32F103ZET62 M. O8 A3 f' Z! s5 ?- Q) M
+ O/ U: a  F  g; Q/ g3 s0 B8 g3 ^
2、STM32CubeMx软件
# O; j# B7 n, G' k
* D9 Z6 A7 d: G, q3、IDE: MDK-Keil软件9 Z& B& }9 }0 Q+ O" d$ v
9 ^& P+ J" e" u8 e$ n9 J! Y" g! t
4、STM32F1xx/STM32F4xxHAL库 # r3 `9 M4 m% v* I
, k. ~& c% d# h" [, B( ?" C
知识概括:1 f. d" E8 {- s, t, r- C

' v2 s! U8 F4 D通过本篇博客您将学到:
1 j: [1 Q+ {2 }& ?  O/ J) o4 n
. l; u* i# d" v( l3 [SMT32定时器输入捕获
; d. R3 j+ s6 N% b, \
3 \- K+ `, t7 ^1 m6 h 测量PWM频率和占空比
) j& C' G+ ]2 f0 B" I0 |" M! N: P/ _. e3 S; i: o5 A4 g, M% ]  l
5 x4 j8 Q9 T( ^6 e, |$ ]
输入捕获
/ u: v1 A9 q2 |0 G输入捕获概念, \5 d; l3 {8 `. {
输入捕获模式可以用来测量脉冲宽度或者测量频率。STM32的定时器,除了TIM6、TIM7,其他的定时器都有输入捕获的功能。' Y; Z9 |. k: ]( @5 M

, y0 r& @" m& o. t7 e  C输入捕获的工作原理( T4 S3 f  t( V5 b: w! e
6 C# [! f' ^; P2 _
20190813094532466.png
5 a3 _8 Y0 a( D0 ]: i" r) [①先设置输入捕获为上升沿检测,9 R9 |* _) G8 T: W3 _5 i, c

% L; {$ ?6 A8 H$ t8 w  D②记录发生上升沿时TIMx_CNT(计数器)的值
$ M. j6 J  |2 _: G7 r: K
& r) j+ R8 U( S# Z. @③配置捕获信号为下降沿捕获,当下降沿到来的时候发生捕获
" u4 @: K6 O1 O+ p9 g; ~( ]$ Z4 G, j! q9 B& _3 [6 [
④记录此时的TIMx_CN(计数器)T的值/ h* f8 U& _$ ?! J

7 J5 ^9 Y8 f% G⑤前后两次TIMx_CNT(计数器)的值之差就是高电平的脉宽。同时根据TIM的计数频率,我们就能知道高电平脉宽的准确时间。
$ E! F. W$ W- X; U5 m/ i* q% m6 s* D7 h7 p  D

- x: [7 m! a$ N$ x简单说:; O4 G, W7 y- ]% C' n- V
8 ?4 A9 I! B! \: H/ |
当你设置的捕获开始的时候,cpu会将计数寄存器的值复制到捕获比较寄存器中并开始计数,当再次捕捉到电平变化时,这是计数寄存器中的值减去刚才复制的值就是这段电平的持续时间,你可以设置上升沿捕获、下降沿捕获、或者上升沿下降沿都捕获,
4 d& V9 Z2 f5 @: {2 ^$ q
9 L9 r- H/ M4 J8 l& N1 Q; d' I  q, y
输入捕获的工作流程(对应CubeMx的四个选项)9 f: U$ ]! x% h& l

* [0 ?" d( B) v 20180419215648175.png . l- Q5 z5 M* M- j, z2 u9 X  O

. _7 C; U7 z7 n0 J8 W4 Z+ f/ v设置输入捕获滤波器
! i* u9 t# }1 d+ {! p% r
STM32在很多功能中都提供了滤波器,滤波器的功能简单来说就是多次检测视为一次有效,达到滤波效果,
2 ^5 u5 {7 H' K3 t/ n8 x( H0 k0 i! Z/ p( h9 t
数字滤波器由一个事件计数器组成,假设我们是检测高电平,滤波N次,那么记录到N个事件后计数器会产生一个输出的跳变。也就是说连续N次采样检测,如果都是高电平,则说明这是一个有效的电平信号,这样便可以过滤掉那些因为某些而干扰产生的一些信号        & W" O/ J# n/ u, Y$ d
. d4 u: B. X% b
输入捕获滤波器IC1F[3:0],这个用于设置采样频率和数字滤波器长度。其中:fCK_INT是定时器的输入频率,fDTS是根据TIMx_CR1的CKD[1:0]的设置来确定的。: m  i( C  s+ |: M
0 N2 V( r+ [; u% i/ m2 B( Q& ~
设置输入捕获极性
! ?  F7 c1 y! @" h6 ]1 o( a, B4 d, l$ A
设置具体为那种
捕获事件& @+ m, D3 g/ }3 A0 ?+ u* R/ X

9 J4 l5 ?% |! I3 D; O: p可以设置上升沿捕获、下降沿捕获、或者上升沿下降沿都捕获7 I% ~& Q& R) _- d, s6 k) z2 c8 a( [
. j- ^4 m$ G/ a9 c4 P4 U
设置输入捕获映射关系
) H* k  V: B' N5 l+ ySTM32为了更好的优化使用,TIMx_CH1通道1捕捉到的信号可以传输到IC1,TIMx_CH1捕捉到的信号也可以连接到IC2,TIMx_CH2捕捉到的信号也可以连接到IC2,也可以连接到IC24 Z9 \- r, H2 Q2 m

" Y. U( l- e7 e" O 20190813111456218.png
$ a6 K; U4 i2 ~0 }0 I7 W- T( g" h% D6 @' K: w8 H7 E- W! b

8 _7 Y7 _# [! l* {) f1 f设置输入捕获分频器: p  P9 D' {9 r2 [1 x' U
设置每N个事件触发一次捕获,可以设置为1/2/4/8次检测到电平变化才触发捕获- [% m: U4 B+ F' M5 h  @

0 S& D0 A# A2 g$ S, J溢出时间计算:2 |. \" d! |* y! ]% B1 a
aHR0cHM6Ly9pbWFnZXMyMDE4LmNuYmxvZ3MuY29tL2Jsb2cvMTIwNzU3Ni8yMDE4MDUvMTIwNzU3Ni0y.png
  D1 L. r+ l; Y& H, N" E$ N- F% J/ e2 ]6 I$ P6 [
t1时刻检测到高电平,发生中断,在中断里将计数值置0,开始记溢出次数N,1 w+ f9 k  _" o

% G; o, Z) _: k. o1 ~其中每计数0xFFFF次溢出一次,直到t2时刻跳变回低电平,/ ~8 \" C, m: w: N; B5 F' r% H5 Y

* t) u6 ~; G9 y5 J获取最后一次溢出时到t2时刻的计数值TIM5CH1_CAPTURE_VAL3 D2 r: M& L8 _4 k9 X* A; o1 c* A
+ Y; [4 ~* p& m8 K3 z
则  高电平时间 = 溢出次数*65535+TIM5CH1_CAPTURE_VAL     us ;根据定时器初始化时的频率即可计算出溢出总次数所占用的时间,即为高电平时间。9 }2 n& m% l( V2 P* H$ T6 j! A+ `# S

$ ]$ N  o- t- C, M3 ^/ s如果计数器值为 32 bit   那么最大为0xFFFFFFFF      
/ ^, Z" O! h# ^$ ^! N- x- s( Q& {- {2 C/ V1 _0 I
高电平时间:' W. N4 q  E' k# m+ V9 i6 W8 Y

4 q5 [% O! f) q3 {% h  f; @- J 20190813172958716.png
9 p) b, Q% {/ E& B# i& |% }3 V$ d2 d: z2 l# f4 {8 D
$ ?( w4 i. C3 z/ m/ L! Z% _
输入捕获的工作框图
! ]$ J9 Z4 c4 A( o
5 |* s! [2 o& J0 Z# r% P' c 20180419213733338.png
' t+ S! |  m! S. x2 g
7 t5 L0 _& L! }: d1 g) ~8 Z5 Y' n4 c& O/ R' ?8 n" s' ?% B1 y0 g
工程创建& t' }% k, O/ P: z8 Z
设置RCC
1 J7 J4 X. X) |! h6 L% _7 c

& C8 J5 d! e. W& q) Z' C8 u" j设置高速外部时钟HSE 选择外部时钟源5 u7 {: V" Y% L/ |) j- T4 }" S# W' @
" e# J! O( p' n4 c: G6 I5 w; Z
20190810145615696.png # ~- o9 x  u1 f8 Q# o# B: J

, k1 p- {6 D7 I2设置时钟8 X1 w9 Z5 m0 W
* F- H& n6 z! a' R# e2 W: z* E$ o1 x5 ~
2019081117400555.png 9 V# S6 d- E% E! r, D1 P5 Y/ {
  W* C) T% c: N: G' V' ?- @
我的是  外部晶振为8MHz ( c, d8 I8 }" U4 o% O6 r3 V
1选择外部时钟HSE 8MHz   
" E  v% G/ j5 f2PLL锁相环倍频72倍; b$ q& F, _" o8 @# E
3系统时钟来源选择为PLL9 r6 J8 @. [, L, W7 U
4设置APB1分频器为 /24 \: w# [- Y# v7 R3 A0 F
5 这时候定时器的时钟频率为72Mhz$ i' P( N( v4 z1 [; l

6 x/ j) d2 r' L" z6 d3定时器配置5 q) n* a# b' C

1 h7 X; s8 e- k: R 20190813120324793.png + B6 o+ c3 b8 F

7 s6 ^1 V+ p, K5 \/ E7 J$ s5 o这里我们选择TIM5的通道1- Z! R1 H$ E" T6 R( j! [4 p5 t

& ^! b+ C& _+ N  S# \8 \4 _预分频系数为71   计数时钟频率就是 72MHz/(71+1) = 1MHz        此时1us计数一次
+ O# a" j5 h1 t- l7 E, z) D1 C自动加载值设置为32bit最大值  0xFFFFFFFF          - F. A. R9 D% [0 k+ E' B* f
上升沿捕获
2 p) a) ]) Q' c( U/ ~# j不分频
! T5 x( `# A- d, ?, H7 Y滤波值为8, }$ J* x5 K0 r2 [5 e' M5 @& {. o

( x4 m) R, ^- r9 A. z同时在NVIC一栏使能TIM5的中断
8 h7 b+ n6 h/ U5 P$ d7 w# h8 N: a2 z5 V) y! X5 `
对应引脚设置下拉电阻,保证没有信号输入的时候电平稳定0 J, g/ g8 h, M

7 p: l' V% z4 z+ S7 X. W 20190813152340197.png & y  `! T; E2 O* W( Q. ?  \4 P

' R4 j+ C. N8 a2 n% q) s4项目文件设置" [+ `/ C/ R" l9 L! B
1 y6 s" A2 b( r8 p6 N
20190811193124463.png
5 x5 Q/ s1 y9 Z; ~8 K0 t; X3 s( }+ z6 k  S$ p4 h/ ~( T
1 设置项目名称( Q, }- {7 w6 `" `/ `3 o
2 设置存储路径0 C6 c9 ?- N# d, m
3 选择所用IDE
6 t+ X& Y$ \, y8 e8 Q5 ~
% ]8 ^) R( V- L4 X$ y% p 2019080921100765.png - I( G8 ~# t  Q8 J2 u
7 V! j1 J5 E( T3 N! o% _) Q% Q
5创建工程文件
5 F4 C3 f- v4 {4 m5 {# d
: `4 ?( }! g' O5 G8 Y; c% @然后点击GENERATE CODE  创建工程9 z9 i8 J3 A; Z& \
: n9 h5 g  ?7 ^7 y* q
配置下载工具
: S2 J0 C! h( R: j: R0 V* B新建的工程所有配置都是默认的  我们需要自行选择下载模式,勾选上下载后复位运行
5 `& F" v( I; C  A& c/ c% T0 i! p9 X$ p3 L% i: l
20190809172359875.png " e2 F0 @; o. }

3 l% W( l# ]8 M* k例程实现:
1 i3 ~8 E! D& Y: ~' f1 O定义变量:
  1. /* USER CODE BEGIN 0 */
    3 Y0 T7 }4 R5 R% M4 q
  2.     uint32_t capture_Buf[3] = {0};   //存放计数值
    7 \3 n: Y& a# ]" I+ {& j
  3.     uint8_t capture_Cnt = 0;    //状态标志位
    4 P) F7 C. \. B. j+ o  S, T
  4.     uint32_t high_time;   //高电平时间7 H/ W& [# B% D9 q
  5. /* USER CODE END 0 */
复制代码

3 J2 U+ L. L" m7 m. g0 x3 I在 while(1)中的用户代码区 3,写入TIM2 CH1通道的输入捕获控制和数据处理  z5 Y  _+ T. F$ Z4 l1 ~7 R

4 W* e; w- l+ ~/ s' a) e
  1. while (1)
    8 g/ `; q% Z  }% S, S
  2. {6 [' t. R6 M- D  ~# _
  3.     /* USER CODE END WHILE */2 B6 {6 b& \3 X0 s( v7 ?' {1 s

  4. + Z3 `/ L4 ~* G2 t1 U' V( X
  5.     /* USER CODE BEGIN 3 */2 E# s) Y; L8 b+ [3 U
  6.   switch (capture_Cnt){% `2 G* x* Y- u% ?0 B: P
  7.         case 0:9 ?; ]/ w) i9 i* L6 ~
  8.                 capture_Cnt++;& s; F3 u0 ~/ ]9 ]
  9.                 __HAL_TIM_SET_CAPTUREPOLARITY(&htim5, TIM_CHANNEL_1, TIM_INPUTCHANNELPOLARITY_RISING);
    7 W8 D4 P3 f: g8 }4 \
  10.                 HAL_TIM_IC_Start_IT(&htim5, TIM_CHANNEL_1);        //启动输入捕获       或者: __HAL_TIM_ENABLE(&htim5);* _3 k+ A) Z$ B6 ?' p& }
  11.                 break;
    - O- D* L9 O, z
  12.         case 3:
      D+ U6 _- J- O5 U* `& ?
  13.                 high_time = capture_Buf[1]- capture_Buf[0];    //高电平时间! }$ C! R. V( o/ j" W0 k; ], S
  14.                 HAL_UART_Transmit(&huart1, (uint8_t *)high_time, 1, 0xffff);   //发送高电平时间) i# ^, U+ M( N% c& M
  15.                                 
    6 L7 Q' \$ y, ^( Y
  16.                                 
    8 D7 Y6 a2 T" J- k
  17.                 HAL_Delay(1000);   //延时1S
    & z+ `; `$ b- R
  18.                 capture_Cnt = 0;  //清空标志位
    ; Z% h) i' y7 A( x
  19.                 break;3 v0 G5 H' z7 b: q4 s
  20.                                 - c8 n) ]5 G% r' y) d& |, Q3 h2 w
  21.         }
    - c' x% K" U' H# Z0 b
  22. }! j7 ^  z+ m6 Q4 M- U( U- K9 Y
  23. /* USER CODE END 3 */
复制代码

) H8 a, Y- r6 d9 ?在main函数下方添加中断回调函数:5 o! e/ J2 y% E. u# {

% `  ~9 `6 e. ^" K2 Z
  1. /* USER CODE BEGIN 4 */7 A3 ?8 T( D4 u- a0 h; D3 A+ m
  2. void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
    , \, U5 `$ C, j
  3. {# ]( x8 r2 l7 r: {$ g- i
  4.         & a+ O  A2 ]2 d9 i* g0 N* ]3 E9 k
  5.         if(TIM5 == htim->Instance)- L4 `% t; I+ D# v' c+ ^; |
  6.         {2 O& f# V9 @/ k1 @# ?- `9 |+ n. x( |$ Z  t
  7.                 switch(capture_Cnt){
    : |4 @: _" l' c# o# v- m  [
  8.                         case 1:
    6 h9 P3 w& x! @% ?: q* w
  9.                                 capture_Buf[0] = HAL_TIM_ReadCapturedValue(&htim5,TIM_CHANNEL_1);//获取当前的捕获值./ D5 U5 R9 E% z+ S- c/ M: Q. |
  10.                                 __HAL_TIM_SET_CAPTUREPOLARITY(&htim5,TIM_CHANNEL_1,TIM_ICPOLARITY_FALLING);  //设置为下降沿捕获
    7 R$ [" l$ i) z  X% t
  11.                                 capture_Cnt++;: @4 S/ j+ T3 b) |
  12.                                 break;
    5 Y. i# M9 a8 w
  13.                         case 2:9 ]' E( K) E' ~' e
  14.                                 capture_Buf[1] = HAL_TIM_ReadCapturedValue(&htim5,TIM_CHANNEL_1);//获取当前的捕获值., }+ p5 K4 ~3 A4 r+ \/ `
  15.                                 HAL_TIM_IC_Stop_IT(&htim5,TIM_CHANNEL_1); //停止捕获   或者: __HAL_TIM_DISABLE(&htim5);2 {. P4 M% X4 q. @- N" `2 K
  16.                                 capture_Cnt++;   
    1 l+ y6 ^, X) ?! s, k5 r
  17.                 }3 G7 x. `# P& G7 X- F
  18.         
    4 y  r3 o- H; |9 h4 H+ Q3 y3 j7 p
  19.         }
    2 B! ]) Q3 S" u7 N9 q. @8 X
  20.         6 V; `" g  E+ K  |$ o, {+ ~+ u6 B8 O
  21. }) d( e( R0 K! {$ _; t
  22. /* USER CODE END 4 */
    , i7 U' c7 b6 j0 [; `
复制代码
% X4 J6 |% o" j  l
具体流程:
+ w5 S- E- D% }* P; g9 I
; t  u% O2 M) Y# F, w1.设置TIM5 CH1为输入捕获功能;  & ~, z  K+ ?8 w) O; \' K' {) F& N
/ H% V3 h, I# ^6 c- `! \. O
2.设置上升沿捕获; & J6 [1 l7 w) \, j

& N( e) C) `) {7 z. ~3.使能TIM2 CH1捕获功能;  
* U( @8 }. K6 j) U# D: j; C/ Y$ }
4.捕获到上升沿后,定时器当前计数值存入capture_buf[0],改为捕获下降沿;   
# F4 W1 U. I6 l" e, ?: O% H( I7 k+ W' \+ k4 g# A
5.捕获到下降沿后,定时器当前计数值存入存入capture_buf[1],关闭TIM2 CH1捕获功能;  capture_Cnt=3;5 l  h- p* [( S, U2 I1 F& G. Z
7 z+ i) Y( U& Q+ T( a* `
6.  高电平时间: capture_buf[1] - capture_buf[0]        发送到上位机  重新启动输入捕获
/ r0 ^. w: o' g. T- s: X
# W. R. ^0 v( S) c7 \6 S# D* p+ ?9 c) [1 c, h
__HAL_TIM_SET_COUNTER(&TIM5_Handler,0);   //设置计数寄存器的值变为0' c3 y: a1 x; o8 k5 _) q
7 J. z6 I: u+ y1 o5 X& ]
HAL_TIM_PWM_Start()              函数用于使能定时器某一通道的PWM输出。- ?9 o  N* f: v& n7 d
! {. L& R9 B2 `8 S- X# _
HAL_TIM_IC_Start_IT()                  函数用于使能定时器某一通道的输入捕获功能,并使能相应的中断
8 Z+ M" t- g* v4 P% ?, s% I  G) ^% V: I  n9 F9 }
HAL_TIM_IC_Stop_IT()                 函数和开启功能相反,是关闭定时器某一通道的输入捕获功能和相应中断
& z' c; }6 Z& v9 M6 M& X
3 V, F0 p5 M/ w% h, i) p1 V__HAL_TIM_SET_CAPTUREPOLARITY
不是函数,而是底层操作的一个宏定义( z- Y: K8 Z% G+ s7 ?3 H) K' h
) s: I4 t1 F, |( Q0 f3 I
在stm32f4xx_hal_tim.h文件中可以找到。其作用是修改定时器某一通道的输入捕获极性
7 }0 l* s) \1 V% C  ]3 a, G6 j, n0 z7 A
20190813171232499.png
% `& Q3 A$ p/ E, X  D$ _7 ^6 J6 L3 A$ |  A
其中有两个函数,第一个为清除清除原来的捕获极性,第二个为设置通道捕捉极性6 b0 c- S3 w9 `0 [" @
6 L7 _% V1 s+ Z
等价于:, \2 m! r5 X/ r4 m: k. N9 _) L

% I& c$ C0 y# r3 {( Q5 I* t+ k
  1. TIM_RESET_CAPTUREPOLARITY(&TIM5_Handler,TIM_CHANNEL_1);   //一定要先清除原来的捕获极性!!
    1 f" q6 [/ x) j% a$ i' z6 Z
  2. TIM_SET_CAPTUREPOLARITY(&TIM5_Handler,TIM_CHANNEL_1,TIM_ICPOLARITY_FALLING);//定时器5通道1设置为下降沿捕获(重设捕获极性)
复制代码

, ^9 z$ C2 s8 o2 x+ o; Z* u) {在修改定时器某一通道的输入捕获极性时,一定要先清除该通道之前捕获极性
& b! Z: S3 Q, e8 J$ E$ q, v7 ?
/ l7 F/ c" }" D__HAL_TIM_GET_COMPARE也是一个宏定义。 : o. K6 p8 p. b+ [2 l5 @# p6 H' b
在stm32f4xx_hal_tim.h文件中可以找到。其作用是获取定时器某一通道的捕获/比较寄存器值1 e/ g9 Q& T% H0 V! u9 T6 p

5 A" K  l3 p  j% f, X 20190813171323391.png + \2 x( J; ]9 |) ]& ^, ^/ G0 n
+ j" f/ s7 ?, ?. w# {
等价于 :  HAL_TIM_ReadCapturedValue(&htim5,TIM_CHANNEL_1);% j( \0 G) H$ ?5 c

" W1 B% F5 b* C* l3 g4 [& x3 J  两者都是直接读取对应CCRx寄存器的值$ s- g6 F. S4 @4 T3 |

" S2 \% N! v, c2 t8 H% v, m  y" U4 J" f7 J# p3 d5 ~" |1 D
! G4 z( G+ u8 t9 ?9 s' {
收藏 评论0 发布时间:2022-3-25 10:29

举报

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