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