一、STM32通用定时器概述
通用定时器包括一个16位或32位自动重载计数器,可通过可编程预分频器进行驱动。定时器可以实现多种功能,包括测量输入信号的脉冲宽度和生成输出波形,通过使用定时器预分频器和RCC时钟控制器预分频器,可以将脉冲宽度和波形周期从几微秒调制到几毫秒。此外,通用定时器之间是完全独立的,不会共享任何资源。定时器可应用于许多不同的领域,例如自动控制等。
通用 TIMx 定时器具有以下特性:● 16 位 (TIM3 和 TIM4) 或 32 位 (TIM2 和 TIM5) 递增、递减和递增 / 递减自动重载计数器。● 16 位可编程预分频器,用于对计数器时钟频率进行分频 (即运行时修改),分频系数介于 1 到 65536 之间。● 多达 4 个独立通道,可用于:— 输入捕获— 输出比较— PWM 生成(边沿和中心对齐模式)— 单脉冲模式输出● 使用外部信号控制定时器且可实现多个定时器互连的同步电路。● 发生如下事件时生成中断/DMA 请求:— 更新:计数器上溢/ 下溢、计数器初始化(通过软件或内部 / 外部触发)— 触发事件(计数器启动、停止、初始化或通过内部/ 外部触发计数)— 输入捕获(红外捕获)— 输出比较(PWM波)● 支持定位用增量(正交)编码器和霍尔传感器电路● 外部时钟触发输入或逐周期电流管理
通用定时器一共有10个如下表
所有的计数器都可以由16位可编程预分频器(1到65536分频)驱动。从而实现将脉冲宽度和波形周期从几微秒调制到几毫秒。
所有的通用定时器都彼此完全独立不共享任何资源。
所有的通用定时器的功能包括基本的定时功能之外,还可以测量输入信号的脉冲宽度(输入捕获),或者生成输出波形〈输出比较、PwM)。
补充:PWM(脉冲宽度调制)波特点:波形的周期/频率不会变化,占空比可以变化。占空比:波形的高电平时间占整个周期的比例。
注意:(方波:波形的周期/频率和占空比都可以变化)
二、通用定时器框架
(1) TIMx..chx,总共有4个,但是左右两边是同一个通道,即是4个GPIO口,为了说明内部功能将其一分为二。
多达4个独立通道,可用于:
一输入捕获
一输出比较---PWM生成一单脉冲模式输出
发生如下事件时生成中断/DMA请求:
一更新:计数器上溢/下溢、计数器初始化(通过软件或内部/外部触发)一触发事件(计数器启动、停止、初始化或通过内部/外部触发计数)
一输入捕获
一输出比较
二、STM32通用定时器捕获输入
1、STM32的捕获输入原理
输入捕获:利用定时器的捕获通道捕获一个输入的信号。
输入捕获原理:通过检测TIMx_CHx通道上的边沿信号,在边沿信号发生跳变(比如上升沿/下降沿)的时候,会产生一个icXps信号(捕捉事件),当产生捕捉事件时会将当前定时器的值(TIMx_CNT)存放到对应的捕获影子寄存器里面(结果),完成一次捕获。
输入捕获的应用:捕获输入信号的脉冲宽度或者周期/频率。
2、STM32的捕获输入框架
总结:捕获的信号周期(频率)计算:
(1)从捕获寄存器中读出捕获的计数器的值(发生更新事件时)。
(2)计数周期(算出计数一个数的时间)。
(3)周期 = 计数 * 计数周期。
3、STM32的捕获输入相关寄存器
STM32的捕获输入
(1)设计:利用定时器的输入捕获功能检测按键按下的时长(脉冲宽度)
原理分析:
硬件分析
PA0配置为复用功能,复用为定时器5的CH1
******************************
@brief :定时器5输入捕获配置
@param : none
@return : none
@note TIM5->CH1 ===PA0 捕获按键按下的时长
*************************************/
void Time5_Init(void)
{
/*1IO配置*/
RCC->AHB1ENR |= 1 << 0;
GPIOA->MODER &= ~(0X3 << 0);
GPIOA->MODER |= (0X2 << 0);//复用功能
GPIOA->AFR[0] &= ~(0XF<< 0);//
GPIOA->AFR[0] |= 2 << 0;//PC6复用为定时器3的ch1
/*2定时器配置*/
RCC->APB1ENR |= 1<<1;//打开TIM3的时钟
//时基单元配置
//配置时基单元(预分频器,自动:重载寄存器,计数值)
TIN5->ARR = 0xFFFF - 1;//10000
TIM5->PSC = 8400 - 1;//10Khz 100us
TIM5->CNT = 0;
TIM5->CR1 = 0;
TIM5->CR1 |= 1 << 7;//使用缓冲区
TIM5->CR1 |= 1 << 2;
//计数器递增计数
//连续模式
//UG位的使用手动产生更新事件,
//目的:首次配置将缓冲区的值加载到时基寄存器中
TIM5->EGR=1<<0;
//清除更新一次标志位
TIM5->SR &= ~(1 << 0);
//配置输入捕获
TIM5->CCMR1 |= 0XF << 4;//最大采样频率
TIM5->CCER &= ~(1 << 3);
TIM5->CCER &= ~(1 << 1);//通道1第一次上升沿触发
TIM5->CCMR1 |= 1 << 0;//CC1通道配置为输入,IC1映射到TI1上
TIM5->CCMR1 &= ~(3 << 2);//00:无预分频器,捕获输入上每检测到一个边沿便执行捕获
TIM5->CCER |= (1 << 0);//使能捕获
TIM5->DIER |= 1 << 1;//打开通道1的捕获中断
//配置捕获中断在NVIC中的中断信息
NVIC_SetPriority(TIM5_IRQn, NVIC_EncodePriority(5,2,1));//为定时器5设置中断信息
NVIC_EnableIRQ(TIM5_IRQn);
TIM5->DIER |= 1 << 0;
//使能计数器
TIM5->CR1 |= 1 << 0;
}
u16 update_num;//完整的周期个数
u32 count;
u32 updatflag;
void TIM5_IRQHandler(void)
{
//判断是否是更新中断
if(TIM5->SR &(1 << 0))
{
TIM5->SR &= ~(1 << 0);
if(updateflag == 1)
{
update_num++;
}
printf("update_num = %d\r\n",update_num);
}
//判断是否是捕获中断
if(TIM5->SR &(1 << 1))
{
if(KEY1)//按键按下
{
updateflag = 1;
TIM5->DIER |= 1 << 0;
TIM5->CNT = 0;
TIM5->CCER &= ~(1 << 3);
TIM5->CCER |= (1 << 1);
}
else//按键松开
{
TIM5->DIER &= ~(1 << 0);
count = update_num * 0XFFFF + TIM5->CCR1;
printf("count = %d\r\n",count);
printf("count = %.2f\r\n",count*0.1);
TIM5->CCER &= ~(1 << 3);
TIM5->CCER &= ~(1 << 1);
update_num = 0;
count = 0;
updateflag = 0;
}
}
}
4、时钟源框架分析
由上图可知计数器时钟可由下列时钟源提供:
内部时钟(CK_INT)
外部时钟模式1:外部输入引脚(TIx)
外部时钟模式2:外部触发输入(ETR),仅适用于 TIM2、TIM3和TIM4。
内部触发输入(ITRx):使用一个定时器作为另一个定时器的预分频器。
注意:在四个时钟输入源中,除了特殊模式外正常情况下选择内部时钟源作为预分频器的时钟输入。
内部时钟源:
如果禁止从模式控制器(TIMx_SMCR [SMS]=000),则CEN位、DIR位(TIMx_CR1寄存器中)和UG位(TIMx_EGR寄存器中)为实际控制位,并且只能通过软件进行更改(UG除外,仍自动清零)。当对CEN位写入1时,预分频器的时钟就由内部时钟CK_INT提供。
如何选择内部时钟源??
TIMx_SMCR[SMS] = 000
TIMx_CR[CEN] = 1时
既可选择为内部时钟源。
外部时钟源模式2
如何选择外部时钟源模式2??
通过在TIMx_SMCR寄存器ECE位中写入=1可选择此模式即TIMx_SMCR[ECE]=1
既可选择为外部时钟源模式2
计数器可在外部触发输入 ETR 出现上升沿或下降沿时计数。
外部时钟源模式1
如何选择外部时钟源模式1??
TIMx_SMCR[SMS]=111
TIMx_SMCR[CEC]=0//关闭模式2。
既可选择为外部时钟源模式1
5、STM32的通用定时器比较输出
输出比较:通用定时器通过定时器通道向外部输出相应的波形(其中最重要的是 PWM 波)
输出 PWM 的应用:控制电机的转速,在充电器充电过程,生活中的灯光控制,声音控制等
补充:
PWM(脉冲宽度调制) 波特点:波形的周期/频率不会变化,占空比可以变化
占空比:波形的高电平时间占整个周期的比例。
注意:(方波:波形的周期/频率和占空比都可以变化 )。
比较输出原理
原理:当计数器的值和比较寄存器的值相同时会产生一个参考信号ocxref(一个完整周期),该参考信号再经过输出控制后,就通过OCX输出到外部。
细节描述:选择计数器向上计数,当计数器开始计数时,计数器的值 < 比较寄存器的值,此时产生一个高电平(或低电平),当计数器的值 > 比较寄存器的值,此时产生一个低电平(或高电平)。
总结:
(1)配置流程
IO配置:
开时钟复用功能
复用为定时器的通道x
(2)定时器配置
开时钟配置计数器:1时基单元
(3)PWM配置过程:
1向比较寄存器写入一个比较值2配置通道为输出方向
3 选择比较模式(PWM1/2)
4选择实际输出的有效电平
5打开输出通道(4)输出PWM的:
周期: 由计数器的值来决定占空比: 比较寄存器的值决定
6、STM32比较输出相关寄存器
通用定时器输出PWM 控制 LED 灯实现呼吸灯或控制灯的亮度
硬件:
选择将PC6复用为定时器3的通道1。
原因:定时器产生的 PWM 波和LED3 灯是同一个管脚,所以信号输出之后直接可以控制LED3,不用使用杜邦线将 LED 灯所在的管脚PWM 波所在的管脚连在一起。
/************************************
@brief:定时器3输出PWM管脚配置
@param:none
@return:none
@note TIM3->CH1 === PC6 控制灯的亮度
*************************************/
void Time3_Init(u16 arr, u16 ZKB)
{
/*IO配置*/
RCC->AHB1ENR |= 1 << 2;
GPIOC->MODER &= ~(0X3 << 12);
GPIOC->MODER |=(0x2 << 12);//复用功能
GPIOC->AFR[0] &= ~(0XF << 24);
GPIOC->AFR[0] |= 2 << 24;//PC6复用为定时器3的ch1
/*2定时器配置*/
RCC->APB1ENR |= 1 << 1;//打开TIM3的时钟
/*时基单元配置*/
//配置时基单元( 预分频,自动重载寄存器,计数值 )
TIM3->ARR = arr - 1;//
TIM3->PSC = 8400 -1;
TIM3->CNT = 0;
TIM3->CR1 = 0;
TIM3->CR1 |= 1 << 7;//使用缓冲区
//计数器递增计数
//连续模式
TIM3->CCR1 = ZKB;
//UG位的使用手动产生更新事件
//目的 : 首次配置将缓冲区的值加载到时基寄存器中
TIM3->EGR |= 1 << 0;
//清除更新一次标志位
TIM3->SR &= ~(1 << 0);
/*配置PWM*/
TIM3->CCMR1 &= ~(0X3 << 8);//通道1配置为输出方向
TIM3->CCMR1 |= (0X6 << 4);//选择PWM1模式
TIM3->CCER &= ~(0X1 << 3);
TIM3->CCER &= ~(0X1 << 1);//有效电平为高
TIM3->CCER |= (0X1<< 0)//开启一在相应输出引脚上输出 OC1 信号
//使能计数器
TIM3->CR1 |= 1<< 0;
}
比较输出相关寄存器分析
TIMx 控制寄存器 1 (TIMx_CR1)
位7:决定当前ARR寄存器有没有影子寄存器
位6:5 -- 00 选择边沿对齐模式
位4:选择递增还是递减模式
位3:
0:连续计数
1:单次计数
位2:1
位1:0--使能UEV
TIMx 从模式控制寄存器 (TIMx_SMCR)
TIMx DMA/中断使能寄存器 (TIMx_DIER)
TIMx 状态寄存器 (TIMx_SR)
更新中断标志位置1:就是一个周期结束
TIMx 事件寄存器 (TIMx_EGR)
TIMx 捕获/比较模式寄存器 1 (TIMx_CCMR1)
位7:0不受ETRF的影响
模式选择:一般可以选用PWM模式1
配置为00,选择输出模式
TIMx 捕获/比较模式寄存器 2 (TIMx_CCMR2)
和CCMR1一致,针对通道3和通道4
TIMx 捕获/比较使能寄存器 (TIMx_CCER)
TIMx 捕获/比较寄存器 1 (TIMx_CCR1)
比较输出:
软件设计
1、配置GPIO口
先打开GPIOC的时钟
配置PC6为复用功能
复用到TIM3_CH1
2、配置TIM3的通道1
打开TIM3的时钟
选择内部时钟源(84M)
写预分频值
写重装载值
配置一些基本的(CR1寄存器)
往CCR1里写值
把通道1配置为输出模式
选择CCR1有影子寄存器
生成更新事件(让UG位置1)
配置OCREF不受ETRF的影响
选择PWM模式1
选择不反相输出
使能OC1,让信号可以输出出去
使能更新中断标志位
配置中断优先级
让核心响应中断
使能是计数器
编写中断服务函数
不断改变CCR1的值
捕获输入
软件设计
1、GPIO口配置
先打开GPIOA的时钟
配置PA0为复用功能
复用到TIM5_CH1
2、TIM5_CH1配置
打开TIM3的时钟
选择内部时钟源(84M)
写预分频值
写重装载值
配置一些基本的(CR1寄存器)
选择CCR1有影子寄存器
生成一次更新事件
先滤波(82kHZ)
选择上下变沿都触发
将CH1映射到TI1上
选择输入模式
每一个边沿都会触发一次捕获事件
使能捕获通道
EGR的CC1G位置0代表不使用软件触发捕获
使能中断(捕获 /比较 1 中断使能,更新中断使能)
配置中断优先级
核心响应中断
使能计数器
编写中断服务函数