[STM32 HAL库]学习笔记,七、定时器
目录
STM32F1系列的三种定时器
1.定时器时基单元模块
(1)时钟来源
(2)降频-预分频器
(3)计数器
(4)自动重装寄存器ARR
(5)重复计数RCR(只有高级定时器有)
*寄存器预加载
2.简单实验:自制延时函数,让LED闪烁
(1)整体代码逻辑
(2)配置参数,生成工程
(3)代码部分
(4)编译并下载
3.输出比较模块
*PWM Pulse Width Modulation 脉冲宽度调制
(1)通过输出比较生成PWM波
(2)输出比较模式
4.简单实验:用PWM波实现呼吸灯(两颗LED交替呼吸)
(1)配置TIM参数
(2)电路接线图
(3)HAL库函数介绍以及呼吸灯原理
(4)代码部分
(5)编译并下载
5.输入捕获模块
6.简单介绍如何配置TIM通道和HAL库函数
(1)配置TIM通道
(2)HAL库函数
7.从模式控制器模块
从机模式
主机模式
8.简单实验:测量PWM波占空比并打印在串口上
基本原理
(1)电路接线图
(2)测试串口打印效果
(3)生成20%占空比的PWM波
(4)配置从模式控制器
(5)代码部分
(6)编译并下载
定时器可以对输入的时钟进行计数,并在计数值达到设定值时触发中断。简单来说就是每隔一段固定时间执行一次特定任务。下面是定时器工作的整体模块。
STM32F1系列的三种定时器
根据复杂度和应用场景分为了高级定时器、通用定时器、基本定时器三种类型。 其中高级定时器功能最多,通用定时器为其阉割版,而基本定时器功能则更少。
而STM32F103C8T6则只有TIM1,TIM2,TIM3,TIM4四个定时器,也就是说没有基本定时器。
1.定时器时基单元模块
(1)时钟来源
时钟来源有三种 ,其中最主要的还是来自RCC时钟树,频率最低为8MHz,对于定时器来说这个频率还是太高了
(2)降频-预分频器
预分频器可以降低输入时钟的频率,分频系数范围0~65535。若分频系数为65535,时钟频率8MHz,则输出8000000/65536=122Hz。
(3)计数器
经过预分频系数后,进入时钟计数器计数,计数方式有三种:上计数,下计数,中心对齐
(4)自动重装寄存器ARR
可以设置定时周期,范围为0~65535,即当计数器清零时重装一个数。
(5)重复计数RCR(只有高级定时器有)
计数器每溢出一次,重复计数器则计数一次。重复计数器取值范围为0~65535,当重复计数器计数到指定数值时,就会触发一次中断。
*寄存器预加载
寄存器预加载其实就是一种缓冲机制,是为了防止定时器跑飞的一种方式
写入的值首先会进入到影子寄存器,在某个事件发生的时候影子寄存器里的值才会进入到活动寄存器,这时写入的值才会生效
自动重装寄存器ARR设置定时周期,每当计数器计到该数值时发生update事件,然后从零开始重新计数。而如果我们想在定时器运行途中突然改变ARR时,改变的值可能比当前的计数值小,为了达到ARR的值,计数器需要计数到65535然后重新从零开始才能达到ARR的值,这一段过程就叫程序跑飞了
预记载机制则把修改后的ARR的值先存在影子寄存器里,程序还是按照原来的值即活动寄存器里的值进行计数,当下一次产生update中断时影子寄存器里的值才会加载到活动寄存器里生效,此时就不会让程序跑飞。
ARR的预加载机制需手动打开
2.简单实验:自制延时函数,让LED闪烁
(1)整体代码逻辑
首先用MyGetTick函数返回一个当前时间的值,而这个时间变量写在定时器里面每隔一段时间自增。
delay逻辑:写入一个要延迟的时间,延迟结束的时间等于当前时间加要延迟的时间,然后在while里不断等待当前时间自增直到超过延迟结束的时间,则完成延时。
然后再在main函数里启动定时器,在回调函数里让时间变量自增
最后在while循环里调用延时函数MyDelay完成LED闪烁。
(2)配置参数,生成工程
选择左侧栏目里Timers的TIM1,TIM1挂在APB2上,需先配置他的工作模式。
首先前两个是定时器的从模式才会用到,本次实验用的是RCC内部时钟,所以用不到,下面有四个通道,跟输入捕获和输出比较有关,这里也用不到,最下面模式本次实验也用不到
这里只需要选择时钟来源,选择内部时钟即RCC
然后配置定时器的参数,定时器需要每一毫秒产生一次更新事件。
内部时钟RCC没设置过默认为8MHz的频率,因此将PSC分频系数配置为7,将ARR配置为999,此时输出的频率为8000000 /(7+1)/(999+1)=1000Hz,即1ms更新一次。计数模式改为Up上计数,重复计数器的值改为0,然后使能auto-reload preload自动重装预加载,即为了安全起见防止程序跑飞。
这里的Internal Clock Division用不到。
最后在NVIC Settins中使能TIM1更新中断,此时定时器已配置好了,然后就可以在中断响应函数里面写时间变量自增的代码,变量就会每隔一毫秒自增。
这个工程还是使用板载LED实现闪烁,则同样配置好参数。
(3)代码部分
在指定区域里写入代码,变量写在变量区(variables)里,函数声明写在函数声明区(function prototypes)里。
最后在main函数里开启中断,并写入闪烁代码。
(4)编译并下载
按下复位键后,可以看到LED成功闪烁,且改变MyDelay中的参数可以明显看到闪烁频率改变,写入1000时,LED灯每秒闪烁一次。
3.输出比较模块
通过定时器产生精确定时的信号。
可以用输出比较产生PWM波
*PWM Pulse Width Modulation 脉冲宽度调制
占空比 = 高电平时间 / 总时间
(1)通过输出比较生成PWM波
这里用到CCR寄存器,在CCR寄存器里写入一个值,这个值会和时基单元里的计数器比较
自动重装寄存器控制的是PWM的周期,而CCR则控制PWM波的占空比。这里想要输出一个占空比为50%的PWM波,则CCR寄存器给4,ARR寄存器给9,计数器计数比CCR小输出高电平,计数器计数比ARR大输出低电平。产生占空比50%的PWM波
而增加CCR的值,PWM波的占空比则会增加
(2)输出比较模式
一共有八种模式,一般选PWM1
4.简单实验:用PWM波实现呼吸灯(两颗LED交替呼吸)
(1)配置TIM参数
首先和上一个实验一样配置TIM1的参数,实现每一毫秒生成一次更新事件,然后在通道一中选择一种输出比较模式。
互补输出的波形恰好和正常输出的波形相反,但两者的占空比相同。
这里选PWM正常输出加互补输出,可以进行两路输出使两颗LED交替呼吸
可以看到右边的芯片图里已经配置好了两个输出引脚,PA8和PA7,PA8代表正常输出,PA7则代表互补输出。
同时参数栏里面也多了几条参数,首先TRGO是从模式控制器的输出不需要配置,下面两个是刹车和死区时间也不需要配置。
下面配置CH1的PWM参数
1.选择模式:PWM mode 1
2.设置CCR初始值:0
3.设置CCR预加载:enable
4.CH/CHN Polarity设置正常输出和互补输出的极性:High正极性
配置完成后生成工程
(2)电路接线图
两颗LED正极分别接该引脚,负极接地,使用的是推挽接法。
(3)HAL库函数介绍以及呼吸灯原理
这里用到两个函数,分别打开PWM的正常输出和互补输出,第一个参数写定时器的句柄,第二个参数写通道编号
以下的参数可以读取或改写寄存器的值,从而改变PWM波的占空比
想实现呼吸灯的效果只需要让亮度随正弦关系变化,然后用占空比来替代亮度(占空比越大,LED越亮)
占空比计算,duty = CCR / ARR +1
根据占空比计算CCR的值
整体代码逻辑:获取当前时间计算占空比,然后读出ARR寄存器的值,根据公式计算CCR的值,最后再写入CCR寄存器。
(4)代码部分
在main函数中写入代码,同时还要包含“math.h”。
(5)编译并下载
可以看到两颗LED交替点亮
5.输入捕获模块
捕捉输入信号变化的时间并保存起来。
可以用于捕获测量脉冲宽度,下面是测量脉冲宽度的大概原理图。将脉冲上升沿的时间保存到通道1的CCR1中,将脉冲下降沿的时间保存到通道2的CCR2中。两者相减并乘以时间间隔就是脉冲宽度。
通道1捕获信号的边沿并将值存储到CCR中的流程图。先进行滤波,把输入信号的毛刺部分滤掉,输出干净的方波;然后在边沿检测中检测到上升沿产生高电平;在信号选择阶段中如果选择上升沿脉冲直接输出,则上升沿脉冲直接输出到分频然后记录下当前CCR的值。
这里通道2悬空,但其信号选择部分选择下降沿脉冲间接输出,则会将通道1检测到的下降沿脉冲输出到通道2的分频部分,然后将计数值存到CCR2中,此时就可以CCR2-CCR1再乘以分辨率就可以算出脉冲宽度。
6.简单介绍如何配置TIM通道和HAL库函数
(1)配置TIM通道
输入捕获有三种模式,这里将通道1设置为直接,通道2设置为间接
下面配置通道的参数,通道1的极性选择上升沿,通道2选择下降沿;两个通道都选不分频
配置计数器参数时需注意定时器的定时周期应该大于最大脉宽,不然在脉冲期间定时器归零重新计数就会出现错误。
(2)HAL库函数
清除CCR
开启或停止通道输入捕获
查询某一标志位
关闭定时器
7.从模式控制器模块
从模式控制器简化图,总共有三个箭头,一个输入一个输出,还有一个控制当前的定时器。
其中TRGI的来源有多种,下面的TF1FP1代表从通道一输入,然后经过滤波,再选择上升沿脉冲极性选择,最后直接输出的信号。TF2FP2也类似。
从模式控制器有两种模式,一种作为从机一种作为主机,主机模式和从机模式可以同时使用
当作为从机时,从模式控制器接收控制信号控制定时器
当作为主机时,从模式控制器输出控制信号控制其他模块
作为从机和作为主机时又分别有多种模式,较常用的是框中的几种
从机模式
1.从模式禁止:不使用从机功能
2.复位模式:使用TRGI的上升沿来复位CNT,同时产生Update事件
3.门模式:使用TRGI控制时基单元的开关
4.触发模式:使用TRGI的上升沿来启动定时器
5.外部时钟模式1:把TRGI作为定时器时钟
主机模式
1.enable-使能:通过TRGO把时基单元的开关状态输出出去
2.update-更新:每产生一个更新事件就向TRGO输出一个脉冲
8.简单实验:测量PWM波占空比并打印在串口上
基本原理
输入一个PWM波,TF1FP1会检测PWM波的上升沿,并产生一个跳变。
而TF1FP1作为从模式控制器的TRGI,从模式控制器设置为复位模式,每当TF1FP1变化时计数器会复位,复位时计数器的数据存到CCR1中,则读取CCR1中的数据即可知道PWM波的周期。
而当PWM波产生下降沿时,CCR2会存储当前计数器的数,则读取CCR2中的数据即可知道PWM波的高电平时间。
最终可算出PWM波的展开波。
(1)电路接线图
(2)测试串口打印效果
设置USART模式为异步模式,其他从参数不变
在main函数中写入代码,在串口上打印“你好世界”四个字
编译下载,打开串口,配置好参数,复位后串口成功接收到你好世界四个字
(3)生成20%占空比的PWM波
选择用TIM3生成PWM波,PSC设7,ARR设999,CCR设为200。此时输出的就是周期为1ms,占空比为20%的PWM波。然后更新代码
在main函数中写入以下代码,在PA6引脚连一个LED灯,编译下载后按下复位键,LED灯亮起微弱的光,说明已产生PWM波
(4)配置从模式控制器
根据此图配置
首先配置通道一通道二,通道一直接模式,通道二间接模式。PSC设为7,ARR设为65535,然后将通道一的极性改为上升沿,通道二的极性改为下降沿。
然后配置从模式,选择复位模式,触发源为TF1FP1
更新代码
(5)代码部分
代码逻辑:
根据以上逻辑写入代码,
补充串口打印函数
(6)编译并下载
串口助手里打印出PWM准确数据
