1.定时器概述
定时器分为基本定时器,通用定时器,高级定时器。
例如:STM32F10x系列包含4个通用定时器(TIM2~TIM5但是STM32F103Rx系列只有3个通用定时器(TIM2~TIM4))。这些通用定时器是完全独立的,不共享任何资源。每个定时器都包含一个16位的计数器(计算范围:0~65535),并且这些定时器都可以通过预分配器来对输入的时钟源进行分频(分频就是降低计数频率),来满足更长的的计时要求。通用定时器除了基本的定时功能以外,还具有输入捕获(测量输入信号脉冲长度)、输出比较(产生输出波形)等功能。
2.特征对比
基本定时器 | 通用定时器 | |
计数器 | 16位自动重装在递增计数器 | 16位自动重装载递增、递减或先增后减计数器 |
预分频器 | 输入的时钟源进行分频 | |
自动重装载计数器 | 放计数器计数周期的最大值(决定了计数器在一个工作周期内的计数次数 | |
上三者组成定时器时基单元 | ||
时钟源 | 内部时钟源CK_INT | 内部时钟源CK_INT 内部触发输入(定时器级联) 外部时钟模式1(来自TIx的边缘检测信号,用于霍尔电机测速) 外部时钟模式2(来源外部触发输入ETR) |
功能 | 定时延时 触发DAC驱动电路,为DAC提供驱动时钟 产生中断或DMA请求 |
定时、延时 输入捕获、输出比较、PWM、单脉冲输出(只输出一个周期)
扫描二维码关注公众号,回复:
12571479 查看本文章
产生中断或DMA请求 支持霍尔传感器电路进行电机转速检测等应用。 |
通道 | 单通道 | 四个通道 |
产生中断或DMA请求条件 | 更新事件 | 更新事件、触发事件、输入捕获以及输出比较 |
3.框图对比与解释
1)基本定时器
向自动重装在计数器写入计数周期(即计数器最大值),向预分频计数器写入分频系数(多久记一次数)。计数器从0开始计数(假设向上计数),当计数达到我们写入的最大值时候,会产生一个更新事件 和 中断或者DMA请求。
为什么要产生更新事件?对于编程人员来说,我们能访问上层寄存器,这个上层寄存器对于CPU来说是访问不到的,CPU能访问的是影子寄存器。因此我们要将上层寄存器和影子寄存器进行关联。更新事件的作用就是:将自动重装载计数器和预分频计数器的值写入影子寄存器,以达到CPU可以访问的目的。当然每次产生更新事件都要更新一下影子寄存器。
2)通用定时器
都在图里
4.通用定时器时钟源
- 内部时钟(CK_INT):定时器的输入时钟源来源于芯片内部系统总线时钟,频率为72M。
- 外部时钟模式1:定时器的输入时钟源来源于外部输入管脚(TIx)上的边缘输入信号(x:TI1FP1、TI2FP2)。霍尔传感电路检测电机转速
- 外部时钟模式2:定时器的输入时钟源来源于外部触发输入(ETR)上的定时器外部触发管脚(TIMx_ETR)上的外部输入信号。
- 内部触发输入(ITRx):定时器的输入时钟源来源于一个定时器的内部输出(TRGO)到ITRx的输入时钟信号(x:ITR0~3)。 定时器级联
5.通用定时器输出比较
输出比较工作流程:先输出比较寄存器CCRx写入数值(类似重装载值),CNT开始计数,通过CNT数值与CCRx值比较==>输出有效电平、无效电平、电平反转等。当CNT的值大于CCRx,会产生对应的中断和标志位。
1)强制输出
通用定时器的输出直接由软件将输出比较信号(OxRef和OCx)强制设置为有效电平、无效电平或者输出不变。无需考虑捕获/比较寄存器(CCRx)和计数器(CNT)之间的任何比较结果
2)比较输出
比较输出模式的输出结果和捕获/比较寄存器(CCRx)和计数器(CNT)之间比较结果相关,当这两个值相等的时候,输出结果为有效电平、无效电平或者电平翻转。如果计数器(CNT)的值大于或等于捕获/比较寄存器(CCRx)中的值时,会产生对应的标志或者中断。而输出比较模式在四个通道可以产生的频率不同.CCRx决定初相位
3)PWM输出
PWM输出模式是输出比较的一个特例,输出结果和捕获/比较寄存器(CCRx)和计数器(CNT)之间的比较值影响,输出结果为有效电平、无效电平。pwm模式在对应定时器上的四个通道产生的频率是同步的
6.通用定时器配置流程
- 时钟使能
- 配置GPIO口
- 配置定时器公共计数器模块:定时器时钟源(内部、外部、触发)、计数方式(加、减、先加后减)、计数频率(预分频)、是否循环、计数周期(重装载值)等。
- 配置定时PWM比较输出模式: PWM模式、具体有效电平、通道工作模式、占空比等。
- 使能定时器输出以及使能定时器模块。
7.代码
舵机的控制一般需要一个20Ms左右的时基脉冲,该脉冲的高电平部分一般为0.5Ms~2.5Ms范围内的角度控制脉冲部分,总间隔为2Ms。
以180°舵机为例,对应的控制关系如下:
0.5Ms————0° 1.0Ms————45° 1.5Ms————90° 2.0Ms————135° 2.5Ms————180°
360°舵机与其他普通舵机不同,它实际相当于无极变速的减速电机,可以控制速度和方向,但是没有0-360°角度控制的功能。控制方向和一般舵机的控制信号相同:
0.5Ms————正向最大转速 1.5Ms————速度为0 2.5Ms————反向最大转速
//PB0 -- pwm--TIM3_CH3---20ms时基---72000-1分频---arr:20000-1 == 20ms
//不分频:定时1s需要计数器加72*10^9
//72000-1分频: 定时1s需要计数器加1*10^6 减一:计数器时钟频率 = f_ckpsc / (psc[15:0]+1)
//20ms就是计数器计数:20000-1 减一:如果想计数100次则写99,因为99加一次就是0刚好100
// PWM_Init1(20000-1,72);
void PWM_Init1(u16 arr,u16 psc)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIO口,相当于GPIOB_Pin_初始化
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
//置定时器时钟(CK_INT)频率与数字滤波器(ETR,TIx)使用的采样频率之间的分频比例的(与输入捕获相关),0表示滤波器的频率和定时器的频率是一样的。
TIM_TimeBaseStructure.TIM_Period = arr;
TIM_TimeBaseStructure.TIM_Prescaler = psc * 1000 - 1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
//TIM_RepetitionCounter 是再次重装载值,正常情况下当计数溢出后清零进入中断,该寄存器配置1后,就是计数器溢出两次才进入中断
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);//初始化定时器
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;//CNT < CCRX 输出有效电平
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; // 开启OC*输出到对应引脚
TIM_OCInitStructure.TIM_Pulse = 0; // TIM3->CCR32 = TIM_OCInitStruct->TIM_Pulse = TIM_SetCompare3(TIM3,800); 此值决定电机转速
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;//输出极性:有效电平是高电平
/***********高级定时器********************/
// TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable; // 互补输出使能。开启OC*N输出到对应的引脚
// TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High; //互补输出极性 高
// TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set; //在空闲状态下的TIM输出比较引脚的状态。仅供TIM1和TIM8有效 高
// TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset; //在空闲时互补输出 低
TIM_OC3Init(TIM3,&TIM_OCInitStructure);//TIM3通道3初始化
TIM_ARRPreloadConfig(TIM3,ENABLE); //初始化预装载值。
TIM_Cmd(TIM3, ENABLE); //使能TIM3定时器
}