/*
本篇博文的所有源代码及其他一切形式(文字、图表等)的知识转述均出自B站up主Keysking。
一切内容仅供学习使用,请勿用作其他用途。
【STM32】一看就懂的定时器从模式讲解_哔哩哔哩_bilibili
*/
前提回顾
定时器外部时钟模式框图
TI1、TI2与ETR均可以在触发器选择后进入从模式控制器,在CubeMX中只需要将从模式设置为外部时钟模式1并且选择一个触发源就可以将来自GPIO口上的信号引入计时器。如下图所示:
除了外部触发模式以外,定时器的从模式还有三种,分别叫做复位模式(Reset Mode)、门模式(Gated Mode)以及触发模式(Trigger Mode)。这三种模式可以控制定时器的状态。
Slave Mode
(1)复位模式
对定时器的计数状态进行复位。此时需要新的计数信号作为时钟源,如果只是单纯为了计时,可以选择内部时钟源(APB1、APB2);而如果想对外部信号进行计数,也可以使用外部触发器ETR通过外部时钟模式2接入定时器。简单举例如果在对TI1接受到的上升沿进行捕获,那么一旦边沿检测器检测到上升沿后,定时器会立刻对预分频器、计数器以及自动重装载器进行复位。复位操作也会触发定时器更新中断。
中断机制会将产生的中断对应的中断标志位设置为1,然后中断控制器NVIC通过中断向量表找到对应外设的中断处理函数,中断处理函数都以_IRQHandler作为后缀。例如:
HAL_TIM_IRQHandler可以通过判断各种中断标志位以及各种设置进一步调用各种中断回调函数。
贴一下代码,ioc文件配置请大家自己看视频。
/* USER CODE BEGIN 0 */
char updateMsg[]="自动重装载";
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){
if(htim==&htim2){
HAL_UART_Transmit(&huart2, (uint8_t*)updateMsg,strlen(updateMsg),100);
}
}
/* USER CODE END 0 */
/* USER CODE BEGIN 2 */
HAL_TIM_Base_Start_IT(&htim2);
int counter=0;
char message[20]={};
/* USER CODE END 2 */
/* USER CODE BEGIN WHILE */
while (1)
{
counter=__HAL_TIM_GET_COUNTER(&htim2);
sprintf(message,"counter=%d",counter);
HAL_UART_Transmit(&huart2, (uint8_t*)message,strlen(message),100);
HAL_Delay(500);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
复位模式下的从模式控制器在接受到触发信号后就会让计数器重新计数,并且还可以触发定时器更新中断。
那么问题来了,我们应该如何判断更新中断的产生原因(复位模式 or 自动重装载)?
从模式控制器在接收到触发信号后,还会设置一个触发器中断标志位。所以只需检查触发器中断标志位是否被置一,也就可以将二者区分。
判断代码:
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){
if(htim==&htim2){
if(__HAL_TIM_GET_FLAG(htim,TIM_FLAG_TRIGGER)!=RESET){
__HAL_TIM_CLEAR_FLAG(htim,TIM_FLAG_TRIGGER);
HAL_UART_Transmit(&huart2, (uint8_t*)triggerMsg,strlen(triggerMsg),100);
}else{
HAL_UART_Transmit(&huart2, (uint8_t*)updateMsg,strlen(updateMsg),100);
}
}
}
(2)门模式
它的效果就像是控制着时钟信号的一个门,输入信号为高电平时门就打开,时钟信号可以进入到计时器,定时器正常计数;输入电平为低电平时,门就关闭,定时器暂停计数。也可以通过修改边沿检测器的极性选择实现”两极反转“/*老艾克了*/。
这里把TIM选项卡中Slave Mode模式选择为门模式。
注意:门模式下控制信号出现上升沿或者下降沿,从模式控制器就会暂停或继续定时器计数。在这两个边沿的时刻,也会将触发器中断标志位置1。但门模式并不会复位计数器值,也就不再触发定时器更新中断。所以在更新中断中判断触发器中断标志位并没有意义。
(3)触发模式
检测到设定的边沿后让计时器开始计数。
One Pulse Mode单脉冲模式:定时器不再循环计数,计数到自动重装载后,便停止计数。
注意:MX_TIM2_Init()会将定时器更新中断标志位置1,因而在我们调用HAL_TIM_Base_Start_IT后,中断机制启动,NVIC马上就检测到定时器更新中断标志位为1,触发中断,进而回调了更新中断中的回调函数。
解决方案:清零这个标志位
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART2_UART_Init();
MX_TIM2_Init();
/* USER CODE BEGIN 2 */
//二选一
// __HAL_TIM_GET_FLAG(&htim2,TIM_FLAG_UPDATE);
__HAL_TIM_CLEAR_IT(&htim2,TIM_IT_UPDATE);
HAL_TIM_Base_Start_IT(&htim2);
int counter=0;
char message[20]={};
/* USER CODE END 2 */
/*这一篇写的有点垃圾,马上过年了真没心思学习了,希望大家海涵,多多点赞收藏。*/