当前位置: 首页 > news >正文

52Hz——STM32单片机学习记录——定时器

1. 系统定时器

  1. 定位与作用

    • 属于ARM Cortex-M内核标准组件,而非STM32外设。

    • 核心功能是提供精确的时间基准,常用于:

      • 操作系统(如FreeRTOS)的心跳时钟(Tick),用于任务调度。

      • 精确延时HAL_Delay() 底层依赖它)。

      • 测量代码执行时间。

    • 优先级高(可设置),中断响应快。

  2.  工作方式与过程

    • 核心单元: 一个简单的24位递减计数器

    • 时钟源: 通常选择内核时钟(HCLK)HCLK/8(通过SysTick控制与状态寄存器 SYST_CSR CLKSOURCE 位选择)。

    • 工作流程:

      1. 初始化: 程序设置重装载值寄存器 SYST_RVR (确定计数周期) 和控制与状态寄存器 SYST_CSR (使能计数器、中断、选择时钟源)。

      2. 计数: 计数器 SYST_CVR 从重装载值 LOAD 开始,每个时钟周期减1

      3. 计数到0:

        • 计数器自动重载 LOAD 值。

        • 状态寄存器 SYST_CSRCOUNTFLAG 置1

        • 如果使能了中断 (SYST_CSRTICKINT 位为1),则触发 SysTick 中断

      4. 中断服务程序 (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)

  1. 定位与作用

    • STM32中最简单的定时器外设。

    • 核心功能是提供基础的时基(Time Base)DAC触发信号

    • 主要用于:

      • 产生精确的定时中断

      • 为内置的数字模拟转换器(DAC) 提供触发信号,实现定时DAC输出更新。

      • 驱动其他需要基础时钟的模块。

  2. 工作方式与过程

    • 核心单元: 16位递增计数器16位预分频器(PSC)16位自动重装载寄存器(ARR)

    • 时钟源: 通常来自内部时钟(CK_INT),即APB1总线时钟(经过可能的倍频)。

    • 工作流程:

      1. 初始化: 配置预分频器 TIMx_PSC(决定计数时钟频率 fCK_CNT=fCK_PSC/(PSC+1)和自动重装载寄存器 TIMx_ARR(确定计数上限)。

      2. 计数: 计数器 TIMx_CNT 从0开始,每个计数时钟周期(fCK_CNTfCK_CNT​)加1

      3. 计数到ARR:

        • 计数器自动归零(复位)。

        • 状态寄存器 TIMx_SR更新中断标志位(UIF)置1

        • 如果使能了更新中断 (TIMx_DIERUIE 位为1),则触发更新中断

        • 如果使能了DMA请求 (TIMx_DIERUDE 位为1),则产生更新事件(UEV),可用于触发DMA传输(例如给DAC送数据)。

        • 如果配置为DAC触发源,此时会产生一个触发输出(TRGO) 信号给DAC。

      4. 中断服务程序 (ISR): 在更新中断服务程序中,软件执行需要的操作(如更新变量、翻转LED等),并手动清除UIF标志

    • 特点: 结构简单,只有时基功能没有输入捕获/输出比较/PWM等高级功能,计数器只能递增。通常与DAC配合使用。

相关寄存器

TIM6 TIM7 控制寄存器 1(TIMx_CR1)

TIM6 TIM7 DMA/中断使能寄存器(TIMx_DIER)

TIM6 TIM7 状态寄存器(TIMx_SR)

TIM6 TIM7 事件产生寄存器(TIMx_EGR)

TIM6 TIM7 计数器(TIMx_CNT)

TIM6 TIM7 预分频器(TIMx_PSC)

TIM6 TIM7 自动重装载寄存器(TIMx_ARR)

案例

/*** 基本定时器:初始化 */
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等)

  1. 定位与作用

    • STM32中数量最多、功能最丰富、应用最广泛的定时器。

    • 在基本定时器时基功能的基础上,增加了输入捕获、输出比较、PWM生成、单脉冲输出、编码器接口等强大功能。

    • 广泛应用于:

      • 测量脉冲宽度、频率、占空比(输入捕获)。

      • 产生精确的PWM波形控制电机、LED亮度等(输出比较/PWM)。

      • 测量旋转编码器信号(编码器接口模式)。

      • 产生单脉冲

      • 作为从模式定时器与其他定时器联动。

  2. 工作方式与过程(核心时基 + 扩展功能)

    • 核心单元(时基部分): 与基本定时器类似(16位PSC、16位CNT、16位ARR),但功能更强:

      • 计数方向: 可配置为递增、递减中心对齐(先递增后递减/先递减后递增)(通过 TIMx_CR1DIRCMS 位控制)。

      • 影子寄存器: ARR、PSC等寄存器通常有影子寄存器(缓冲)。更新事件发生时,预装载值才从预装载寄存器(如 TIMx_ARR)拷贝到影子寄存器(真正起作用的寄存器)。这保证了波形/定时的连续性,避免中间值更新导致波形畸变。

    • 扩展功能单元:

      • 捕获/比较通道(通常4个,TIMx_CH1~CH4): 每个通道可独立配置为输入捕获或输出比较模式。

      • 输入捕获:

        • 过程: 当配置为输入捕获的通道引脚上检测到指定边沿(上升沿、下降沿或双边沿)时:

          1. 当前计数器值 TIMx_CNT锁存到对应的捕获/比较寄存器 TIMx_CCRy 中。

          2. 状态寄存器 TIMx_SR捕获/比较中断标志位(CCyIF)置1

          3. 如果使能了捕获中断 (TIMx_DIERCCyIE 位为1),则触发捕获中断

          4. 如果使能了DMA请求 (TIMx_DIERCCyDE 位为1),则产生捕获事件,触发DMA读取捕获值。

        • 用途: 通过测量连续两次捕获的 CCRy 值差,可计算脉冲宽度周期

      • 输出比较:

        • 过程: 计数器 TIMx_CNT 不断与配置为输出比较模式的通道的捕获/比较寄存器 TIMx_CCRy 中的值进行比较。

          • 当两者匹配时:

            1. 根据配置的输出模式 (TIMx_CCMRyOCyM 位),控制对应的输出引脚 TIMx_CHy 的电平翻转、置高、置低或保持不变

            2. 状态寄存器 TIMx_SR捕获/比较中断标志位(CCyIF)置1

            3. 如果使能了比较中断 (TIMx_DIERCCyIE 位为1),则触发比较中断

        • 用途: 产生单脉冲强制输出电平、生成基本PWM(需结合ARR,通过改变 CCRy 值改变占空比)。

      • PWM生成(模式1/模式2): 输出比较的特殊应用。

        • 过程(以PWM模式1递增计数为例):

          1. 计数器 TIMx_CNT 从0开始递增。

          2. CNT < CCRy 时,通道 CHy 输出有效电平(高或低,由 TIMx_CCERCCyPCCyNP 定义)。

          3. CNT >= CCRyCNT < ARR 时,通道 CHy 输出无效电平。

          4. CNT 达到 ARR 时:

            • 计数器复位回0。

            • 产生更新事件。

            • 通道 CHy 恢复输出有效电平,开始下一个周期。

          • 占空比 = CCRy / ARR

        • 用途: 控制电机速度、LED亮度、舵机角度等。

      • 编码器接口模式:

        • 过程: 将两个通道(通常是CH1和CH2)配置为编码器输入模式 (TIMx_SMCRSMS=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) 并重新从预装载值加载 RCRARRPSC 等寄存器。

    • 作用: 可以方便地降低更新事件和PWM周期的频率,而无需修改 PSC 和 ARR 的值。例如,设置 RCR = N-1,则PWM的实际周期将是 (ARR+1) * (PSC+1) * N 个时钟周期。这对于生成频率低但分辨率依然很高的PWM非常有用,或者用于指定特定数量的PWM脉冲。

