STM32定时器详细教程
本文介绍了STM32定时器的基本原理与应用。STM32定时器分为基本定时器、通用定时器和高级控制定时器三类,分别适用于不同场景。文章详细讲解了定时器的时基单元结构、影子寄存器机制以及定时周期计算方法,并提供了HAL库配置基本定时器和PWM生成的代码示例。此外,还概述了输入捕获、输出比较等高级功能。STM32定时器在嵌入式系统中广泛应用于精确计时、波形生成和信号测量等任务。
STM32定时器
1. 引言
STM32微控制器以其丰富的外设和强大的性能,在嵌入式领域得到了广泛应用。其中,定时器作为其核心外设之一,在实现精确时间控制、波形生成、事件测量等方面发挥着不可替代的作用。本教程将深入探讨STM32定时器的分类、工作原理、主要寄存器配置以及常见应用,旨在帮助读者全面理解并熟练运用STM32定时器。
2. STM32定时器分类
STM32系列微控制器通常包含以下三类定时器:
- 基本定时器 (Basic Timers):如TIM6、TIM7。功能相对简单,主要用于产生时基,触发中断或DAC转换。它们不具备输入捕获、输出比较、PWM生成等高级功能。
- 通用定时器 (General-Purpose Timers):如TIM2、TIM3、TIM4、TIM5等。功能较为全面,除了基本定时器的功能外,还支持输入捕获、输出比较、PWM生成、单脉冲模式等,适用于各种通用定时需求。
- 高级控制定时器 (Advanced-Control Timers):如TIM1、TIM8。功能最为强大,在通用定时器的基础上,增加了重复计数器、死区生成、互补输出、刹车输入等高级特性,特别适用于电机控制、电源管理等需要高精度和复杂波形输出的应用。
3. 定时器工作原理与核心寄存器
STM32定时器的核心是一个可编程的计数器,通过对时钟信号进行计数来实现定时功能。其基本工作原理和主要寄存器如下:
3.1. 时基单元
所有STM32定时器都包含一个时基单元,这是实现定时功能的基础。时基单元主要由以下几个核心寄存器组成:
- 计数器寄存器 (TIMx_CNT):这是一个16位或32位的计数器,它会根据定时器时钟(CK_CNT)进行计数。计数模式可以是向上计数、向下计数或向上/向下计数。
- 预分频器寄存器 (TIMx_PSC):这是一个16位的寄存器,用于对定时器时钟源(CK_INT)进行分频。实际分频系数为
PSC + 1。通过调整PSC的值,可以改变计数器的计数速度,从而控制定时周期。 - 自动重载寄存器 (TIMx_ARR):这是一个16位或32位的寄存器,用于设置计数器的上限值。当计数器(TIMx_CNT)的值达到ARR中设定的值时,会触发一个更新事件(Update Event, UEV),计数器可以清零或重新加载,从而完成一个定时周期。
- 重复计数器寄存器 (TIMx_RCR):仅存在于高级控制定时器中。它用于控制更新事件的生成频率。当计数器溢出时,并不会立即产生更新事件,而是先使RCR减1,直到RCR减到0时才产生更新事件。这在PWM输出中非常有用,可以控制PWM的周期数。
3.2. 影子寄存器
STM32定时器中的一些重要寄存器(如ARR、PSC)具有“影子寄存器”机制。这意味着我们对这些寄存器进行写入操作时,实际上是写入到其“预装载寄存器”(Preload Register,也称为本体寄存器),而不是直接写入到实际工作的“影子寄存器”。只有在特定事件(如更新事件UEV)发生时,预装载寄存器中的值才会被传输到影子寄存器中,从而生效。
这种机制的目的是为了防止在定时器运行过程中,由于修改寄存器值而导致的不确定性或毛刺。例如,在PWM输出过程中,如果直接修改ARR或PSC,可能会导致PWM波形出现异常。通过影子寄存器,可以确保在当前周期结束后,新的配置才会在下一个周期开始时生效,从而保证波形的平滑过渡。
3.3. 定时周期计算
定时器的中断周期(或溢出时间)可以通过以下公式计算:
中断周期 = (ARR + 1) * (PSC + 1) / 定时器时钟频率
其中:
定时器时钟频率:通常是APB1或APB2总线时钟经过倍频后的频率。PSC:预分频器寄存器的值。ARR:自动重载寄存器(周期)的值。
例如,如果定时器时钟频率为72MHz,PSC设置为7199,ARR设置为4999,则中断周期为:
(4999 + 1) * (7199 + 1) / 72,000,000 = 5000 * 7200 / 72,000,000 = 36,000,000 / 72,000,000 = 0.5 秒
这意味着每0.5秒会产生一次定时器中断。
3.4. 其他重要寄存器
- 控制寄存器1 (TIMx_CR1):用于配置定时器的工作模式,如计数器使能、计数方向、时钟分频等。
- 事件生成寄存器 (TIMx_EGR):通过写入特定位,可以软件触发更新事件(UEV),强制将预装载寄存器中的值传输到影子寄存器。
- DMA/中断使能寄存器 (TIMx_DIER):用于使能或禁用定时器的各种中断和DMA请求,如更新中断、捕获/比较中断等。
4. 基本定时器配置示例 (HAL库)
以STM32 HAL库为例,配置一个基本定时器(如TIM6)实现定时中断的步骤如下:
- 开启定时器时钟:
__HAL_RCC_TIM6_CLK_ENABLE(); - 配置时基单元:
TIM_HandleTypeDef htim6; htim6.Instance = TIM6; htim6.Init.Prescaler = 7199; // 预分频器,例如,如果时钟为72MHz,分频后为10KHz htim6.Init.Period = 4999; // 自动重载值,例如,配合预分频器实现0.5秒中断 htim6.Init.CounterMode = TIM_COUNTERMODE_UP; // 向上计数模式 htim6.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; // 时钟不分频 HAL_TIM_Base_Init(&htim6); - 配置NVIC中断:
HAL_NVIC_SetPriority(TIM6_DAC_IRQn, 0, 0); // 设置中断优先级 HAL_NVIC_EnableIRQ(TIM6_DAC_IRQn); // 使能中断 - 启动定时器并使能中断:
HAL_TIM_Base_Start_IT(&htim6); - 编写中断回调函数:
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { if(htim->Instance == TIM6) { // 在这里编写定时器中断服务代码,例如翻转LED } }
5. 通用定时器与高级定时器功能概述
在基本定时器的基础上,通用定时器和高级定时器提供了更丰富的功能:
5.1. 输入捕获 (Input Capture)
输入捕获功能用于测量外部信号的脉冲宽度、频率或周期。当外部信号的边沿(上升沿、下降沿或双边沿)发生时,定时器会将当前计数器的值锁存到捕获/比较寄存器(TIMx_CCR)中,并触发中断。通过两次捕获事件之间计数器值的差值,可以计算出信号的周期或脉宽。
5.2. 输出比较 (Output Compare)
输出比较功能用于在特定时间点产生输出事件,可以控制GPIO引脚电平翻转,或生成单脉冲。通过将计数器的值与捕获/比较寄存器(TIMx_CCR)中的预设值进行比较,当两者相等时,会触发输出事件。
5.3. PWM波形生成 (PWM Generation)
PWM(Pulse Width Modulation,脉冲宽度调制)是利用定时器的输出比较功能实现的。通过周期性地改变输出方波的占空比,可以模拟模拟信号的输出。广泛应用于电机调速、LED亮度控制、D/A转换等。通用定时器和高级定时器都可以生成PWM波形。
HAL库PWM生成示例:
以下是一个使用STM32 HAL库配置通用定时器(如TIM3)生成PWM波的示例:
- GPIO和定时器时钟使能:
__HAL_RCC_GPIOC_CLK_ENABLE(); // 假设PWM输出引脚为PC6 (TIM3_CH1) __HAL_RCC_TIM3_CLK_ENABLE(); - 配置GPIO为复用推挽输出:
GPIO_InitTypeDef GPIO_InitStruct = {0}; GPIO_InitStruct.Pin = GPIO_PIN_6; // PC6 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; // 复用推挽输出 GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; GPIO_InitStruct.Alternate = GPIO_AF2_TIM3; // PC6复用为TIM3_CH1 HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); - 配置定时器时基单元:
TIM_HandleTypeDef htim3; htim3.Instance = TIM3; htim3.Init.Prescaler = 71; // 预分频器,例如,如果时钟为72MHz,分频后为1MHz htim3.Init.Period = 999; // 自动重载值,例如,周期为1ms (1MHz / (999+1) = 1KHz) htim3.Init.CounterMode = TIM_COUNTERMODE_UP; htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; HAL_TIM_Base_Init(&htim3); - 配置PWM输出通道:
TIM_OC_InitTypeDef sConfigOC = {0}; sConfigOC.OCMode = TIM_OCMODE_PWM1; // PWM模式1 sConfigOC.Pulse = 499; // 占空比,例如,50%占空比 (499+1)/(999+1) = 0.5 sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; // 输出极性高 sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_1); - 启动PWM输出:
HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1);
通过修改 sConfigOC.Pulse 的值,可以动态调整PWM的占空比,从而实现调光、调速等功能。
5.4. 编码器接口 (Encoder Interface)
高级定时器通常支持编码器接口模式,可以直接解码正交编码器信号。通过监测编码器A、B相信号的相位差和脉冲数,定时器可以自动更新计数器的值,从而精确测量旋转位置和速度。
5.5. 死区生成与互补输出 (Dead-Time Generation & Complementary Outputs)
这是高级控制定时器特有的功能,主要用于电机控制。在驱动半桥或全桥电路时,为了避免上下桥臂同时导通造成短路(直通),需要在开关管关断和导通之间插入一个短暂的延时,即死区时间。高级定时器可以自动生成带有死区时间的互补PWM输出,简化了电机驱动的设计。
5.6. 刹车输入 (Break Input)
高级控制定时器还支持刹车输入功能。当外部刹车信号有效时,定时器可以立即停止PWM输出,并将所有输出引脚置于预设的安全状态,用于紧急停机或故障保护。
openvela 操作系统专为 AIoT 领域量身定制,以轻量化、标准兼容、安全性和高度可扩展性为核心特点。openvela 以其卓越的技术优势,已成为众多物联网设备和 AI 硬件的技术首选,涵盖了智能手表、运动手环、智能音箱、耳机、智能家居设备以及机器人等多个领域。
更多推荐
所有评论(0)