
最近有同事问起合泰单片机的开发方式我顺手把手里那块合泰HT32开发板翻了出来重新走了一遍从零搭建Keil5开发环境的过程。折腾下来发现网上关于HT32的资料确实不多很多细节都得靠翻官方手册和反复试错才能摸出来。这篇文章就用最直白的方式把合泰单片机HT32在Keil5环境下的开发环境搭建完整记录一遍从MDK安装到DFP支持包再到用官方固件库手搓一个最小工程模板最后聊几个容易卡住人的报错和坑。想用HT32做产品或者参加比赛、做课程设计的同学看完这篇基本就能顺顺利利编译下载跑起来了。这个环境不算复杂但有几个地方跟STM32的玩法不太一样。比如HT32的PACK不能靠Keil自动从服务器拉取得手动去官网下载又比如它的Flash起始地址是0x0而不是0x08000000从STM32转过来的朋友最容易在这两个地方栽跟头。本文默认你手上有合泰官方EVB开发板或者至少有一块带SWD接口的HT32核心板下载器用板上自带的e-Link32或者手头的J-Link都行。1. 开发方式选型为什么HT32的主战场在Keil51.1 HT32能用的IDE其实不少但Keil5最省心合泰HT32系列使用的是ARM Cortex-M0、M3、M4内核所以严格来说所有支持ARM内核的IDE都能开发。官方资料里提到过支持Keil MDK、IAR EWARM后来甚至还出了自家基于VS Code生态的HT32 IDE。我实际用下来最推荐新手的还是Keil MDK v5也就是大家常说的Keil5。理由很简单合泰官方提供的HT32 Firmware Library固件库里绝大多数例程都是MDK-ARM工程格式。下载下来解压打开工程选好Device编译下载就能跑。这意味着你不用自己从头配置头文件路径、启动文件、链接脚本这些东西直接站在官方肩膀上改代码就行。Keil5的调试器支持也很全面官方开发板自带的e-Link32调试器在Keil里就是标准的CMSIS-DAP设备即插即用。如果你手头有J-Link同样可以一步到位。相比之下IAR的工程需要自己转换操作繁琐纯GCC工具链虽然能折腾但对于大多数人来说有点杀鸡用牛刀。1.2 库开发优先别一上来就裸写寄存器HT32的开发方式和STM32标准库非常像官方固件库已经把所有外设驱动封装好了。GPIO、UART、SPI、I2C、ADC、定时器等外设都有对应的库函数函数命名风格也能看到标准库的影子。比如时钟模块叫CRM跟STM32的RCC对应配置GPIO输出时用GPIO_Init传入端口和初始化结构体。会一点STM32标准库的人切到HT32上手成本其实很低。很多初学者纠结要不要从寄存器开始学我的意见是除非你要做极端性能优化或者想深入了解芯片内部结构否则直接用固件库。HT32的寄存器手册是英文的命名习惯又跟ST不完全一样自己对着数据手册一个个寄存器抠效率太低还容易出错。先靠库把功能跑通再回头研究寄存器反而理解得更快。1.3 那CMake、VS Code这些能不能替代Keil最近总有人问能不能用CMake加VS Code来开发HT32就像开发STM32那样。答案是可以但没必要作为起点。合泰的PACK、Flash算法、调试脚本这些都是围绕Keil和IAR生态来做的你用VS Code加EIDE插件不是不行只是要自己处理芯片头文件、链接脚本、烧录算法配置成本相当高。我的建议很直接开发HT32就用Keil5把精力花在写代码和理解芯片特性上工具链稳定压倒一切。等哪天真有工程需要自动化构建或者CI集成再考虑引入CMake也不迟。2. 环境安装与DFP支持包先把MDK喂饱2.1 安装MDK-ARM的版本选择与避坑Keil5这个说法其实有点笼统。准确讲ARM生态里对应的是MDK-ARM而现在官网主推的是MDK v5.3x之后的版本有些版本把编译器换成了AC6。安装文件可以从ARM官网的Keil页面下填写基本资料注册一个账号就能拿到下载链接。安装本身没什么技巧一路Next就能装好。但有几个细节值得留意不要装到带中文或者空格的路径里比如D:\开发工具\Keil_v5这种路径后面编译某些老工程时报错会让你怀疑人生。推荐直接默认路径或者用一个纯英文目录。合泰的官方例程很多是用AC5编译器写的而新版MDK默认是AC6。如果你打开官方例程编译直接报一堆莫名其妙的错误十有八九是编译器版本不匹配。解决办法是去Keil官网下载并安装AC5编译器然后在工程Options里的Target选项卡中把编译器切回AC5。注意区分Keil C51和MDK-ARM。很多人电脑上同时装了C51版和MDK版来做8051和STM32但合泰HT32是ARM内核只能用MDK打开用C51直接连工程都建不了。两个版本可以共存装好之后启动的确实是MDK的话新建Project窗口里应该能看到ARM选项。关于许可证MDK的社区评估版对代码大小有限制个人学习做点小项目完全够用。如果公司商用或者代码量超了那就走正常渠道买授权。不要图省事去找什么注册机之类的东西Keil的正版授权在官网上就能买几百块钱的事别给自己惹麻烦。2.2 手动安装HT32的DFP支持包别指望自动拉取这是整个搭建过程里最容易卡住的一步。安装完MDK之后你打开Pack Installer在Device Family里搜索Holtek大概率什么都搜不到。原因是合泰的PACK并不在Keil的默认服务器列表里需要你去合泰官网手动下载。具体流程是这样的打开合泰官网进入32-bit MCU相关页面找到「开发工具与软件」或者「Software」下载区域。搜索你的芯片型号对应的Device Family Pack文件名一般是Holtek.HT32_DFP.x.x.x.pack这种格式。下载下来后不用解压直接双击这个.pack文件Keil会自动导入并安装。安装完成后在Pack Installer的Devices列表里就能看到Holtek栏目展开后能找到具体的HT32型号。如果你手头有合泰官方提供的光盘或者网盘资料里面可能还带旧版本的DFP包建议还是去官网下一个最新版因为旧版有时对齐Flash算法和新型号的支持不够好。装好DFP包之后新建工程时在Device选择界面搜索型号能看到对应的HT32芯片就说明PACK安装成功了。这一步没走通后面全部白搭。2.3 固件库也别忘了下载除了DFP包还需要下载HT32 Firmware Library也就是固件库。这个包是后续建工程的核心里面包含了Libraries目录CMSIS相关文件、芯片头文件、系统初始化文件、外设驱动库源码。Example目录官方例程LED闪烁、串口打印、ADC采集、定时器等常见外设都有现成例子。Utilities目录一些应用层的公共组件。下载解压后建议把整个固件库保存在一个固定的、不含中文的路径下。因为你后面要反复从这里面拷贝文件到工程模板里路径太乱容易找不着。我自己习惯把所有芯片相关的SDK统一放在D:\MCU_SDK\Holtek_HT32\下面需要的时候直接翻。3. 新建Keil工程从目录规划到编译通过3.1 先搞懂官方固件库里哪些文件有用拿到HT32 Firmware Library之后不要急着双击例程先把目录结构看一遍。以HT32F52352这种Cortex-M0型号为例你会在Libraries目录下看到CMSIS和Peripheral两个大目录。CMSIS里面放的是内核相关的核心文件具体到HT32你需要关注这几个core_cm0plus.hCortex-M0内核寄存器定义和内核函数实现这是CMSIS标准文件。ht32f5xxxx.h芯片总头文件所有外设寄存器地址、中断号、外设基地址都在这里相当于STM32的stm32f10x.h。system_ht32f5xxxx.c/h系统时钟初始化SystemInit()函数就在这里。startup_ht32f5xxxx.s汇编启动文件负责建立中断向量表、初始化堆栈、调用SystemInit()和__main是整个程序跑起来的第一行代码。Peripheral目录下则是外设驱动库每个外设对应一对.c/.h文件文件名类似ht32f5xxxx_gpio.c、ht32f5xxxx_crm.c、ht32f5xxxx_usart.c。你用到哪个外设就拷贝哪个不需要把所有外设源文件都加进工程。全加进去不仅编译慢还会因为某些外设依赖的宏没定义而报错。3.2 建目录、拷文件、搭工程框架我不建议直接在官方例程上改因为例程文件杂乱改成自己的模板后也不方便管理。更推荐的做法是建一个干净的模板工程以后复制模板创建新项目相当于把地基打牢。我习惯的工程目录结构长这样HT32_Template/ ├─ User/ │ ├─ main.c │ ├─ ht32f5xxxx_it.c │ └─ ht32f5xxxx_conf.h ├─ Startup/ │ └─ startup_ht32f5xxxx.s ├─ Library/ │ ├─ CMSIS/ │ │ ├─ core_cm0plus.h │ │ ├─ system_ht32f5xxxx.c │ │ └─ system_ht32f5xxxx.h │ └─ Peripheral/ │ ├─ inc/ │ └─ src/ └─ Doc/其中ht32f5xxxx_conf.h是官方库的配置文件里面通过条件编译决定要包含哪些外设头文件同时可以控制断言机制的开和关。ht32f5xxxx_it.c存放中断服务函数比如SysTick_Handler、HardFault_Handler这些模板里可以直接从官方例程复制。文件拷贝来源也很简单打开固件库里任意一个GPIO例程把它里面的User目录下的main.c、ht32f5xxxx_it.c、ht32f5xxxx_conf.h拷出来再把Libraries整个目录拷过来最后把启动文件从相应路径找出来放进Startup目录。官方例程的工程结构已经帮你验证过路径对不对照着抄最稳。3.3 Keil里一步步新建工程新建工程的操作不难但每一步都值得说清楚。打开Keil5点ProjectNew uVision Project选择一个纯英文路径作为工程保存位置。我建议把工程文件直接放在HT32_Template\Mdk子目录下避免工程文件和源码混在一起太乱。保存工程后会弹出Device选择窗口。在搜索框里输入你的芯片型号比如HT32F52352就能看到对应的Device选中后点击OK。正常情况下DFP包安装成功后这里一定能找到找不到就说明第二章里PACK没装好。这一步特别提醒一下合泰HT32的Flash起始地址是0x00000000不是0x08000000。Keil会根据你选择的芯片型号自动填好IROM1和IRAM1的地址范围如果你是从STM32工程改过来的或者复制了别人的配置一定要检查Target选项卡里IROM1是不是0x0开头IRAM1是不是0x20000000开头。这个地址填错了程序烧进去直接跑飞各种诡异现象都会出现。选好Device之后Keil会问你要不要添加Run-Time Environment组件。这里可以直接关掉不需要勾选任何东西。HT32的工程管理沿用传统的分组方式不用CMSIS软件包的方式。接下来在Project窗口里右键Target选择Add Group依次建立四个组Startup放启动文件startup_ht32f5xxxx.s。CMSIS放system_ht32f5xxxx.c、core_cm0plus.h头文件可以不加入工程但加上便于在工程里查看。Peripheral放你实际用到的外设库源文件比如ht32f5xxxx_gpio.c、ht32f5xxxx_crm.c。User放main.c、ht32f5xxxx_it.c、ht32f5xxxx_conf.h。文件添加完毕工程框架算是搭起来了但先别急着编译还有几个关键配置没做。3.4 Options配置宏定义、头文件路径、Debugger一个都不能少右键Target选择Options for Target打开配置窗口。这里面的配置项比较多我按Tab逐个说。Target选项卡确保Device是你选的芯片型号。如果编译器版本选择区域里可选AC5和AC6建议选择AC5因为官方例程老工程在AC6下经常有一堆警告。代码优化等级建议先用-O0方便调试单步跟踪等运行稳定了再改-O2之类的优化等级。C/C选项卡这是最关键的配置页。在Define一栏填入你芯片型号对应的宏比如USE_HT32F52352。这个宏的作用是让芯片头文件知道该编译哪个型号的寄存器定义和中断号。不同型号的宏名不同打开ht32f5xxxx.h看一下条件编译的#if defined语句就能找到准确写法。在Include Paths一栏点击后面的三个点图标把所有头文件所在的目录都加进去至少包括UserLibrary\CMSISLibrary\Peripheral\incStartup路径最好用相对路径即相对于工程所在的.uvprojx文件位置。点击右侧...后勾选每个目录时Keil会自动转换为.\..\User这种相对路径。相对路径的好处是以后整个工程拷贝到别的电脑或者别的目录不用重新配置路径。同一个选项卡里我记得有一个One ELF Section per Function的优化选项建议勾上。它的作用是链接时把没用的函数从最终镜像里剥离能有效减小Flash占用避免函数没用到但编译器非要把整段库编译进去的浪费。Debug选项卡在右上角Use右侧下拉框里选择调试器。如果你用的是板载e-Link32选CMSIS-DAP Debugger如果外接J-Link就选J-LINK/J-TRACE Cortex。选好之后点Settings进入连接配置界面。在Debug页面确认Port是SW模式Max Clock可以先设成1MHz后面连接稳定了再往高调。很多烧录失败的问题其实就是SWD速度设太高导致通信不稳定降到1MHz基本都能解决。Flash Download选项卡勾选Reset and Run这样烧录完成之后芯片会自动复位运行省去手动按复位的麻烦。下方Programming Algorithm列表里要确保有对应容量的Flash算法如果没有点旁边的Add在DFP包提供的算法列表里选择对应芯片Flash容量的算法。比如256KB Flash的HT32F52352就选HT32F52352 256KB Flash那种。配置完这几个Tab关掉窗口顺手在Options里把Use MicroLIB勾上。这个选项在Target选项卡的下方它的作用是启用一个精简版C运行库能大幅减少代码体积同时也是后面重定向printf到串口的前提条件。不过要注意勾选MicroLIB后如果程序里用了比较复杂的标准库功能比如浮点格式化输出部分情况下会有兼容性问题到时候根据实际需求取舍。3.5 写一个最简main.c验证链路配置完之后别急着写复杂业务先保证一个最小程序能编译烧录。清空main.c写入下面这段代码。#include ht32f5xxxx.h void Delay(void) { volatile uint32_t i; for (i 0; i 500000; i); } int main(void) { /* 使能GPIOC时钟LED所在端口以板子原理图为准 */ CRM_PeriphClockCmd(CRM_GPIOC_PERIPH, ENABLE); GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.Pin GPIO_PIN_13; GPIO_InitStructure.Mode GPIO_MODE_OUTPUT_PP; GPIO_InitStructure.Rate GPIO_RATE_50MHZ; GPIO_Init(GPIOC, GPIO_InitStructure); while (1) { GPIO_SetOutBits(GPIOC, GPIO_PIN_13); Delay(); GPIO_ClearOutBits(GPIOC, GPIO_PIN_13); Delay(); } }这段代码干的事很简单打开GPIOC的时钟把PC13配置成推挽输出然后循环拉高拉低实现LED闪烁效果。不同型号的HT32开发板LED接的引脚可能不一样可能是PB4、PA8之类的抄代码前先翻一下你手上板子的原理图把端口和引脚号改掉。函数名在不同版本的固件库里可能略有差异比如端口宏有的版本写作GPIOC有的版本写作HT_GPIOC以你下载的固件库例程为准。写完之后点编译按钮正常情况下应该0 Error 0 Warning通过。4. 下载调试与问题排查别让板子卡在最后一步4.1 e-Link32连接设置程序编译通过下一步就是烧录。合泰官方开发板上的调试器通常是e-Link32它对外是一个CMSIS-DAP兼容调试器所以Keil里选择CMSIS-DAP Debugger就行。把USB线插到开发板的调试口此时Windows应该会识别出一个CMSIS-DAP设备。如果设备管理器里看到黄色感叹号或者Unknown Device多半是USB线的问题或者调试器驱动没装好。Keil里点Download按钮正常情况下Flash Download进度条会很快走完然后程序自动复位运行板载LED开始闪烁。这一步跑通整个开发环境就算是彻底搭好了。如果第一次下载失败先不要慌多数情况不是工程配置的问题而是连接不稳。检查一下USB线是不是数据线很多线只能充电不能传数据这个坑太常见了再看看开发板有没有独立供电开关。SWD接口如果是杜邦线外接的线长尽量控制在10厘米以内线越短越稳。4.2 你可能会遇到的几个报错直接抄答案新手在环境搭建阶段摔跤太正常了我把高频报错整理成了速查表照着排查就行。报错现象可能原因解决办法No ULINK/ME or CMSIS-DAP Device Found调试器没识别到驱动没装好检查USB线是否为数据线重新插拔查看设备管理器是否识别到CMSIS-DAPRDDI-DAP Error目标板没上电SWD接线松动确认板子供电重新插紧线缆把SWD速率降到1MHzFlash Download failed - Target DLL has been cancelled芯片型号选择不对Flash算法缺失检查Device是否选对Flash Download里确认有对应Flash算法Undefined symbol SystemInit启动文件里调用了SystemInit但没把system_ht32f5xxxx.c加入工程在CMSIS组里添加system_ht32f5xxxx.cL6218E: Undefined symbol GPIO_Init外设库源文件没加入工程把ht32f5xxxx_gpio.c等用到的库文件加入Peripheral组cannot open source input file xxx.h头文件路径没配好回到C/C选项卡补全Include Paths编译没问题但下载后程序不运行启动文件缺失Flash地址配置错误确认工程含启动文件Target里IROM1起始地址是否为0x0HardFault发生在启动阶段时钟初始化异常或者向量表偏移问题确认芯片型号宏定义跟实际型号一致4.3 几个更容易忽略的日常使用技巧整个环境搭好之后我再分享几个平时用Keil开发HT32时特别顺手的小技巧。第一个是关于工程模板的复用。我把搭建好的最小工程复制一份命名为模板基地每次新项目直接复制这个文件夹改名后打开工程重新选一次Device再改宏定义和Include Paths里的相对路径即可。不用每次从零建工程效率至少提升一半。第二个是左侧工程树不见了的问题。有时候不小心关了Project窗口很多人到处找怎么调出来。其实在菜单栏View选项卡里点Project Window左侧就会恢复或者直接快捷键AltP。第三个是编译很慢的问题。很多人把所有外设库源文件一股脑加进工程编译一次十几秒。实际上没用到的那部分外设源文件完全可以不加只用你代码里实际引用的几个外设驱动。另外勾选One ELF Section per Function之后最终会去掉多余函数但编译速度不会因此变快想快就尽量从源头上只保留必要的文件。第四个是关于printf重定向。HT32做串口调试打印时通常需要重定向fputc函数到UART发送接口。这个操作网上很多文章在讲STM32时都会说但HT32的UART寄存器结构和ST不完全一样重定向代码不能直接照搬。建议等后面用到串口时从官方例程的UART工程里抄一份现成的重定向实现别自己拼写寄存器代码。最后一个提醒是关于项目路径的。Keil历史上对中文字符和特殊符号的支持一直不太友好虽然新版有所改善但为了不给自己找麻烦工程路径保持纯英文是最稳妥的选择。把工程项目放在云盘同步目录里的同学也要注意有些云盘的同步机制会锁文件导致编译时报无法打开文件尽可能用本地目录开发。环境这块做到这里基本上就齐活了。我自己的感觉是合泰HT32虽然生态比不上STM32那么庞大但官方固件库的完整度和例程覆盖度足够撑起项目开发。很多看起来唬人的问题比如Flash下载失败、编译报错本质上都是PACK版本不匹配、路径配置错误或者SWD连接不稳定这几类原因。前期把这些基础工作做扎实后面写功能代码时会顺畅很多。如果你也是第一次接触合泰的板子建议把整个流程完整走一遍别跳过PACK安装和工程配置。照着官方例程先跑通一个LED闪烁再慢慢往外设去扩展这是最稳妥的学习路径。下一篇我准备把HT32的串口调试讲一讲包括printf重定向和常见串口乱码的处理思路到时候咱们接着聊。