news 2026/4/23 22:32:45

蓝桥杯(嵌入式)——输入捕获实战:从原理图到LCD显示的PWM测量

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
蓝桥杯(嵌入式)——输入捕获实战:从原理图到LCD显示的PWM测量

1. 硬件原理图分析

拿到开发板第一件事就是看懂原理图。这次我们要测量的是XL555芯片生成的两路PWM信号,分别连接到STM32的PA15和PB4引脚。这两个引脚可不是随便选的,它们都支持定时器的输入捕获功能。

PA15对应的是TIM2_CH1,PB4对应的是TIM3_CH1。这里有个小细节要注意:PA15默认是JTAG的JTDI功能,使用前需要先禁用JTAG。我在第一次调试时就栽在这个坑里,死活捕获不到信号,后来才发现是复用功能没配置对。

555芯片的电路设计也有讲究。典型应用中,频率由RC电路决定,计算公式是f=1.44/((R1+2R2)*C)。比赛时建议准备几个不同阻值的电阻,方便快速调整输出频率范围。实测发现,当频率超过10kHz时,软件计算可能会遇到溢出问题,这点后面写代码时要特别注意。

2. CubeMX工程配置

2.1 基础工程设置

打开CubeMX新建工程,选择对应型号的STM32芯片。我习惯先配置时钟树,把HSE时钟源勾选上,系统时钟设为72MHz。调试接口选择SWD模式,这样既节省引脚又方便调试。

定时器时钟要特别注意,APB1总线上的定时器时钟默认是36MHz,如果直接使用这个频率,输入捕获的测量精度会受限。建议在时钟树配置里把APB1的预分频设为2,这样定时器时钟就是72MHz,测量分辨率直接翻倍。

2.2 定时器参数配置

TIM3的配置最为关键:

  1. 时钟源选择内部时钟
  2. Channel1设为输入捕获直接模式
  3. Slave Mode选择Reset Mode
  4. Trigger Source选TI1FP1
  5. 预分频设为71,这样计数器时钟就是1MHz(72MHz/(71+1))
  6. 自动重装载值设为65535
  7. Channel2设为输入捕获间接模式,边沿选择下降沿
  8. 别忘了勾选定时器中断

TIM2的配置与TIM3类似,只是引脚对应PA15。两个定时器的中断优先级建议都设为3,确保不会互相抢占导致数据错乱。

3. 核心代码实现

3.1 变量定义与初始化

在main.c的USER CODE BEGIN PV区域定义测量变量:

uint16_t PWM1_T_Count, PWM2_T_Count; // 周期计数值 uint16_t PWM1_D_Count, PWM2_D_Count; // 高电平计数值 float PWM1_Duty, PWM2_Duty; // 占空比

初始化部分放在USER CODE BEGIN 2区域:

HAL_TIM_Base_Start(&htim2); HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_1); HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_2); HAL_TIM_Base_Start(&htim3); HAL_TIM_IC_Start_IT(&htim3, TIM_CHANNEL_1); HAL_TIM_IC_Start_IT(&htim3, TIM_CHANNEL_2);

3.2 中断回调函数

这是整个项目的核心算法所在。在stm32f1xx_it.c中找到中断回调函数:

void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim) { if(htim->Instance==TIM2) { if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1) { PWM2_T_Count = __HAL_TIM_GET_COMPARE(htim,TIM_CHANNEL_1)+1; PWM2_Duty = (float)PWM2_D_Count/PWM2_T_Count; } else if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2) { PWM2_D_Count = __HAL_TIM_GET_COMPARE(htim,TIM_CHANNEL_2)+1; } } if(htim->Instance==TIM3) { if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1) { PWM1_T_Count = __HAL_TIM_GET_COMPARE(htim,TIM_CHANNEL_1)+1; PWM1_Duty = (float)PWM1_D_Count/PWM1_T_Count; } else if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2) { PWM1_D_Count = __HAL_TIM_GET_COMPARE(htim,TIM_CHANNEL_2)+1; } } }

这里有个优化技巧:原始代码直接使用HAL_TIM_ReadCapturedValue,实测发现改用__HAL_TIM_GET_COMPARE宏能减少约20%的中断处理时间。在测量高频信号时,这个优化能显著提高稳定性。

