关于stm32的定时器的运用配置
定时器是stm32的一大利器,现在的项目中可以说没有一个不会用到定时器的,所以掌握理解运用定时器才会做出好的产品来。
本章内容说一说关于stm32的定时器TIM_GetCounter(TIMx)的运用。之前的项目中曾经用这个来获取高低电平的时长,在超声波测距,红外遥控解码中运用过。Stm32的定时器除了1和8其他都是通用定时器。如何用这句函数来捕捉电平时长呢?首先看一下初始化内容,以TIM4为例
void Timer4_CFG()
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOE | RCC_APB2Periph_AFIO , ENABLE);
GPIO_InitStructure.GPIO_Pin = IR_LED_PIN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(IR_LED_PORT, &GPIO_InitStructure);
TIM_TimeBaseStructure.TIM_Prescaler = 3599; //TIM_CKD_DIV1
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //
TIM_TimeBaseStructure.TIM_Period = 200; // ARR
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
//TIM_TimeBaseStructure.TIM_RepetitionCounter = 4;
TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);
//TIM_PrescalerConfig(TIM4,3599,TIM_PSCReloadMode_Immediate);//72MHz/(3599+1)=20 000 HZ 50uS
TIM_ARRPreloadConfig(TIM4,DISABLE);
TIM_ITConfig(TIM4,TIM_IT_Update,ENABLE);
TIM_ITConfig(TIM4,TIM_IT_Trigger,ENABLE);
TIM_Cmd(TIM4, DISABLE);
}
APB1是36M时钟,经过分频后产生20KHZ 50us周期的波形。TIM->CNT这个是计数器,在这里计算TIM_TimeBaseStructure.TIM_Period的值时有一定的规律,就是你采集的高低电平最大是多少要知道,比如我采集的波形中的电平最长的是4ms,基准计时器是50us,那么我要计算80个才能达到4ms,所以TIM_TimeBaseStructure.TIM_Period的值一定要比80大,否则就会出错。这里要提醒大家 TIM-CNT的值达到TIM_TimeBaseStructure.TIM_Period的值时,就会清零重新计数如下图。这是利用定时器的TIMX-CNT计数器获得高低电平的寄存器配置方法,当然cnt=TIM_GetCounter(TIMx);cnt要乘以50us才是真正的时间。
如果不用计数器,想在中断里用一个全局变量来表示中断的次数 来计算高低电平的时长,注意,这种方法可能因为程序功能多而造成不准确,在功能较少的情况下可以尝试,那么配置定时器就又要改了,基准还是50us,
TIM_TimeBaseStructure.TIM_Prescaler =3599; //TIM_CKD_DIV1
这个时候不能考虑最大值了,而是考虑一个最小公约数,比如我要采集的高低电平有多少呢,有8ms,4ms,1ms,500us,那么TIM_TimeBaseStructure.TIM_Period的值就有要求了,只要是50us的倍数并和50us相乘后小于500us还是他的约数就可以了。举个例子
TIM_TimeBaseStructure.TIM_Prescaler = 3599; //
TIM_TimeBaseStructure.TIM_Period=1;//
这两句话代表50us发生一次中断。
最新评论