项目完整教程
项目完整飞书文档 https://my.feishu.cn/docx/TXDYdtXg9ovE1QxlFsGcX5FXndh?from=from_copylink
1. 项目与构建
MCU:CW32L010;系统时钟 48 MHz HSI。
固件分为应用 FAN_CONTROL/ 与自定义 UART2 Bootloader BOOTLOADER/。
构建:CMake + Ninja + arm-none-eabi-gcc,C11;应用使用 cw32l010_flash.ld,Bootloader 使用 cw32l010_bootloader.ld。
当前测试固件版本:v1.1.0;对应上位机版本:0.9.6。版本信息来自当前源码与 2026-09-27 成品说明;实际设备版本以连接后读取的信息为准。
主要模块:应用入口和主机协议 FAN_CONTROL/USER/src/main.c;设备 UI ui.c;WS2812 ws2812.c;背景存储与传输 background.c;UART 收帧 interrupts_cw32l010.c;风扇与编码器驱动位于 FAN_CONTROL/Drive_Model/。
2. 硬件与存储布局
2.1 主要外设
功能 | 当前接口/实现 |
|---|---|
LCD | ST7789,320×172,RGB565,SPI 单向写屏,流式绘制,不使用整屏 framebuffer |
背光 | PA5 / GTIM1 CH2,百分比调节(与风扇 PWM 共用 GTIM1 时基,25 kHz) |
风扇 PWM | PB4 / GTIM1 CH3,25 kHz(GTIM1 PSC=0 / ARR=1919),目标值 0–100% |
风扇测速 | PB3 输入捕获脉冲,周期性换算 RPM |
WS2812 | PB2,10 颗,GRB,GPIO bit-bang |
编码器 | PB1/PB0 旋转输入,PA6 按键 |
主机通信 | UART2,115200 8N1,无硬件流控 |
2.2 Flash 分区
区域 | 地址 | 容量 | 用途 |
|---|---|---|---|
自定义 Bootloader | 0x0000–0x1FFF | 8 KiB | UART2 IAP、应用校验与跳转 |
应用代码 | 0x2000–0xBBFF | 39,424 B | 应用程序和向量表 |
主机/设备设置 | 0xBC00–0xBDFF | 512 B | 持久化运行设置 |
应用元数据 | 0xBE00–0xBFFF | 512 B | 应用长度、CRC32、版本和有效性信息 |
背景图 | 0xC000–0xFFFF | 16 KiB | 背景头部及压缩图像数据 |
设置区、元数据区和背景区是相互独立的用途范围。烧录工具按产物类型选择目标范围;应用升级 BIN 不包含 Bootloader,完整烧录 HEX 则包含 Bootloader、应用、元数据和背景数据,并不填充设置区。
3. 应用启动与任务运行
应用启动后初始化时钟、UART2、SysTick、WS2812、Flash 设置、芯片 UID、LCD、编码器和风扇;播放开机画面后装载设置并应用,之后进入常规任务循环。
主循环负责:
解析并处理 UART 主机命令;
采集本地编码器输入并执行页面/数值操作;
更新风扇目标与 RPM;
延时保存设置并发送状态上报;
执行 UI 页面状态更新、背景绘制和局部重绘;
执行 WS2812 效果任务。背景上传期间跳过 WS2812 刷新,以避免上传数据接收与 LED 软件时序同时占用执行时间。
SYSCTRL_GotoSleep() 用于主循环空闲等待中断唤醒,不表示深度休眠或关机。
4. 设备端界面与本地操作
4.1 主菜单与子页面
主菜单三项为:灯效、转速、夜灯。编码器旋转切换选项,按键进入/返回;主机模拟编码器事件复用同一套设备输入处理逻辑。
子页面提供灯效选择、风扇实际转速显示、风扇目标百分比调节和夜灯亮度调节。数值调整采用局部区域刷新;页面切换/首次整屏绘制采用独立的过渡流程。子页面空闲约 3 秒后返回主界面;夜灯调到 0 时显示 OFF,随后返回灯效选择页。
4.2 灯效
当前固件有 8 种灯效:STATIC、BREATH、RAINBOW、MARQUEE、STAR、AURORA、LAVA、OFF。其中 STATIC 和 BREATH 使用 RGB888 自定义颜色,其余为设备端内置效果。灯带物理数量为 10,亮度输出有固件上限;动画效果由 WS2812 任务按各自周期更新。
4.3 夜灯
夜灯是与灯效并列的独立显示模式,维护自己的开关状态和 0–100% 亮度;使用设备端固定暖白色。进入夜灯或调整亮度不改写普通灯效 ID/颜色,退出夜灯时恢复当前保存的灯效。夜灯亮度单独持久化;上位机当前没有独立夜灯控件,SET_NIGHT 命令保留为协议兼容接口。
4.4 风扇与屏幕
风扇目标百分比由编码器或上位机设置,底层通过 GTIM1 CH3 输出 PWM;测速脉冲周期性换算为 RPM 并更新屏幕与状态上报。LCD 使用 RGB565 局部绘制,页面包含设备状态、菜单图标、数值、灯效名称及时间信息等元素。
5. 设置持久化
应用在 0xBC00–0xBDFF 保存 HostSettings,包含风扇目标百分比、灯效 ID/颜色、UI 强调色、背光百分比和夜灯亮度等设置。记录采用 magic、格式版本和 checksum 校验;无效或不兼容记录时使用默认设置。
运行中设置变化后延迟约 1 秒再写 Flash,减少频繁擦写。修改持久化结构时必须同步处理版本兼容及 checksum;应用升级的擦除范围不得覆盖此设置区。
6. UART2 应用主机协议
6.1 普通控制帧
应用控制帧格式:
43 57 LEN CMD PAYLOAD... SUM
LEN 为命令字节加 payload 长度;SUM 为此前帧字节的 8 位累加校验。UART 接收使用 RC 中断并按协议长度组帧;普通控制帧与背景 0xB0 帧分流处理。
当前主机命令:
命令 | 用途 |
|---|---|
0x01 | PING |
0x02 | 设置风扇目标百分比 |
0x03 | 设置灯效,可为静态/呼吸灯效携带 RGB 颜色 |
0x04 | 设置自定义灯效颜色 |
0x05 | 设置 LCD UI 强调色 |
0x06 | 设置背光百分比 |
0x07 | 设置夜灯亮度(兼容接口) |
0x08 | 设置显示的星期与时间 |
0x09 | 查询设备状态 |
0x0A | 查询设备信息 |
0x0B | 申请进入 Bootloader,payload 为 A5 5A |
0x0C | 模拟编码器输入,供上位机设备模拟/测试流程使用 |
设备响应包括 0x80 ACK、0x81 STATE 和 0x82 INFO。状态内容涵盖协议/运行标志、风扇目标与 RPM、灯效、颜色、背光和夜灯亮度等。设备在运行中周期性上报状态;上位机应按帧类型及命令回显关联响应,而不是假设串口只会返回当前命令的 ACK。
6.2 主机接管与本地输入
收到有效主机命令后,设备进入主机控制活动状态;在控制超时前抑制本地编码器操作,超时后恢复本地输入。上位机按周期发送心跳以保持控制连接。控制指令、本地输入和状态上报共用应用状态,因此 UI、协议和设备输出均由同一应用状态驱动。
6.3 进入 Bootloader
应用验证 0x0B 命令及 A5 5A 标记后先返回 ACK,再延时并触发系统复位。此 ACK 只证明应用受理了切换请求;上位机还需在复位后单独完成 0xB1 GET_INFO,才能开始升级传输。
7. 背景图存储与传输
背景图储存在 0xC000–0xFFFF。20 字节头部记录 magic、尺寸、格式、调色板数量、payload 长度和 CRC32;尺寸为 320×172,调色板使用 RGB565,最多 16 色。当前桌面端编码器使用格式 3(LZW);格式 1(RLE)保留兼容读取。负载上限为 16,364 B。
背景上传是应用运行时的独立 0xB0 协议,不经过固件 Bootloader:
43 57 B0 CMD LEN_L LEN_H PAYLOAD CRC16_L CRC16_H
命令为 BEGIN 0x01、DATA 0x02、END 0x03、INFO 0x04。DATA 每包最多 128 B,且按实际 Flash 地址 0xC014 + offset 计算 512 B 页边界,不能跨页。设备对相同活动镜像 BEGIN 和内容相同的 DATA 重传提供幂等处理;END 校验完整长度与 CRC32 后发布有效头,magic 最后写入。ACK 携带 status、offset 和命令号,便于主机忽略迟到或不匹配响应。
当前 Flash 为单背景槽,背景更新与固件升级分开管理;背景上传期间应用暂停 WS2812 周期刷新。
8. 自定义 Bootloader 与固件升级
8.1 Bootloader 帧协议
Bootloader 使用独立帧类型 0xB1,CRC16-CCITT,低字节先发:
43 57 B1 CMD LEN_L LEN_H PAYLOAD CRC16_L CRC16_H
命令:GET_INFO 0x01、BEGIN 0x02、DATA 0x03、END 0x04、ABORT 0x05、REBOOT 0x06;响应 ACK 0x80、INFO 0x81。DATA 上限 128 B,Flash 页大小 512 B,数据块不跨页。
8.2 启动、校验与应用跳转
Bootloader 上电后提供约 2 秒升级命令等待窗口;若未开始升级且应用有效,则转入 0x2000 应用。应用有效性检查使用独立元数据(magic、镜像尺寸、CRC32、版本、header CRC32),并检查初始 MSP、Reset Handler 地址和 Thumb 状态。应用向量表位于 0x2000;跳转流程设置应用向量表与栈指针后进入 Reset Handler。
UART2 轮询接收按字节超时读取;消费接收数据后按 CW32 UART 标志语义清 RC/ORE。该处理属于 Bootloader 传输链路,不应与应用 ISR 收帧状态混为一谈。
8.3 升级与元数据提交
升级流程为:应用 ENTER_BOOTLOADER → Bootloader GET_INFO → BEGIN(镜像大小、CRC32、版本)→ 逐包 DATA → END 校验并提交元数据 → REBOOT → 应用 PING/INFO。
应用数据写入范围为 0x2000–0xBBFF;元数据页位于 0xBE00–0xBFFF,提交时单独解锁/擦除元数据范围,先写头部数据、最后写有效 magic。结束路径重新锁定应用代码范围;设置区 0xBC00–0xBDFF 不属于应用镜像擦除范围。
上位机逐包等待 ACK,并按命令、status 和 next offset 验证响应;升级结束需确认 END 成功、应用镜像读回/CRC 与包一致、元数据有效,重启后应用通信恢复。
9. 上位机配合
桌面端上位机提供设备连接、控制、状态与设备信息显示、设备端灯效/颜色/背光配置、背景图片选择与上传、固件升级和本地背景图库管理。串口协议实现位于 上位机模拟 device-controller/mofun-serial.js,页面位于 home.html、settings.html。
背景图流程为将图片裁切/缩放至 320×172、编码为设备支持格式、逐帧发送并等待 ACK;本地背景文件夹保存裁切后的无损 PNG 源图,不保存设备端调色板压缩结果。自定义 UI 颜色按设备 RGB565 表示量化后显示/发送。固件升级界面接收应用升级 BIN,不把 Bootloader 镜像与应用升级包混用。
10. 当前交付产物
成品说明记录该版本 Release 构建(xpack arm-none-eabi-gcc 15.2.1)应用使用 Flash 31064/39424 B(78.79%)、RAM 3568/4096 B(87.11%);Bootloader 使用 Flash 5304/8192 B(64.75%)、RAM 552/4096 B(13.48%)。应用编译选项为 -O2,Bootloader 为 -Os。
占用记录须附工具链版本:应用 Flash 占用对编译器版本敏感。同为 -O3 时,ST GCC 14.3.1 编译为 38848 B,xpack GCC 15.2.1 编译为 41492 B(超出 39424 B 分区)。