打印
[STM32F1]

stm32 高级定时器使用

[复制链接]
334|19
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主

高级定时器简介


使用特权

评论回复
沙发
一路向北lm|  楼主 | 2024-11-27 16:33 | 只看该作者
TIM2 和 TIM5 计数器是 32 位的,其他的都是 16 位的。
通用定时器和高级定时器其实也就是在基本定时器的基础上,添加了一些其他功能,如:输入
捕获、输出比较、输出 PWM 和单脉冲模式等,其特性有一些的差异,但是基本原理都一样。
互补输出则是高级定时器特有的功能

使用特权

评论回复
板凳
一路向北lm|  楼主 | 2024-11-27 16:34 | 只看该作者
高级定时器的框图

使用特权

评论回复
地板
一路向北lm|  楼主 | 2024-11-27 16:35 | 只看该作者
高级定时器时钟可由下列的时钟源提供:
1)内部时钟 (CK_INT)
2)外部时钟模式 1:外部输入引脚 (TIx),x=1,2,3,4
3)外部时钟模式 2:外部触发输入 (ETR)
4)内部触发输入 (ITRx):使用一个定时器作为另一定时器的预分频器

使用特权

评论回复
5
一路向北lm|  楼主 | 2024-11-27 16:35 | 只看该作者
控制器
控制器包括:从模式控制器、编码器接口和触发控制器(TRGO)。从模式控制器可以控
制计数器复位、启动、递增/递减、计数。编码器接口针对编码器计数。触发控制器用来提供
触发信号给别的外设,比如为其他定时器提供时钟或者为 DAC/ADC 的触发转换提供信号。

使用特权

评论回复
6
一路向北lm|  楼主 | 2024-11-27 16:36 | 只看该作者
时基单元
高级定时器时基单元包括:计数器寄存器(TIMx_CNT)、预分频器寄存器(TIMx_PSC)、自动重载寄存器(TIMx_ARR)、重复计数器寄存器(TIMx_RCR)。其中,前 3 个寄存器的内容和基本定时器是基本一样的,大家可以参考基本定时器的介绍。

使用特权

评论回复
7
一路向北lm|  楼主 | 2024-11-27 16:38 | 只看该作者
高级定时器的计数模式有三种:递增计数模式、递减计数模式和中心对齐模式。
递增计数模式在讲解基本定时器的时候已经讲过了,那么对应到递减计数模式就很好理
解了。就是来了一个计数脉冲,计数器就减 1,直到计数器寄存器的值减到 0,减到 0 时定时
器溢出,由于是递减计数,故而称为定时器下溢,定时器溢出就会伴随着更新事件的发生。然
后计数器又从自动重载寄存器影子寄存器的值开始继续递减计数,如此循环。最后是中心对
齐模式,字面上不太好理解。该模式下,计数器先从 0 开始递增计数,直到计数器的值等于自
动重载寄存器影子寄存器的值减 1 时,定时器上溢,同时生成更新事件,然后从自动重载寄
存器影子寄存器的值开始递减计算,直到计数值等于 1 时,定时器下溢,同时生成更新事件,
然后又从 0 开始递增计数,依此循环。每次定时器上溢或下溢都会生成更新事件。计数器的
计数模式的设置请参考 TIMx_CR1 寄存器的位 CMS 和位 DIR。
下面通过一张图给大家展示定时器工作在不同计数模式下,更新事件发生的情况。

使用特权

评论回复
8
一路向北lm|  楼主 | 2024-11-27 17:37 | 只看该作者
输出比较包括:4 个输出比较通道、3 个互补通道、死区发生器以及输出控制器,用于输
出比较模式或 PWM 输出模式。
高级定时器输出比较部分和通用定时器相比,多了带死区控制的互补输出功能。图 4.3.1.1
第⑥部分的 TIMx_CH1N、TIMx_CH2N 和 TIMx_CH3N 分别是定时器通道 1、通道 2 和通道
3 的互补输出通道,通道 4 是没有互补输出通道的。DTG 是死区发生器,死区时间由 DTG[7:0]
位来配置。如果不使用互补通道和死区时间控制,那么高级定时器 TIM1 和 TIM8 和通用定时
器的输出比较部分使用方法基本一样,只是要注意 MOE 位得置 1 定时器才能输出。

使用特权

评论回复
9
一路向北lm|  楼主 | 2024-11-27 17:41 | 只看该作者
断路功能也称刹车功能,一般用于电机控制的刹车。F4 系列有一个断路通道,断路源可
以是刹车输入引脚(TIMx_BKIN),也可以是一个时钟失败事件。时钟失败事件由复位时钟控
制器中的时钟安全系统产生。系统复位后,断路功能默认被禁止,MOE 位为低。
使能断路功能的方法:将 TIMx_BDTR 的位 BKE 置 1。断路输入引脚 TIMx_BKIN 的输
入有效电平可通过 TIMx_BDTR 寄存器的位 BKP 设置。
使能刹车功能后:由 TIMx_BDTR 的 MOE、OSSI、OSSR 位,TIMx_CR2 的 OISx、OISxN
位,TIMx_CCER 的 CCxE、CCxNE 位控制 OCx 和 OCxN 输出状态。无论何时,OCx 和 OCxN
输出都不能同时处在有效电平。

使用特权

评论回复
10
一路向北lm|  楼主 | 2024-11-27 17:51 | 只看该作者
1.输出pwm波形
高级定时器的初始化函数
void atim_timx_int_init(uint16_t arr, uint16_t psc)
{
ATIM_TIMX_INT_CLK_ENABLE() /* 使能 TIMx 时钟 */

g_timx_handle.Instance = ATIM_TIMX_INT; /* 定时器 x */
g_timx_handle.Init.Prescaler = psc; /* 预分频系数 */
g_timx_handle.Init.CounterMode = TIM_COUNTERMODE_UP; /* 递增计数模式 */
g_timx_handle.Init.Period = arr; /* 自动装载值 */
HAL_TIM_Base_Init(&g_timx_handle);
/* 设置中断优先级,抢占优先级 1,子优先级 3 */
HAL_NVIC_SetPriority(ATIM_TIMX_INT_IRQn, 1, 3);
HAL_NVIC_EnableIRQ(ATIM_TIMX_INT_IRQn); /* 开启 ITMx 中断 */
HAL_TIM_Base_Start_IT(&g_timx_handle); /* 使能定时器 x 和定时器 x 更新中断 */
}

使用特权

评论回复
11
一路向北lm|  楼主 | 2024-11-27 17:52 | 只看该作者
这里配置的参数和基本定时器中断实验的是一样的,只是这里没有使用到 HAL 库的
HAL_TIM_Base_MspInit 函 数 来 存 放 NVIC 和 使 能 时 钟 的 代 码 , 而 是 全 部 存 放 到
atim_timx_int_init 函数里。在一个项目中,用到多个定时器时,建议大家使用这种方式来处理
代码,这样方便代码的管理。

使用特权

评论回复
12
一路向北lm|  楼主 | 2024-11-27 17:53 | 只看该作者
定时器中断服务函数,其定义如下
void GTIM_TIMX_INT_IRQHandler(void)
{
/* 以下代码没有使用定时器 HAL 库共用处理函数来处理,而是直接通过判断中断标志位的方式 */
if(__HAL_TIM_GET_FLAG(&g_timx_handle, TIM_FLAG_UPDATE) != RESET)
{
LED1_TOGGLE();
/* 清除定时器溢出中断标志位 */
__HAL_TIM_CLEAR_IT(&g_timx_handle, TIM_IT_UPDATE);
}
}

使用特权

评论回复
13
一路向北lm|  楼主 | 2024-11-27 17:54 | 只看该作者
高级定时器 PWM 输出
脉冲宽度调制(PWM),是英文“Pulse Width Modulation”的缩写,简称脉宽调制,是利用
微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术。我们可以让定时器产生
PWM,在计数器频率固定时,PWM 频率或者周期由自动重载寄存器(TIMx_ARR)的值决定,
其占空比由捕获/比较寄存器(TIMx_CCRx)的值决定。PWM 产生原理示意图如下图所示

使用特权

评论回复
14
一路向北lm|  楼主 | 2024-11-27 17:55 | 只看该作者
定时器工作在递增计数模式,纵轴是计数器的计数值 CNT,横轴表示时。当
CNT<CCRx 时,IO 输出低电平(逻辑 0);当 CNT>=CCRx 时,IO 输出高电平(逻辑 1);当
CNT=ARR 时,定时器溢出,CNT 的值被清零,然后继续递增,依次循环。在这个循环中,改
变 CCRx 的值,就可以改变 PWM 的占空比,改变 ARR 的值,就可以改变 PWM 的频率,这
就是 PWM 输出的原理

使用特权

评论回复
15
一路向北lm|  楼主 | 2024-11-27 17:57 | 只看该作者
定时器产生 PWM 的方式有许多种,下面我们以边沿对齐模式(即递增计数模式/递减计
数模式)为例,PWM 模式 1 或者 PWM 模式 2 产生 PWM 的示意图

使用特权

