TIM(Timer,定时器),在捕捉脉冲宽度,计数PWN占空比,输出PWM波形,编码器计数中是不可或缺的一部分。
定时器原理
计数器与时钟信号相连,当时钟信号的上升沿/下降沿到达时,计数器会+1,但计数器仅有16位,仅能存储65535数据,因此在计数器之前还有一个预分频器(Prescaler),默认地,预分频器设置为0,即不对进入预分频器的信号进行处理。当预分频器被设置为1时,会将每两个脉冲分频为一个脉冲,同样地,当预分频器被设置为n-1时,会将每n个脉冲分频为一个脉冲,即n分频。预分频器同样是16位,因此最大能进行65536分频。

但是,仅有计数器还不足以实现定时功能,我们还需要一个自动重装载寄存器,它的作用就是检测计数器的值是否与自己相同,当计时器的值和自己相同时,则将计时器的值重设为0,并且触发定时器更新中断,提醒定时时间已到,然后通过中断回调函数执行指令。和预分频器类似,由于是从0开始计数,设定自动重装载寄存器数值为m-1时,才能实现在m个脉冲后触发中断。

芯片配置
- 先设置HSE为外部晶振:在左侧的System Core中选择RCC,在High Speed Clock(HSE)下拉菜单中选择Crystal/Ceramic Resonator,即可启用外部晶振。
- 在顶部选择Clock Configuration栏目,将HCLK更改为72MHz。
- 在左侧Timers中选择通用定时器TIM4,勾选Internal Clock,对于TIM1和TIM2,则是在Clock Source中选择Internal Clock。
- 底侧各个选项,则是对此定时器的配置:
- Prescaler:预分频器,例如要进行7200分频,则填入7200-1,即将72MHz的输入信号预分配为10000Hz;
- Counter Period:自动重装载寄存器,例如希望计数器从0计数到9999,则可设置为10000-1,这样即可每1秒触发一次计数器中断回调函数。
代码配置
定时器寄存器
启动定时器TIM4的函数:
HAL_TIM_BASE_START(&htim4);宏定义函数__HAL_TIM_GET_COUNTER可用于获取定时器计数器的值,然后拼接字符串并通过串口将其发送出来:
int counter=0;char sendBuffer[20];counter=__HAL_TIM_GET_COUNTER(&htim4);sprintf(sendBuffer, "counter:%d",counter);HAL_UART_Transmit_IT(&huart2, (uint8_t*)sendBuffer, strlen(sendBuffer));HAL_Delay(100-1);可以看到,每间隔100ms,便发来计数器中存储的值:

还有以下宏函数:
__HAL_TIM_SET_COUNTER:设置计数器的值;__HAL_TIM_GET_AUTORELOAD:获得当前重装载寄存器的值;__HAL_TIM_SET_AUTORELOAD:设定重装载寄存器的值;__HAL_TIM_SET_PRESCALER:设定预分频器的值。
除此之外,还有一个叫做影子寄存器的机制,它存在于预分频器和自动重装载寄存器中,它的作用是更改预分频器和自动重装载寄存器后,修改的数值会在下一个计数周期再生效,从而不影响当前的计数周期。
默认地,预分频器影子寄存器是开启的,而自动重装载寄存器影子寄存器需要我们手动开启,在CubeMX的设置栏中启用auto-reload preload即可。
若不启用影子寄存器机制,则修改自动重装载寄存器时,有可能修改后的数值小于当前的计数器数值,导致计时器一直计数到65535才归零。
中断回调函数
回到CubeMX,先将TIM4中NVIC Settings的TIM4 global interrupt开启;
再将HAL_TIM_Base_Start替换为HAL_TIM_Base_Start_IT,即可开启中断计时模式;
当计时器与自动重装载寄存器数值相同触发计时器归零时,会触发以下中断回调函数:
HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim);重新定义此函数,再对其进行重写,即可实现定时功能:
static const char *message="1234567890";void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){ if(htim==&htim4){ HAL_UART_Transmit_IT(&huart2, (uint8_t*)message, strlen(message)); } return;}可以看到,通过定时器中断回调函数,实现了每秒通过串口发送消息:

总结
相关函数
操作寄存器宏函数:
__HAL_TIM_GET_COUNTER(__HANDLE__);//获得计数器寄存器的数值__HAL_TIM_SET_COUNTER(__HANDLE__, __COUNTER__);//设置计数器寄存器的数值__HAL_TIM_GET_AUTORELOAD(__HANDLE__);//获得自动重装载寄存器的数值__HAL_TIM_SET_AUTORELOAD(__HANDLE__, __AUTORELOAD__);//设置自动重装载寄存器的数值__HAL_TIM_SET_PRESCALER(__HANDLE__, __PRESC__);//设置预分频器的数值抽象层函数:
HAL_TIM_Base_Start(TIM_HandleTypeDef *htim);//启用定时器HAL_TIM_Base_Start_IT(TIM_HandleTypeDef *htim);//启动定时器(中断模式)HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim);//自动重装载寄存器中断回调函数定时器内部寄存器
- 预分频器:将时钟信号预分频;
- 计数器:遇到时钟信号上升沿/下降沿时,使自身计数+1;
- 自动重装载寄存器:将计数器归零,并触发中断。
部分信息可能已经过时