4. LCD显示实现

4.1 数据显示格式

在main函数的while循环中添加显示代码:

sprintf((char *)Lcd_Disp_String, "PWM1:%05dHz %4.1f%%", (unsigned int)(1000000/PWM1_T_Count), PWM1_Duty*100); LCD_DisplayStringLine(Line8, Lcd_Disp_String); sprintf((char *)Lcd_Disp_String, "PWM2:%05dHz %4.1f%%", (unsigned int)(1000000/PWM2_T_Count), PWM2_Duty*100); LCD_DisplayStringLine(Line9, Lcd_Disp_String);

显示格式做了三点优化:

  1. 频率显示固定5位数字,避免数值跳动
  2. 占空比保留1位小数
  3. 添加了单位标识,提高可读性

4.2 防抖处理

实测发现当PWM频率较低时,LCD刷新会导致显示闪烁。解决方法是在sprintf前添加判断:

if(abs(1000000/PWM1_T_Count - last_freq1) > 5) { last_freq1 = 1000000/PWM1_T_Count; // 更新显示代码 }

这个阈值5可以根据实际测量需求调整,既能过滤抖动又不会影响实时性。

5. 调试技巧与常见问题

5.1 信号捕获失败排查

如果始终捕获不到信号,建议按以下步骤排查:

  1. 先用示波器确认555芯片确实输出了PWM
  2. 检查CubeMX中引脚复用配置是否正确
  3. 确认定时器时钟使能且分频配置合理
  4. 测量信号电压是否在STM32识别范围内(最好3.3V)
  5. 检查中断优先级是否冲突

5.2 精度优化方法

要提高测量精度,可以尝试:

  1. 提高定时器时钟频率(最大72MHz)
  2. 使用定时器的输入滤波功能(适合噪声较大的环境)
  3. 对连续10次测量结果取平均值
  4. 在中断回调中添加时间戳校验,避免丢失边沿

我在实际测试中发现,当PWM频率超过50kHz时,建议将定时器预分频设为0(即72MHz时钟),这样可以获得1us的时间分辨率。不过要注意自动重装载值不能太小,否则会频繁溢出。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/23 22:32:25

2026年怎么部署Hermes Agent/OpenClaw?搭建及Coding Plan配置保姆级教程

2026年怎么部署Hermes Agent/OpenClaw?搭建及Coding Plan配置保姆级教程。还在为部署OpenClaw到处找教程踩坑吗?别再瞎折腾了!OpenClaw一键部署攻略来了,无需代码、只需两步,新手小白也能轻松拥有专属AI助理&#xff0…

作者头像 李华
网站建设 2026/4/23 22:31:50

Flask响应的艺术:自定义状态码、响应头与多格式数据返回(JSON/文件流)

更多内容请见: 《Python Web项目集锦》 - 专栏介绍和目录 文章目录 第一章:破除迷思——Flask视图函数的“多面体”本质 第二章:精准表达——HTTP状态码的艺术运用 2.1 元组语法:最简洁的控制方式 2.2 make_response:获取响应对象的控制权 2.3 RESTful API 状态码使用指南…

作者头像 李华
网站建设 2026/4/23 22:27:44

Pgloader实战:除了MySQL,我还用它把SQLite和CSV数据同步到了PostgreSQL

Pgloader全栈数据迁移指南:从SQLite、CSV到MySQL的PostgreSQL整合方案 当你的数据版图横跨多个数据库引擎和文件格式时,如何实现高效、可靠的数据整合?Pgloader作为PostgreSQL生态中的"数据搬运工",其能力远不止于常见的…

作者头像 李华
网站建设 2026/4/23 22:24:21

【C安全编码黄金清单】:2026规范新增的12个禁用API、8个替代方案及LLVM插件自动迁移脚本(限业内首批开放)

https://intelliparadigm.com 第一章:现代 C 语言内存安全编码规范 2026 概览 C 语言在嵌入式系统、操作系统内核与高性能基础设施中仍具不可替代性,但传统内存操作模式正面临日益严峻的安全挑战。2026 版规范并非对 ISO/IEC 9899 的简单修订&#xff0…

作者头像 李华