STM32教程-----定时器的使用
OC(Output Compare) : 输出比较输出比较可以通过比较CNT和CRR寄存器值的关系,来对输出电平进行置0、置1或者翻转的操作,用于输出一定频率和占空比的PWM波形每个高级定时器和调用定时器都用4个输出比较通道高级定时器的前三个通道额外拥有死区生成和互补输出的功能。
·
一、STM32定时器简介
(一)分类

常规定时器:
- 基本定时器(TIM6和TIM7):拥有定时中断、主模式触发DAC的功能
- 通用定时器(TIM2到TIM7,TIM9到TIM14):拥有基本定时器全部功能,并额外具有内外时钟源选择、输入捕获、输出比较、编码器接口、主从触发模式等功能。
- 高级定时器(TIM1和TIM8):拥有通用定时器全部功能,并额外具有重复计时器、死区生成、互补输出、刹车输入等功能。
| 定时器种类 | 位数 | 计数器模式 | 产生DMA请求 | 捕获/比较通道 | 互补输出 | 特殊应用场景 |
|
高级定时器 (TIM1,TIM8) |
16 |
向上,向下 向上/向下 |
可以 | 4 | 有 | 带可编程死区互补输出 |
|
通用定时器 (TIM2,TIM5) |
32 |
向上,向下 向上/向下 |
可以 | 4 | 没有 |
定时计数、PWM输出、 输入捕获、输出比较 |
|
通用定时器 (TIM3,TIM4) |
16 |
向上,向下 向上/向下 |
可以 | 4 | 没有 |
定时计数、PWM输出、 输入捕获、输出比较 |
|
通用定时器 (TIM9~TIM14) |
16 |
向上 |
没有 | 2 | 没有 |
定时计数、PWM输出、 输入捕获、输出比较 |
|
基本定时器 (TIM6,TIM7) |
16 |
向上,向下 向上/向下 |
可以 | 0 | 没有 | 主要应用于驱动DAC |
(二 )各种定时器的结构框图
1、基本定时器

2、通用定时器

3、高级定时器

二、定时器定时中断
(一)定时器定时时序

- 计数器计数频率:CK_CNT = CK_PSC / (PSC+1)
- 计数器溢出频率:CK_CNT_OV = CK_CNT/( ARR+ 1) = CK_PSC/(PSC+1)/(ARR + 1)
- 计数器溢出时间:(PSC+1)(ARR + 1) / CK_PSC
(二)定时器中断基本结构
(三)配置流程
- 配置定时器基础工作参数:HAL_TIM_Base_Init()
- 定时器基础MSP初始化:HAL_TIM_Base_Msplnit() 配置NVIC、CLOCK等
- 使能更新中断并启动计数器:HAL_TIM_Base_Start_IT()
- 设置优先级,使能中断:HAL_NVIC_SetPriority(), HAL_NVIC_EnableIRQ()
- 编写中断服务函数:TIMx_IRQHandler()等 → HAL_TIM_IRQHandler()
- 编写定时器溢出回调函数:HAL_TIM_PeriodElapsedCallback()
(四)代码实现
TIM_HandleTypeDef htim2;
/*
计数器计数频率:CK_CNT = CK_PSC / (PSC+1)
计数器溢出频率:CK_CNT_OV = CK_CNT/( ARR+ 1)
= CK_PSC/(PSC+1)/(ARR + 1)
计数器溢出时间:(PSC+1)(ARR + 1) / CK_PSC
*/
//定时器中断初始化
void Timer_Tnit(u16 arr, u16 psc){
htim2.Instance = TIM2;
htim2.Init.Period = arr; //自动重装载值ARR
htim2.Init.Prescaler = psc; //预分频值PSC
htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; //时钟分频因子
htim2.Init.CounterMode = TIM_COUNTERMODE_UP; //向上计数
if(HAL_TIM_Base_Init(&htim2) != HAL_OK){
Error_Handler();
}
HAL_TIM_Base_Start_IT(&htim2); //开启定时器中断
}
//定时器基础MSP回调初始化函数
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef *htim){
if(htim->Instance == TIM2){
//使能定时器7的时钟
__HAL_RCC_TIM2_CLK_ENABLE();
HAL_NVIC_SetPriority(TIM2_IRQn,2,0);
HAL_NVIC_EnableIRQ(TIM2_IRQn);
}
}
//定时器中断服务函数
void TIM2_IRQHandler(void){
HAL_TIM_IRQHandler(&htim7);
}
//定时器中断回调函数(溢出中断)
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) {
if(htim->Instance == TIM2){
LED1_TOGGLE();
}
}
三、输出比较(PWM输出)
(一)输出比较介绍
- OC(Output Compare) : 输出比较
- 输出比较可以通过比较CNT和CRR寄存器值的关系,来对输出电平进行置0、置1或者翻转的操作,用于输出一定频率和占空比的PWM波形
- 每个高级定时器和调用定时器都用4个输出比较通道
- 高级定时器的前三个通道额外拥有死区生成和互补输出的功能
(二)STM32输出比较模块

