在平時的工作做經常會遇到需要延時處理的情況。對於對時間要求不嚴格的延時來說,我們可以用for loop這些循環結構來實現延時。但對於一些對時間要求比較嚴格的情況,for loop明顯就不適用了。這個時候我經常會使用定時器來輔助延時,STM32的定時器又灰常的NB,也灰常的讓人頭大(對於我這樣的小白來說)。下面通過一個例子來說明定時器定時相關計算。
Timer相關計算
1 /*set the timer to 1ms*/ 2 void timer_config(void) 3 { 4 TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct; 5 6 TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1; 7 TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up; 8 TIM_TimeBaseInitStruct.TIM_Period = 9; 9 TIM_TimeBaseInitStruct.TIM_Prescaler = 7199; 10 TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0; 11 TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStruct); 12 13 TIM_ClearFlag(TIM2, TIM_FLAG_Update); 14 TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); 15 TIM_Cmd(TIM2, ENABLE); 16 }
上面代碼的功能是將TIM2的定時時間設置為1ms。下面我們來說說我對TIM_TimeBaseInitTypeDef中各個字段的理解。
TIM_ClockDivision | 手冊上說的是內部時鍾(CK_INT)和數字濾波器(ETR ,TIx) 使用的采樣頻率之間的分頻比例。這里我不太明白,希望知道的人說一下 |
TIM_CounterMode | 計數模式,是向上計數還是向下計數 |
TIM_Period | Auto-Reload Register的值 |
TIM_Prescaler | 定時器分頻數,0-65535 |
TIM_RepetitionCounter | 重復計數,也就是說Timer重復溢出多少次才給給出一個溢出中斷, 它對應的寄存器叫RCR. 如果這個值不初始化,因為上電的時候寄存器值可是隨機的,所以本來1s中斷一次,可能變成Ns中斷一次,這肯定不是我們希望見到的情景 |
那下面就來看看上面的代碼為什么能夠實現1ms定時,因為我是使用庫的,所以默認TIM2的時鍾是72MHz。因此想要得到1ms的定時就需要對時鍾進行72000分頻。因為720000〉65535所以無法單純的使用prescaler來實現分頻。因此,需要將prescaler和period兩個結合起來達到定時的效果。
TIM_Prescaler = 7199, //7200分頻 72MHz/(7199+1)=1MHz
TIM_Period = 9; //計數值9
最終定時結果fout = ((1+TIM_Prescaler)/72M)*(1+TIM_Period ) = ((7200)/72M)*(1+9) = 1000Hz。