小华半导体 HC32 开发指南
编制日期 2026-10-14
从 DDL 包装不起来、启动文件 missing、时钟配不到目标频率、SWD 被占用锁死,一路到量产烧录、QSPI 外挂存储与三相 FOC —— 一份把「第一次上手会踩的坑」全部前置的工程手册
结论:HC32 是国产 MCU 里模拟外设密度与电机 PWM 能力最突出的一支—— 小华把大量资源压在 PGA / OPA / CMP / 高 MSPS ADC 与互补 PWM 上,空调室外机、洗衣机、变频电机、数字电源这类场景的性价比明显优于同主频竞品。
但上手门槛有三个真实的坎:① 官方 DDL 包只给工程容器不给启动文件,Keil 新工程必然报 missing startup file;② 没有 CubeMX 式配置器,时钟树得照着 CMU 手册一格格算;③ GPIO 必须 PORT_Init() 与 PORT_SetFunc() 成对调用,只调前者引脚完全没反应。
本文按「装环境 → 建工程 → 编译 → 下载 → 调试 → 跑业务 → 量产」的真实顺序组织,每一段都给出可复制的命令、可对照的表格、以及该段最常踩的坑。
报告总结
小华的资料在官网分得很细:数据手册(DS)讲电气与引脚、参考手册(RM)讲寄存器、DDL 驱动库含几十个外设模块与例程,而 Keil DFP 又是独立的 .pack 安装包。网上的中文教程绝大多数停留在「装 DFP → 新建工程 → 点编译 → 点下载」,一旦遇到启动文件找不到、引脚没反应、时钟配不出 200MHz、串口 DMA 收不到数据就无解。本文档做了三件官方分散文档没有做的事:
- 把分散在官网、DS、RM、DDL、社区博客里的事实合并成一份可检索清单,并逐条标注「已核实 / 社区口径 / 待核」,避免把博客里的猜测当规格书用。
- 把「症状 → 原因 → 处置」写成可查的表:22 条高频故障按编译期 / 烧录期 / 运行期分层,每条给根因与最小验证动作。
- 专门补齐外挂存储与电机控制两条实战线:QSPI 接 SPI NOR 的引脚落点与 XIP 窗口、SDIO 挂 SD NAND / eMMC 的资源预算、三相 FOC 对定时器与模拟通道的占用清单。
读者路径
本指南按「你现在卡在哪一步」组织,不必从头读:
1 · 文档导读与阅读路径
先说清楚这份文档管什么、不管什么,避免你在第 6 章卡住时回头翻第 20 章。
1.1 覆盖范围
覆盖以下型号与内容:
| 范围 | 具体内容 |
|---|---|
| 通用控制 MCU | HC32F0 / F1 / F334 / F4 全系列,重点 HC32F460(200MHz)与 HC32F4A0(240MHz) |
| 超低功耗 MCU | HC32L0 / L1,重点 HC32L136(M0+@48MHz,深度休眠 0.5µA) |
| 电机与电源 MCU | HC32M1 / M4 / HC32F334,含三相互补 PWM、编码器接口与霍尔捕获 |
| 汽车电子 MCU | HC32A1 / A4 的定位与命名,仅作选型参考 |
| 软件体系 | DDL 驱动库结构、启动文件、链接脚本、CMU 时钟配置、GPIO 两步法、DMAC、中断向量表 |
| 工具链 | Keil MDK + HDSC.HC32F4xx_DFP、GCC + openEuler drv-frame、SWD 调试与量产脱机烧录 |
| 实战专题 | QSPI 外挂 SPI NOR 的 XIP、SDIO 挂载 SD NAND / eMMC、三相 FOC 资源预算、家电主变一体方案 |
每章末尾的「本章要点」是可压缩成 3 条的结论;如果你是赶项目,直接看第 19 章故障排查速查表和附录 E 上手核查清单,其余按需检索。
1.2 不覆盖什么
为了避免误导,以下内容明确不在本文档范围内:
- 寄存器位级参考。本文只列「哪个模块有哪些资源、配置顺序是什么」,具体位定义请查对应型号的参考手册(RM)。
- 电气认证与安规。EMC/ESD 等级引用 DS 数值,但整机认证不在讨论范围。
- 官方图形化配置工具。截至本文编写日期,本次核查未发现小华官方提供类似 STM32CubeMX 的配置与代码生成工具;若后续官网下载中心上线离线工具,以官方为准。
- 车规 AEC-Q100 认证细节与 ISO 26262 功能安全流程。
- 具体型号的完整料号表。本文只列代表性型号,量产选型请以官网选型表为准。
1.3 版本与命名约定
文中出现的三类词严格区分,别混用:
| 标注 | 含义 | 可信度 | 使用建议 |
|---|---|---|---|
| 已核实 | 来自官方 DS / RM / 官网产品页 | 高 | 可直接作为设计依据 |
| 社区 | 来自工程师实践帖或开源仓库 | 中 | 参考即可,关键值必须回官方文档复核 |
| 待核 | 本次未能证实 | 低 | 不要写进设计文档,先查 RM/UM |
另外,厂商标识有个历史遗留:资料包、器件头文件与 Keil 器件包里的厂商前缀仍是 HDSC(华大半导体),而品牌已改为「小华半导体 / XHSC」。下载时不要因为 HDSC. 前缀而以为下错了厂商。
1.4 事实来源与免责
本文事实来源按优先级排序:
- 小华半导体官网产品线页与型号页(产品特性表、选型表);
- 官方数据手册:
HC32F460DS 版本号 Rev1.42/Rev1.60、HC32F4A0DS Rev1.50/Rev1.60、HC32L13xDS Rev2.1; - Keil MDK 官方器件页;
- openEuler
drv-frame开源仓库中的 HC32F460 平台移植层源码(DDL 版本宏、启动文件、链接脚本段名); - 工程师实践帖(标记为「社区」,只用于补充工程经验)。
数据手册会改版。本文引用的多为 Rev1.5~Rev1.6;量产前请到官网下载中心核对最新版 DS,重点核对:时钟精度表、电气电流表、封装引脚表、选型表中的 GPIO 数量。这几张表最容易在改版中变动。
本文不构成设计建议。量产项目请以你手上型号的最新版数据手册、参考手册与官方例程为唯一依据。
2 · HC32 家族全景与选型
先把「HC32 到底有多少个系列」这件事搞清楚,再谈型号选择。这一章的表是全文引用的基础。
2.1 一句话认识小华 HC32
小华半导体(XHSC)是中国的 32 位 MCU 供应商,产品线覆盖 Cortex-M0 / M0+ / M4 三个档次。它最有辨识度的地方不是主频,而是把大量模拟资源与电机 PWM 能力做进了中低端型号:
- HC32F448(200MHz M4)能同时提供三相互补 PWM、3 单元 12bit 2.5MSps ADC、2 路 DAC 与 4 路比较器,实现「压缩机 + 风机 + 高频 PFC」三合一单芯片控制;
- HC32L136(M0+@48MHz)在 64KB Flash / 8KB SRAM 的体量上放了 3 个运放、2 路带 6bit DAC 的电压比较器、LCD 驱动与 2 路可在深度休眠下工作的 LPUART,深度休眠 0.5µA;
- HC32F4A0(240MHz M4)更极端:4 个 15MSPS DAC、4 个 PGA、8 个 DCU 协处理单元、数学协处理器 MAU 与 16 阶 FIR 滤波器。
理解了这个取向,选型逻辑就简单了:凡是「电机 + 模拟采样 + 成本敏感」的场景,先看小华有没有对口型号,往往比先看主频更有效。
2.2 命名规则怎么读
型号不是随机编码,拆开看基本能推出定位:
| 片段 | 含义 | 例子 |
|---|---|---|
HC32 | 固定前缀 | HC32F460 |
| 第 4 位字母 | 类别:F 通用 / L 超低功耗 / M 电机与电源 / A 汽车电子 / D 显示专用 | F / L / M / A |
| 数字段 | 性能档次:0 M0+ 超低成本 / 1 M0+ 主流 / 3 电机电源特色 / 4 M4 高性能 | HC32F4A0 |
| 尾部数字 | 通常指 Flash 容量档:60 = 512KB;容量更大者另加后缀 A0(2MB) | F460 → 512KB |
| 引脚/温度码 | P=100 脚、K=64/60 脚、J=48/32 脚;T=LQFP 薄型、U=QFN、B=BGA;末位 A=工业温度扩展(-40~105℃) | HC32F460PETB |
「子系列别数字 ↔ Flash」「引脚码 ↔ 脚数」的映射在不同子系列之间并不一致。例如 F4A0 的尾号编码与 F460 不是同一套规则,跨系列套用会选错料。量产选型一律以对应型号 DS 的 Part numbering 表与官网选型表为准。
2.3 产品线总览
官网产品线页把 MCU 分成四大类共 14 条子线。选型时先定类别,再定档次:
| 官网分类 | 子线 | 内核 / 主频 | 典型定位 |
|---|---|---|---|
| 通用控制 | HC32F0 | M0+ / 48MHz | 超低成本,小封装(QFN20/32) |
| 通用控制 | HC32F1 | M0+ / 48MHz | 家电主控主力,型号最多 |
| 通用控制 | HC32F4 | M0+/M4 / 48~240MHz | 高性能通用平台,F460 与 F4A0 在此 |
| 通用控制 | HC32D3 | 待核 | 显示 / 专用方向,定位待官网确认 |
| 电机与电源 | HC32M1 | M0+ / 48MHz | 通用电机控制 |
| 电机与电源 | HC32M4 | M0+ / 120MHz | 带 Cache 与电机加速单元,高端电机 |
| 电机与电源 | HC32F334 | M4 / 84MHz | 数字电源专用,高分辨率 PWM + 运放/CMP |
| 电机与电源 | HCM3043 | 待核 | 独立命名的电机/电源器件,不在 HC32 体系内 |
| 超低能耗 | HC32L0 | M0+ / 48MHz | 超低功耗入门 |
| 超低能耗 | HC32L1 | M0+ / 48MHz | 低功耗主流,LCD + LPUART + OPA |
| 汽车电子 | HC32A1 | M4 / 48MHz | 车规入门,功能安全 |
| 汽车电子 | HC32A4 | M4 / 200~240MHz | 车规旗舰,对标 F4A0 |
先问三件事:① 系统主频下限多少(决定 F1 还是 F4);② 需要几个高速 ADC 与互补 PWM(决定 F448 还是 F4A0);③ 生命周期与供货要求。前两问决定能不能用,第三问决定敢不敢用。
2.4 旗舰 F4A0:240MHz 与 2MB Dual-bank
HC32F4A0 是小华当前的性能天花板,2024 年获 AspenCore/IIC Shanghai 中国 IC 设计成就奖「年度最佳 MCU」,累计出货近 3000 万颗。关键特性(官方 DS Rev1.60):
| 项目 | 参数 |
|---|---|
| 内核 | Cortex-M4 + FPU + MPU + SIMD DSP + 全指令跟踪 ETM + CoreSight |
| 主频与算力 | 240MHz,300DMIPS / 825 CoreMark |
| Flash | 最大 2048KB dual bank |
| SRAM | 最大 516KB,含 128KB 单周期访问高速 RAM |
| 供电 | 1.8~3.6V |
| 模拟 | 3×12bit 2.5MSPS ADC(三通道同时采样)+ 4×12bit 15MSPS DAC + 4 PGA + 4 CMP + 1 OTS |
| 定时器 | 32 个:8 Timer6 + 16 路 50ps HRPWM + 3 Timer4 + 12 TimerA + 4 Timer2 + 2 Timer0 + RTC + 2 WDT |
| 通信 | 最多 32 个接口:10 USART / 6 SPI / 6 I²C / 4 I²S / 2 SDIO / 1 QSPI / 2 CAN(含FD) / USB HS + FS / 1× 10-100M 以太网 MAC |
| 协处理 | 8 DCU + MAU(Sin/Sqrt)+ FMAC(16 阶 FIR)+ AOS 事件互触发 |
| 外部存储 | EXMC(静态 + 动态存储控制器)、DVP |
| GPIO | 最多 142 个,其中最多 134 个 5V 容忍;单端口支持多达 64 种外设功能 |
| 温度 | -40~105℃ |
| 多电机能力 | 多通道模拟 + 高性能 PWM,可支撑 5 个电机 FOC |
需要以太网、CAN FD、USB HS、EXMC 挂外部 SRAM/SDRAM,或者需要 5 台以上电机 FOC 时,F4A0 几乎是唯一选择。如果只是单相或三相单电机 + 少量通信,F460 + 外挂一颗栅极驱动就能完成,BOM 更低。
2.5 通用主力 F460:200MHz 的均衡之选
HC32F460 是出货面最广的通用 M4,官方 DS Rev1.42 的特性:
| 项目 | F460 | 对比 F4A0 |
|---|---|---|
| 主频 / 算力 | 200MHz,250DMIPS / 680 CoreMark | 240MHz,300DMIPS / 825 CoreMark |
| Flash | 最大 512KB(另有 256KB 档) | 最大 2048KB 双 Bank |
| SRAM | 最大 192KB(32KB 高速 + 4KB Retention) | 最大 516KB(128KB 高速) |
| ADC | 2×12bit 2MSPS | 3×12bit 2.5MSPS(可同时采样) |
| DAC | 2×8bit | 4×12bit 15MSPS |
| PGA / CMP | 1 PGA / 3 CMP | 4 PGA / 4 CMP |
| 定时器 | 14 个(含 3 Timer6 + 3 Timer4 + 6 TimerA + 2 Timer0) | 32 个(另加 Timer2 与 16 路 HRPWM) |
| CAN | 1 个 CAN 2.0B(ISO11898-1) | 2 个,含 CAN FD |
| USB | 1× USB 2.0 FS OTG(内置 PHY) | USB HS + USB FS |
| 以太网 | 无 | 1× 10/100M MAC(MII/RMII + PTP) |
| GPIO | 最多 83 个,最多 81 个 5V 容忍 | 最多 142 个,最多 134 个 5V 容忍 |
| DMAC | 8 通道双主机 + USBFS 专用 | 16 通道双主机 + USBHS/FS/ETH 专用 |
这是最容易搞错的点之一:HC32F460 的 CAN 只支持 CAN 2.0B + TTCAN,不支持 CAN FD。CAN FD 需求必须上 F4A0。同时注意 F460 没有 Timer8(有些资料罗列了 8 类定时器,那是 F4A0 才有 Timer2 与 HRPWM)。
F460 官方选型表覆盖 5 种封装,脚数从 48 到 100,Flash 从 256KB 到 512KB,全部 200MHz / 192KB SRAM:
| 型号 | Flash | GPIO | ADC 通道 | 温度 | 封装 |
|---|---|---|---|---|---|
| HC32F460PETB-LQFP100 | 512KB | 83 | 16 | -40~105℃ | LQFP100 (14×14) |
| HC32F460PEHB-VFBGA100 | 512KB | 83 | 16 | -40~105℃ | VFBGA100 (7×7) |
| HC32F460KETA-LQFP64 | 512KB | 52 | 16 | -40~85℃ | LQFP64 (10×10) |
| HC32F460KEUA-QFN60TR | 512KB | 50 | 15 | -40~85℃ | QFN60 (7×7) |
| HC32F460JETA-LQFP48 | 512KB | 38 | 10 | -40~85℃ | LQFP48 (7×7) |
| HC32F460JEUA-QFN48TR | 512KB | 38 | 10 | -40~85℃ | QFN48 (5×5) |
| HC32F460PCTB-LQFP100 | 256KB | 83 | 16 | -40~105℃ | LQFP100 |
| HC32F460KCTA-LQFP64 | 256KB | 52 | 16 | -40~85℃ | LQFP64 |
| HC32F460JCTA-LQFP48 | 256KB | 38 | 10 | -40~85℃ | LQFP48 |
从 100 脚降到 64 脚,GPIO 只从 83 掉到 52(少 31 个),但 ADC 通道数从 16 掉到 10、定时器可能也减少。选封装时别只看 GPIO 总数,把 ADC 通道、USART 数量、定时器通道一起数一遍,这是最常见的「选完才发现模拟不够用」的原因。
2.6 超低功耗 L 系列:0.5µA 深度休眠
HC32L13x 是低功耗主力(官方 DS Rev2.1)。它最反直觉的地方是在 8KB RAM 的体量上塞了 3 个运放和 2 路带 6bit DAC 的比较器——这是为电池供电的传感器节点准备的:
| 项目 | HC32L130 / L136 |
|---|---|
| 内核 / 主频 | Cortex-M0+ / 48MHz |
| Flash / RAM | 64KB Flash(带擦写保护)/ 8KB RAM(带奇偶校验) |
| 供电范围 | 1.8~5.5V,耐压范围比 F 系列宽得多 |
| GPIO | 56IO/64pin、40IO/48pin、26IO/32pin、23IO/28pin |
| 时钟 | 外部高速 4~32MHz;外部低速 32.768kHz;内部高速 4/8/16/22.12/24MHz;内部低速 32.8/38.4kHz;PLL 8~48MHz;硬件支持内外时钟校准与监控 |
| 深度休眠 | 0.5µA@3V:所有时钟关闭,POR 有效,IO 状态保持,IO 中断有效,寄存器/RAM/CPU 数据保持 |
| 深度休眠 + RTC | 0.9µA@3V |
| 低速工作 | 7µA@32.768kHz:CPU 与外设运行,从 Flash 执行 |
| 休眠 / 工作 | 35µA/MHz@3V@24MHz / 130µA/MHz@3V@24MHz |
| 唤醒时间 | 4µs 超低功耗唤醒 |
| LCD 驱动 | 4×40 / 6×38 / 8×36 段 |
| 模拟 | 12bit 1Msps SAR ADC(内置运放可测微弱信号)+ 3×OPA + 2 路 VC(集成 6bit DAC + 可编程参考)+ 16 档 LVD |
| 安全 | AES-128 协处理器、TRNG、全球唯一 10 字节 ID |
| 封装 | QFN32/48、LQFP64/48、TSSOP28 |
小华官网的额温枪方案以 HC32L136 为核心,指标是 0.5µA 待机功耗、1µA LCD 显示功耗、4µs 高速唤醒,靠 MCU 内置 LCD 驱动 / 12 位 ADC / SPI / I²C / 模拟传感器降低 BOM。
参考型号:HC32L136K8TA、HC32L136J8TA、HC32L130F8UA、HC32L130E8PA、HC32L130J8TA、HC32L130J8UA。
2.7 电机与家电特色型号
这是小华最有竞争力的部分,官方与公开报道口径:
| 型号 | 内核 / 主频 | 定位 | 关键能力 |
|---|---|---|---|
| HC32F448 | M4 / 200MHz | 空调室外变频主控 | 电机专用定时器输出三相互补 PWM + 硬件死区;3 单元 12bit 2.5Msps ADC;2 路 DAC;4 路比较器;支持压缩机 + 风机 + 高频 PFC 三合一;已在头部客户大规模出货 |
| HC32F115 / HC32F155 | M0+ / 48MHz | 空调内机、冰箱、洗衣机主控 | 通讯接口丰富、高性价比 |
| HC32L180 | M0+ / 48MHz | 空调室内机单芯片 | 集成主控与风机变频 |
| HC32M413 | M0+ / 120MHz | 洗衣机主变一体、高端空调内机主变一体 | 带 Cache + 电机加速单元;3.6Msps 高速 ADC、高精度 CMP、高性能 OPA;UART 等接口丰富 |
| HC32M120 / HC32M140 | M0+ / 48MHz | 通用电机控制 | LQFP32/48/64 |
| HC32F334 | M4 / 84MHz | 数字电源 | 高分辨率 PWM + 运放/CMP |
HC32F448 能在一颗芯片里同时跑压缩机的矢量控制、风机的变频调速和高频 PFC 的功率级闭环。这意味着原来需要「一颗 MCU + 一颗 PFC 专用芯片」的两芯片方案可以合并,BOM 与 PCB 面积都会下降。代价是软件复杂度上升:三套控制回路共享 ADC 采样资源与定时器 PWM,必须在第 20.4 节的资源预算表上逐项核对,不能拍脑袋。
2.8 选型决策路径
把上面这些收敛成五个问题,从上往下问,命中即停:
- 先用类别字母筛掉一半:电池供电 → L;电机/电源 → M 或 F334;车规 → A;其余 → F。类别定了再看具体子线,能省 80% 的比对时间。
- 同系列内优先选大 Flash 那一档。F460 的 512KB 与 256KB 差价极小,而后期发现 Flash 不够的成本(改板、加外部器件、重做认证)远高于差价。
- 数完 ADC 通道和定时器通道再定封装。100 脚降到 48 脚时 ADC 从 16 通道掉到 10 通道,模拟项目最容易在这里翻车。
- 需要 CAN FD / 以太网 / USB HS / EXMC,直接上 F4A0,F460 没有这些。
- 量产前确认脱机烧录与 SWD 保护方案,别等到产线上才发现只有调试器直烧这条路。
3 · 内核与架构:Cortex-M 加上小华自有外设体系
HC32 的内核就是标准 ARM Cortex-M,所以「算力」和「生态」这两件事不用担心。真正需要重新理解的是外面那一层小华自研的外设体系。
3.1 Cortex-M0+ 与 M4F 的取舍
两个档次的选择非常清晰,选错了后面会很难受:
| 维度 | Cortex-M0+(F0/F1/L1/M1/M4 子线) | Cortex-M4F(F4 子线、F334) |
|---|---|---|
| 典型主频 | 48MHz | 84 / 200 / 240MHz |
| FPU | 无 | 有(单精度) |
| 指令集 | Thumb-2(ARMv6-M) | Thumb-2 + DSP + SIMD(ARMv7-M) |
| 单周期乘法 | 有硬件乘法器(更快) | 有,且饱和指令可选 |
| 典型算力 | 约 55 DMIPS 量级 | 250DMIPS(F460)~ 300DMIPS(F4A0) |
| 适合 | 表计、家电主控、传感器节点、电机辅助控制 | 电机 FOC、数字电源、以太网、网关 |
| 典型 RAM 瓶颈 | 8~24KB,要精打细算 | 192~516KB,可放开用 |
没有 FPU 时做 FOC 的三角函数与浮点运算会非常吃 CPU。M0+ 型号的做法有两种:一是把控制放在定点/查表(常见于 HC32M120/M140 这类通用电机),二是像 HC32M413 这样用 M0+ @120MHz 并集成电机加速单元来补。选型时要明确你的算法跑在哪,别指望 M0+ 能扛 200MHz M4 上的算法直接搬过来。
3.2 小华外设体系的命名逻辑
小华的模块前缀不是随机取的,有一条自己的规则。理解它之后,看手册目录就知道大概有哪些东西:
这张图要记住的核心是三件事:
- 时钟管理叫 CMU,不是 RCC。你在 STM32 里所有
RCC_开头的调用,迁移时都要换成CLK_系列。 - 引脚模块叫 PORT,不是 GPIO。而且它不只管 GPIO,还管复用功能的选择 —— 这就是两步法的根源。
- 模拟外设归在
MO模块(ADC / OPA / CMP / DAC 相关的寄存器与 API 常以 MO 开头或归在 MO 章),不分散在各个外设里。
因为迁移时最容易「编译通过、运行不通」。把 STM32 的 GPIO_Init() 换成小华的 PORT_Init() 之后,代码能编译、下载也成功,但外设一点反应都没有 —— 而最常见的原因就是漏了 PORT_SetFunc()。这类「静默失败」不报错,最耗调试时间。
3.3 CMU 时钟管理模块
CMU 负责六件事:
- 时钟源选择:六个源(见 10.1 节)里选一个作为 PLL 输入或系统时钟源;
- PLL 控制:输入分频、倍频、输出分频,以及专用音频 PLL(供 I²S);
- 系统时钟切换:把选定的时钟源切到系统时钟(SWT),切换期间 CPU 会短暂停顿;
- 总线分频:HCLK 与各 PCLK 的分频系数;
- Flash 等待周期:主频升高后要插入等待周期,否则 Flash 读出错;
- 时钟监控:CSS 时钟失效检测(时钟挂了能检测到)、时钟输出 MCO。
3.4 PWC 电源与时钟门控
PWC 是电源与时钟的门控枢纽,有三类职责:
- 外设时钟门控(FCG):每个外设有一组 FCG 位,关掉就省电。移植时最常见的一类错误就是忘了开某个 FCG —— 写寄存器全无效果。
- 电源模式控制:进入 Sleep / Stop / Power down,以及唤醒后恢复。
- VBAT 与备份域:F4A0 有 VBAT 独立供电 + 128Byte 备份寄存器 + 4KB 备份 SRAM。
典型症状:USART_Init() 成功、波特率算对、TX 也配了,但串口一个字节都不发。八成是漏了对应的 PWC_FCG0 外设时钟使能。判定方法很简单:寄存器值写进去后读回来,如果还是复位值 0,就是时钟没开。这条判定适用于所有外设,值得养成习惯。
3.5 AOS 外设事件互触发
AOS(Analog to Digital / Event routing)是一个事件路由矩阵,让外设之间可以互相触发而不经过 CPU。典型用法:
- 定时器触发 ADC 采样 → 采样率由定时器节拍精确决定,抖动远小于软件触发;
- ADC 采样完成触发 DMA 传输 → 数据不落 CPU;
- ADC 转换完成触发定时器更新 → PWM 与采样严格同步,这对电机 FOC 的电流采样对齐是刚需。
用 AOS 之前必须先打开 PWC_FCG0_PERIPH_AOS 时钟。很多「串口 DMA 收不到数据」的问题根源就在这里:代码里写了 IDLE/DMA 的接收逻辑,但 AOS 时钟没开。
3.6 协处理单元 DCU / MAU / FMAC
这是 F4A0 相对 F460 最明显的算力增量,做算法时可以省很多 CPU:
| 单元 | 功能 | 典型用途 |
|---|---|---|
| DCU | 8 个数据计算单元(F4A0)/ F460 有 DCU | 乘累加、移位、饱和等基本算术,替代软件循环 |
| MAU | 数学协处理单元,支持 Sin / Sqrt | FOC 的 sin/cos 表、电机角度计算 |
| FMAC | 16 阶 FIR 数字滤波器 | Sinc 插值、采样滤波、音视频处理 |
| ETM | 全指令跟踪单元(F4A0) | 指令级 trace,配合高端调试器做疑难问题定位 |
如果你的算法里大量是三角函数,F4A0 的 MAU 能直接吃下来;F460 只能用查表 + 插值。注意 F460 的 DAC 只有 2×8bit,做波形输出要谨慎。
3.7 与 STM32 的兼容边界
这是全章最实用的一节。按「能复用」和「必须重写」分开看:
换句话说,HC32 与 STM32 的兼容只到「指令集 + CMSIS 规范」这一层,往下全部要重写。把它当成「新建一个工程,只是 MCU 换了」,比当成「移植」来做,心态会好很多,成功率也高很多。
启动文件、向量表偏移、时钟初始化、Flash 算法四项全不同。直接复用 STM32 的 .axf / .hex 烧进 HC32 芯片,绝不会工作,而且现象往往不是「跑不起来」,而是跑出一个完全无关的错误行为,比直接失败更难查。
4 · 开发环境:DDL 驱动库与 Keil / GCC
这一章解决「装不起来」的问题。HC32 的环境安装有两个独立的包,加上一个历史遗留的坑。
4.1 官方资料包与版本
需要准备两样东西,缺一不可:
| 包 | 作用 | 获取 | 备注 |
|---|---|---|---|
| DDL 驱动库 | 外设驱动源码 + 头文件 + 启动文件 + 链接脚本 + 例程 | 官网下载中心 / GitHub 官方仓库 | 文件名形如 hc32f460_ddl_RevX.Y.Z.zip |
| Keil DFP | 器件描述包(.pack) | Keil Pack Installer | 厂商前缀 HDSC,器件树形如 HDSC::HC32F460 |
DDL 库内的版本宏定义在 hc32_ddl.h 中(社区移植源码实测):
| 宏 | 值 | 含义 |
|---|---|---|
HC32_DDL_VERSION_MAIN | 0x02 | 主版本 |
HC32_DDL_VERSION_SUB1 | 0x02 | 次版本 1 |
HC32_DDL_VERSION_SUB2 | 0x00 | 次版本 2 |
HC32_DDL_VERSION_RC | 0x00 | 发布候选标记 |
HC32_DDL_VERSION | 0x02020000 | 合并版本值 = Rev 2.2.0 |
两个版本不匹配会出现「底层寄存器定义差异」导致的怪异问题 —— 比如明明按文档写了却没生效,或者结构体字段名对不上。做项目时在 README 里记一笔两个包的确切版本号,将来复现问题时这条信息至关重要。
4.2 DDL 目录结构(两套并存)
这是最让人困惑的一点:不同来源拿到的 DDL 包,目录结构不一样,但说的是同一套东西。
| 来源 | 结构 | 特点 |
|---|---|---|
| 官方 DDL 包 (Keil / 资料中心) | driver/(inc + src)、mcu/common/、example/、project/MDK-ARM/、utilities/;启动文件实际在 DDL_Driver/Source/Startup/ARM/ | 大小写混用(startup_HC32F460.s),project/MDK-ARM 只有 .uvprojx 不含源码 |
| openEuler drv-frame (开源社区移植) | platform/mcu/hc32f460/driver/inc/、mcu/GCC/Startup/、mcu/GCC/LinkerScript/、mcu/common/ | 路径全小写,结构规范,带 CMSIS 接口与 HAL 层,GCC 路线最省力的参考 |
无论哪套结构,核心都一样:hc32_ddl.h 是统一 include 入口,它按 ddl_config.h 的宏条件包含各外设头文件;器件主头是 hc32f460.h;系统头 system_hc32f460.h 定义时钟常量与 SystemCoreClock。
4.3 启动文件与向量表
启动文件是第一个会绊住你的地方。官方包里它不在你以为的路径:
| 项目 | 内容 |
|---|---|
| 文件位置(官方包) | DDL_Driver/Source/Startup/ARM/startup_HC32F460.s |
| 文件位置(drv-frame) | platform/mcu/hc32f460/mcu/GCC/Startup/startup_hc32f460.s |
| 命名差异 | 官方包大小写混写(startup_HC32F460.s),drv-frame 全小写。部分工程另有分型号版本如 startup_HC32F460PITB.s |
| 栈 / 堆 | Stack 0x1000(4KB)、Heap 0xC00(3KB) |
| 中断总数 | 144(IRQ000_Handler ~ IRQ143_Handler) |
| 向量表内容 | ARM 标准 16 个系统异常 + 128 个外部 IRQ,含 HC32 私有中断(ADC1_IRQHandler、USARTx_IRQHandler、QSPI_IRQHandler、XTAL32K_ERR_IRQHandler 等) |
| 启动流程 | 向量表 → SystemInit() → __main → main() |
在 Keil 里打开官方示例工程直接编译,几乎必然报:
Error: #5: cannot open source input file "startup_HC32F460.s"
原因是官方 DDL 包的 project/MDK-ARM/ 只提供工程容器(.uvprojx),不包含源文件实体,启动文件深埋在 DDL_Driver/Source/Startup/ARM/ 子目录且未登记到工程里。修复四步:
- 建一个名为
Startup的工程分组; - 把
startup_*.s手动 Add Existing Files 进这个组; Options → Target → Startup中取消勾选「Use default startup file」,手动填精确文件名;- 若使用分型号启动文件,文件名后缀必须与 Keil 里选的 Part Number 严格一致(区分大小写)。
千万不要用 startup_ARMCMx.s 这类 ARM 通用启动文件代替:它没有 HC32 的私有中断向量,也没有 SystemInit(),运行时会直接进 HardFault_Handler 死循环。
4.4 链接脚本与内存映射
链接脚本决定 Flash 与 SRAM 怎么划分。HC32F460 的链接脚本(社区移植版命名 hc32f460xe_flash.ld.s,x 是容量档代号)里有两个特殊段值得记住:
| 段名 | 内存区 | 用途 | 为什么重要 |
|---|---|---|---|
.ret_ram_data | RET_RAM | 已初始化的保持 RAM 数据 | 这 4KB Retention RAM 在 Power down 下仍保持内容,是低功耗产品存关键状态的地方 |
.ret_ram_bss | RET_RAM | 未初始化的保持 RAM 数据 | 同上,省掉每次唤醒后重新初始化 |
.high_speed_sram | RAMH | 32KB @200MHz 单周期高速 RAM | 把中断向量、栈、热点数据放这里,性能差别明显 |
链接脚本还支持 bootloader / application 双模式宏切换,做 IAP 时必需 —— 用它把 BootLoader 与 App 的地址空间隔开。具体宏名请查你所用版本的链接脚本注释,本文不硬写版本相关的宏名。
Keil 用 .sct 分散加载文件而不是 .ld。官方包若未提供 .sct,可以先用默认的 Flash/RAM 布局跑通,再按需补做分区。建议先用默认布局打通编译与下载,不要一上来就抠链接脚本。
4.5 Keil MDK 配置全流程
按这个顺序配,每一步都有验收标志:
- 安装编译器组件。勾选 ARM Compiler 6(ARMCLANG) —— 官方示例工程默认用它。验收:Pack Installer 里能看到 ARMCC/ARMCLANG。
- 安装 DFP。Pack Installer 搜索
HDSC.HC32F4xx_DFP安装(社区包名,确切名称与版本以官网为准)。验收:器件树里能看到HDSC厂商与HC32F460系列。 - 新建工程并选对器件。
Project → New uVision Project,选HDSC::HC32F460对应型号。询问是否添加启动文件时选「否」,用 DDL 自带的。验收:工程树里出现设备名。 - 加入源码与头文件路径。Include Paths 加:
./driver/inc、./driver/src、./mcu、./CMSIS/Core/Include;Asm 的 Include Path 要加同样的路径,否则汇编找不到符号。 - 定义全局宏。加
HC32F460;部分库版本还需USE_DDL_DRIVER。验收:编译不报未定义宏。 - 配置 Target。Xtal(MHz) 填实际外部晶振频率(默认 8);必要时启用 MicroLIB。
- 加载 Flash 算法。
Flash Download里添加 HC32F460 对应.FLM(DFP 自带)。验收:没有No Algorithm found报错。 - 加启动文件。按 4.3 节的四步做。验收:编译日志里能看到
assembling startup_*.s与__Vectors defined in startup_*.o。
Keil 里 Xtal 只是给 IDE 用于换算调试符号地址的参考值,但如果你的代码用 XTAL_VALUE 宏做 PLL 计算,两边不一致就会得到错误的系统频率。改法:system_hc32f460.h 里的 XTAL_VALUE 改成实际晶振频率,然后确认 SystemCoreClockUpdate() 被调用。
4.6 GCC / openEuler drv-frame 路线
如果你偏好 GCC(免费、可进 CI、或需要 openEuler 这类上游社区支持),可行路径有两条:
| 路径 | 做法 | 优点 | 代价 |
|---|---|---|---|
| 直接用 DDL 的 GCC 目录 | 用 DDL 里的 startup_hc32f460.s + hc32f460xe_flash.ld.s,配 arm-none-eabi-gcc | 最贴近官方,示例代码可直接编译 | 启动脚本与 CMake/Make 需要自己写 |
| openEuler drv-frame | 用其 platform/mcu/hc32f460 平台层 | 自带 CMSIS 接口 + HAL + 低功耗管理,结构清晰,有维护者 | 跟随上游版本,非官方支持 |
drv-frame 的 DDL 版本宏、启动文件参数、链接脚本段名(见 4.3 / 4.4 节)就是从官方 DDL 抄过来的,可以作为交叉验证。
4.7 没有 CubeMX 该怎么办
本次核查没有找到类似 STM32CubeMX 或 AT32 Work Bench 的官方配置与代码生成器。这意味着时钟树、外设初始化、引脚复用都得自己写代码。实际影响:
- 好处:不会有「工具生成的代码把外设配错」这类问题,每一行的来源都可查;
- 代价:没有现成时钟配置生成器,第 10 章的 CMU 流程必须自己走一遍;多引脚工程(100 脚)配置工作量不小。
如果官网下载中心后续上线离线工具,以官方为准。
没有生成器的情况下,把「可复用样板」自己攒起来是最划算的投资:把时钟配置、GPIO 初始化、串口重定向、Flash 封装这四段做成自己项目里的 bsp/ 模块,后面所有项目直接拷贝改,比每次重查手册快得多。本文第 5 章与附录 C 就是这套样板。
5 · 第一个工程:从新建到点亮 LED
目标:一小时内让 LED 亮、能下断点、并能通过串口打印。这一章的每一步都给出验收标志,卡住就停在那一步别往下走。
5.1 硬件前提
调试期最小系统只要四样东西:
| 项 | 要求 | 说明 |
|---|---|---|
| 供电 | VCC 按型号给(F460/F4A0 为 1.8~3.6V,L13x 为 1.8~5.5V) | 每个电源引脚都要就近去耦 |
| 调试器 | J-Link 或 CMSIS-DAP(两者都可以) | 只需 SWD 两根信号 + GND |
| BOOT | 确保复位后从主 Flash 启动 | 接可靠下拉,不要悬空 |
| LED | GPIO 驱动,或直接用开发板自带 LED | 先确认 LED 接在哪个引脚 |
第一次上手建议买官方 EVB(如 EVB-HC32F4A0)。板载调试器电路、排针、晶振、Flash 芯片都配好,能省掉一半接线类故障。等自制板跑通后再回来做量产板。
5.2 工程目录组织
建议按下面组织,核心原则是DDL 当第三方库引用而不是搬进自己源码改:
这个结构的好处:升级 DDL 版本时只需替换库目录,不用解冲突;自己的业务代码与驱动代码边界清楚,出问题好定位。
5.3 点亮 LED 的六步
- 确认时钟能跑对。上电后先读
SystemCoreClock,或用 MCO 示波器测输出频率。验收:数值与目标一致。时钟不对就不要往下走 —— 后面所有现象都会失真。 - 配置 LED 引脚。两步都要写:
PORT_SetFunc()选功能 +PORT_Init()配电气属性。验收:读回寄存器值符合预期。 - 配好 SysTick 或定时器时基。
SysTick_Init()之后SysTick_GetTick()能返回递增的毫秒数。 - 配置串口并重定向 printf(见 5.4 节)。验收:串口助手能看到
printf输出。 - 在
main()里下第一个断点。验收:能停在main()入口,能单步走过时钟初始化而不跑飞。 - 翻灯并加断言。用
GPIO_SetPins/GPIO_ClearPins(注意不是 STM32 的 SetBits/ResetBits)翻转,同时开__DEBUG断言。
LED 那一段代码的要点就三句:
/* 1. 复用功能与电气属性分开配置 —— 顺序可换,但两步都不能少 */
PORT_SetFunc(GPIOA, GPIO_PIN_05, Func_GPIO_Port); /* 第 1 步:选功能 */
stc_port_init_t stcPortInit;
PORT_Init(GPIOA, &stcPortInit); /* 第 2 步:配电气属性 */
/* 2. 输出翻转:命名与 STM32 不同 */
GPIO_SetPins(GPIOA, GPIO_PIN_05); /* 不是 GPIO_SetBits */
GPIO_ClearPins(GPIOA, GPIO_PIN_05); /* 不是 GPIO_ResetBits */
凡是「写完没反应」的故障,第一步不是查代码逻辑,而是把寄存器读回来:值是 0 说明外设时钟没开(FCG 未使能);值与预期不符说明配置顺序或宏用错了;值对了还没反应,才去查引脚电气与接线。这个判定顺序能砍掉大量无效搜索。
5.4 printf 与串口重定向
DDL 自带 printf 支持,启用方式很简洁:
/* 1) 让能 printf:ddl_config.h 或编译宏里定义 */
#define DDL_PRINT_ENABLE DDL_ON
/* 2) 初始化串口后调用一次 */
UART_PrintfInit(); /* 宏别名 DDL_PrintfInit */
/* 3) 之后直接用 printf 即可 */
printf("SystemCoreClock = %lu Hz\n", SystemCoreClock);
相关工具函数都在 hc32f460_utility.h:
| 函数 | 实现方式 | 适用场景 |
|---|---|---|
Ddl_Delay1ms() / Ddl_Delay1us() | 软件估算延时 | 短延时,不要求精确 |
SysTick_Init() / SysTick_Delay() / SysTick_GetTick() | 硬件精确延时与毫秒计数 | 需要精确时序与超时管理 |
DDL 还有一套受 __DEBUG 宏控制的断言系统。开发期务必打开:参数越界、非法状态这些在正式版本里会静默出问题,在断言下会立刻停在现场。量产固件再关掉以省体积。
5.5 编译产物与体积核算
第一次跑通后要做一次体积体检,把结论写进项目 README:
| 产物 | 用途 | 关注点 |
|---|---|---|
.axf | 调试镜像 | 带完整符号,供调试器使用 |
.hex | 通用烧录格式 | 含地址信息,绝大多数烧录工具吃这个 |
.bin | 裸机镜像 | 无地址,烧到固定地址;某些脱机烧录器要这个 |
.map | 链接映射报告 | 看 SRAM 占用与函数体积的唯一依据 |
具体核对的三个数:
- Flash 占用 vs 型号容量(注意 F460 有 256KB 与 512KB 两档,选型时就该留余量);
- SRAM 静态占用(data + bss)加上栈预留 vs 可用 SRAM。M0+ 型号尤其紧张,8KB SRAM 用掉 6KB 就该考虑换型号了;
- 哪些模块被链接进去了。
ddl_config.h里那些没关掉的模块会自动编译进来,白占体积 —— 靠 map 文件逐个确认。
HC32L136 只有 8KB RAM。官方 DDL 默认栈 4KB + 堆 3KB 就占掉 87%。这类型号一定要在链接脚本或工程选项里把栈堆调小,并认真评估是否需要动态内存 —— 小 RAM 型号上 malloc 往往是崩溃根源。