Skip to content
Atropine33333Public

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

HRT_Test —— STM32F411 夜灯状态机 + 串口调速风扇

代码仓库:https://github.com/Atropine33333/HRTTest

HRT 硬件组 2026 秋季招新试题的双题实现(两题共用一块外设扩展板):

  • 题目 A:智能状态机小夜灯(三色 LED + 双按键 + 状态机 + 三击呼吸灯加分项)
  • 题目 B:串口调速风扇 + NTC 温度上报(HEX)协议 + 图形化上位机)

1. 功能一览

题目 A:夜灯

按键 操作 功能
KEY1(PA0) 单击(按住 < 300ms) 颜色循环:红 → 蓝 → 黄
双击(抬起间隔 < 300ms) 进入/退出 0.5s 亮 + 0.5s 灭 闪烁
三击(加分项) 进入/退出呼吸灯:红 → 蓝 → 黄 → 三灯一起,每段一个完整呼吸 2s
四击 进入/退出跑马灯:亮度波在红/蓝/黄之间错开 1/3 周期流动
长按(≥ 1s) 点亮 / 关闭(任何模式直接生效)
KEY1+KEY2 同时长按 ≥ 1s 进入/退出"温度显示":<25℃ 黄灯、25~40℃ 蓝灯、≥40℃ 红灯(阈值可由上位机修改)
KEY2(PA1) 单击 进入/退出报警:三灯全亮并屏蔽 KEY1,退出后恢复原灯效
  • 按键识别:软件状态机(消抖 20ms)+ 连续点击计数窗口,无 delay 死等;
  • 按压时长 300ms ~ 1s 之间不产生任何事件,长按触发后不再产生单击/双击;
  • 呼吸亮度查 100 点升余弦表(20ms 步进),硬件 PWM(TIM2_CH2 / TIM3_CH1 / TIM3_CH2),运行时不做三角函数运算。

题目 B:风扇与温度

  • 协议:AA 55 | 命令 | 数据 | XOR 校验(校验 = 命令字与数据区异或,不收帧头),大端;
  • 命令:0x01 设占空比、0x02 查温度、0x03 查占空比、0x04 查灯效状态(扩展);
  • 上报:每 500ms 自动上报 0x81(温度 0.1℃ + 占空比);灯效状态变化时主动上报 0x84(扩展);
  • 占空比:16 位 0~65535 线性映射到定时器 ARR,PWM 96kHz(96MHz / 1000);
  • 温度:NTC 10k/B=3950 + 10k 分压,ADC 8 点滑动平均,-20 ~ 80℃ 限幅;
  • 风扇启动/升速带 100% 冲速(默认 300ms),越过低压起转死区;
  • 温度闭环(板载):0x07 切换手动/自动,自动时 30℃ 以下停转、30~60℃ 按 30%~100% 线性映射、60℃ 以上满速;
  • 摩尔斯电码灯:0x06 帧携带"长度 + 文本",蓝灯按点/划闪出(单位 120ms,支持 A-Z / 0-9 / 空格)。

2. 硬件平台

  • 核心板:STM32F411CEU6 Black Pill(25MHz 晶振,HSE→PLL→96MHz);
  • 外设板:自绘 PCB(嘉立创 EDA),原理图 / PCB / Gerber 见 ../HRT_Test_HDWare。
功能 引脚 说明
LED 红/蓝/黄 PB3 / PB4 / PB5 串 470Ω,共地
KEY1 / KEY2 PA0 / PA1 10k 上拉 + 100nF 硬件消抖
风扇 PWM PA8(TIM1_CH1) 串 100Ω → AO3400 栅极(原理图含栅极 10k 下拉,实物板现状见下方说明)
NTC 采样 PA2(ADC1_IN2) 10k 分压,对地 100nF
串口 PA9 / PA10(USART1) 115200 8N1,接 USB-TTL(3.3V)

硬件现状与改动说明(重要):

打样版本(V1.0)的 R2 接在了 MOSFET 源极与 PGND 之间,源极没有直接接地,风扇电流被 10 kΩ 挡住而无法转动(完整排查过程见 docs/排错报告.md 案例 3)。最终处理与现状:

  1. 实物板:把 R2 短接为 0 Ω(两端堆锡或焊细铜丝),源极直接落地,风扇恢复正常(100% 时端电压 4.96 V,满转);
  2. 代价:实物板没有栅极下拉电阻(R2 被当成了接地跳线)。本项目里 PA8 在上电后很快被配置为推挽输出,实测功能一切正常;仅在"芯片复位、GPIO 尚未初始化"的窗口内栅极悬空,属于理论隐患,不影响交付功能;
  3. 不再重新打板:原理图已按修正方案更新(R2 移到栅极做下拉、源极直接接地),PCB / Gerber 保留打样版本 V1.0 作为记录,与实物板"R2 短接"的状态对应。后续若再打板,直接按修正后的原理图即可(另:实物 PCB 上存在而原理图尚未画入的 R9(GND–PGND 单点连接),下次打板一并补齐);
  4. 风扇 5V 供电与板子共地;VIN 排针不要接 12V(它与核心板 5V 相连)。

3. 工程结构

Core/Inc, Core/Src     应用代码
  main.c               主循环调度 + 灯效模式状态机
  key_task.c/.h        按键状态机(消抖/单击/双击/三击/长按)
  led.c/.h             常亮/闪烁的 GPIO 点灯
  breath.c/.h          呼吸灯:TIM2/TIM3 硬件 PWM + 亮度查表
  temp_sensor.c/.h     ADC + NTC 温度换算
  fan_control.c/.h     PWM 占空比 + 冲速启动
  protocol.c/.h        HEX 帧解析/发送(含错误恢复)
Drivers/               STM32F4 HAL + CMSIS
cmake/, CMakeLists.txt CMake + Ninja 构建
SerialGUI.py           上位机:实时曲线 + 自动映射 + 日志(Tkinter + pyserial + matplotlib)
SerialProbe.py         原始串口探针:绕过 GUI 直接看 HEX / 发指令
ProtocolTest.py        协议健壮性黑盒测试(坏校验/粘包/半包/压力)
docs/                  排错报告、人机协作报告、提交记录
package.py             一键打包提交物

4. 构建与烧录

工程用 CMake + Ninja + arm-none-eabi-gcc(STM32CubeCLT 1.22.0)构建,工具链路径在 CMakePresets.json / CMakeLists.txt 里(Windows):

cmake --preset default
cmake --build build

产物:build/HRT_Test.elf,用 ST-Link / STM32CubeProgrammer 烧录即可。


5. 上位机与工具

python SerialGUI.py                # 图形界面:串口连接、曲线、自动映射、日志保存
python SerialProbe.py COM3         # 只看原始帧(排查链路)
python SerialProbe.py COM3 --send  # 每秒查询温度
python SerialProbe.py COM3 --duty 50   # 直接设 50% 占空比
python ProtocolTest.py COM3        # 协议健壮性测试(输出 PASS/FAIL)

GUI 说明:

  • 温度 / 占空比 30s 实时曲线;
  • Auto Mapping:设定温度区间与占空比区间(如 25℃→30%、60℃→100%),勾选后按上报温度自动下发 SET_DUTY,第三张图实时显示映射线与工作点;
  • Night Lamp 面板:实时显示灯效状态文字(solid/blink/breathe/temp/marquee、ON/OFF、ALARM),旁边可直接修改温度显示阈值(Apply 下发 0x08,Query 读回 0x86);
  • Morse Text:输入文字点 "Send Morse",板子会用蓝灯把电码闪出来;
  • 风扇控制默认用 GUI 的 Auto Mapping;板载温度闭环(0x07)在固件里仍然可用,GUI 上的开关默认隐藏(SHOW_MCU_AUTO 改 True 可显示);
  • 日志区可保存为 serial_log_*.txt;
  • 若 MCU 开启了文本日志(见下),日志区不受影响(非帧字节会被自动跳过)。

6. 协议表

方向 命令 数据 说明
上位机 → MCU 0x01 2B 占空比(大端) 设 PWM,0x7FFF=50%
0x02 — 查询温度 → 0x82
0x03 — 查询占空比 → 0x83
0x04 — 查询灯效状态 → 0x84
0x05 — 查询风扇模式 → 0x85
0x06 1B 长度 + N 字符 摩尔斯电码(N ≤ 16)
0x07 1B 模式 风扇 0=手动 / 1=温度闭环 → 0x85
0x08 2B + 2B(0.1℃) 温度显示阈值:黄灯上限、蓝灯上限 → 0x86
0x09 — 查询温度显示阈值 → 0x86
MCU → 上位机 0x81 2B 温度 + 2B 占空比 每 500ms 主动上报
0x82 2B 温度(0.1℃) 温度查询回复
0x83 2B 占空比 占空比查询回复
0x84 1B 模式 + 1B 颜色 + 1B 标志 + 1B 呼吸相位 灯效状态:模式 0/1/2/3/4=常亮/闪烁/呼吸/温度显示/跑马灯,颜色 0/1/2=红/蓝/黄,bit0=亮灭 bit1=报警,相位 0/1/2/3=红/蓝/黄/三灯一起(非呼吸时 0xFF),呼吸每换相位都会上报
0x85 1B 模式 + 2B 目标占空比 风扇模式与目标值
0x86 2B + 2B(0.1℃) 温度显示阈值(修改成功后回读)

文本状态日志:app_config.h 中 LED_STATE_TEXT_LOG = 1 时,灯效每次变化会额外发一行 [LED] mode=solid color=red on=1 alarm=0;呼吸模式下为 [LED] mode=breathe phase=yellow on=1 alarm=0, 便于串口助手直接观察状态机(非帧数据,不影响协议解析)。


7. 已知现象与说明

现象 结论
复位/烧录后蓝灯微亮,LED 两端约 2.5V PB4 是 JTAG NJTRST,芯片复位默认带内部上拉(~40kΩ),经 470Ω 注入约 20µA 电流。程序运行后 MX_GPIO_Init 配成推挽输出即消失,非故障
5V 风扇在 50% 占空比下不转 该风扇欠压保护阈值接近 5V,只能满速或停(详见排错报告第 3 条);固件仍按标准映射输出 PWM,可用万用表在 PA8 观察平均电压
双击响应有约 300ms 延迟 为了让"单击/双击/三击"判定可靠,统一在 300ms 连续点击窗口结束后发事件(KEY_MULTI_CLICK_MS 可调)

8. 交付物与打包

python package.py     # 生成 dist/HRT_Test_提交包_YYYYMMDD/
                      #  ├─ 源码/HRT_Test_src.zip
                      #  ├─ 上位机/SerialGUI.py, SerialProbe.py, ProtocolTest.py
                      #  ├─ 硬件资料/原理图.pdf, PCB.png, Gerber.zip
                      #  └─ 报告/README.md, 排错报告.md, 人机协作报告.md

排错报告、人机协作报告与完整提交记录见 docs/。

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages