1. 程式人生 > 實用技巧 >《SLAM機器人基礎教程》第三章 微控制器與STM32:定時器實驗

《SLAM機器人基礎教程》第三章 微控制器與STM32:定時器實驗

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; //預分頻值,不分頻,即為該定製器時鐘值72M
TIM_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系統滴答定時器實現延時。