STM32开启定时器就立即进Update中断问题探索
問題描述:意外發現定時器再剛使能后立即就進了中斷,且是Update中斷,比較奇怪,難道Update中斷不是定時器計數溢出后才觸發嗎?因此寫下此文章記錄相關情況。
測試平臺: STM32F103VET6
驅動庫版本:標準庫V3.5.0
一、首先上測試代碼
void TIM3_Int_Init(u16 arr,u16 psc) {TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;NVIC_InitTypeDef NVIC_InitStructure;RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //時鐘使能//定時器TIM3初始化TIM_TimeBaseStructure.TIM_Period = arr; //設置在下一個更新事件裝入活動的自動重裝載寄存器周期的值 TIM_TimeBaseStructure.TIM_Prescaler =psc; //設置用來作為TIMx時鐘頻率除數的預分頻值TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //設置時鐘分割:TDTS = Tck_timTIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上計數模式TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根據指定的參數初始化TIMx的時間基數單位TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE ); //使能指定的TIM3中斷,允許更新中斷//中斷優先級NVIC設置NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; //TIM3中斷NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //先占優先級0級NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //從優先級3級NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能NVIC_Init(&NVIC_InitStructure); //初始化NVIC寄存器printf("TIM3 EN\r\n");TIM_Cmd(TIM3, ENABLE); //使能TIMx } //定時器3中斷服務程序 void TIM3_IRQHandler(void) //TIM3中斷 {if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) //檢查TIM3更新中斷發生與否{TIM_ClearITPendingBit(TIM3, TIM_IT_Update); //清除TIMx更新中斷標志 printf("TIM3IRQ\r\n");LED0=!LED0;} }結果如下:(定時器是配置的500ms溢出)
可見在TIM使能后立即進了一次中斷。后面才正常。
圖中是用了串口助手的時間戳功能,TIM3 EN 和TIM3IRQ兩條之間時間極短所以串口助手沒有區分開時間
二、進一步探究
void TIM3_Int_Init(u16 arr,u16 psc) {TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;NVIC_InitTypeDef NVIC_InitStructure;RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //時鐘使能printf("TIM3SR=%08X\r\n",TIM3->SR);//定時器TIM3初始化TIM_TimeBaseStructure.TIM_Period = arr; //設置在下一個更新事件裝入活動的自動重裝載寄存器周期的值 TIM_TimeBaseStructure.TIM_Prescaler =psc; //設置用來作為TIMx時鐘頻率除數的預分頻值TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //設置時鐘分割:TDTS = Tck_timTIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上計數模式TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根據指定的參數初始化TIMx的時間基數單位printf("TIM3 ITEN\r\n");printf("TIM3SR=%08X\r\n",TIM3->SR);TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE ); //使能指定的TIM3中斷,允許更新中斷printf("TIM3 ITEN2\r\n");//中斷優先級NVIC設置NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; //TIM3中斷NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //先占優先級0級NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //從優先級3級NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能NVIC_Init(&NVIC_InitStructure); //初始化NVIC寄存器printf("TIM3 EN\r\n");TIM_Cmd(TIM3, ENABLE); //使能TIMx }結果如下:
以上情況發現,這個誤觸發的中斷還不是出在開啟定時器之后,而是在配置了NVIC TIM中斷之后立即就觸發了,上述測試我們還發現,TIM_TimeBaseInit之后,TIM3->SR寄存器中的更新中斷位還被置位了,導致一配置好TIM3中斷立即就觸發了中斷。
三、解決辦法
知道了問題出在哪里就好解決了,在使能中斷前手動清除更新中斷標記即可。
void TIM3_Int_Init(u16 arr,u16 psc) {TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;NVIC_InitTypeDef NVIC_InitStructure;RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //時鐘使能printf("TIM3SR=%08X\r\n",TIM3->SR);//定時器TIM3初始化TIM_TimeBaseStructure.TIM_Period = arr; //設置在下一個更新事件裝入活動的自動重裝載寄存器周期的值 TIM_TimeBaseStructure.TIM_Prescaler =psc; //設置用來作為TIMx時鐘頻率除數的預分頻值TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //設置時鐘分割:TDTS = Tck_timTIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上計數模式TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根據指定的參數初始化TIMx的時間基數單位printf("TIM3 ITEN\r\n");printf("TIM3SR=%08X\r\n",TIM3->SR); // TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE ); //使能指定的TIM3中斷,允許更新中斷printf("TIM3 ITEN2\r\n");//中斷優先級NVIC設置NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; //TIM3中斷NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //先占優先級0級NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //從優先級3級NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能NVIC_Init(&NVIC_InitStructure); //初始化NVIC寄存器printf("TIM3 EN\r\n");printf("TIM3SR=%08X\r\n",TIM3->SR);TIM_ClearITPendingBit(TIM3, TIM_IT_Update); //清除更新中斷請求位printf("TIM3SR=%08X\r\n",TIM3->SR);TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE); //使能定時器更新中斷TIM_Cmd(TIM3, ENABLE); //使能TIMx }正常的結果如下:
至于為什么TIM_TimeBaseInit函數初始化后SR寄存器的更新標志就置位了,與定時器里UG位和URS位的使用,分別在TIMx->EGR和TIMx->CR1寄存器里,應該有一定關系。
在TIM_TimeBaseInit函數的最后一句:
這句置位了TIMx->EGR的0bit也就是UG,但在TIM_TimeBaseInit函數之后立即打印TIMx->EGR的寄存器值已經為0x00了(因為UG是軟件置位,硬件自動清除,生效后自動就被清除了),如果注釋掉TIM_TimeBaseInit函數的最后一句,測試如下:
由上圖的測試結果可見,確實與TIMx->EGR的0bit也就是UG有關系,不使能UG位就不會有SR最后一位被置位了。但不知道為啥,這時SR中的更新標志沒有置位,定時器更新中斷打開后依然立即觸發了一次中斷,這就有點奇怪了,所以改庫函數還是有點行不通,只能用手動清楚標志位的方法。
參考鳴謝:
https://blog.csdn.net/ygt666/article/details/79586390
http://www.51hei.com/bbs/dpj-40940-1.html
總結
以上是生活随笔為你收集整理的STM32开启定时器就立即进Update中断问题探索的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: MDK KEIL 烧录STM32下载错误
- 下一篇: RT-Thread工程代码框架分析——(