一.定时器简介
定时器功能:定时,输出比较,输入捕获,互补输出
定时器分类:基本定时器,通用定时器,高级定时器
二.基本定时器
1.基本定时器:16位,向上计数,只有TIM6和TIM7,没有外部GPIO,只能用来定时。2~7定时器在APB1上。
预分频器和自动重装载寄存器都有影子寄存器。影子寄存器起到一个缓冲的作用。用户值-》寄存器-》影子寄存器-》起作用。一般不需要使用。数据直接写到寄存器之后起作用。
2.定时时间的计算:
如何实现5ms的定时?(200hz)
如果使用高级定时器,挂载在APB2上,预分频为1,时钟为72MHz。设置为向上计数,初值为0。一个中断周期为5ms。
ARR寄存器值0-65535,预分频值0-65535
PSC决定每一次计数多少时间
ARR一个周期计数多少次
(ARR+1)*(PSC+1)/72M=一个周期的时间
那么,5*72000=360000,ARR=PSC=600-1=599;
3.初始化时基结构体
- Prescaler 预分频
- counterMode计数模式,在基本计时器只能向上计数。
- Period:ARR值
- ClockDivision:外部输入时钟分频因子。由于基本定时器没有外部GPIO,所以没有此项.高级定时器需要设置此项,与死区时间相关。
- RepetitionCounter:重复计数器。当计数到ARR值时,不产生中断,清零重新计数,RepetitionCounter值+1直到它的值等于预先配置好的值后产生中断。这种做法会延长计时时间。
void TIM1_Config(uint16_t Period,uint16_t Prescaler)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
TIM_TimeBaseStructure.TIM_Prescaler = Prescaler; //时钟预分频
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;//向上计数
TIM_TimeBaseStructure.TIM_Period = Period; //自动重装值
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //时钟分频1
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM1,&TIM_TimeBaseStructure);
TIM_ClearFlag(TIM1,TIM_FLAG_Update);
TIM_ITConfig(TIM1,TIM_IT_Update,ENABLE);
NVIC_InitStructure.NVIC_IRQChannel = TIM1_UP_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; //抢占优先级2
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2; //响应优先级1
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
三.高级定时器TIM1,TIM8
1.高级定时器:16位,可以上下两个方向计数。有一个重复计数器RCR。有4个GPIO,其中通道1~3还有互补输出GPIO。时钟来自APB2(72M)。
定时器的GPIO选用时尽量不要选择复用接口,防止干扰。
2.时钟源
内部时钟源;
外部时钟模式1:来自外部GPIO。
外部时钟模式2: 来自ETR引脚。
内部触发输入:实现定时器同步或者级联。高级定时器和通用定时器的内部连接在一起。
3.输入捕获
输入捕获可以对输入信号的上升沿,下降沿或者双边沿进行捕获,常用于测量输入信号的脉宽和PWM输入信号的频率和占空比。
输入通道TIx用来输入信号。捕获通道ICx是用来捕获输入信号的通道。TIx经过滤波和边沿检测之后的TIFP1和TIFP2可以进入捕获通道IC1和IC2。这其实就是PWM输入捕获。只有一路TIx却占用了两个IC。当需要测量输入信号的脉宽时,只需要用一个捕获通道就行了。
4.输出比较
CCR决定占空比,ARR决定周期。当CNT计数到CCR值时,电平跳变;当CNT计数到ARR值时,计数器清零,电平翻转。
带死区插入的半桥驱动电路将PWM电信号放大后才能驱动电机。为什么要加入死区呢?MOS管导通时,电机正转;截至时,电机反转。由于MOS工艺原因,转换时,无法顺畅承接。因此设置死区时间来承接过渡这段时间。死区时间的设置要看控制的元件,比如电机。可以通过示波器,看输出的方波的死区时间,然后设置死区时间。
5.输出比较模式--PWM输出模式
PWM输出模式,对外输出脉宽可调的方波信号。有PWM1和PWM2两种模式。常用PWM1的递增模式。
四.写代码
1.PWM互补输出(带死区时间和刹车控制)
互补输出需要2个GPIO(一个为正定时器通道,一个是互补TIM通道),刹车控制需要1个GPIO。死区时间可以通过软件设置,不需要设置GPIO。STM32上I/O上太多引脚有复用,PWM的输出使用专用的小板子比较好。一般情况下,驱动小型电机用10KHz。
初始化GPIO,TimeBaseStructure,TIM_OC输出比较,TIM_BDTR死区和刹车结构体。
GPIO有三个,设置为复用推挽输出,BKIN,正通道和互补通道。BKIN拉低。在刹车功能启用之后,BKIN接高电平会触发刹车(刹车设置为高电平触发),输出信号被禁止,输出通道和互补通道输出空闲电平。
可以看出,控制PWM输出信号控制电机转速,是控制这两个GPIO的电平。但是电机不需要互补通道的电平,所以1个电机控制只要一个正通道输出PWM就足够了。
时基结构体初始化(省略);
输出四路PWM,怎么写代码?看野火四路输出的程序,可参考。
2.输入捕获,测量脉宽
TIM_IC输入捕获结构体,设置捕获通道,捕获边沿,输入通道和捕获通道的映射关系,分频,滤波。开启更新和捕获中断。写中断服务函数,NVIC。在中断服务函数里判断是哪种中断,再具体执行对应的任务。
当设置的捕获时间大于CNT的计数范围时,CNT会先产生更新中断,因此在触发中断时,要判断是否是更新中断,是更新中断的话,要计数更新中断次数。
定时器设置成上升沿捕获,产生中断,CNT计数清零,中断触发改为下降沿,第一次下降沿中断。第二次捕获到下降沿,获取CCR的值。
如果CCR的值等于1,则判断是否CNT有溢出,计算高电平时间的计数器值
3.输入捕获,测量PWM信号的频率和占空比
捕获用高级定时器T1的通道1,输出信号用通用定时器的T3的通道1.同一个定时器不能同时用于输入和输出。