评论回复
16
一路向北lm|  楼主 | 2024-11-27 17:58 | 只看该作者
高级定时器 PWM 输出初始化函数
void atim_timx_pwm_chy_init(uint16_t arr, uint16_t psc)
{
g_timx_pwm_chy_handle.Instance = ATIM_TIMX_PWM; /* 定时器 x */
g_timx_pwm_chy_handle.Init.Prescaler = psc; /* 定时器分频 */
g_timx_pwm_chy_handle.Init.CounterMode = TIM_COUNTERMODE_UP;/* 向上计数 */
g_timx_pwm_chy_handle.Init.Period = arr; /* 自动重装载值 */
g_timx_pwm_chy_handle.Init.RepetitionCounter = 0; /* 不重复计数*/
HAL_TIM_PWM_Init(&g_timx_pwm_chy_handle); /* 初始化 PWM */
g_timx_oc_pwm_chy.OCMode = TIM_OCMODE_PWM2; /* 模式选择 PWM2 */
/* 设置比较值,此值用来确定占空比 ,默认比较值为自动重装载值的一半,即占空比为 50%*/
g_timx_oc_pwm_chy.Pulse = ( arr + 1 ) / 2;
g_timx_oc_pwm_chy.OCPolarity = TIM_OCPOLARITY_HIGH;/* 输出比较极性为高 */
HAL_TIM_PWM_ConfigChannel(&g_timx_pwm_chy_handle, & g_timx_oc_pwm_chy,
ATIM_TIMX_PWM_CHY); /* 配置 TIMx 通道 y */
HAL_TIM_PWM_Start(&g_timx_pwm_chy_handle,
ATIM_TIMX_PWM_CHY); /* 开启对应 PWM 通道 */
}



使用特权

评论回复
17
一路向北lm|  楼主 | 2024-11-27 17:59 | 只看该作者
PWM 的 MSP 初始化回调函数
void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef *htim)
{
if (htim->Instance == ATIM_TIMX_PWM)
{
GPIO_InitTypeDef gpio_init_struct;
ATIM_TIMX_PWM_CHY_CLK_ENABLE(); /* 开启 IO 时钟 */
ATIM_TIMX_PWM_CHY_GPIO_CLK_ENABLE(); /* 开启定时器 X 时钟 */
gpio_init_struct.Pin = ATIM_TIMX_PWM_CHY_GPIO_PIN; /* 通道 y 的 GPIO 口 */
gpio_init_struct.Mode = GPIO_MODE_AF_PP; /* 复用推挽输出 */
gpio_init_struct.Pull = GPIO_PULLUP; /* 上拉 */
gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH; /* 高速 */
gpio_init_struct.Alternate = ATIM_TIMX_PWM_CHY_GPIO_AF; /* 端口复用 */
HAL_GPIO_Init(ATIM_TIMX_PWM_CHY_GPIO_PORT, &gpio_init_struct);
}
}



使用特权

评论回复
18
一路向北lm|  楼主 | 2024-11-27 18:00 | 只看该作者
main.c 里面编写如下代码
int main(void)
{
uint16_t ledrpwmval = 0;
uint8_t dir = 1;
HAL_Init(); /* 初始化 HAL 库 */
sys_stm32_clock_init(336, 8, 2, 7); /* 设置时钟, 168Mhz */
delay_init(168); /* 延时初始化 */
usart_init(115200); /* 串口初始化为 115200 */
led_init(); /* 初始化 LED */
/* 168M/168=1M 的计数频率,自动重装载为 500,那么 PWM 频率为 1M/500=2kHz */
gtim_timx_pwm_chy_init(500 - 1, 168 - 1);
while (1)
{
delay_ms(10);
if (dir)ledrpwmval++; /* dir==1 ledrpwmval 递增 */
else ledrpwmval--; /* dir==0 ledrpwmval 递减 */
if (ledrpwmval > 300)dir = 0; /* ledrpwmval 到达 300 后,方向为递减 */
if (ledrpwmval == 0)dir = 1; /* ledrpwmval 递减到 0 后,方向改为递增 */
/* 修改比较值控制占空比 */
__HAL_TIM_SET_COMPARE(&g_timx_pwm_chy_handle, GTIM_TIMX_PWM_CHY,
ledrpwmval);
}
}



使用特权

评论回复
19
一路向北lm|  楼主 | 2024-11-27 18:01 | 只看该作者

这里把输出比较极性低和输出比较极性高的 PWM 波形都显示出来了。本实验默认设置
PWM 模式 2、输出比较极性高,当 CCR1 寄存器的值设置为 200 时,对应的 PWM 波形如上
图黄色的波形图。如果把输出比较极性设置为低,对应的波形图就是绿色的波形图了

使用特权

评论回复
20
飘向北方| | 2024-11-27 21:51 | 只看该作者
确保使用正确的库函数和寄存器地址。不同型号的 STM32 微控制器可能有不同的定时器结构和寄存器地址,因此在使用之前,请查阅相应的数据手册和参考手册。
注意定时器的时钟源和分频器的配置,以确保满足定时精度要求。
在配置定时器参数时,注意自动重装载寄存器和计数器的值,以防止溢出或错误触发中断。
在使用中断时,确保正确地配置中断优先级和中断服务程序(ISR),以避免潜在的冲突和错误处理。
在开发过程中,使用调试工具和调试器来监控定时器的状态和值,有助于发现和解决问题。
以上是使用 STM32 高级定时器的基本步骤和注意事项。具体的实现细节可能因不同的 STM32 型号和开发环境而有所不同,因此建议参考相关的开发文档和示例代码进行学习和实践。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

277

主题

3815

帖子

76

粉丝