
前言: 本系列教程将外设原理,HAL库与STM32CubeMX结合在一起讲解,使您可以更快速的学会各个模块的使用 所用工具:, 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软件 3、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 通过本篇博客您将学到: SMT32定时器输入捕获 测量PWM频率和占空比 . e3 S; i: o5 A4 g, M% ] l 5 x4 j8 Q9 T( ^6 e, |$ ] 输入捕获 输入捕获概念, \5 d; l3 {8 `. { 输入捕获模式可以用来测量脉冲宽度或者测量频率。STM32的定时器,除了TIM6、TIM7,其他的定时器都有输入捕获的功能。' Y; Z9 |. k: ]( @5 M 输入捕获的工作原理( T4 S3 f t( V5 b: w! e 6 C# [! f' ^; P2 _ ![]() ①先设置输入捕获为上升沿检测,9 R9 |* _) G8 T: W3 _5 i, c ②记录发生上升沿时TIMx_CNT(计数器)的值 ③配置捕获信号为下降沿捕获,当下降沿到来的时候发生捕获 ( ]$ Z4 G, j! q9 B& _3 [6 [ ④记录此时的TIMx_CN(计数器)T的值/ h* f8 U& _$ ?! J ⑤前后两次TIMx_CNT(计数器)的值之差就是高电平的脉宽。同时根据TIM的计数频率,我们就能知道高电平脉宽的准确时间。 % m6 s* D7 h7 p D 简单说:; O4 G, W7 y- ]% C' n- V 8 ?4 A9 I! B! \: H/ | 当你设置的捕获开始的时候,cpu会将计数寄存器的值复制到捕获比较寄存器中并开始计数,当再次捕捉到电平变化时,这是计数寄存器中的值减去刚才复制的值就是这段电平的持续时间,你可以设置上升沿捕获、下降沿捕获、或者上升沿下降沿都捕获, 8 l& N1 Q; d' I q, y 输入捕获的工作流程(对应CubeMx的四个选项)9 f: U$ ]! x% h& l ![]() 设置输入捕获滤波器! i* u9 t# }1 d+ {! p% r STM32在很多功能中都提供了滤波器,滤波器的功能简单来说就是多次检测视为一次有效,达到滤波效果, / 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& ~ 设置输入捕获极性 1 o( a, B4 d, l$ A 设置具体为那种捕获事件& @+ m, D3 g/ }3 A0 ?+ u* R/ X 可以设置上升沿捕获、下降沿捕获、或者上升沿下降沿都捕获7 I% ~& Q& R) _- d, s6 k) z2 c8 a( [ . j- ^4 m$ G/ a9 c4 P4 U 设置输入捕获映射关系 STM32为了更好的优化使用,TIMx_CH1通道1捕捉到的信号可以传输到IC1,TIMx_CH1捕捉到的信号也可以连接到IC2,TIMx_CH2捕捉到的信号也可以连接到IC2,也可以连接到IC24 Z9 \- r, H2 Q2 m ![]() ( g" h% D6 @' K: w8 H7 E- W! b 设置输入捕获分频器: p P9 D' {9 r2 [1 x' U 设置每N个事件触发一次捕获,可以设置为1/2/4/8次检测到电平变化才触发捕获- [% m: U4 B+ F' M5 h @ 溢出时间计算:2 |. \" d! |* y! ]% B1 a ![]() $ N- F% J/ e2 ]6 I$ P6 [ t1时刻检测到高电平,发生中断,在中断里将计数值置0,开始记溢出次数N,1 w+ f9 k _" o 其中每计数0xFFFF次溢出一次,直到t2时刻跳变回低电平,/ ~8 \" C, m: w: N; B5 F' r% H5 Y 获取最后一次溢出时到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 如果计数器值为 32 bit 那么最大为0xFFFFFFFF & {- {2 C/ V1 _0 I 高电平时间:' W. N4 q E' k# m+ V9 i6 W8 Y ![]() : z2 l# f4 {8 D $ ?( w4 i. C3 z/ m/ L! Z% _ 输入捕获的工作框图 ![]() & O/ R' ?8 n" s' ?% B1 y0 g 工程创建& t' }% k, O/ P: z8 Z 设置RCC1 J7 J4 X. X) |! h6 L% _7 c 设置高速外部时钟HSE 选择外部时钟源5 u7 {: V" Y% L/ |) j- T4 }" S# W' @ " e# J! O( p' n4 c: G6 I5 w; Z ![]() 2设置时钟8 X1 w9 Z5 m0 W * F- H& n6 z! a' R# e2 W: z* E$ o1 x5 ~ ![]() W* C) T% c: N: G' V' ?- @ 我的是 外部晶振为8MHz ( c, d8 I8 }" U4 o% O6 r3 V 1选择外部时钟HSE 8MHz 2PLL锁相环倍频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 3定时器配置5 q) n* a# b' C ![]() 这里我们选择TIM5的通道1- Z! R1 H$ E" T6 R( j! [4 p5 t 预分频系数为71 计数时钟频率就是 72MHz/(71+1) = 1MHz 此时1us计数一次 自动加载值设置为32bit最大值 0xFFFFFFFF - F. A. R9 D% [0 k+ E' B* f 上升沿捕获 不分频 滤波值为8, }$ J* x5 K0 r2 [5 e' M5 @& {. o 同时在NVIC一栏使能TIM5的中断 7 w# h8 N: a2 z5 V) y! X5 ` 对应引脚设置下拉电阻,保证没有信号输入的时候电平稳定0 J, g/ g8 h, M ![]() 4项目文件设置" [+ `/ C/ R" l9 L! B 1 y6 s" A2 b( r8 p6 N ![]() 0 t; X3 s( }+ z6 k S$ p4 h/ ~( T 1 设置项目名称( Q, }- {7 w6 `" `/ `3 o 2 设置存储路径0 C6 c9 ?- N# d, m 3 选择所用IDE ![]() 7 V! j1 J5 E( T3 N! o% _) Q% Q 5创建工程文件 然后点击GENERATE CODE 创建工程9 z9 i8 J3 A; Z& \ : n9 h5 g ?7 ^7 y* q 配置下载工具 新建的工程所有配置都是默认的 我们需要自行选择下载模式,勾选上下载后复位运行 / c% T0 i! p9 X$ p3 L% i: l ![]() 例程实现: 定义变量:
在 while(1)中的用户代码区 3,写入TIM2 CH1通道的输入捕获控制和数据处理 z5 Y _+ T. F$ Z4 l1 ~7 R
在main函数下方添加中断回调函数:5 o! e/ J2 y% E. u# {
具体流程: 1.设置TIM5 CH1为输入捕获功能; & ~, z K+ ?8 w) O; \' K' {) F& N / H% V3 h, I# ^6 c- `! \. O 2.设置上升沿捕获; & J6 [1 l7 w) \, j 3.使能TIM2 CH1捕获功能; # D: j; C/ Y$ } 4.捕获到上升沿后,定时器当前计数值存入capture_buf[0],改为捕获下降沿; % 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] 发送到上位机 重新启动输入捕获 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() 函数用于使能定时器某一通道的输入捕获功能,并使能相应的中断 , s% I G) ^% V: I n9 F9 } HAL_TIM_IC_Stop_IT() 函数和开启功能相反,是关闭定时器某一通道的输入捕获功能和相应中断 __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文件中可以找到。其作用是修改定时器某一通道的输入捕获极性 3 a, G6 j, n0 z7 A ![]() $ _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
在修改定时器某一通道的输入捕获极性时,一定要先清除该通道之前捕获极性 __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 ![]() + j" f/ s7 ?, ?. w# { 等价于 : HAL_TIM_ReadCapturedValue(&htim5,TIM_CHANNEL_1);% j( \0 G) H$ ?5 c 两者都是直接读取对应CCRx寄存器的值$ s- g6 F. S4 @4 T3 | % v, m y" U4 J" f7 J# p3 d5 ~" |1 D ! G4 z( G+ u8 t9 ?9 s' { |
基于定时器捕获测量脉宽的应用示例
狂欢三】STM32C031使用TIM定时器DMA方式实现WS2812彩灯输出(三)
【狂欢三】STM32C031使用TIM定时器DMA方式实现PWM输出(二)
【狂欢三】STM32C031使用TIM定时器PWM输出
stm32使用定时器触发dma传输,启动dma没反应的几种情况的解决方法
定时器剩余通道是否可以做PWM输出呢?
基于STM32双定时器+ADC+DMA实战经验分享
基于STM32的定时器触发ADC时可能遇到的情形
【NUCLEO-U545RE-Q评测】5. 基本计时器
基于STM32的定时器不按设定超时产生中断