沁恒 CH32 开发指南
编制日期 2026-10-14
从 MounRiver Studio 装不起来、WCH-Link 连不上,一路到量产烧录与 USB / PD 开发 —— 一份把「第一次上手会踩的坑」全部前置的工程手册
结论:CH32 的开发链路比同价位 MCU 简单得多 —— 一个 MRS 装完就有「编译器 + 下载器 + 调试器 + OpenOCD」全套,片上 两线 SDI 调试口只需要两个 GPIO,出厂 BootLoader 又留了 USART1 与 USB 两条 ISP 后路。真正让人卡住的从来不是代码,而是三件小事: WCH-Link 停在 ARM 模式没切到 RISC-V、读保护一旦使能就把整片擦掉、USB 时钟没配到 48 MHz 就永远枚举不上。 本文按「装环境 → 建工程 → 编译 → 下载 → 调试 → 量产」的流水线的真实顺序组织,每一段都给出可复制的命令、可对照的表格、以及该段最常踩的坑。
报告总结
沁恒官网把 CH32 的资料拆得非常细:数据手册(DS)讲电气与引脚、参考手册 / 应用手册(RM)讲寄存器、 青稞微处理器手册讲内核、EVT 压缩包含评估板说明与几十个例程,而 MounRiver Studio 的用法又在另一个站点(mounriver.com)。 网上的中文教程绝大多数停留在「用 MRS 新建工程 → 点编译 → 点下载」这一步,一旦遇到连接失败、读保护、USB 枚举不上就无解。本文档做了三件官方分散文档没有做的事:
- 把接力棒画清楚:明确指出「装 IDE」到「能断点调试」之间实际要经过哪几步,以及每一步做完了用什么现象验收。
- 把坑写在坑发生的地方:不单独罗列「常见问题」,而是在讲每个环节时就把该环节的失效现象、原因、处置一起给出。
- 标注来源与版本:所有数值型信息(引脚、电压、容量、寄存器地址、等待周期配置)都追溯到官方 DS/RM 的版本号。
读者路径
本文档共 19 章 + 4 个附录,按「先跑通、再理解」的顺序组织:
- 只想尽快跑通第一个程序:第 4 章(装 MRS)→ 第 5 章(建工程点灯)→ 第 7 章(下载)→ 第 19 章(核查清单),四章足够。
- 要做产品开发:第 2 章选型 → 第 3 章内核差异 → 第 6 章工程结构 → 第 16 章硬件设计。
- 调不通、报错:直接翻第 18 章故障排查速查表,按现象分层定位。
- 要写驱动:第 9 章 GPIO/EXTI → 第 10 章 PFIC → 第 11 章时钟 → 第 12 章外设 → 第 13 章定时器。
- 从 STM32 切过来:第 17 章是专门的移植对照,先看这一章能省两三天。
- 做 USB 或快充产品:第 14 章(含 USBHS 与 Type-C PD 资源矩阵)。
- 做电池产品:第 15 章低功耗,注意「待机模式唤醒等于复位」这件事。
1 · 文档导读与阅读路径
这一章说明本文档的边界:覆盖什么、不覆盖什么,以及为什么把内容按「流水线」而不是按「功能模块」组织。
1.1 覆盖范围
本文档覆盖从拿到一块 CH32 最小系统板,到固件跑起来、能在断点处停下来、并能量产烧录的完整链路:
- 家族与选型:CH32V / CH32F / CH32X / CH32L / CH32M 五大分支的规格对照,以及按「成本 / 主频 / 外设 / 封装」的选型号思路。
- 内核:青稞 V2A / V3A / V4A / V4B / V4C / V4F 的差别,PFIC 中断控制器、HPE 硬件压栈、VTF 免表中断的原理与配置。
- 开发环境:MounRiver Studio 的安装、工具链构成、首次配置、常见安装故障。
- 工程与构建:官方 EVT 工程结构、启动文件、链接脚本、编译选项、体积优化。
- 下载与量产:WCH-Link 三种硬件形态、两种工作模式、SDI 两线/单线接线、串口与 USB ISP、读保护与用户选择字。
- 外设:GPIO / EXTI / PFIC / RCC / USART / SPI / I2C / ADC / DMA / TouchKey / 定时器 / RTC / 看门狗 / USB / PD。
- 硬件与迁移:最小系统电路设计要点、从 STM32 移植的改动清单、批量排障。
1.2 不覆盖什么
以下内容超出本文档范围,需要时请查阅对应官方资料:
- 蓝牙协议栈细节:CH32V208 的 BLE 5.3 协议栈 API、GATT 配置、射频认证(SRRC/CE/FCC)属于独立的无线文档。
- 以太网协议栈深度用法:CH32V307 / V208 的 ETH + LWIP 移植细节属于例程包中的独立示例。
- 每一款封装的完整管脚定义:本文档只给最常用封装的关键引脚(调试、自举、电源、USB),完整管脚表请查对应 DS。
- 寄存器位域全集:RM 有近 300 页寄存器描述,本文档只给关键模块的常用位域,写代码时仍需对着 RM 核一遍。
- 电机算法本身:CH32M007 的 FOC / 无感观测器算法属于电机控制理论,本文档只覆盖它的外设资源与调试接口。
1.3 版本与命名约定
CH32 的命名非常规整,看懂名字基本就能知道它属于哪一档。型号由「前缀 + 系列号 + 细分号」构成:
| 字段 | 取值 | 含义 |
|---|---|---|
| 前缀 | CH32V / CH32F / CH32X / CH32L / CH32M | V = 青稞 RISC-V 内核;F = Arm Cortex-M3 内核;X = 带 USB PD 的连接型;L = 低功耗;M = 电机专用 |
| 系列号 | 0 / 1 / 2 / 3 | 0 = 超值入门(V003);1 = 经典通用(V103/F103);2 = 增强 V2x 系列(V203/V208/F203);3 = 大容量 V3x 系列(V303/305/307/317) |
| 细分号 | 03/05/07/17/35 | 同系列内按资源多少区分,数字越大通常资源越多 |
CH32V203 和 CH32F203 引脚与外设高度一致,但一个是青稞 V4B(RISC-V),一个是 Cortex-M3。
它们的参考手册是同一本 CH32FV2x_V3xRM,但内核部分完全不同 —— 下载工具要切 RISC-V 模式还是 ARM 模式,就是这一位字母决定的。
1.4 事实来源与免责
本文档所有数值型信息来自沁恒官方资料,章节正文中会标注出处。主要来源及版本如下:
| 资料 | 版本 | 提供的内容 |
|---|---|---|
CH32V103DS0.PDF | V1.2(2024-03) | V103 电气参数、引脚定义、封装、自举模式 |
CH32xRM.PDF | V2.0(2025-10) | CH32F103x / CH32V103x 应用手册,286 页,含全部外设寄存器 |
CH32V307DS0.PDF | V3.9(2026-08) | CH32V303/305/307/317 数据手册 |
CH32F203DS0.PDF | V2.5 | CH32F203 数据手册 |
| 青稞处理器产品页与 QingKeV2/V3/V4 微处理器手册 | — | HPE / VTF / XW / PFIC CSR 的定义 |
WCH-Link 产品页与 WCH-LinkUserManual | V2.8 | 调试器接线、模式切换、各芯片调试脚对照 |
沁恒的 RM / DS 修订非常频繁(仅 2026 年 CH32V307DS0 就更新到 V3.9),料号也会按 PCN 变更。文中引用某型号时一定标了版本;
正式立项前请到 wch.cn/downloads 复核目标料号的最新 DS 与 PCN 状态。特别提醒:青稞 V2A 是 RV32E 子集,只有 16 个通用寄存器,
编译选项配错会直接报链接错误,这一点在任何地方都不会被自动纠正。
2 · CH32 家族全景与选型
CH32 不是一个系列,而是沁恒 MCU 业务的整个货架。这一章先把货架摆在桌子上,讲清每个分支的存在理由,再给选型路径。
2.1 一句话认识 CH32
沁恒微电子(WCH,南京)长期做的是「连接」生意:USB 转串口芯片(CH340 系列)、USB HUB、蓝牙、以太网桥接芯片, 这些产品线给它攒下了USB PHY、以太网 PHY、蓝牙射频与协议栈三套自研 IP。CH32 就是在这三套 IP 之上, 配上自研的青稞 RISC-V 处理器内核(以及 Arm Cortex-M3 授权内核)搭出来的 MCU 货架。
这带来两个和其它国产 MCU 不太一样的特征:
- USB 是真强项:CH32V103 就有「1 路 FS Host/Device + 1 路 FS Device」,CH32V307 更是做到 480 Mbps HS 且内置 PHY。做 USB 相关产品时,CH32 往往是成本最低的方案。
- 调试口极省 IO:不用标准 4 线 JTAG,而是沁恒自己的两线 SDI(Serial Debug Interface),CH32V003 甚至只要 1 根线。这对 8 脚、16 脚的小封装意义重大。
2.2 两大阵营:青稞 RISC-V 与 Cortex-M3
选型第一刀永远是内核,因为它决定了整个工具链和调试器形态。CH32 里同时存在两条线:
| 对比项 | CH32V(青稞 RISC-V) | CH32F(Arm Cortex-M3) |
|---|---|---|
| 内核 | 青稞 V2A / V2C / V3A / V4A / V4B / V4C / V4F | Cortex-M3(CH32F103 为 72 MHz,F203 为 144 MHz) |
| 指令集 | RV32EC(V2A)/ RV32IMAC(V3A、V4x)/ RV32IMACF(V4F,带单精度浮点) | Thumb-2 |
| 调试接口 | 两线 SDI(SWCLK / SWDIO),V003 与 M007 支持单线 | 标准 SWD(PA13 / PA14),WCH-Link 切 ARM 模式后即 CMSIS-DAP |
| 推荐 IDE | MounRiver Studio(必选,XW 扩展压缩指令只有它的工具链支持) | Keil MDK 或 MRS 均可 |
| 参考手册 | CH32V:青稞微处理器手册 + 对应 RM | CH32F 与 CH32V 的外设章节共用同一本 RM |
| 中断控制器 | PFIC(快速可编程中断控制器),支持 HPE 硬件压栈与 VTF 免表中断 | 标准 NVIC,16 级嵌套 |
| 系统定时器 | 64 位自增型 SysTick(V3A),HCLK/8 时基 | 24 位自减型 SysTick(内核自带),HCLK 或 HCLK/8 |
同一个外设,在 CH32F 上用 CMSIS 的 NVIC_EnableIRQ(),在 CH32V 上要用 PFIC 的 NVIC_EnableIRQ() 同名函数但走完全不同的实现。
沁恒的库函数把两个平台的 API 名字做成了一样的,底下的寄存器操作完全不同。这意味着移植时不能只看能否编译通过,
要确认所选 SDK 分支与目标芯片的内核一致。
2.3 全家族规格速查
下表把 CH32 主流型号的核心资源拉平对比。所有数字取自官网产品页对应 Revision 的特性清单:
| 型号 | 内核 | 主频 | SRAM | Flash | 关键外设 | 供电 | 封装 |
|---|---|---|---|---|---|---|---|
| CH32V003 | 青稞 V2A(RV32EC) | 48 MHz | 2 KB | 16 KB | 1×USART、1×I2C、1×SPI、10 位 ADC、运放比较器、18 IO | 3.3 / 5 V | SOP8 / SOP16 / TSSOP20 / QFN20 |
| CH32V103 | 青稞 V3A(RV32IMAC) | 80 MHz | 20 KB | 64 KB | USB FS Host/Device、16 路 TouchKey、16 路 12 位 ADC、7 定时器、2×I2C、3×USART、2×SPI、7 路 DMA、51 IO | 2.7~5.5 V | LQFP48 / LQFP64M / QFN48X7 |
| CH32V203 | 青稞 V4B(RV32IMAC) | 144 MHz | 20 KB | 64 KB | 双路 USB FS(1 主/从 + 1 从)、CAN、OPA、10 路 TouchKey、37 IO | 2.4~3.6 V | TSSOP20 ~ LQFP64M 共 9 种 |
| CH32V303 | 青稞 V4F(RV32IMACF) | 144 MHz | 64 KB | 256 KB | 1×USB FS Host/Device、1×CAN、SDIO、FSMC、DAC、8 串口、10 定时器、80 IO | 2.5 / 3.3 V | LQFP48 / LQFP64M / LQFP100 |
| CH32V307 | 青稞 V4F(RV32IMACF) | 144 MHz | 64 KB | 256 KB | USB HS 480 Mbps(内置 PHY)、USB FS OTG、2×CAN、千兆 ETH(内置 10M PHY)、DVP、SDIO、FSMC、TRNG、80 IO | 2.5 / 3.3 V | LQFP64M / LQFP100 |
| CH32V208 | 青稞 V4C(RV32IMAC) | 144 MHz | 64 KB | 128 KB | BLE 5.3(2 Mbps)、10M ETH MAC+PHY、USB FS Host/Device + Device、CAN、53 IO | 2.4~3.6 V | QFN28 / QFN48 / QFN68 / LQFP64M |
| CH32X035 | RISC-V4C | 48 MHz | 20 KB | 65 KB | USB PD + Type-C 控制器及 PHY、PIOC 可编程协议 IO、28 KB SRAM 级 DMA 8 路、2 高级定时器、4×USART、14 路 TouchKey | 2~5.5 V | QFN12 ~ LQFP64M 共 7 种 |
| CH32L103 | RISC-V4C | 96 MHz | 20 KB | 64 KB | USB PD + Type-C PHY、4×USART(LIN/ISO7816)、2×I2C、2×SPI、CAN(部分型号支持 CAN FD)、低功耗定时器、16 外部中断 | 1.8~3.6 V | TSSOP20 ~ LQFP48 共 5 种 |
| CH32M007 | 青稞 RISC-V2C | 48 MHz | 8 KB | 65 KB | 3 Msps 12 位 ADC、高压摆率 OPA、2×CMP、7 路 DMA、内置三相预驱(48 V 双 N / 24 V P+N)、自举二极管与高压 LDO | 6~48 V / 6~24 V | QSOP24 / QFN26C3 / QSOP28 / QFN32 |
| CH32F103 | Cortex-M3 | 72 MHz | 20 KB | 64 KB | 双路 USB FS、CAN、12 位 DAC、16 路 TouchKey、7 定时器、51 IO | 2.7~5.5 V | LQFP48 / LQFP64M / QFN48X7 |
2.4 通用型:CH32V103 / CH32F103
整个 CH32 货架里最稳的那块砖,也是绝大多数 projects 的默认答案。两者外设几乎一模一样、共用同一本 RM,差别只在内核。
CH32V103:青稞 V3A,RV32IMAC,最高 80 MHz。20 KB SRAM / 64 KB CodeFlash,另有 3.75 KB 出厂固化的 BootLoader 区。CH32F103:Cortex-M3,72 MHz。相比 V103 多了一路独立 USB FS Device 与 1 个 CAN 控制器,并带 12 位 DAC。- 供电范围 2.7~5.5 V 且 GPIO 与 MCU 同步供电 —— 这意味着它能直接做 5 V 系统里的主控,省掉电平转换,这在同价位 MCU 里并不多见。
- 封装 LQFP48 / LQFP64M / QFN48X7,与 STM32F103 的封装高度兼容,这也是第 17 章「直接换片」成立的前提。
预算敏感、不需要 5 V 以上到 Case 之外的特殊处理、也不介意用 MRS 开发 —— V103 就是答案。 它的 USB 是 Host/Device 复合,做一个 USB 键盘 / 转串口 / 读卡器时,外围器件数量能压到很低。
2.5 增强低功耗型:CH32V203
V203 的定位是「在不牺牲 144 MHz 性能的前提下把功耗做下去」,官网给出的两个关键数字非常能说明问题:
| 指标 | CH32V203 | 说明 |
|---|---|---|
| 待机模式典型电流 | 0.5 μA | 官网特性清单明确标注,适合纽扣电池长期值守 |
| 运行功耗 | 约 52 μA/MHz | 按 144 MHz 满速估算约 7.5 mA,明显低于同频传统 MCU |
| 主频 | 144 MHz,零等待 | 零等待意味着 Flash 不需要插入等待周期 |
| USB | 双路 FS(1 路 Host/Device + 1 路 Device) | 一路做 USB 升级通道、一路做产品功能,互不干扰 |
| 调试口 | 两线 SDI | PA13 / PA14,与 V103 一致 |
2.6 互联大容量型:CH32V303 / 305 / 307 / 317
这是 CH32 的旗舰线,青稞 V4F 内核(带单精度 FPU)、144 MHz、最高 256 KB Flash / 64 KB SRAM(V307 系列实际登到更高容量档)。 命名和资源的关系大致是:
- CH32V303:大容量通用型。1×USB FS Host/Device、1×CAN、SDIO、FSMC、2×DAC、TRNG、8 组串口(3 USART + 5 UART)、10 组定时器。
- CH32V305:连接型,在 303 基础上增加 USB HS。
- CH32V307:互联型,USB HS 480 Mbps 内置 PHY + USB FS OTG、千兆 ETH 控制器并集成 10M PHY、2×CAN、DVP 数字图像接口。
- CH32V317:官方描述为集成 USB HS PHY 与 100M 以太网 PHY 的版本,选型时要按料号核对 DS。
V103 是「VDD 一个电源搞定」,而 V303/305/307 分成 VDD / VIO / VDDA / VBAT 四路: VDD 给部分 IO 与调压器(含 USB PHY、ETH PHY),VIO 决定 IO 输出电平幅度,VDDA 给模拟部分且电压必须与 VIO 相同。 做原理图时这三路不能随便并到一起,详见第 16 章。
2.7 无线型:CH32V208
V208 是「青稞 V4C + BLE 5.3 + 10M 以太网 MAC/PHY」的组合,64 KB SRAM / 128 KB Flash,144 MHz。 它的价值在于用一颗芯片同时解决无线与有线联网:BLE 做配网与近场维护,ETH 做上行回传,中间不需要再加一颗网络协处理器。
2.8 超值型:CH32V003
沁恒用来打 8 位 MCU 市场的产品。青稞 V2A 内核,RV32EC 子集(只有 16 个通用寄存器),48 MHz,2 KB SRAM / 16 KB Flash, 最小封装做到 SOP8,支持单线调试。
① RV32E 只有 16 个通用寄存器(x0~x15),编译工具链必须配 -march=rv32ec,用普通 rv32i 工具链编译出的镜像跑不起来。
② 2 KB SRAM 极小,任何稍大的全局变量、递归、RTOS 任务栈都要非常克制。
③ V003 的 ADC 是 10 位而不是 12 位,采样精度需求高于 10 位的场景不能选它。
2.9 PDUSB 型:CH32X035 / CH32L103
这两颗的共同点是内置 USB PD 与 Type-C 控制器及 PHY,做快充、PD 诱骗、充电宝、电动工具电池管理时几乎不用外加 PD 协议芯片。
| 型号 | 主频 | 独有资源 | 典型用途 |
|---|---|---|---|
| CH32X035 | 48 MHz | PIOC 可编程协议 IO 控制器、2 组高级定时器、8 路 DMA、14 路 TouchKey、4×USART(LIN/ISO7816) | PD 充电器、 Type-C 多口快充、带屏显的充电产品 |
| CH32L103 | 96 MHz | 1.8~3.6 V 宽压、低功耗定时器、CAN(部分型号 CAN FD)、USB PD + Type-C PHY | 电池供电的便携设备、需要 PD 取电的低功耗终端 |
2.10 电机专用:CH32M007
一颗把三相栅极预驱做进 MCU 的料。青稞 RISC-V2C、48 MHz、8 KB SRAM / 65 KB Flash,12 位 ADC 采样率高达 3 Msps, 内置高压摆率 OPA 与比较器,支持单电阻 / 双电阻电流采样与 3 通道轮询比较器无感定位。
CH32M007K8U7/CH32M007G8R6:内置 48 V 三相双 N 预驱 + 自举二极管 + 高压 LDO,额定 6~48 V。CH32M007E8:内置 24 V 三相 P+N 预驱 + 高压 LDO,额定 6~24 V。- 预驱内含死区控制(防高低侧直通)与欠压保护,这两个都不需要软件兜底。
2.11 料号怎么读
以 CH32V103C8T6 为例,拆解规则如下(沁恒与多数国产 MCU 的命名习惯一致):
| 字段 | 示例值 | 含义 |
|---|---|---|
| 系列前缀 | CH32V | V = 青稞 RISC-V;换成 F 即 Cortex-M3 同资源版本 |
| 系列号 | 103 | 产品线代号,103 为经典通用线 |
| 引脚数代码 | C | C = 48 pin,R = 64 pin,V = 100 pin,K/G = 32/28 pin 区间 |
| Flash 容量代码 | 8 | 6 = 32 KB,8 = 64 KB,B = 128 KB,C = 256 KB |
| 封装代码 | T | T = LQFP,U = QFN / VFQFPN,P = TSSOP,R = 其它小型封装 |
| 温度范围 | 6 | 6 = -40 ~ 85 ℃ 工业级;7 = -40 ~ 105 ℃ 扩展级 |
不同系列的引脚数 / 封装代码映射不完全一致,比如 CH32V003 的 F4P6 是 SOP8 而 V203 的 F6P6 是 TSSOP20。
下单前一定对照该系列的 DS 选型表,不要跨系列套用这两张表。
2.12 选型决策路径
把上面这些收敛成六个问题的决策树,从上往下问,命中即停:
来源:wch.cn 产品页 + CH32xRM V2.0
补充三条不成文经验:
- 第一次接触就买 V103 或 V307 的官方评估板,别直接从最小系统板起步。官方板带板载 WCH-Link 电路与排针,能省掉一半接线类故障。
- 同一产品线内优先选大 Flash 那一档。CH32 各档差价极小,后期发现 Flash 不够的成本远高于差价。
- 需要量产烧录就先确认有没有 WCH-LinkUtility 的命令行接口,别等到产线上才发现只有 GUI 版本。
3 · 青稞 RISC-V 内核:CH32 的真正差异点
很多人把 CH32V 当成「换了编译器的 STM32」,这在写 GPIO 时没问题,但在涉及时序、中断延迟、RTOS 移植时会付出代价。这一章讲清楚青稞到底改了什么。
3.1 青稞处理器家族
「青稞」是沁恒自研 32 位微处理器的总称,遵循并兼容开放 RISC-V 指令集,在此之上加了若干自定义扩展。官网给出的家族表如下:
| 型号 | 指令集 | 硬件堆栈级数 | 中断嵌套级数 | 免表中断通道 | 发射宽度 | 流水线 | 向量表模式 | XW 扩展 | PMP 区域数 |
|---|---|---|---|---|---|---|---|---|---|
| 青稞 V2A | RV32EC | 2 | 2 | 2 | 1 | 2 | 地址 / 指令 | √ | — |
| 青稞 V3A | RV32IMAC | 2 | 2 | 4 | 1 | 3 | 指令 | — | — |
| 青稞 V4A | RV32IMAC | 2 | 2 | 4 | 1 | 3 | 地址 / 指令 | — | 4 |
| 青稞 V4B | RV32IMAC | 2 | 2 | 4 | 1 | 3 | 地址 / 指令 | √ | 4 |
| 青稞 V4C | RV32IMAC | 2 | 2 | 4 | 1 | 3 | 地址 / 指令 | √ | 4 |
| 青稞 V4F | RV32IMACF | 3 | 8 | 4 | 1 | 3 | 地址 / 指令 | √ | 4 |
| 青稞 V5A | RV32IMACBF | 8 | 4 | 2 | 7~9 | 地址 / 指令 | √ | √ | 8 |
几个容易被读漏的点:
- V2A 的指令集是 RV32EC 而不是 RV32I:这是 RV32I 的精简子集,只有 16 个通用寄存器 x0~x15。V003/M007 用的就是这一类,编译选项必须与之匹配。
- 硬件堆栈级数 = 中断嵌套级数:青稞的 HPE 由硬件内部的栈区实现,级数有限。V3A 只有 2 级嵌套;要做到 8 级必须上 V4F。
- 免表中断通道数:V2A 只有 2 路,V3A 及以后是 4 路。这决定了你能把多少个最紧急的中断改成 VTF 方式。
- XW 扩展:V3A 不支持,V4B/V4C/V4F/V5A 支持,在 MRS 里选错内核型号会导致用了扩展指令的代码无法反汇编回来。
- PMP(物理内存保护):V4A 及以后才有,V2A/V3A 内部甚至没有设计 PMP 单元,做安全分区时不能指望它。
3.2 PFIC 快速可编程中断控制器
PFIC 是青稞替代标准 RISC-V PLIC 的方案,也是它对比经典 RISC-V MCU 最大的工程价值。以 CH32V103(青稞 V3A)为例,官方 RM 给的描述是:
| 项目 | CH32F103(Cortex-M3 / NVIC) | CH32V103(青稞 V3A / PFIC) |
|---|---|---|
| 中断总数 | 44 个可屏蔽外部中断 + 10 个内核中断 | 最多支持 255 个中断向量,当前管理 44 个外设中断 + 5 个内核中断 |
| 不可屏蔽中断 | NMI(优先级 -2) | 2 个:NMI 与 EXC |
| 嵌套能力 | 16 级嵌套,优先级可动态修改 | 2 级嵌套中断进入/退出,硬件自动压栈恢复 |
| 快速中断 | — | 4 路可编程快速中断通道,可自定义中断向量地址 |
| 每通道触发/屏蔽/状态 | 由 NVIC 寄存器统一管理 | 每个中断请求有独立的触发位、屏蔽位、状态位 |
| 系统定时器 | 24 位自减型 SysTick,HCLK 或 HCLK/8,优先级 6 | 64 位自增型 SysTick,HCLK/8 时基,校准后可用作时间基准 |
| 软件复位来源 | AIRCR 的 bit2 置 1 | PFIC_CFGR 寄存器 SYSRST 位置 1 |
CH32V103 向量表中编号 0 与 1 都标注为「保留」,编号 2 才是 NMI(-2 固定优先级),编号 3 是 EXC(-1)。
编号 12 是 SysTick,编号 14 是 SWI 软件中断,编号 16 开始才是外设中断 —— 所以数据库主动发中断这件事要走 SWI,
熟悉 Cortex-M 的朋友需要对这个编号偏移有心理准备。
3.3 HPE 硬件压栈
标准 RISC-V 进入中断时需要软件执行一堆 sw 指令把 Caller Saved 寄存器存到栈里。青稞把这件事做进了硬件:
- V2 系列(V003/M007)由硬件自动把 10 个整形 Caller Saved 寄存器(x1、x5、x6、x7、x10~x15)保存到用户堆栈区。
- 压栈顺序为 x1、x5、x6、x7、x10、x11、x12、x13、x14、x15,SP 自动偏移 48 字节。
- 异常返回时由硬件自动从用户堆栈区恢复到这 10 个寄存器。
- HPE 支持嵌套,V2 最大嵌套深度为 2 级。
① 必须使用 MRS 或它提供的工具链编译,通用 riscv-gcc 不知道这套机制。
② 中断函数必须使用 __attribute__((interrupt("WCH-Interrupt-fast"))) 声明;
走软件压栈的普通中断函数则声明成 __attribute__((interrupt()))。
把这两个写反,现象是「中断能进去,但出来后程序跑飞」,极难定位。
3.4 VTF 免表中断
VTF 是在 HPE 基础上再省一步:连中断向量表都不查,直接跳到 ISR 入口。配置方法是:
- 先按正常方式配置中断:使能对应中断线、写好中断使能位与优先级。
- 写中断号:把该中断的中断号写入免表中断 ID 寄存器
PFIC_VTFIDR的某一路通道 x。 - 写入口地址:把中断服务函数的入口地址写入对应的地址寄存器
VTFADDRRx。 - 使能该路 VTF:使能对应通道。
青稞 V2A 只有 2 路 VTF,V3A/V4x 是 4 路。这意味着你最多只能挑选最紧急的 2~4 个中断走这条快车道。 一般留给:电机控制的电流环采样触发、高频脉冲计数溢出、关键的通信超时。
3.5 XW 扩展压缩指令与 WFE
标准 RISC-V 的压缩指令扩展(C)只支持字操作的压缩指令,而嵌入式场景大量出现字节与半字操作。青稞为此增加了八条自定义压缩指令:
| 类别 | 指令 | 作用 |
|---|---|---|
| 加载类 | c.lbu / c.lhu | 压缩形式的无符号字节 / 半字加载 |
| 存储类 | c.sb / c.sh | 压缩形式的字节 / 半字存储 |
| 栈相关加载 | c.lbusp / c.lhusp | 基于 SP 的压缩字节 / 半字加载 |
| 栈相关存储 | c.sbsp / c.shsp | 基于 SP 的压缩字节 / 半字存储 |
这些指令属于沁恒自定义的 XW 子集,只有 MRS 提供的工具链或它的编译器才知道怎么生成与反汇编。这也是「CH32V 必须用 MRS」这条规矩的技术根因。
WFE 指令是另一个非标准扩展:RISC-V 规范里只有 WFI,没有 WFE(Wait For Event)。青稞的做法是——
把 PFIC 中系统控制寄存器的特定位置 1,WFI 指令就变成 WFE 行为。这样做的好处是不占用指令编码空间,
保证了与标准 RISC-V 工具链的二进制兼容性,同时满足了蓝牙等低功耗场景对事件等待的需求。
3.6 和 Cortex-M3 的差异对照
如果你是从 STM32 迁移过来的工程师,这张表比任何文字描述都管用:
| 概念 | Cortex-M3 | 青稞 RISC-V | 迁移时的动作 |
|---|---|---|---|
| 中断控制器 | NVIC,标准 CMSIS API | PFIC,沁恒提供同名函数的适配实现 | 同名但不同实现,换 SDK 分支 |
| 中断优先级 | 抢占优先级 + 子优先级,可分组 | PFIC_IPRIOR 配置,值越小优先级越高 | 原来 0 最低的习惯要反过来 |
| 嵌套 | 16 级 | V3A 只有 2 级(V4F 8 级) | 深度嵌套的软件架构必须改名 |
| 系统节拍 | 24 位自减,一般配 1 ms | 64 位自增,HCLK/8 | RTOS 节拍配置要重算重载值 |
| 调试口 | SWD(PA13 / PA14) | 两线 SDI(同为 PA13 / PA14) | 物理连线一致,协议不同 |
| 位带操作 | 有真正的外设 / SRAM 位带区 | 没有位带,靠 GPIOx_BSHR/BCR 实现原子置位 | 改用 BSHR/BCR |
| 睡眠指令 | WFI / WFE / SEV 三条都有 | WFI + 「把 WFI 变成 WFE」的开关位 | 事件唤醒的写法要改 |
| 中断延迟优化 | 末尾连锁 / 迟到抢占,由 NVIC 做 | HPE + VTF,由软件和 HPE 共同实现 | 关键中断要显式配置 VTF |
| 通用寄存器数 | R0~R15 + 特殊寄存器 | V2A 只有 x0~x15,其余 V3A/V4x 为 32 个 | V003 上写汇编要注意这个 |
来源:青稞处理器手册 + wch.cn 青稞处理器产品页
4 · 开发环境:MounRiver Studio 安装与配置
CH32 的开发环境是「一次性打包」的 —— MRS 把编译器、下载器、调试器、OpenOCD 全装好了。但正因为装得太「自动」,出问题时反而不知道去哪儿找。
4.1 为什么是 MRS
MounRiver Studio(MRS,官网 mounriver.com)由 MounRiver 团队基于 GNU Eclipse 深度定制,是沁恒官方指定的 RISC-V 集成开发环境。
它同时支持 RISC-V 与 Arm 两类内核 —— 这也是为什么同一个调试器(WCH-Link)要区分 RISC-V 模式与 ARM 模式:MRS 都能带,但得告诉它现在带的是哪一类。
官方对它的定位描述是:提供包括定制版 GCC、宏汇编、链接器、调试器、下载器在内的完整开发资源,免费使用。
| 能力 | 说明 |
|---|---|
| 双核开发 | 同一界面下切换 RISC-V / ARM 目标,自动替换工具链与配置 |
| 组件在线更新 | MounRiver Studio II 支持在线更新 SDK、OpenOCD 等模块 |
| 组件发布平台 | 申请账号后可提交自己的组件供其他用户下载(面向方案商的机制) |
| GUI 设计与代码生成 | 内置可视化代码分析与智能补齐 |
| 多种下载方式 | 支持 ISP 等多种下载方式,不局限于自有调试器 |
| 在线异常追踪 | 调试时可即时查错 |
4.2 下载与安装
MRS 的安装包与版本说明在官网 www.mounriver.com 的下载页。安装流程本身是标准 Windows 安装向导,但有四条硬约束:
| 约束 | 原因 | 违反后的现象 |
|---|---|---|
| 安装路径不能有中文、空格 | Eclipse 系工具链对路径很敏感,Makefile 传递时会被截断 | 编译时 make: *** No rule to make target,但文件明明在 |
| 工程路径同样不能有中文/空格 | 同上,且相对路径计算会失效 | 能新建工程但一按编译就报找不到头文件 |
| 不要用带空格的用户目录 | Windows 用户名是中文时尤其致命(C:/Users/张三/) | 工具链报奇怪的 No such file |
| 安装时先关杀软或加白名单 | 工具链里大量 .exe 会被误杀 | 装完发现 riscv-none-embed-gcc.exe 不见了 |
直接装到 D:/MounRiver/MRS_<版本> 这样的短路径;工程统一放 D:/mrs_workspace/;
如果 Windows 用户名是中文,不要用默认的工作空间位置,手动改到 D 盘。
4.3 工具链构成
装完之后,MRS 目录里实际包含了这些东西 —— 知道它们在哪,出问题时才能救:
| 组件 | 作用 | 出问题时的判断依据 |
|---|---|---|
riscv-none-embed-gcc 系列 | 编译、汇编、链接,沁恒定制版 | 命令行敲 riscv-none-embed-gcc -v 能出版本号 |
| 定制 binutils | 生成 hex / bin / map / lst 文件 | objcopy / size 是否可用 |
| OpenOCD(WCH 版) | 调试服务器,认识 WCH-Link 与青稞 SDI | 能否启动并识别到 WCH-Link |
| GDB | 命令行调试 | 能否连上 localhost:3333 |
| WCH-LinkUtility | 独立烧录工具,可脱离 IDE 使用 | 能否单独完成擦除与下载 |
| Link 固件包 | WCH-Link 自身的固件,位于 MRS 与 Utility 安装路径下 | Link 掉固件时用来救砖 |
4.4 首次启动的配置项
MRS 主界面主要由六块区域构成:菜单栏、快捷工具栏、工程目录空间、工程大纲空间、代码编辑空间、输出显示空间。 切到调试视角后会多出反汇编窗口、变量监控窗口、堆栈与断点窗口、内存与外设窗口。
首次使用建议立刻确认三件事:
- 确认工具链路径:偏好设置里看 RISCV 工具链是否指向 MRS 安装目录下的
toolchain/bin,不要让它指向某个系统 GCC。 - 确认 OpenOCD 路径:下载调试配置里指向的 OpenOCD 必须是 WCH 版本,社区版 OpenOCD 不认识青稞的 SDI 协议。
- 插上 WCH-Link 看设备管理器:Windows 下应识别成 WINUSB 设备。出现黄色感叹号就是驱动没装好,这一步没过后面全是白搭。
4.5 安装阶段最常见的五个坑
| 现象 | 原因 | 处置 |
|---|---|---|
| 双击 MRS 没反应 / 闪退 | JDK 缺失或版本冲突;路径有中文 | 确认安装目录下的 jre 完好;把安装目录搬到纯英文短路径 |
| 新建工程向导里看不到 CH32 型号 | 组件包没更新成功 | 联网更新一次组件,或手动导入对应 EVT 支持包 |
编译时报 No such file or directory 但文件在 | 路径含中文/空格,或大小写不一致 | 把工程搬到 D:/mrs_ws/proj 这类路径下重建 |
make: *** [xxx.elf] Error 1 无其它信息 | 链接脚本与实际 SRAM/Flash 容量不匹配 | 检查 Link.ld 里的 MEMORY 段是否与目标料号一致 |
| 设备管理器里 WCH-Link 是未知设备 | 驱动未安装 | 用 WCH-LinkUtility 或官网驱动包重装 WINUSB 驱动 |
来源:mounriver.com + 官方竞赛资料中对 MRS 的描述
5 · 第一个工程:从新建到点亮 LED
这一章的目标非常具体:新建工程、写十行代码、编译通过、下载成功、灯在闪。跑通之后再回头理解原理。
5.1 官方 EVT 例程包结构
每个系列都对应一个 EVT 压缩包(例如 CH32V103EVT.ZIP、CH32V20xEVT.ZIP、CH32V307EVT.ZIP),里面通常包含:
- 评估板说明书 PDF:板子每个跳线、排针、LED 对应的 IO,第一次上手一定要先看它。
EXAM/目录:按外设分目录的示例工程(GPIO、USART、SPI、I2C、ADC、TouchKey、USB Device/Host、RTC、低功耗……)。SRC/或各工程内的公共层:Core、Debug、Startup、Ld、Peripheral。- USB 相关例程:通常会单独给出 CDC / HID / MSC / Host 枚举的完整实现。
不要上来就用向导新建一个空工程。正确顺序是:编译一个官方 GPIO 例程 → 下载 → 看到 LED 行为变化, 这一步能一次性验证「工具链、Link、接线、芯片」四个环节全是好的。之后再把自己代码塞进这个工程里。
5.2 用向导新建工程
MRS 里通过 File → New → MounRiver Project 进入向导。关键选项:
- 芯片系列:选中对应的 CH32 系列(例如 CH32V103)。选错会导致启动文件与链接脚本完全对不上。
- 具体料号:部分版本要求选到具体型号,例如 CH32V103C8T6 —— 这决定了 Flash/RAM 大小。
- 工程模板:选「裸机 + 对应系列」模板,它会自动带出 Core / Startup / Ld / Peripheral 骨架。
- 工具链:默认即可,不要手动改成其它 RISC-V 工具链。
- 完成后先按一次构建,确认「零改动也可以编译通过」。
5.3 工程目录与关键文件
一个标准工程长成下面这样。真正需要你动手的只有 User/ 里的文件,其余四层是骨架:
5.4 编译与产物
点击构建后,MRS 会在工程的 obj/ 目录产出这些文件:
| 产物 | 用途 | 什么时候会用到 |
|---|---|---|
*.elf | 带符号表的可执行镜像 | 调试时必须用这个文件,GDB 靠它找源码行号 |
*.hex | Intel HEX 格式 | 发给产线或用第三方烧录器时 |
*.bin | 纯二进制镜像 | 做 IAP、OTA、自定义 bootloader 时用 |
*.map | 符号地址表 | 查 Stack/Heap 用了多少、函数占用多大 |
*.lst | 反汇编列表 | 排查 HPE / VTF 属性是否真的生效 |
如果 obj/ 里只有 .hex 没有 .elf,调试器即使连上芯片也会「能下载但不能断点」。
这是 link 阶段失败或构建配置里被勾选了「只生成 hex」的典型症状。
5.5 点亮 LED 的完整代码
下面这份代码是 CH32V103 的最小可运行形态。注意三点:时钟默认是内部 HSI 8 MHz;GPIO 属于 APB2 外设必须开对应时钟;
GPIO_WriteBit 走的是 BSHR/BCR 原子寄存器,不存在读-改-写竞态。
#include "debug.h" // 提供 Delay_Init / Delay_Ms / printf 支持
#include "ch32v10x.h" // 外设寄存器定义与库函数
int main(void)
{
GPIO_InitTypeDef GPIO_InitStructure = {0};
/* 1. 延时机初始化(基于 SysTick) */
Delay_Init();
/* 2. 打开 GPIOA 的时钟 —— APB2 外设,漏掉这行 LED 永远不会亮 */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
/* 3. 配置 PA0 为推挽输出,50 MHz */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
while (1)
{
GPIO_SetBits(GPIOA, GPIO_Pin_0); // → BSHR,原子置 1
Delay_Ms(300);
GPIO_ResetBits(GPIOA, GPIO_Pin_0); // → BCR,原子清 0
Delay_Ms(300);
}
}
/* 也可以直接用位翻转:GPIOA->OUTDR ^= GPIO_Pin_0; 但那是读-改-写,中断里不能用 */
| 这一行 | 如果漏了会怎样 | 备注 |
|---|---|---|
RCC_APB2PeriphClockCmd(...) | LED 完全不亮,但编译器和下载都不报错 | 新手第一大坑,GPIO 都在 APB2 上 |
Delay_Init() | Delay_Ms 的时长完全不对(可能是几百倍误差) | 它依赖 SysTick 校准 |
GPIO_Mode_Out_PP | 选成 GPIO_Mode_Out_OD 时必须外加 pull-up 才有高电平 | 开漏输出不驱动高电平 |
结构体初始化 = {0} | 成员是随机值,某些国产库会直接死机 | MRS 的工程里这条是模板自带的好习惯 |
① 编译输出里有明确的 text / data / bss 三行数字;
② obj/ 目录下同时存在 .elf 与 .hex;
③ 下载窗口提示成功,且板载 LED 按 300 ms 节奏翻转。
三条全中,说明「工具链 + 下载链路 + 最小系统」全部正常,可以进入第 7 章正式研究下载原理。