一、定时器概述
通过软件延时(延时函数、汇编指令)的缺点:
1.延时不精准
2.CPU死等(卡在延时函数中)
定时器的原理核心:计数器
分类:
基本定时器:常用来做时基
通用定时器:除了时基外可以作输入捕获/输出比较
高级定时器:能输出互补输出
时钟来源:TIM1、8挂在APB2总线上 时基是72MHZ
TIM2-7挂在APB1总线上,时基也是36*2=72MHZ
溢出条件:增计数:CNT=ARR
减计数:CNT=0
增减计数:CNT=ARR-1 CNT=1
工作流程:
二、基本定时器
2.1 定时器简述:TIM6、7
16位递增计数0-65535
16位预分频器1-65536
可触发DAC
溢出时可产生中断/DMA请求
2.2相关寄存器了解
ARPE:会使用在两次中断时间不同的情况,可以缓冲更新ARR寄存器的值。
CEN:使能计数器
UIE:使能定时器中断
UIF:产生中断后硬件置1,软件写1清除
CNT:计数器实时数值
2.2定时器溢出公式
如:一个500ms中断任务:Ft=72Mhz,为了好算,将PSC+1=7200,也就是100us记一次数,那么ARR+1=5000,即ARR=4999.,PSC=7199
这两个数是初始化定时器的两个参数
2.3定时器软件设置
2.3.1 配置过程
- HAL_TIM_Base_Init(TIM_HandleTypeDef *htim);
该函数型参是一个结构体,主要关注该结构体中两个结构体类型变量
TIM_TypeDef *Instance; //定义基地址
TIM_Base_InitTypeDef Init;定时器初始化结构体
typedef struct
{
uint32_t Prescaler; //预分频系数 基本定时器
uint32_t CounterMode; //计数模式
uint32_t Period; //自动重装载值 基本定时器
uint32_t ClockDivision; //时钟分频因子
uint32_t RepetitionCounter; //重复计数器值
uint32_t AutoReloadPreload; //重装载使能 基本定时器
} TIM_Base_InitTypeDef;
2.HAL_StatusTypeDef HAL_TIM_Base_Start_IT(TIM_HandleTypeDef *htim)
2.3.2 软件
使用定时器6定时500ms的任务,在中断翻转LED0
TIM_HandleTypeDef g_timx_handle;
//定时器中断初始化函数
void btim_timx_int_init(uint16_t arr, uint16_t psc)
{
g_timx_handle.Instance = TIM6; /* 通用定时器X */
g_timx_handle.Init.Prescaler = psc; /* 设置预分频系数 */
g_timx_handle.Init.Period = arr; /* 自动装载值 */
HAL_TIM_Base_Init(&g_timx_handle);
HAL_TIM_Base_Start_IT(&g_timx_handle); /* 使能定时器x及其更新中断 */
}
//定时器基础MSP初始化函数
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef *htim)
{
if (htim->Instance == TIM6)//判断中断
{
__HAL_RCC_TIM6_CLK_ENABLE(); /* 使能TIM时钟 */
HAL_NVIC_SetPriority(TIM6_IRQn, 1, 3); /* 抢占1,子优先级3,组2 */
HAL_NVIC_EnableIRQ(TIM6_IRQn); /* 开启ITM3中断 */
}
}
/* 定时器6中断服务函数 */
void TIM6_IRQHandler(void)
{
HAL_TIM_IRQHandler(&g_timx_handle);
}
/* 定时器溢出中断中断回调函数 */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if (htim->Instance == TIM6)
{
HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_5);
}
}
//最后在主函数中调用btim_timx_int_init()函数设置定时时间
btim_timx_int_init(4999,7199);
三、通用定时器
3.1定时器简介:TIM2、3、4、5
16位递增、减、中心对称0-65535
16位预分频
可触发DAC、ADC
更新事件、触发事件、捕获事件后可产生中断、DMA
4个独立通道:单脉冲、PWM、输入捕获、输出比较;可实现定时器之间级联;支持编码器和霍尔传感器电路
3.1.1 时钟源
STM32 F1系列的通用定时器有四个时钟源:
①:内部时钟,来自APB总线的时钟
②:外部时钟模式①:外部输入引脚CH1或者CH2(单边沿或者双边沿检测)
③:外部时钟模式②:外部触发ETR引脚
④:内部触发输入:ITR0~3,即来自其他定时器级联
设置方法:寄存器
3.2 通用定时器输出PWM
3.2.1 寄存器及原理分析
阴影部分为输入,不看
3.2.2 软件配置步骤
在PWM模式中,配置通道只配置前面三个
HAL_TIM_Base_Init();//初始化定时器的基本参数,基地址,计数模式,分频和重装载值
HAL_TIM_PWM_ConfigChannel();//配置PWM模式,比较值以及输出极性等
HAL_TIM_PWM_Start();//启动PWM
HAL_TIM_PWM_MspInit();//需要初始化中断,使能定时器时钟,以及GPIO也在此初始化
__HAL_TIM_SET_COMPARE();//设置变量修改占空比
__HAL_TIM_ENABLE_OCxPRELOAD();//修改预装载值使能
3.2.3、软件
输出TIM3使得PB5以2KHZ的频率翻转的任务
有效电平通过TIMx_CCER CC1P位设置 0为高电平有效
注:1.在原理图上并没有看见PB5与定时器的复用有关,查阅数据手册后发现有IO口重定义
/*
该函数首先初始化HAL_TIM_PWM_Init();定时器基地址/分频/重装载值/计数模式
*/
void gtim_timx_pwm_chy_init(uint16_t arr, uint16_t psc)
{
TIM_OC_InitTypeDef timx_oc_pwm_chy;
g_timx_pwm_chy_handle.Instance = TIM3;
g_timx_pwm_chy_handle.Init.Prescaler = psc;
g_timx_pwm_chy_handle.Init.Period = arr;
g_timx_pwm_chy_handle.Init.CounterMode = TIM_COUNTERMODE_UP;
HAL_TIM_PWM_Init(&g_timx_pwm_chy_handle);
timx_oc_pwm_chy.OCMode = TIM_OCMODE_PWM1;
timx_oc_pwm_chy.Pulse = arr / 2;
timx_oc_pwm_chy.OCPolarity = TIM_OCPOLARITY_LOW;
HAL_TIM_PWM_ConfigChannel(&g_timx_pwm_chy_handle, &timx_oc_pwm_chy, TIM_CHANNEL_2);
HAL_TIM_PWM_Start(&g_timx_pwm_chy_handle, TIM_CHANNEL_2);
}
/*
由于需要用定时器通道输出,需要对其通道进行配置,首先打开输出通道的时钟,在RCC.h中
如果需要重定义的话,需要打开重定义的时钟,在gpioex.h里,然后选择重定义的宏
*/
void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef *htim)
{
if(htim->Instance == TIM3)
{
GPIO_InitTypeDef gpio_init_struct;
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_TIM3_CLK_ENABLE();
gpio_init_struct.Pin = GPIO_PIN_5;
gpio_init_struct.Mode = GPIO_MODE_AF_PP; /* 推挽复用 */
gpio_init_struct.Pull = GPIO_PULLUP; /* 上拉 */
gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH; /* 高速 */
HAL_GPIO_Init(GPIOB, &gpio_init_struct);
__HAL_RCC_AFIO_CLK_ENABLE();
__HAL_AFIO_REMAP_TIM3_PARTIAL();
}
}
__HAL_TIM_ENABLE_OCxPRELOAD();//修改预装载值使能 该函数怎么用
四、高级定时器
4.1定时器简介TIM1、8
定时器的基本功能兼容通用定时器,增加的功能有死区配置(DTG)和刹车功能(TIMxBKIN)、带有重复计数器(溢出后减1,减到0再溢出产生更新中断)。有1、2、3通道带互补输出,通道4不带互补输出。
高级定时器有输出使能开关MOE位
4.2 可输出指定个数的 PWM
使用重复计数器,达到N-1个RCR中进入中断关闭计数器
4.2.1 配置步骤
typedef struct
{
uint32_t OCMode; /* 输出比较模式选择 */
uint32_t Pulse; /* 设置比较值 */
uint32_t OCPolarity; /* 设置输出比较极性 */
uint32_t OCNPolarity; /* 设置互补输出比较极性 */
uint32_t OCFastMode; /* 使能或失能输出比较快速模式 */
uint32_t OCIdleState; /* 空闲状态下OC1输出 */
uint32_t OCNIdleState; /* 空闲状态下OC1N输出 */
} TIM_OC_InitTypeDef;
OCMode=PWM1,PWM模式1 有效电平在计数值之下
typedef struct
{
uint32_t OffStateRunMode; /* 运行模式下的关闭状态选择 */
uint32_t OffStateIDLEMode; /* 空闲模式下的关闭状态选择 */
uint32_t LockLevel; /* 寄存器锁定设置 */
uint32_t DeadTime; /* 死区时间设置 */
uint32_t BreakState; /* 是否使能刹车功能 */
uint32_t BreakPolarity; /* 刹车输入极性 */
uint32_t BreakFilter; /* 刹车输入滤波器(F1/F4系列没有) */
uint32_t AutomaticOutput; /* 自动恢复输出使能,即使能AOE位 */
} TIM_BreakDeadTimeConfigTypeDef;
4.2.2 软件配置
4.3 输出比较模式
该模式下输出占空比固定50,周期和频率由ARR决定,相位由CCRx决定
4.4 输出互补带死区的PWM波
4.4.1 原理
4.4.2死区时间计算
若选择CKD==0,即1分频
死区配置
若选择死区为2.5us,则
2500=(64+x)✖2✖1000/72 得到x=26,即DTG=0b10011010=0x9A
4.4.3 刹车功能
4.4.4 配置步骤
关键结构体
4.4.5 软件实现
- 使用定时器1产生三路频率为10Khz,占空比为50,死区低电平时间为3us,使能刹车功能
注:计数模式采用中心对齐模式
计算:PWM 频率 = TIMxCLK /( Prescaler + 1) /(Period+ 1)/ 2
PMW 占空比 = Pulse/(Period + 1)
设置PSC=71 ARR=49
pulse==arr/2
软件