採用單片機的定時計數器進行毫秒和微妙級延時,精度較準。檢測溢出時產生的標誌位來判斷延時到達。下面以STM8L101芯片爲例及配合代碼說明。
一、實現原理:
1、初始化Timer2時鐘源(附上相應代碼)
void TIM2Init (void)
{
TIM2_DeInit ();
CLK_PeripheralClockConfig(CLK_Peripheral_TIM2, ENABLE);
TIM2->CR1 &= ((uint8_t)(~TIM_CR1_CMS)) & ((uint8_t)(~TIM_CR1_DIR));
TIM2->CR1 |= ( (TIM2_CounterMode_Up) | (TIM_CR1_ARPE) ); /*counter up, enable Auto-Reload*/
TIM2_SetCounter(0x00);
TIM2->IER &= (~TIM2_IT_Update); /*disable timer2 interrupt*/
TIM2->CR1 &= (~TIM_CR1_CEN); /*disable timer2*/
}
打開外設時鐘源;
選擇向上計數模式和打開自動重加載功能;
填裝計數器的初始值;
關閉Timer2中斷功能;
關閉Timer2;
2、毫秒延時代碼示例
void DelayMs (uint16_t timeVal)
{
uint16_t i = 0;
TIM2_TimeBaseInit(TIM2_Prescaler_64, TIM2_CounterMode_Up, 124); /*AutoReload Value = 124, 1ms*/
TIM2->CNTRH = (uint8_t)0; /*counter value = 0*/
TIM2->CNTRL = (uint8_t)0;
TIM2->CR1 |= (TIM_CR1_CEN); /*enable timner2*/
for(i = 0; i < timeVal; i++)
{
TIM2->SR1 &= (~TIM2_FLAG_Update); /*clear timer2 update flag*/
while( ((TIM2->SR1) & TIM2_FLAG_Update) != TIM2_FLAG_Update ); /**/
}
TIM2->CR1 &= (~TIM_CR1_CEN); /*disable timer2*/
}
設置Timer2分頻,向上加1計數模式,填裝自動重載寄存器目標值。這裏每經過8us計數器加1,從0一直到124,共延時1ms,這時Timer2產生溢出標誌位。通過檢查寄存器TIM2->SR1的位[0]判斷。
for(i = 0; i < timeVal; i++)
{
TIM2->SR1 &= (~TIM2_FLAG_Update); /*clear timer2 update flag*/
while( ((TIM2->SR1) & TIM2_FLAG_Update) != TIM2_FLAG_Update ); /**/
}
先軟件清除TIM2->SR1位[0],再等待判斷TIM2->SR1位[0]。這裏加上for循環,表示延時多少毫秒。
關閉Timer2。
3、微妙延時代碼示例
void DelayUs (uint16_t timeVal)
{
TIM2->PSCR = (uint8_t)(TIM2_Prescaler_8);
TIM2->CR1 |= (uint8_t)(TIM2_CounterMode_Up);
TIM2->EGR = TIM2_EventSource_Update;
TIM2->CNTRH = (uint8_t)0;
TIM2->CNTRL = (uint8_t)0;
TIM2->ARRH = (uint8_t)0xff;
TIM2->ARRL = (uint8_t)0xff;
TIM2->SR1 &= (~TIM2_FLAG_Update); /*clear timer update flag*/
TIM2->CR1 |= (TIM_CR1_CEN); /*enable timner*/
while(1)
{
if( (TIM2->CNTRH == (uint8_t)((timeVal - 1) >> 8)) &&
(TIM2->CNTRL == ((uint8_t)(timeVal - 1) & 0x00ff)) )
{
break;
}
}
TIM2->CR1 &= (~TIM_CR1_CEN); /*disable timer*/
}
設置Timer2分頻係數,向上加1計數模式,計數器初始值和自動重裝載目標值。這裏計數器每經過1us自動做加1計數。
清除溢出標誌位,並打開Timer2;
while(1)
{
if( (TIM2->CNTRH == (uint8_t)((timeVal - 1) >> 8)) &&
(TIM2->CNTRL == ((uint8_t)(timeVal - 1) & 0x00ff)) )
{
break;
}
}
這裏不是檢測溢出標誌位,而是檢測計數器當前的計數值。比較是否等於預定設置值。
關閉Timer2。