扩展功能单元增强:

  1. 捕获/比较通道(通常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干预。

  2. PWM生成增强(带死区时间的互补PWM)

    • 过程(以生成带死区的互补PWM为例)

      1. 配置主通道(CHy)为PWM模式1或2。

      2. 使能互补通道(CHyN)的输出(TIMx_CCER 的 CCyNE 位)。

      3. 配置死区时间寄存器 (TIMx_BDTR 的 DTG[7:0]) 来设置死区时长。硬件会根据设定的死区时间,自动在标准通道(CHy)和互补通道(CHyN)的信号跳变沿之间插入一段延迟(Dead Time)。

        • 例如,当CHy输出关闭(从有效变为无效)时,会延迟一段时间后,才允许CHyN输出开启(从无效变为有效),反之亦然。

    • 用途: 这是驱动半桥/全桥电路的核心功能,彻底防止上下两个开关管同时导通(直通)造成的短路灾难。

  3. 触发输入/输出 (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();}

http://www.dtcms.com/a/457458.html

相关文章:

  • PID--微分项D
  • 如何配置 GitHub 远程仓库及本地 Git 环境
  • 旋转矩阵的推导+矩阵在3DGS中的应用
  • 泰山派无 eMMC 版:嘉立创 Linux 镜像 “大 SD 卡资源浪费” 问题解析与解决
  • 人物摄影网站济宁网站建设优惠
  • WebClient工具调用HTTP接口报错远程主机断开连接
  • 【C语言基础详细版】09. 文件操作完全指南:从基础到高级应用
  • 卡盟网站专用主机批量建wordpress
  • Java高并发常见架构、处理方式、api调优
  • 基于 Delphi 与 ICS 的 Mosquitto Broker 重构实现:架构创新与技术比较分析
  • rag的评估优化应用前景
  • 1.2 openEuler - 安装OpenStack云计算平台基础框架
  • wordpress值得买模板百度智能小程序怎么优化排名
  • 徐州网站建设咨询2022年国际十大新闻
  • 中山精品网站建设机构wordpress目录列表
  • 智能体大模型基础入门(RAG难点图片详细讲解)
  • php网站数据迁移建网站自己做服务器
  • 河源盛世网站建设福州市城乡建设发展总公司网站
  • 嵌入式 Linux 启动优化:从 8 秒到 3 秒的极致加速
  • 网站建设 手机app网站建设书籍 知乎
  • 函数映射在不等式中的作用
  • JavaScript 事件流:事件捕获和事件冒泡
  • 数据湖架构
  • 对网站有效的优化软件长沙网站托管
  • 网站用户 分析宁波网站建设联系电话查询
  • Docker 镜像结构
  • RAG 让你的 AI 更聪明
  • 软测面经(二)
  • 微信小程序入门学习教程,从入门到精通,微信小程序核心组件详解与使用方法(12)
  • redis的集群中的简单问题