输出比较模式(输出模式控制器逻辑):
| 模式[OC1M] | 描述 |
| 冻结[000] |
CNT=CCR时,REF保持为原状态 |
| 匹配时置有效电平[001] |
CNT=CCR时,REF置有效电平 |
| 匹配时置无效电平[010] | CNT=CCR时,REF置无效电平 |
| 匹配时电平翻转[011] | CNT=CCR时,REF电平翻转 |
| 强制为无效电平[100] | CNT与CCR无效,REF强制为无效电平 |
| 强制为有效电平[101] | CNT与CCR无效,REF强制为有效电平 |
| PWM模式1[110] |
向上计数:CNT<CCR时,REF置有效电平,CNT>=CCR时,REF置无效电平 向下计数:CNT>CCR时,REF置无效电平,CNT<=CCR时,REF置有效电平 |
| PWM模式2[111] |
向上计数::CNT<CCR时,REF置无效电平,CNT>=CCR时,REF置有效电平 向下计数::CNT>CCR时,REF置有效电平,CNT<=CCR时,REF置无效电平 |
(三)PWM基本结构

- PWM频率:Freq = CK_PSC /(PSC + 1) / (ARR + 1)
- PWM占空比: Duty = CRR / (ARR + 1)
- PWM分辨率:Reso = 1 / (ARR + 1)
(四)配置流程
- 配置定时器基础工作参数:HAL_TIME_PWM_Init()
- 定时器PWM输出MSP初始化:HAL_TIM_PWM_MspInit() 配置NVIC、CLOCK、GPIO等
- 配置PWM模式、比较值:HAL_TIM_PWM_ConfigChannel()
- 使能输出并启动计数器:HAL_WIN_PWM_Start()
- 修改比较值控制占空比(可选):__HAL_TIM_PWM_COMPARE()
- 是能通道预装载值(可选):__HAL_TIME_PWM_OSxPRELOAD()
(五)代码实现
TIM_HandleTypeDef htim3;
void MYPWM_Init(u16 arr, u16 psc)
{
// 初始化定时器3
//配置定时器基础工作参数
htim3.Instance = TIM3;
htim3.Init.Prescaler = psc; // PSC
htim3.Init.CounterMode = TIM_COUNTERMODE_UP; //向上计数模式
htim3.Init.Period = arr; // ARR值,
htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
HAL_TIM_PWM_Init(&htim3);
// 配置PWM通道1
sConfigOC.OCMode = TIM_OCMODE_PWM1; //PWM模式1
sConfigOC.Pulse = 500; // 占空比 = 500/1000 = 50%
sConfigOC.OCPolarity = TIM_OCPOLARITY_LOW; //低电平有效
HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_1);
// 启动PWM
HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1);
}
//PWM初始化回调函数
void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef *htim){
if(htim->Instance == TIM3){ //将PA6复用为定时器3通道1
GPIO_InitTypeDef GPIO_InitStruct = {0};
__HAL_RCC_TIM3_CLK_ENABLE(); //使能定时器3
__HAL_RCC_GPIOA_CLK_ENABLE(); //开启GPIOA时钟
GPIO_InitStruct.Pin=GPIO_PIN_6; //PA6
GPIO_InitStruct.Mode=GPIO_MODE_AF_PP; //复用推挽输出
GPIO_InitStruct.Pull=GPIO_NOPULL; //不上下拉
GPIO_InitStruct.Sped=GPIO_SPEED_FREQ_LOW; //高速
HAL_GPIO_Init(GPIOF,&GPIO_InitStruct);
}
}
//修改占空比的值:修改比较值CRR
void ChangeDuty(float per){
u32 compare = 0;
uint32_t arr = __HAL_TIM_GET_AUTORELOAD(&htim3); // 获取ARR值
compare = (uint32_t)((float)arr * per); // 计算CCR值
TIM14->CCR1=compare;
}更多推荐



所有评论(0)