STM32通用定时器基本原理
Posted 想成为大师啊
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了STM32通用定时器基本原理相关的知识,希望对你有一定的参考价值。
参考正点原子视频
STM32定时器
共有 8 个定时器,分为基本定时器,通用定时器和高级定时器。基本定时器 TIM6 和 TIM7 是一个 16 位的只能向上计数的定时器,只能定时,没有外部 IO。通用定时器 TIM2/3/4/5 是一个 16 位的可以向上/下计数的定时器,可以定时,可以输出比较,可以输入捕捉,每个定时器有四个外部 IO。高级定时器 TIM1/8是一个 16 位的可以向上/下计数的定时器,可以定时,可以输出比较,可以输入捕捉,还可以有三相电机互补输出信号,每个定时器有 8 个外部 IO。
三种STM32定时器区别
TIM1和TIM8主要特性和TIM1和TIM8定时器的功能包括:
- 16位向上、向下、向上/下自动装载计数器
- 16位可编程(可以实时修改)预分频器,计数器时钟频率的分频系数为1~65535之间的任意数值
- 多达4个独立通道: ─ 输入捕获 ─ 输出比较 ─ PWM生成(边缘或中间对齐模式) ─ 单脉冲模式输出
- 死区时间可编程的互补输出
- 使用外部信号控制定时器和定时器互联的同步电路
- 允许在指定数目的计数器周期之后更新定时器寄存器的重复计数器
- 刹车输入信号可以将定时器输出信号置于复位状态或者一个已知状态
- 如下事件发生时产生中断/DMA: ─ 更新:计数器向上溢出/向下溢出,计数器初始化(通过软件或者内部/外部触发) ─
触发事件(计数器启动、停止、初始化或者由内部/外部触发计数) ─ 输入捕获 ─ 输出比较 ─ 刹车信号输入 - 支持针对定位的增量(正交)编码器和霍尔传感器电路
- 触发输入作为外部时钟或者按周期的电流管理
TIMx主要功能通用TIMx (TIM2、TIM3、TIM4和TIM5)定时器功能包括:
-
位于低速的APB1总线上(APB1)
-
16位向上,向下,向上/向下(中心对齐)计数模式,自动重装载计数器(TIMx_CNT)
-
16位可编程(可以实时修改)预分频器,计数器时钟频率的分频系数为1~65536之间的任意数值
-
4个独立通道(TIMx_CH1~4)可用作: ① 输入捕获 ;② 输出比较 ;③ PWM生成(边缘或中间对齐模式) ;④ 单脉冲模式输出
-
可使用外部信号(TIMx_ETR)控制定时器和定时器互连(可以用1个定时器控制另一个定时器)的同步电路
-
如下事件发生时产生中断/DMA(6个独立的IRQ/DMA请求生成器):①更新:计数器向上溢出/向下溢出,计数器初始化(通过软件或者内部/外部触发);②触发事件(计数器启动,停止,初始化或者由内部/外部触发计数);③输入捕获;④输出比较;⑤支持针对定位的增量(正交)编码器和霍尔传感器电路;⑥触发输入作为外部时钟或者按周期的电流管理
-
STM32的通用定时器可以被用于:测量输入信号的脉冲长度(输入捕获)或者产生输出波形(输出比较和PWM)等
-
使用定时器预分频器和RCC时钟控制器预分频器,脉冲长度和波形周期可以在几个微秒到几个毫秒间调整。STM32的每个通用定时器都是完全独立的,设有互相共享的任何资源
TIM6和TIM7的主要特性TIM6和TIM7定时器的主要功能包括:
-
16位自动重装载累加计数器
-
16位可编程(可实时修改)预分频器,用于对输入的时钟按系数为1~65536之间的任意数值分频
-
触发DAC的同步电路 注:此项是TIM6/7独有功能.
-
在更新事件(计数器溢出)时产生中断/DMA请求
强大,高级定时器应该是用于电机控制方面
计数器模式
通用定时器可以向上计数,向下计数,向上/向下双向计数模式
- 向上计数模式:计数器从0计数到自动重装载值(TIMx_ARR),然后重新从0开始计数并且产生一个计数器溢出事件
- 向下计数模式:计数器从自动装入的值(TIMx_ARR)开始向下计数到0,然后从自动装入的值重新开始,并产生一个计数器向下溢出事件
- 中央对齐模式(向上/向下计数):计数器从0开始计数到自动装入的值-1,产生一个计数器溢出事件,然后向下计数到1并且产生一个计数器溢出事件;然后再从0开始重新计数
通用定时器工作过程
第一部分是时钟发生器。第二部分为时基单元。第三部分为输入捕获。第四部分为输出比较。第五部分包含了几个捕获/比较寄存器。
第一部分首先看到第二部分中psc预分频器需要接收时钟源,而时钟源共有四种来源,分别如下:
1、RCC寄存器中的APB1外设时钟使能寄存器,经过倍频之后输出时钟源,这是因为该寄存器的位0到位5分别表示的是定时器2到定时器7的使能位。(位于图上第一部分)
2、外部触发引脚TIMx_ETR的外部触发输入ETR,对应的引脚可以通过查数据手册得到。ETR经过分频得到ETRP,在经过滤波得到ETRF作为时钟信号。(位于图上第一部分)
3、内部触发输入(ITRx),来自其他的定时器的时钟,即将,经过后面的选择器,进入到触发控制器。(位于图上第一部分)
4、外部输入引脚Tix,这个主要来自于TIMx_CHx (四个通道)。(位于图上第三部分)
第二部分为时基单元,包括PSC预分频器、自动重装载寄存器和CNT计数器。首先由第一部分产生时钟源,进入PSC预分频器进行分频处理,得到新的时钟信号CK_CNT,使得CNT计数器加1或者减1,此时在自动重装载寄存器中有一个预先设定的装载值,当计数器的值达到装载值的时候,会产生溢出事件,然后触发中断。
第三部分为输入捕获,TIMx_CH1——TIMx_CH4 这四个通道,在芯片中都有对应的引脚,当脉冲从通道口进入时,经过输入滤波器(抗干扰的作用),然后经过边沿检测器检测到上升沿(下降沿),经过分频器,输入到第五部分中的捕获寄存器中,然后捕获寄存器记录此刻CNT计数器的值,当下一次下降沿(上升沿)过来时,也记录下CNT计数器的值,这样就可以计算出输入脉冲的宽度。
第四部分为输出比较(注意输入捕获和输出比较不可以同时进行),比如在比较寄存器中预先设定一个值,计数器从初始值到装载值之间计数时,当正好等于比较寄存器中的预设值时,控制TIMx_CH1——TIMx_CH4通道输出低电平或者高电平,这样随着计数器不断的计数,就可以获得一个脉冲,通过调整预设值,就可以调整脉冲宽度,调整初始值和装载值就可以调整周期。
计数时钟的选择
计数器的时钟有8种选择:
-
内部RCC提供的时钟:TIMxCLK
-
内部触发输入口1~4:
ITR1 / ITR2 / ITR3 / ITR4
用一个定时器作为另一定时器的分频器 -
外部捕捉比较引脚
引脚1:TI1FP1或TI1F_ED
引脚2:TI2FP2 -
外部引脚:ETR
使能/禁止位
可编程设定极性
4位外部触发过滤器
外部触发器分频器:①分频器关闭,②二分频,③四分频,④八分频
内部时钟选择
时钟计算方法
默认调用Systemlnit函数情况下:
- SYSCLK = 72M
- AHB时钟 = 72M
- APB1时钟 = 36M
- 所以APB1的分频系数 = AHB/APB1时钟 = 2
- 所以,通用定时器时钟CK_INT = 2*36M = 72M
向上计数模式(时钟分频因子=1)
计数器当前值寄存器CNT
预分频寄存器TIMx_PSC
计数器的时钟频率CK_INT=(CK_PSC的频率)/(PSC[15:0]+1)
自动重装载寄存器TIMx_ARR
控制寄存器1 (TIMx_CR1)
DMA中断使能寄存器(TIMx_DIER)
常用库函数
定时器参数初始化:
void TIM_TimeBaseInit(TIM_TypeDef* TIMx,TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);
结构定义
typedef struct
{
uint16_t TIM_Prescaler;
uint16_t TIM_CounterMode;
uint16_t TIM_Period;
uint16_t TIM_ClockDivision;
uint8_t TIM_RepetitionCounter;
}TIM_TimeBaseInitTypeDef;
例子配置
TIM_TimeBaseStructure.TIM_Period = 4999;// 设置在下一个更新事件装入活动的自动重装载寄存器周期值
TIM_TimeBaseStructure.TIM_Prescaler = 7199;// 设置用来作为TIMx时钟频率除数的预分频值
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;// 不分频
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;// TIM向上计数模式
TIM_TimeBaseInit(TIM3,&TIM_TimeBaseStructure);// 根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
TIM_ClearFlag(TIM3, TIM_FLAG_Update);// 清除更新中断,免得一打开中断立即产生中断
TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);// 打开定时器更新中断
定时器使能函数:
void TIM_Cmd(TIM_TypeDef* TIMx,FunctionalState NewState);
定时器中断使能函数:
TIM_ITConfig(TIM_TypeDef* TIMx, uint16_t TIM_IT, FunctionalState NewState);// 打开定时器更新中断
状态标志位获取和清除
FlagStatus TIM_GetFlagStatus(TIM_TypeDef* TIMx, uint16_t TIM_FLAG);
void TIM_ClearFlag(TIM_TypeDef* TIMx, uint16_t TIM_FLAG);// 清除更新中断,免得一打开中断立即产生中断在这里插入代码片
ITStatus TIM_GetITStatus(TIM_TypeDef* TIMx, uint16_t TIM_IT);
void TIM_ClearITPendingBit(TIM_TypeDef* TIMx, uint16_t TIM_IT);
定时器中断实现步骤
-
使能定时器时钟:
RCC_APB1PeriphClockCmd();
-
初始化定时器,配置ARR,PSC:
TIM_TimeBaseInit();
-
开启定时器中断,配置NVIC:
void TIM_ITConfig(); NVIC_Init();
-
使能定时器:
TIM_Cmd();
-
编写中断服务函数:
TIMx_IRQHandler();
Tout(溢出时间)=(ARR+1)(PSC+1)/Tclk
以上是关于STM32通用定时器基本原理的主要内容,如果未能解决你的问题,请参考以下文章