某客戶設計需要啟動定時器在 3ms 後產生中斷,其後定時器不再運行,直至下一次軟體要求再次啟動定時器產生中斷,實測代碼後發現定時器啟動後立即產生了超時中斷。
2.調研
客戶通過 STM32CubeMX 配置 TIM7 並生成工程,在主循環中添加定時器啟動代碼;在定時器中斷處理函數處理 update event 回調時停止定時器,並翻轉一個 I/O 腳指示定時器啟停,代碼如下:
圖1.啟動定時器
圖2.定時器中斷回調
客戶期待的結果是啟動定時器時 I/O 拉高並保持 3ms,當 3ms 到達後產生中斷拉低I/O,但實測時發現,定時器啟動後立即產生了超時中斷(高電平持續時間約 2us):
圖3.實測結果
3.分析
應用代碼在初始化定時器時會調用 HAL_TIM_Base_Init( )接口,此接口會調用TIM_Base_SetConfig( ) 配置定時器,並產生更新事件(TIMx->EGR = TIM_EGR_UG)加載寄存器,此事件標誌 UIF 會被置位,在調用 HAL_TIM_Base_Start_IT( ) 啟動定時器,在此使能定時器中斷時,由於 UIF 已經置位,所以會立即觸發並進入中斷處理函數,中斷回調函數會停止定時器計數,並禁止定時器中斷;但當從中斷處理函數返回繼續執行HAL_TIM_Base_Start_IT( )時,此接口會使能定時器開始計數,進而在下一次調用HAL_TIM_Base_Start_IT( )時又會立即產生中斷,循環往復,詳細時序和具體代碼如下:
圖4.問題產生時序描述
圖5.定時器啟動代碼
4.處理
修改代碼,在啟動定時器前強制停止定時器計數、清除中斷位、清除 NVIC 掛起的中斷後,再啟動定時器,詳見下圖紅框內代碼:
圖6.問題修正代碼
圖7.修正 BUG 後的運行結果
5.小結
在碰到這類定時器異常問題時,可以利用 I/O 口指示運行狀態,結合代碼分析找到原因 並加以解決。
評論