
前言:9 N3 _2 {2 X2 h8 r! ^ 本系列教程将外设原理,HAL库与STM32CubeMX结合在一起讲解,使您可以更快速的学会各个模块的使用6 ~- o( L1 v9 d M4 S! B) x+ B9 Z 所用工具:: P+ n3 m }/ p3 D) [ ; o0 s) o! V" x- h) T- F 1、芯片: STM32F407ZET6/STM32F103ZET69 g# m" s* T! z) V5 y4 e+ R 2、STM32CubeMx软件 + y, c( c& j$ q1 X4 r1 H8 u 3、IDE: MDK-Keil软件8 k4 y0 x& E8 ~7 }5 ]. |* w 4、STM32F1xx/STM32F4xxHAL库 3 \3 B. ^5 u& X4 s/ K 知识概括:5 m0 F# H3 x7 x1 G; h, r6 L , b1 N9 _ U! ^" i: J 通过本篇博客您将学到:( w6 J a0 i2 Z o8 [ SMT32定时器输入捕获0 [5 H( @( E" k, p7 L( M! W 5 Y/ `4 p: r/ B* n5 F 测量PWM频率和占空比 输入捕获 输入捕获概念! ]1 U- @- W( B( f. r, {" z6 a 输入捕获模式可以用来测量脉冲宽度或者测量频率。STM32的定时器,除了TIM6、TIM7,其他的定时器都有输入捕获的功能。2 [+ t3 M% i" o' M5 a7 h 输入捕获的工作原理 ' |& U j [; y( c; Y ![]() ①先设置输入捕获为上升沿检测, ( v/ D* \7 x8 r; \; h; ]0 ~7 a1 } ②记录发生上升沿时TIMx_CNT(计数器)的值3 A) t. }: C4 k. Q r ③配置捕获信号为下降沿捕获,当下降沿到来的时候发生捕获* X% ~0 V8 M! F # o8 n# I% {: u( U2 _ u ④记录此时的TIMx_CN(计数器)T的值 $ E: q* |' D$ C ⑤前后两次TIMx_CNT(计数器)的值之差就是高电平的脉宽。同时根据TIM的计数频率,我们就能知道高电平脉宽的准确时间。 简单说: 6 {2 s9 q- A! i! q/ W4 w! a- n 当你设置的捕获开始的时候,cpu会将计数寄存器的值复制到捕获比较寄存器中并开始计数,当再次捕捉到电平变化时,这是计数寄存器中的值减去刚才复制的值就是这段电平的持续时间,你可以设置上升沿捕获、下降沿捕获、或者上升沿下降沿都捕获,' x5 W9 E3 F0 P3 Q4 _8 R 5 [) G$ |" z% A 输入捕获的工作流程(对应CubeMx的四个选项) ![]() 设置输入捕获滤波器. m: F6 m: Y' } STM32在很多功能中都提供了滤波器,滤波器的功能简单来说就是多次检测视为一次有效,达到滤波效果, 数字滤波器由一个事件计数器组成,假设我们是检测高电平,滤波N次,那么记录到N个事件后计数器会产生一个输出的跳变。也就是说连续N次采样检测,如果都是高电平,则说明这是一个有效的电平信号,这样便可以过滤掉那些因为某些而干扰产生的一些信号 * h% D1 v; l' n% B. z 输入捕获滤波器IC1F[3:0],这个用于设置采样频率和数字滤波器长度。其中:fCK_INT是定时器的输入频率,fDTS是根据TIMx_CR1的CKD[1:0]的设置来确定的。9 [$ q" s9 N4 I2 Q8 G! R $ j( S$ r. @6 | 设置输入捕获极性 设置具体为那种捕获事件 可以设置上升沿捕获、下降沿捕获、或者上升沿下降沿都捕获 设置输入捕获映射关系8 ] {, z3 z9 `+ S O3 J* _ STM32为了更好的优化使用,TIMx_CH1通道1捕捉到的信号可以传输到IC1,TIMx_CH1捕捉到的信号也可以连接到IC2,TIMx_CH2捕捉到的信号也可以连接到IC2,也可以连接到IC26 s, Z* x1 I2 T, V* R- W # f' [! n, B1 {6 M5 ^/ g ![]() 2 O4 c2 ?. h. K) U- h& `* h, m& { 设置输入捕获分频器 设置每N个事件触发一次捕获,可以设置为1/2/4/8次检测到电平变化才触发捕获; T* n& ]) ` V 溢出时间计算:7 H' V( S, N% k! ~- A/ |9 H* I ![]() t1时刻检测到高电平,发生中断,在中断里将计数值置0,开始记溢出次数N, 其中每计数0xFFFF次溢出一次,直到t2时刻跳变回低电平, 获取最后一次溢出时到t2时刻的计数值TIM5CH1_CAPTURE_VAL+ b& I* \" a1 u8 Q$ R 则 高电平时间 = 溢出次数*65535+TIM5CH1_CAPTURE_VAL us ;根据定时器初始化时的频率即可计算出溢出总次数所占用的时间,即为高电平时间。 如果计数器值为 32 bit 那么最大为0xFFFFFFFF 高电平时间:, {! W+ f7 v# |/ |; W * V# g: X( N% @9 s5 T) c1 U ![]() . I0 t' R* [1 Y( m3 X 输入捕获的工作框图 8 Z0 g4 p. Q1 K6 s, Z ^( d* M3 C+ R ![]() + Y. y1 |% W! `# o% Y 工程创建! Q/ a: `: T4 B 设置RCC1 i/ ~/ G" m" p! z6 e , i) O3 o4 J, g: d# W) F 设置高速外部时钟HSE 选择外部时钟源 7 G, X9 @- B5 S$ s ![]() % Y6 Z) o% U1 Z4 g+ A 2设置时钟 ![]() 我的是 外部晶振为8MHz ! q: \6 s/ F# P3 x# u6 X 1选择外部时钟HSE 8MHz - e! O( T. [% N% m* E7 v 2PLL锁相环倍频72倍! N; Q! M D L- O 3系统时钟来源选择为PLL 4设置APB1分频器为 /2$ g: V9 K" | v$ b8 C/ x" U 5 这时候定时器的时钟频率为72Mhz 3定时器配置# b0 N" e1 u8 @% [& h e# l & f5 f5 y/ ~. t: g6 e ![]() 这里我们选择TIM5的通道1 % V8 w1 F1 S4 X$ n# W 预分频系数为71 计数时钟频率就是 72MHz/(71+1) = 1MHz 此时1us计数一次7 Q# v6 G$ v2 [6 G 自动加载值设置为32bit最大值 0xFFFFFFFF + x. j( s% t/ t ?5 B 上升沿捕获 不分频 滤波值为8 同时在NVIC一栏使能TIM5的中断2 @+ ~" d1 b: g5 ^6 ` 9 c2 s1 B0 D* P6 e' k0 L 对应引脚设置下拉电阻,保证没有信号输入的时候电平稳定: o7 ?" |$ f2 G( L( f ; t- |+ u/ h6 B$ ?, L) v; d ![]() 4项目文件设置 4 M, }) v- k1 R% `9 R5 n$ t8 q" d4 o ![]() 1 设置项目名称 2 设置存储路径6 W1 V: X f W0 w7 Q- q 3 选择所用IDE 5 `( D) d/ B& E( M3 U8 z2 @ ![]() . E' A, \$ e, A' F 5创建工程文件: O2 H! H; |7 {" m- c/ u 然后点击GENERATE CODE 创建工程" L* v# e( l/ V# \) h 配置下载工具 新建的工程所有配置都是默认的 我们需要自行选择下载模式,勾选上下载后复位运行 , Q9 Q3 w/ c5 Y) {& S8 g3 J ![]() ) j: ~7 c; _, I6 \ 例程实现: S, S2 A. k! v4 f: c: ~ 定义变量:
在 while(1)中的用户代码区 3,写入TIM2 CH1通道的输入捕获控制和数据处理6 V) [1 t, l4 F5 p: S0 }# ]
在main函数下方添加中断回调函数: # h" I, n! t6 e& z' {5 D" }
具体流程: ]* u [/ J# z7 U $ \* a4 _1 l( B) ~ 1.设置TIM5 CH1为输入捕获功能; * |9 W7 d& l+ Z: C) \+ C 4 m4 c" [: j; Z1 X9 ~ 2.设置上升沿捕获; ( f+ J8 \( @6 j, A 3.使能TIM2 CH1捕获功能; , ]- c4 [' B, U# U6 b 4.捕获到上升沿后,定时器当前计数值存入capture_buf[0],改为捕获下降沿; v- i# L. P% W0 m$ Z2 ] $ P. L1 S0 j# X+ `) U' N8 O 5.捕获到下降沿后,定时器当前计数值存入存入capture_buf[1],关闭TIM2 CH1捕获功能; capture_Cnt=3;4 a$ q5 h. I3 j! u: ?' Z t G4 C0 Q 6. 高电平时间: capture_buf[1] - capture_buf[0] 发送到上位机 重新启动输入捕获5 V' d- V2 @1 }% ~! U 7 A0 V" |/ b# P3 n% I% o ! a8 c5 E$ d& N9 P& d) ?% p __HAL_TIM_SET_COUNTER(&TIM5_Handler,0); //设置计数寄存器的值变为07 I$ k! \) {# l# ]& t7 M; @# k HAL_TIM_PWM_Start() 函数用于使能定时器某一通道的PWM输出。) w; u6 n1 b; s8 ] 0 g3 m1 i$ U8 {# C2 B HAL_TIM_IC_Start_IT() 函数用于使能定时器某一通道的输入捕获功能,并使能相应的中断 S) ^9 z. Z& f8 r7 O0 l' ~ ' }! a9 e# ?0 Y2 ^0 t5 c HAL_TIM_IC_Stop_IT() 函数和开启功能相反,是关闭定时器某一通道的输入捕获功能和相应中断 __HAL_TIM_SET_CAPTUREPOLARITY不是函数,而是底层操作的一个宏定义 3 W# j. W G: s: W, t/ n# C v 在stm32f4xx_hal_tim.h文件中可以找到。其作用是修改定时器某一通道的输入捕获极性4 I5 K/ t' O7 p/ @6 u " e% Q7 G7 L: r& V% A) j ![]() 其中有两个函数,第一个为清除清除原来的捕获极性,第二个为设置通道捕捉极性8 t/ j2 F t" _9 h1 }0 p ; ?" p/ W6 L/ E 等价于:. [7 x* q; R. E* C2 K/ S 6 c. N$ q$ U. r% m; `: b; W$ x
在修改定时器某一通道的输入捕获极性时,一定要先清除该通道之前捕获极性/ l- f- B" L P6 c6 c, t- ^ __HAL_TIM_GET_COMPARE也是一个宏定义。 ( k$ l- T/ O: N 在stm32f4xx_hal_tim.h文件中可以找到。其作用是获取定时器某一通道的捕获/比较寄存器值+ u v$ r0 B7 s" X9 K, e ![]() 等价于 : HAL_TIM_ReadCapturedValue(&htim5,TIM_CHANNEL_1); - V' V( y d' r2 `; I P 两者都是直接读取对应CCRx寄存器的值 1 B: `) \1 e F0 A ^7 Y4 H % |- ]" K5 n2 ~: f7 ~+ q' S # C# e+ w- X: z8 a$ m8 K; F: h |
基于定时器捕获测量脉宽的应用示例
狂欢三】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的定时器不按设定超时产生中断