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

STM32 定时器(级联实现32位定时器)

在STM32F103微控制器中,通过主从定时器模式将两个16位定时器级联为32位定时器,可显著扩展定时范围(最长可达数天)。以下是实现原理、配置步骤及代码示例:


⚙️ ​一、实现原理

  1. 级联核心机制

    • 主定时器​(如TIM2):配置为周期性更新事件(如1ms),通过内部触发线(ITRx)输出触发信号。
    • 从定时器​(如TIM3):工作于外部时钟模式​(TIM_SlaveMode_External1),将主定时器的触发信号作为计数时钟源。
    • 协同计数​:主定时器每溢出一次,从定时器计数值加1,实现主定时器周期 × 从定时器ARR值的扩展定时。
  2. 32位扩展计算

    • 主定时器周期:Tmaster​=(PSCmaster​+1)×(ARRmaster​+1)​ / fclock​
    • 总定时周期:Ttotal​=Tmaster​×(ARRslave​+1)
    • 最大定时范围:若 ARRslave​=65535(16位),则总定时范围扩展至32位(约49.7天 @72MHz)。

🔧 ​二、配置步骤与代码(标准库实现)​

1. 硬件连接与时钟设置
  • 内部触发线选择​:
    主定时器从定时器内部触发线(ITRx)
    TIM2TIM3ITR1
    TIM3TIM4ITR2
  • 使能时钟​:
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2 | RCC_APB1Periph_TIM3, ENABLE);
2. 主定时器配置(TIM2)​
void TIM2_Master_Config(uint32_t prescaler, uint32_t period) 
{TIM_TimeBaseInitTypeDef TIM_TimeBaseStruct;// 时基单元:1ms周期示例(72MHz时钟)TIM_TimeBaseStruct.TIM_Prescaler = prescaler;     // 预分频值(72-1 → 1MHz)TIM_TimeBaseStruct.TIM_Period = period;          // 重装载值(1000-1 → 1ms)TIM_TimeBaseStruct.TIM_CounterMode = TIM_CounterMode_Up;TIM_TimeBaseStruct.TIM_ClockDivision = TIM_CKD_DIV1;TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStruct);// 触发输出:更新事件作为触发源TIM_SelectOutputTrigger(TIM2, TIM_TRGOSource_Update);TIM_SelectMasterSlaveMode(TIM2, TIM_MasterSlaveMode_Enable);TIM_Cmd(TIM2, ENABLE);
}
3. 从定时器配置(TIM3)​
void TIM3_Slave_Config(uint32_t slave_period) 
{TIM_TimeBaseInitTypeDef TIM_TimeBaseStruct;// 时基单元:计数主定时器的溢出次数TIM_TimeBaseStruct.TIM_Period = slave_period;     // 从定时器ARR(扩展定时范围)TIM_TimeBaseStruct.TIM_Prescaler = 0;             // 无分频TIM_TimeBaseStruct.TIM_CounterMode = TIM_CounterMode_Up;TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStruct);// 从模式:外部时钟模式 + ITR1触发TIM_SelectInputTrigger(TIM3, TIM_TS_ITR1);        // TIM2触发TIM3TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_External1); // 外部信号驱动计数TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);        // 使能更新中断TIM_Cmd(TIM3, ENABLE);
}
4. 中断配置(处理定时完成事件)​
void NVIC_Config(void){NVIC_InitTypeDef NVIC_InitStruct;NVIC_InitStruct.NVIC_IRQChannel = TIM3_IRQn;      // TIM3中断通道NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStruct);
}// TIM3中断服务函数
void TIM3_IRQHandler(void) 
{if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) {TIM_ClearITPendingBit(TIM3, TIM_IT_Update);// 此处执行定时完成后的任务(如翻转LED、触发操作)}
}
5. 主函数调用
int main(void) 
{// 配置60秒定时:主定时器1ms周期,从定时器计数60,000次(60s/1ms)TIM2_Master_Config(72-1, 1000-1);  // 1ms周期TIM3_Slave_Config(60000-1);         // 60秒总定时NVIC_Config();while(1);
}

⚠️ ​三、关键注意事项

  1. 触发模式匹配

    • 主定时器需选择 TIM_TRGOSource_Update(更新事件触发)。
    • 从定时器必须选 TIM_SlaveMode_External1(外部时钟模式)。
  2. 中断优化

    • 仅需处理从定时器的更新中断,避免主定时器中断占用资源。
    • 若需超高精度,禁用全局中断期间操作计数器。
  3. 预分频与周期计算

    • 主定时器周期不宜过短(避免高频触发导致从定时器计数溢出)。
    • 最大扩展周期公式:Tmax​=72MHz(65535+1)×(65535+1)​≈59.65小时

💡 ​四、应用场景

  • 长周期任务​:数据日志定时存储、设备状态巡检(小时/天级)。
  • 步进电机控制​:精确输出指定数量的PWM脉冲(如
    实现3个脉冲输出)。
  • 低功耗定时唤醒​:休眠模式下由级联定时器唤醒系统。

通过此方案,可将STM32F103的定时能力扩展至32位,兼顾精度与灵活性。实际代码需根据时钟频率调整预分频和ARR值。

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

相关文章:

  • 机器学习数据预处理全流程:从缺失值处理到特征编码
  • Python 全栈开发常用命令
  • 安路EF2系列芯片单口ram ip核使用方法
  • 阿里通义千问Qwen-Long 快速文档解析
  • 【Git】执行命令时要求输入Username、Password
  • RabbitMQ:SpringAMQP Topic Exchange(主题交换机)
  • Flink双流join
  • 【黑客技术零基础入门】PHP环境搭建、安装Apache、安装与配置MySQL(非常详细)零基础入门到精通,收藏这一篇就够
  • (认识异常)
  • 建模工具Sparx EA的多视图协作教程
  • [系统架构设计师]面向服务架构设计理论与实践(十五)
  • Shader学习路线
  • C++ MFC/BCG编程:文件对话框(CFileDialog、CFolderPickerDialog)
  • 【免费AI文档助手开发实战系列】基于正则表达式的PDF脱敏python服务构建(一)
  • 国产化PDF处理控件Spire.PDF教程:如何使用 Python 添加水印到 PDF
  • 太阳光模拟器在无人机老化测试中的应用
  • JVM参数优化
  • Nacos-8--分析一下nacos中的AP和CP模式
  • InfoNES模拟器HarmonyOS移植指南
  • SpringAI接入openAI配置出现的问题全解析
  • hadoop技术栈(九)Hbase替代方案
  • 深入理解计算机系统
  • 9-302 家里网能搜出两个ip, 无法联大堂监控室
  • LangChain —多模态 / 多源上下文管理
  • 银河麒麟V10一键安装Oracle 11g脚本分享
  • 【运维进阶】管理大项目
  • Linux数据库:【索引】
  • 如何成功初始化一个模块
  • 第4章 React状态管理基础
  • TDengine IDMP 运维指南(4. 使用 Docker 部署)