《SLAM機器人基礎教程》第三章 微控制器與STM32:定時器實驗
阿新 • • 發佈:2020-07-26
3.7節 定時器實驗
在上一節我們使用SysTick實現了延時,本節介紹使用定時器實現延時。
a.實驗準備:USB轉串列埠模組,ST-Llink下載器,CHEAPX機器人控制板
b.實驗目的:使用定時器延時檢驗上一節SysTick延時函式的準確度
c.相關知識點:
STM32定時器和串列埠一樣,具有中斷函式。但我們開啟定時器時,定時器就會按我們設定好的頻率開始計數直到溢位,溢位會產生溢位中斷。同樣的,我們可以通過計數的數值轉化為時間。STM32F1系列晶片的定時器的解析度可以達到1/72us。
d.程式設計及執行
(1)初始化定時器TIM4,編寫中斷函式
void initTimeStamp(void) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStruct; NVIC_InitTypeDef NVIC_InitStruct; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);//開啟TIM4時鐘 //TIM4 TIM_TimeBaseStruct.TIM_ClockDivision = 0; //時鐘分割,不分割,即為該定製器時鐘最大值72M TIM_TimeBaseStruct.TIM_Prescaler = 0; //預分頻值,不分頻,即為該定製器時鐘值72MTIM_TimeBaseStruct.TIM_Period = 65000-1; //最大計數值,也是計數週期=1/72M*65000s=65000/72us TIM_TimeBaseStruct.TIM_CounterMode = TIM_CounterMode_Up;//向上計數模式 TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStruct);//傳入結構TIM_TimeBaseStruct,配置TIM4 TIM_ClearFlag(TIM4, TIM_FLAG_Update); //清除更新中斷 TIM_ITConfig(TIM4,TIM_IT_Update,ENABLE ); //開啟更新中斷,計數器到達最大值65000-1,從該值轉變至0時,會產生一次更新中斷 NVIC_InitStruct.NVIC_IRQChannel = TIM4_IRQn; //通道值:定時器4 NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0; //搶佔優先順序 0,最高 NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1; //子優先順序 1,次高 NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; //使能 NVIC_Init(&NVIC_InitStruct); //傳入結構體NVIC_InitStruct,配置NVIC TIM_ARRPreloadConfig(TIM4, ENABLE);//開啟自動裝載 TIM_Cmd(TIM4, ENABLE); } void TIM4_IRQHandler(void) { if (TIM_GetITStatus(TIM4, TIM_IT_Update) != RESET) //判斷是否為更新中斷 { timerTSCount++; TIM_ClearITPendingBit(TIM4, TIM_IT_Update ); //清除更新中斷標誌 } }
(2)編寫SysTick測試函式。我們只需要記錄SysTick實現的延時函式前後的TIM4計數值即可。
void testTimestamp(void) { u32 T=0; u32 lastT=0; u32 deltaT=0; printf("Timestamp Test\n"); while(1) { lastT=getTimestampUS(); T=getTimestampUS(); deltaT=T-lastT; lastT=getTimestampUS(); delay_us(1); T=getTimestampUS(); printf("cmd=1us,Real:%6fus;",((T-lastT-deltaT)/72.0f)); lastT=getTimestampUS(); delay_ms(1); T=getTimestampUS(); printf("cmd=1000us,Real:%6fus\r\n",((T-lastT-deltaT)/72.0f)); delay_ms(1000); } }
volatile static u32 timerTS=0; //TimeStamp(unit:1/72us) volatile static u32 timerTSH=0; //TimeStamp(unit:65000/72us) volatile static u8 timerTSCount=0; //TimeStamp(unit:65000/72us) /*** unit:1/72us ***/ u32 getTimestampUS(void) { timerTSH+=timerTSCount; timerTS=timerTSH*65000+TIM4->CNT; timerTSCount=0; return timerTS; }
(3)主函式
//定時器實驗 int main(void) { NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //PriorityGroupConfig NVIC中斷分組設定 組2(2位搶佔優先順序,2位響應優先順序) initDebugSerial(500000);//初始化除錯串列埠USART1,波特率500000 initSysTick();//初始化滴答定時器和TIM4定時器 showVersion();//顯示版本 while(1) { ; } }
(4)實驗結果:
e.實驗總結:TIM定時器除了定時外還可以用於輸出PWM等,是STM32晶片中很重要的外設資源。因此,我們常用SysTick系統滴答定時器實現延時。