STM32的定时器_计时与计数功能
定时器的计时功能
定时频率的配置与原理
-
定时时间公式
从时基单元一节的介绍中,我们可以得到可知从开始计数到发生一次计数溢出的用时(该式仅适用向上与向下计算模式):
-
溢出周期T=(PSC分频系数+1)×(ARR重装载值+1)/CK_PSC预分频时钟
-
定时器溢出频率为上式倒数:F=CK_PSC/[(PSC+1)×(ARR+1)]
ARR需要加1是因为在计时过程中计时值0与最终的计数值ARR都会持续一个完整的计数脉冲
-
-
定时参数计算
以蓝桥杯要求运行在HCLK=80MHz为例,在没有配置外设时钟ABP分频的情况下CK_INT=CK_PSC=TIMx_CLK=80MHz,显然这个值太大了,即便有16位的计数值,不进行分频就不能完成长于毫秒级的计时
例如我们要求使用定时器计时3s,那么首先使PSC=7999,将时钟频率分频为80M/(7999+1)=10000Hz,再配置计数值为29999,就实现了计时3s
-
定时功能的初始化配置
-
首先配置系统时钟,具体见前文,总之可得HCLK=80MHz
-
点进左侧栏Timers中选择要使用的TIM,配置其时钟源以让该计时器用作计时功能
- 对高级计时器,在弹出的TIM Mode and Configuration中间栏上部时钟源Clock Source选项中Internal Clock内部时钟源
- 对基本计时器,勾选Activated以使能即可
-
在右侧窗口的下部Parameter Settings中配置Prescaler分频系数与Counter Period自动重装载系数(这两处数值对应PSC与ARR);
计数模式选择Up向上计数;内部时钟分频保持默认不开启;
-
auto-reload preload自动重装载功能可按需开启
启用这个预装载功能后能在修改ARR时保护计时进程;禁用则会使ARR值直接写入影子寄存器,更适合需要动态调整ARR的场合,如后文的PWM调节
-
切换到NVIC标签页,使能定时器的全局中断,让定时器溢出时产生中断
-
在配置完成后,CubeMX生成的代码将自动包含
HAL_TIM_Base_Init()以初始化时基单元,下文不再介绍
-
定时功能的使用
-
定时器中断方式启动HAL_TIM_Base_Start_IT
用于以中断方式启动定时器
void HAL_TIM_Base_Start_IT(TIM_HandleTypeDef *htim) //TIM_HandleTypeDef *htim: TIM的句柄,如使用TIM6时,写为&htim6 -
定时器中断回调函数HAL_TIM_PeriodElapsedCallback
在中断一章中已经介绍过回调函数,启动中断的定时器发生更新事件后就会执行该函数
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) -
定时中断的代码实现
HAL_TIM_Base_Start_IT(&htim6); //在需要启用定时的地方插入中断启动 void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { if(htim->Instance == TIM6) { //在中断回调函数中判断中断源,并执行操作 //HAL_TIM_Base_Start_IT(&htim6) 如有需要可以再次开启定时 } }
定时器的计数功能
计数功能的配置与原理
-
外部信号输入途径
计数功能和定时功能原理本质上是一样的,当定时器对有固定频率的时钟源进行计数时就工作在定时模式下,而对外部脉冲进行计数时就工作在计数模式下
在数据手册中可以查询到ETR/TIx引脚对应的GPIO
- 外部触发输入引脚ETR:从ETR引脚输入信号,经过极性选择、分频与滤波后输入到时基单元
- 外部输入引脚TIx:从定时器的捕获/比较通道TIMx_CHn输入信号,经过滤波与分频检测后输入到时基单元
因为使用TI时定时器工作于从模式,而且占用了捕获/比较通道,因此实际工作中一般使用ETR来完成计数
-
外部信号的处理
-
极性选择:选择外部脉冲信号的触发极性,反相表示在下降沿触发,不反相表示在上升沿触发
-
分频:计数模式下的分频指的是多少个有效边沿触发一次计数
-
滤波:防止外部脉冲信号的噪声与边缘抖动导致误计数
分频与滤波处理不是必须的,视信号频率高低与干净程度决定
-
-
ETR功能的初始化配置
-
将GPIO引脚的功能配置为对应TIM定时器的ETR引脚,具体对应见数据手册
-
点进左侧栏Timers中选择要使用的TIM,配置其时钟源以让该计时器工作于外部时钟模式2:在弹出的TIM Mode and Configuration中间栏上部时钟源Clock Source选项中选择ETR2
-
在右侧窗口的下部Parameter Settings的Clock部分配置滤波长度、时钟极性、时钟分频
-
配置分频系数、计数模式、预装载、ARR值
需注意,为了防止计数溢出,将ARR值设置较大,也可以使能更新中断,在更新中断中记录溢出次数,溢出次数×(ARR+1)+CNT即当前计数值
-
计数功能的使用
-
定时器轮询方式启动函数HAL_TIM_Base_Start
因为计数功能不需要使用中断,因此用轮询方式启动定时器
void HAL_TIM_Base_Start(TIM_HandleTypeDef *htim) -
读取计数值__HAL_TIM_GET_COUNTER
开头的两个下划线表示该函数是宏函数(带参数的宏),不发生函数调用而是进行宏替换,因此效率更高
__HAL_TIM_GET_COUNTER(__HANDLE__) //参数__HANDLE__是指向定时器句柄的指针,即定时器句柄地址 result=__HAL_TIM_GET_COUNTER(&htim2); //跳转到该宏函数的定义,可见这个宏函数实际上会被替换为如下代码 result=TIM2->CNT;//本质上就是读取TIM2_CNT寄存器 -
外部触发计数的代码实现
HAL_TIM_Base_Start(&htim2); //启动计数 result=__HAL_TIM_GET_COUNTER(&htim2); //读取ETR引脚传来的脉冲计数结果
本文来自博客园,作者:无术师,转载请注明原文链接:https://www.cnblogs.com/artlessist/p/18880717
本文使用知识共享4.0协议许可 CC BY-NC-SA 4.0
特别说明版权归属的文章以及不归属于本人的转载内容(如引用的文章与图片)除外
浙公网安备 33010602011771号