為了獲取精確延時,STM32芯片中往往會使用內核中的嘀嗒時鍾Systick作為參考時鍾。當嘀嗒時鍾被占用做其他用途時,比如RTOS中的節拍器;就需要采用其他方法進行延時。
這里提出一種采用通用定時器作為延時的參考時鍾的方法。
首先選擇基礎定時器即可,配置定時器參數,主要關注預分頻器寄存器TIMx_PSC,它的大小決定了延時的最小單位,由於TIM2的時鍾為84MHz,所有TIM2_PSC設置為84,即每一次計數對應1us。另外,這里計數器采用向下計數,便於程序判斷。
1 void Delay_Timer_Init(void) 2 { 3 TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct; 4 5 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); 6 7 TIM_TimeBaseStructInit(&TIM_TimeBaseInitStruct); 8 TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1; 9 TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Down; 10 TIM_TimeBaseInitStruct.TIM_Period = 100-1; 11 TIM_TimeBaseInitStruct.TIM_Prescaler = (84-1); 12 TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStruct); 13 14 while((TIM3->SR & TIM_FLAG_Update)!=SET); 15 TIM3->SR = (uint16_t)~TIM_FLAG_Update; 16 }
延時函數如下,對CNT寄存器賦延時值,然后通過判斷Update標志位進行阻塞延時。
1 void Delay_us(uint32_t us_cnt) 2 { 3 TIM3->CNT = us_cnt-1; 4 TIM3->CR1 |= TIM_CR1_CEN; 5 while((TIM3->SR & TIM_FLAG_Update)!=SET); 6 TIM3->SR = (uint16_t)~TIM_FLAG_Update; 7 TIM3->CR1 &= ~TIM_CR1_CEN; 8 }
在沒有外部中斷的情況下,對延時精度進行測試。測試方法是周期性控制GPIO管腳的輸出電平:
1 while(1) 2 { 3 PEOUT_REG(1) = 1; 4 Delay_us(1); 5 PEOUT_REG(1) = 0; 6 Delay_us(1); 7 }
以下結果來自示波器測量,與實際1us稍有偏差,大概在1.2us左右: