在平时的工作做经常会遇到需要延时处理的情况。对于对时间要求不严格的延时来说,我们可以用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。