52Hz——STM32单片机学习记录——定时器
1. 系统定时器
定位与作用
属于ARM Cortex-M内核标准组件,而非STM32外设。
核心功能是提供精确的时间基准,常用于:
操作系统(如FreeRTOS)的心跳时钟(Tick),用于任务调度。
精确延时(
HAL_Delay()
底层依赖它)。测量代码执行时间。
优先级高(可设置),中断响应快。
工作方式与过程
核心单元: 一个简单的24位递减计数器。
时钟源: 通常选择内核时钟(HCLK) 或 HCLK/8(通过SysTick控制与状态寄存器
SYST_CSR
的CLKSOURCE
位选择)。工作流程:
初始化: 程序设置重装载值寄存器
SYST_RVR
(确定计数周期) 和控制与状态寄存器SYST_CSR
(使能计数器、中断、选择时钟源)。计数: 计数器
SYST_CVR
从重装载值LOAD
开始,每个时钟周期减1。计数到0:
计数器自动重载
LOAD
值。状态寄存器
SYST_CSR
的COUNTFLAG
位置1。如果使能了中断 (
SYST_CSR
的TICKINT
位为1),则触发 SysTick 中断。中断服务程序 (ISR): 在中断服务程序中,软件可以执行需要的操作(如操作系统调度、更新延时计数等),并读取或清除
COUNTFLAG
(读取SYST_CSR
会自动清除该标志)。特点: 结构简单、精度高(依赖于内核时钟)、用途特定(核心系统时间基准)。
相关寄存器
有4个寄存器与SysTick有关。在core_cm3.h中可以看到有个类型定义的就是SysTick。
typedef struct
{
__IO uint32_t CTRL; /*!< Offset: 0x00 SysTick Control and Status Register */
__IO uint32_t LOAD; /*!< Offset: 0x04 SysTick Reload Value Register */
__IO uint32_t VAL; /*!< Offset: 0x08 SysTick Current Value Register */
__I uint32_t CALIB; /*!< Offset: 0x0C SysTick Calibration Register */
} SysTick_Type;
CTRL(SysTick控制和状态寄存器)
说明:关于CLKSOURCE位,当0时,时钟频率是AHB/8;当1时,时钟频率是AHB。
LOAD(SysTick重装载寄存器)
VAL(SysTick当前数值寄存器)
案例(每一毫秒触发一次中断)
uint16_t counter = 0;void SysTick_Init(void)
{//滴答定时器为内核功能,所以无需开启时钟SysTick->CTRL |= SysTick_CTRL_CLKSOURCE;SysTick->CTRL |= SysTick_CTRL_TICKINT; SysTick->LOAD = 72 * 1000 - 1;SysTick->VAL = 0;//配置中断NVIC_SetPriorityGrouping(3);NVIC_SetPriority(SysTick_IRQn,3);SysTick->CTRL |= SysTick_CTRL_ENABLE;
}void SysTick_Handler(){counter++;if(counter == 500){LED_Toggle(LED_1);counter=0;}
}
2. 基本定时器 (TIM6, TIM7)
定位与作用
STM32中最简单的定时器外设。
核心功能是提供基础的时基(Time Base) 和 DAC触发信号。
主要用于:
产生精确的定时中断。
为内置的数字模拟转换器(DAC) 提供触发信号,实现定时DAC输出更新。
驱动其他需要基础时钟的模块。
工作方式与过程
核心单元: 16位递增计数器、16位预分频器(PSC)、16位自动重装载寄存器(ARR)。
时钟源: 通常来自内部时钟(CK_INT),即APB1总线时钟(经过可能的倍频)。
工作流程:
初始化: 配置预分频器
TIMx_PSC
(决定计数时钟频率 fCK_CNT=fCK_PSC/(PSC+1)和自动重装载寄存器TIMx_ARR
(确定计数上限)。计数: 计数器
TIMx_CNT
从0开始,每个计数时钟周期(fCK_CNTfCK_CNT)加1。计数到ARR:
计数器自动归零(复位)。
状态寄存器
TIMx_SR
的更新中断标志位(UIF)置1。如果使能了更新中断 (
TIMx_DIER
的UIE
位为1),则触发更新中断。如果使能了DMA请求 (
TIMx_DIER
的UDE
位为1),则产生更新事件(UEV),可用于触发DMA传输(例如给DAC送数据)。如果配置为DAC触发源,此时会产生一个触发输出(TRGO) 信号给DAC。
中断服务程序 (ISR): 在更新中断服务程序中,软件执行需要的操作(如更新变量、翻转LED等),并手动清除UIF标志。
特点: 结构简单,只有时基功能,没有输入捕获/输出比较/PWM等高级功能,计数器只能递增。通常与DAC配合使用。
相关寄存器






案例
/*** 基本定时器:初始化 */
void TIM6_Init(void) {// 1. 开启时钟RCC->APB1ENR |= RCC_APB1ENR_TIM6EN;// 2. 配置定时器// 时基单位配置// !计算公式: (输入时钟频率:72000000 Hz) -> 定时器(36000000) -> (输出时钟频率 2Hz)// 预分频 : 16 ( 65535 )// !PSC寄存器的默认值为0,但是计算时不能为0,所以计算时会加一使用TIM6->PSC = 7200-1; // 7199// !自动重装载// 如果定时器只是单一执行,那么自动重装载可以直接使用的,但是如果是周期性循环执行,那么应该减去1使用TIM6->ARR = 5000-1; // 4999 // 0// 10 / ms// !产生更新事件,直接让影子寄存器起作用// !不能执行更新中断TIM6->CR1 |= TIM_CR1_URS;TIM6->EGR |= TIM_EGR_UG;// 3. 配置中断TIM6->DIER |= TIM_DIER_UIE;NVIC_SetPriorityGrouping(3);NVIC_SetPriority(TIM6_IRQn, 3);NVIC_EnableIRQ(TIM6_IRQn);// 4. 启动定时器TIM6->CR1 |= TIM_CR1_CEN;//LED_Toggle(LED_BLUE);
}
void TIM6_IRQHandler(void) {// 状态复位TIM6->SR &= ~TIM_SR_UIF;// if ( first_flg == 0 ) {// first_flg = 1;// } else {// LED_Toggle(LED_BLUE);// }LED_Toggle(LED_BLUE);
}
3.通用定时器 (TIM2, TIM3, TIM4, TIM5等)
定位与作用
STM32中数量最多、功能最丰富、应用最广泛的定时器。
在基本定时器时基功能的基础上,增加了输入捕获、输出比较、PWM生成、单脉冲输出、编码器接口等强大功能。
广泛应用于:
测量脉冲宽度、频率、占空比(输入捕获)。
产生精确的PWM波形控制电机、LED亮度等(输出比较/PWM)。
测量旋转编码器信号(编码器接口模式)。
产生单脉冲。
作为从模式定时器与其他定时器联动。
工作方式与过程(核心时基 + 扩展功能)
核心单元(时基部分): 与基本定时器类似(16位PSC、16位CNT、16位ARR),但功能更强:
计数方向: 可配置为递增、递减或中心对齐(先递增后递减/先递减后递增)(通过
TIMx_CR1
的DIR
和CMS
位控制)。影子寄存器: ARR、PSC等寄存器通常有影子寄存器(缓冲)。更新事件发生时,预装载值才从预装载寄存器(如
TIMx_ARR
)拷贝到影子寄存器(真正起作用的寄存器)。这保证了波形/定时的连续性,避免中间值更新导致波形畸变。扩展功能单元:
捕获/比较通道(通常4个,TIMx_CH1~CH4): 每个通道可独立配置为输入捕获或输出比较模式。
输入捕获:
过程: 当配置为输入捕获的通道引脚上检测到指定边沿(上升沿、下降沿或双边沿)时:
当前计数器值
TIMx_CNT
被锁存到对应的捕获/比较寄存器TIMx_CCRy
中。状态寄存器
TIMx_SR
的捕获/比较中断标志位(CCyIF)置1。如果使能了捕获中断 (
TIMx_DIER
的CCyIE
位为1),则触发捕获中断。如果使能了DMA请求 (
TIMx_DIER
的CCyDE
位为1),则产生捕获事件,触发DMA读取捕获值。用途: 通过测量连续两次捕获的
CCRy
值差,可计算脉冲宽度或周期。输出比较:
过程: 计数器
TIMx_CNT
不断与配置为输出比较模式的通道的捕获/比较寄存器TIMx_CCRy
中的值进行比较。
当两者匹配时:
根据配置的输出模式 (
TIMx_CCMRy
的OCyM
位),控制对应的输出引脚TIMx_CHy
的电平翻转、置高、置低或保持不变。状态寄存器
TIMx_SR
的捕获/比较中断标志位(CCyIF)置1。如果使能了比较中断 (
TIMx_DIER
的CCyIE
位为1),则触发比较中断。用途: 产生单脉冲、强制输出电平、生成基本PWM(需结合ARR,通过改变
CCRy
值改变占空比)。PWM生成(模式1/模式2): 输出比较的特殊应用。
过程(以PWM模式1递增计数为例):
计数器
TIMx_CNT
从0开始递增。当
CNT < CCRy
时,通道CHy
输出有效电平(高或低,由TIMx_CCER
的CCyP
和CCyNP
定义)。当
CNT >= CCRy
且CNT < ARR
时,通道CHy
输出无效电平。当
CNT
达到ARR
时:
计数器复位回0。
产生更新事件。
通道
CHy
恢复输出有效电平,开始下一个周期。
占空比 = CCRy / ARR
用途: 控制电机速度、LED亮度、舵机角度等。
编码器接口模式:
过程: 将两个通道(通常是CH1和CH2)配置为编码器输入模式 (
TIMx_SMCR
的SMS=3
)。硬件自动根据两个输入信号(A相和B相)的相位差,判断旋转方向,并自动控制计数器
TIMx_CNT
递增或递减计数。每次信号边沿(可配置)都会触发计数。
用途: 直接读取计数器值即可获得位置和方向信息,用于读取旋转编码器。
触发输入/输出 (TRGI/TRGO): 允许定时器之间同步或级联(主/从模式),或由外部信号触发定时器启动/停止/复位等。
输出比较
#include "TIME5.h"void Driver_TIM5_Init(void){//开启定时器5的时钟RCC->APB1ENR |= RCC_APB1ENR_TIM5EN;//GPIOA PARCC->APB2ENR |= RCC_APB2ENR_IOPAEN;//配置引脚模式 PA2 复用推挽输出GPIOA->CRL |= GPIO_CRL_MODE1_1;GPIOA->CRL |= GPIO_CRL_MODE1_0;GPIOA->CRL |= GPIO_CRL_CNF1_1;GPIOA->CRL &= ~GPIO_CRL_CNF1_0;GPIOA->CRL |= GPIO_CRL_MODE0_1;GPIOA->CRL |= GPIO_CRL_MODE0_0;GPIOA->CRL |= GPIO_CRL_CNF0_1;GPIOA->CRL &= ~GPIO_CRL_CNF0_0;//配置定时器寄存器//预分频配置TIM5->PSC = 7200 - 1; // 72M => 1M = 1 / us//自动重装载TIM5->ARR = 99;// (16Hz ~ 1M Hz)//计数方式TIM5->CR1 &= ~TIM_CR1_DIR;//配置通道二的捕获比较寄存器TIM5->CCR2 = 50;//配置通道模式TIM5->CCMR1 &= ~TIM_CCMR1_CC2S;TIM5->CCMR1 &= ~TIM_CCMR1_CC1S;//配置通道的输出比较模式TIM5->CCMR1 |= TIM_CCMR1_OC2M_2;TIM5->CCMR1 |= TIM_CCMR1_OC2M_1;TIM5->CCMR1 &= ~TIM_CCMR1_OC2M_0;TIM5->CCMR1 |= TIM_CCMR1_OC1M_2;TIM5->CCMR1 |= TIM_CCMR1_OC1M_1;TIM5->CCMR1 &= ~TIM_CCMR1_OC1M_0;//使能通道TIM5->CCER |= TIM_CCER_CC2E;TIM5->CCER |= TIM_CCER_CC1E;//设置通道极性TIM5->CCER &= ~TIM_CCER_CC2P;TIM5->CCER &= ~TIM_CCER_CC1P;}void Driver_TIM5_Start(void){TIM5->CR1 |= TIM_CR1_CEN;
}void Driver_TIM5_Stop(void){TIM5->CR1 &= ~TIM_CR1_CEN;
}void Driver_TIM5_SetDutyCycle(uint8_t duty){TIM5->CCR2 = duty;TIM5->CCR1 = 100 - duty;
}
输入捕获
#include "TIME4.h"void Driver_TIM4_Init(void){//开启时钟RCC->APB1ENR |= RCC_APB1ENR_TIM4EN;RCC->APB2ENR |= RCC_APB2ENR_IOPBEN;//配置引脚工作模式 PB6 :输入浮空 MODE : 00 CNF: 01GPIOB->CRL &= ~GPIO_CRL_MODE6;GPIOB->CRL &= ~GPIO_CRL_CNF6_1;GPIOB->CRL |= GPIO_CRL_CNF6_0;//配置定时器//配置时基// 预分频TIM4->PSC = 71;//自动重装载TIM4->ARR = 65535;//配置通道TIM4->CR2 &= ~TIM_CR2_TI1S;//工作模式TIM4->CCMR1 &= ~TIM_CCMR1_CC1S_1;TIM4->CCMR1 |= TIM_CCMR1_CC1S_0;TIM4->CCMR1 |= TIM_CCMR1_CC2S_1;TIM4->CCMR1 &= ~TIM_CCMR1_CC2S_0;//电路流转 滤波 预分频TIM4->CCMR1 &= ~TIM_CCMR1_IC1F;TIM4->CCMR1 &= ~TIM_CCMR1_IC1PSC;TIM4->CCMR1 &=~TIM_CCMR1_IC2F;TIM4->CCMR1 &=~TIM_CCMR1_IC2PSC;//中断TIM4->DIER |= TIM_DIER_CC1IE;NVIC_SetPriorityGrouping(3);NVIC_SetPriority(TIM4_IRQn, 3);NVIC_EnableIRQ(TIM4_IRQn);//开启通道TIM4->CCER &= ~TIM_CCER_CC1P;TIM4->CCER |= TIM_CCER_CC1E;TIM4->CCER |= TIM_CCER_CC2P;TIM4->CCER |= TIM_CCER_CC2E;}void TIM4_IRQHandler(void) {if ( TIM4->SR & TIM_SR_CC1IF ) {TIM4->SR &= ~TIM_SR_CC1IF;// !实现测量的逻辑// if ( TIM4->CCR1 > last_ccr_value ) {// pwm_freq_value = 1000000.0 / (TIM4->CCR1 - last_ccr_value);// pwm_cycle_value = ( TIM4->CCR1 - last_ccr_value ) / 1000.0;// } else {// pwm_freq_value = 1000000.0 / (65535 + TIM4->CCR1 - last_ccr_value);// pwm_cycle_value = ( 65535 + TIM4->CCR1 - last_ccr_value ) / 1000.0;// }// // 保存上一次的CCR的值// last_ccr_value = TIM4->CCR1;TIM4->CNT = 0;}
}void Driver_TIM4_Start(void){TIM4->CR1 |= TIM_CR1_CEN;}void Driver_TIM4_Stop(void){TIM4->CR1 &=~TIM_CR1_CEN;}/*** 获取定时器信号的频率(Hz) */
double TIM4_GetPWMFreq(void){return 1000000.0 / TIM4->CCR1;
}
/*** 获取定时器信号的周期 (ms)*/
double TIM4_GetPWMCycle(void){return TIM4->CCR1 / 1000.0;
}/*** 获取定时器信号的占空比 (%)*/
double TIM4_GetPWMDutyCycle(void) {return 100.0 * TIM4->CCR2 / TIM4->CCR1;
}
4. 高级定时器(TIM1, TIM8)
定位与作用
STM32中功能最强大的定时器,具备通用定时器的全部功能,并增加了面向电机控制、数字电源转换(如PFC、逆变器)、照明(PWM驱动LED)等高级应用的三相PWM生成、互补输出和紧急保护(刹车)功能。
广泛应用于:
驱动三相无刷直流电机(BLDC)和永磁同步电机(PMSM),通过生成6步或矢量控制(FOC)所需的互补PWM信号。
开关电源(SMPS)和逆变器的控制。
生成高精度、带死区互补的PWM信号,驱动半桥或全桥电路。
需要紧急故障保护机制的复杂控制系统。
工作方式与过程(核心时基 + 扩展功能增强)
核心单元(时基部分)增强:
重复计数器 (RCR): 这是高级定时器独有的16位寄存器 (TIMx_RCR)。
过程: 普通的更新事件(UEV)在计数器
CNT
溢出到ARR
时发生。而高级定时器中,CNT
溢出一次只会使重复计数器减1。只有当重复计数器递减到0时,才会产生真正的更新事件 (UEV) 并重新从预装载值加载RCR
,ARR
,PSC
等寄存器。作用: 可以方便地降低更新事件和PWM周期的频率,而无需修改
PSC
和ARR
的值。例如,设置RCR = N-1
,则PWM的实际周期将是(ARR+1) * (PSC+1) * N
个时钟周期。这对于生成频率低但分辨率依然很高的PWM非常有用,或者用于指定特定数量的PWM脉冲。扩展功能单元增强:
捕获/比较通道(通常4个,TIMx_CH1~CH4)功能增强:
互补输出通道 (TIMx_CHyN): 每个标准输出通道(CHy)都对应一个互补输出通道(CHyN)。例如,TIM1_CH1对应TIM1_CH1N。
作用: 用于驱动桥式电路的上下两个开关管(如MOSFET/IGBT)。标准通道(CHy)和互补通道(CHyN)的输出通常是反相的,但中间插入死区时间以防止上下管直通短路。
刹车输入 (BKIN):
过程: 当外部刹车引脚(BKIN)出现指定电平(通常高电平),或内部时钟失效时,硬件会自动触发刹车事件。
作用: 发生刹车事件时,定时器会立即根据配置(TIMx_BDTR 的 MOE, OSSI, OSSR 位)将所有的输出通道(CHy和CHyN)强制到一个预设的安全状态(通常为无效电平或高阻态)。这是一种最高优先级的硬件保护机制,用于在系统故障(如过流、过压)时立即关闭功率输出,保护电路和设备,响应速度极快,无需CPU干预。
PWM生成增强(带死区时间的互补PWM):
过程(以生成带死区的互补PWM为例):
配置主通道(CHy)为PWM模式1或2。
使能互补通道(CHyN)的输出(TIMx_CCER 的 CCyNE 位)。
配置死区时间寄存器 (TIMx_BDTR 的 DTG[7:0]) 来设置死区时长。硬件会根据设定的死区时间,自动在标准通道(CHy)和互补通道(CHyN)的信号跳变沿之间插入一段延迟(Dead Time)。
例如,当CHy输出关闭(从有效变为无效)时,会延迟一段时间后,才允许CHyN输出开启(从无效变为有效),反之亦然。
用途: 这是驱动半桥/全桥电路的核心功能,彻底防止上下两个开关管同时导通(直通)造成的短路灾难。
触发输入/输出 (TRGI/TRGO) 增强:
高级定时器可以作为其他定时器的主定时器,输出多种类型的触发信号(TRGO),如更新事件、捕获比较事件等,以实现复杂的定时器同步链。
它也可以被其他定时器或外部信号从模式触发,如复位、门控、触发等模式。
关键控制寄存器:
刹车和死区寄存器 (TIMx_BDTR): 这是高级定时器最具特色的寄存器,需要同时写入 MOE (主输出使能) 位为1,所有输出(标准通道和互补通道)才能正常生效。该寄存器集成了死区时间配置、刹车功能配置、互补输出空闲状态配置和主输出使能控制。
#include "Timer1.h"void Int_Timer1_Init(void){RCC->APB2ENR |= RCC_APB2ENR_TIM1EN;RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;//pa8GPIOA->CRH |= GPIO_CRH_MODE8;GPIOA->CRH |= GPIO_CRH_CNF8_1;GPIOA->CRH &= ~GPIO_CRH_CNF8_0;TIM1->PSC = 7199;//0.5sTIM1->ARR = 4999;TIM1->CR1 &= ~TIM_CR1_DIR;//重复计数TIM1->RCR = 4;TIM1->CR1 |= TIM_CR1_URS;TIM1->EGR |= TIM_EGR_UG;//通道//输出模式TIM1->CCMR1 &= ~TIM_CCMR1_CC1S; TIM1->CCMR1 |= TIM_CCMR1_OC1M_2;TIM1->CCMR1 |= TIM_CCMR1_OC1M_1;TIM1->CCMR1 &= ~TIM_CCMR1_OC1M_0;TIM1->CCR1 = 2500;TIM1->CCER &= ~TIM_CCER_CC1P;//使能TIM1->CCER |= TIM_CCER_CC1E;TIM1->BDTR |= TIM_BDTR_MOE;TIM1->DIER |= TIM_DIER_UIE;NVIC_SetPriorityGrouping(3);NVIC_SetPriority(TIM1_UP_IRQn, 3);NVIC_EnableIRQ(TIM1_UP_IRQn);}void Int_Timer1_Start(void){TIM1->CR1 |= TIM_CR1_CEN;}void Int_Timer1_Stop(void){TIM1->CR1 &= ~TIM_CR1_CEN;}void TIM1_UP_IRQHandler(void){TIM1->SR &= ~TIM_SR_UIF;Int_Timer1_Stop();}