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

  • 定时功能的初始化配置
    1. 首先配置系统时钟,具体见前文,总之可得HCLK=80MHz

    2. 点进左侧栏Timers中选择要使用的TIM,配置其时钟源以让该计时器用作计时功能

      • 对高级计时器,在弹出的TIM Mode and Configuration中间栏上部时钟源Clock Source选项中Internal Clock内部时钟源
      • 对基本计时器,勾选Activated以使能即可
    3. 在右侧窗口的下部Parameter Settings中配置Prescaler分频系数与Counter Period自动重装载系数(这两处数值对应PSC与ARR);

      计数模式选择Up向上计数;内部时钟分频保持默认不开启;

    4. auto-reload preload自动重装载功能可按需开启

      启用这个预装载功能后能在修改ARR时保护计时进程;禁用则会使ARR值直接写入影子寄存器,更适合需要动态调整ARR的场合,如后文的PWM调节

    5. 切换到NVIC标签页,使能定时器的全局中断,让定时器溢出时产生中断

    6. 在配置完成后,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功能的初始化配置
    1. 将GPIO引脚的功能配置为对应TIM定时器的ETR引脚,具体对应见数据手册

    2. 点进左侧栏Timers中选择要使用的TIM,配置其时钟源以让该计时器工作于外部时钟模式2:在弹出的TIM Mode and Configuration中间栏上部时钟源Clock Source选项中选择ETR2

    3. 在右侧窗口的下部Parameter Settings的Clock部分配置滤波长度、时钟极性、时钟分频

    4. 配置分频系数、计数模式、预装载、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引脚传来的脉冲计数结果
    

posted on 2025-05-16 22:06  无术师  阅读(587)  评论(0)    收藏  举报