简介:面向嵌入式开发者与单片机工程师,辉芒微32位MCU库与Keil MDK-ARM DFP 1.0.5整合包,主要解决FT32F072XB等基于Cortex-M0内核的芯片在Keil环境下缺少设备支持包、库函数不完整、工程模板难以搭建等问题。压缩包共130个文件、约33.91MB,包含c/h源文件、uvprojx工程文件、pdf参考手册、hex/axf烧录文件及o/crf等编译中间文件,既有可直接编译的工程模板,也有详细使用说明,便于对照学习。已有649人学习浏览。借助预先优化的库函数,开发者可快速操作GPIO、定时器、串口等外设接口,配合内置示例工程与配置文档,缩短开发周期;同时支持低功耗、高性能的Cortex-M0架构,适配工业控制与消费电子等嵌入式场景,适合有C语言基础、正在基于辉芒微MCU做实际项目的工程师。 前段时间做项目选型,供应链给了一颗辉芒微的32位MCU样片,FT32F030系列,说这颗料在国产替代上很能打,价格比ST便宜不少,供货也稳定。我拿到手的第一反应不是看数据手册,而是先把开发环境跑通——毕竟芯片再便宜,环境搭不起来一切白搭。结果在Keil5的DFP(Device Family Pack)这一步就被卡了一晚上,版本对不上、芯片列表里搜不到、烧录算法加载失败,各种问题轮着来。
后来把辉芒微官方提供的DFP 1.0.5装好、固件库的工程模板搭起来,才真正体会到这颗芯片用起来有多顺。说实话,辉芒微的32位MCU和STM32F0系列在引脚和寄存器层面兼容度非常高,固件库的写法也几乎一模一样,从ST生态转过来基本没什么学习成本。这篇博文就把我从零搭建Keil5开发环境、安装DFP 1.0.5、用固件库建工程、以及一路踩坑的过程完整记录下来,给准备上手辉芒微32位MCU的朋友做个参考,尤其是那些已经在用Keil MDK的老手,看完这篇文章基本能无缝切换。
1. 辉芒微32位MCU与开发工具链的整体认识
1.1 一款能“无缝替换”的国产Cortex-M0芯片
辉芒微电子(FMD)过去在8位MCU领域做得非常扎实,FT60E和FT61F系列在电饭煲、电磁炉、小家电这些市场占有率很高。近几年他们把重心转向32位MCU,推出了FT32F系列,内核是ARM Cortex-M0,主频最高到72MHz,Flash从16KB到256KB都有覆盖,几乎就是对着STM32F030/031/051这几颗经典料型做的定位。
我手上这颗FT32F030F8P6,TSSOP20封装,64KB Flash、8KB SRAM,3路USART、2路SPI、2路I2C、1个12位ADC、4个16位定时器,外设配置和STM32F030F4P6简直像是双胞胎。这也意味着项目里原来写的ST代码,改改头文件就能往辉芒微上搬,硬件上也经常可以直接贴板使用而不需要改原理图。不过要注意,是完全兼容还是基本兼容,需要仔细核对具体型号的引脚定义,特别是电源引脚和BOOT引脚的差异。这一点我后面在实战环节会专门讲。
1.2 为什么选择Keil5+DFP方案
辉芒微官方提供了两种开发环境支持:一是基于VSCode的fmd-ide v3.1.3,二是直接支持Keil MDK5的设备支持包。我个人的建议是,如果你之前用STM32,直接用Keil5加DFP是最平滑的过渡路径。
Keil5从MDK5.0版本开始引入了Pack(软件包)管理机制,芯片厂商只需要按照ARM CMSIS的标准封装一个DFP,包含SVD调试描述文件、Flash Algorithm烧录算法、启动文件、设备寄存器定义这些内容,用户装进Keil后就能在Device选项里直接选到对应的芯片型号。辉芒微的DFP 1.0.5会把整个FT32F系列的型号都加进来,一次性搞定选型、调试、烧录三件事。
为什么强调用DFP而不是手工添加各种文件?因为DFP把所有底层的、针对每颗芯片定制的东西都封装好了。比如Flash算法,芯片的Flash操作时序不同,必须要有对应的FLM文件烧录器才知道怎么写入,这种文件手工去搞非常容易出错,用官方DFP自动挂载就省心得多。如果你是从8位MCU转过来的,可能会习惯手工去配置烧录参数,但在Cortex-M的世界里,用官方Pack是标准姿势,也是效率最高的选择。
2. DFP 1.0.5安装的完整操作流程
2.1 正确下载DFP包的两种方式
先说下载DFP的渠道,很多人会在这个环节被“假官网”或者过期的下载链接坑一把。目前最靠谱的方式有两个:
第一种是通过Keil内置的Pack Installer搜索。打开Pack Installer(在Keil MDK的工具栏图标里能找到,或者从菜单Project -> Manage -> Pack Installer进入),然后在右侧的Packs标签页搜索框输入“FMD”或“辉芒微”。如果网络正常,一般能搜到FMD.FT32Fxx_DFP这个包,点击Install安装即可。国内网络环境下有时候会卡在下载环节,进度条半天不动,那就是网络问题了。
第二种是去辉芒微官网下载DFP安装包,然后双击离线安装。搜索“辉芒微电子官网”,进入下载中心找到FT32F系列的开发工具栏目,下载DFP 1.0.5这个文件,解压后双击里面的Pack文件,Keil会自动识别并安装。如果Pack Installer一直刷新不出来,直接走这个离线安装路径,速度快,也不依赖网络环境。
2.2 离线安装DFP后的关键验证步骤
安装完成后,千万别直接就开始建工程,先花一分钟验证一下装好了没有,避免后面所有步骤全部白做。验证分两步:
第一步,在Keil的Pack Installer里查看Installed列表,确认FMD.FT32Fxx_DFP 1.0.5已经出现在已安装列表中,并且没有黄色感叹号图标。如果有感叹号,说明依赖的某个组件(比如CMSIS版本太低)不满足,需要先升级对应的组件。
第二步,随便新建一个工程,在Device选择对话框中输入“FT32”搜索,看能不能搜到具体的芯片型号。能搜到FT32F030、FT32F031、FT32F072这些型号,就说明DFP正常工作了。我在这一步遇到的问题比较典型:安装时一切正常,但搜索芯片却搜不到。后来发现是因为Keil启动时没有重新加载Pack,重启Keil5就好了。所以装了Pack之后记得先重启Keil,再继续后面的操作。
3. 用辉芒微固件库搭建Keil5工程模板
3.1 认识固件库的核心架构
辉芒微的32位固件库(FMD Standard Peripheral Library)结构上和ST的标准外设库几乎如出一辙。库的主要功能是把寄存器操作封装成函数,比如GPIO配置、UART收发、ADC采样这些,开发者不需要去翻寄存器手册记那一堆偏移地址,直接调用库函数就行了。
库的核心文件我整理了一张表:
| 文件(夹)名 | 作用 |
|---|---|
| fmd32f0xx.h | 芯片寄存器地址定义合集,所有外设的寄存器结构体都在这 |
| system_fmd32f0xx.c | 系统时钟初始化函数SystemInit(),以及SystemCoreClock全局变量 |
| startup_fmd32f0xx.s | 启动文件,定义栈空间、中断向量表、复位入口 |
| fmd32f0xx_gpio.c/h | GPIO配置读写函数 |
| fmd32f0xx_rcc.c/h | 时钟使能、复位控制函数 |
| fmd32f0xx_usart.c/h | 串口收发驱动 |
| fmd32f0xx_spi.c/h | SPI总线驱动 |
| fmd32f0xx_i2c.c/h | I2C总线驱动 |
| fmd32f0xx_adc.c/h | ADC采样配置驱动 |
| fmd32f0xx_tim.c/h | 定时器配置驱动 |
一眼看上去,这些文件名和ST标准库的文件名惊人地相似,实际用起来也确实差不多。但这里必须提醒一句:寄存器地址和库函数内部实现的细节还是不一样的,你在ST工程里写的代码,复制过来能编译通过,但底层硬件不同,寄存器配置最终会映射到不同地址上。所以代码可以借鉴,但别以为完全的API兼容,尤其是涉及芯片UID、Flash操作这些底层功能的地方,一定以辉芒微的库为准。说白了,就是“神似而型不似”,别被表面相似给骗了。
3.2 从零新建工程的12个关键步骤
直接上干货,我从新建一个空工程开始,到点灯成功为止的操作步骤:
第1步:新建工程文件夹,在本地磁盘上创建工程根目录,建议命名为“FT32F030_Demo”,如果后续有版本管理需求,这一步就同步建立Git仓库。
第2步:打开Keil5,选择Project -> New uVision Project,工程文件命名后保存到刚才创建的文件夹。
第3步:选择芯片型号,在Device对话框搜索“FT32F030”,选择你自己的实际型号,点击OK。如果这个步骤里搜索不到芯片,回头检查DFP安装是否成功。
第4步:在弹出的Run-Time Environment对话框中,点Cancel。这一步很关键,Keil默认会让你勾选CMSIS的组件,因为我们之后会从辉芒微官方固件库添加文件,这里全部不勾选,保持工程干净。
第5步:在工程中新建分组。在Target1上右键 -> Manage Project Items,把默认的Source Group 1重命名,推荐建这几个分组:Startup(启动文件)、FWlib_Source(固件库源文件)、User(用户代码)。
第6步:拷贝固件库文件到工程目录。从辉芒微官方固件库压缩包中,找到CMSIS和StdPeriph_Driver两个文件夹,整体拷贝到刚才的工程根目录下,这是库文件的物理基础。
第7步:把启动文件添加到Startup分组。在固件库的Device文件夹下找到startup_fmd32f0xx.s文件,右键Startup分组 -> Add Existing Files,选择这个文件。没有启动文件,芯片上电后连C环境都建立不起来,这个缺失会导致程序完全无法运行。
第8步:把固件库源文件添加到FWlib_Source分组。固件库目录下的src文件夹里有一堆.c文件,全选添加进去。或者按需添加,只加你用到的外设模块,比如这个点灯工程只需要RCC和GPIO,但是为了后面开发省事,建议全部添加,编译通过不影响代码体积。
第9步:配置头文件路径。点Options for Target -> C/C++选项卡,在Include Paths一栏点击右侧的“...”按钮,确保以下路径都被添加进去:工程根目录下的FWlib/inc、CMSIS/Include、以及用户代码目录。这个配置不做好,编译时就会报“fmd32f0xx.h: No such file or directory”。
第10步:配置预处理宏。在C/C++选项卡的Define一栏,填入“USE_STDPERIPH_DRIVER”。加这个宏是为了让库文件中的条件编译部分生效,让库的接口函数能被正常调用。如果你用的是FMD32F030系列,还需要确认是否需要在Define里定义具体的型号宏(比如FMD32F030x6),具体参考库包里的说明文档,不同版本的库要求不一样。
第11步:配置调试器和烧录算法。点Options for Target -> Debug选项卡,选择你的调试器类型(ST-Link、J-Link、DAP-Link,因为Cortex-M0统一走CMSIS-DAP,调试器兼容性很好)。然后点击Settings,进入Flash Download页面,点击Add按钮,在列表里找到“FT32F030 Flash”这个烧录算法并添加。这一步直接决定了你下载程序时会不会报“Flash Download failed”。
第12步:配置晶振频率和优化选项。在Target选项卡中,晶振频率(Xtal)填入“8.0MHz”或你板子上实际焊接的晶振频率,没接外部晶振就填内部RC,比如8MHz。在C/C++选项卡中把优化等级设为-O0,方便调试;在Output选项卡中勾选Create HEX File,方便后续量产烧录。
3.3 点亮一颗LED的实战解析
工程框架搭好之后,写一个最简单的点灯程序验证全链路。先看代码:
#include "fmd32f0xx.h" void Delay_Init(void); void Delay_ms(uint32_t ms); int main(void) { GPIO_InitTypeDef GPIO_InitStructure; /* 使能GPIOC端口时钟,如果你用的是PA1或PB5,这里改成对应的RCC宏 */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); /* 配置GPIOC Pin13为推挽输出,初始状态为高电平 */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOC, &GPIO_InitStructure); /* 初始化延时,这里我用定时器或者简单循环都可以 */ Delay_Init(); while (1) { GPIO_WriteBit(GPIOC, GPIO_Pin_13, Bit_RESET); /* 输出低电平,点亮LED */ Delay_ms(500); GPIO_WriteBit(GPIOC, GPIO_Pin_13, Bit_SET); /* 输出高电平,熄灭LED */ Delay_ms(500); } }这里有几个小知识点值得展开:
GPIO模式里我用了GPIO_Mode_OUT,在ST的标准库中这个模式对应的是通用推挽输出。辉芒微的库在命名上保持了同样的风格,不过有的版本还会细分GPIO_Mode_Out_PP和GPIO_Mode_Out_OD,如果你手头的库版本不一样,注意看一下头文件里的枚举定义,选推挽输出那个即可。推挽输出意味着引脚既可以输出高电平、也可以输出低电平,驱动能力足够直接点亮一个LED;开漏输出则只能主动拉低,高电平需要外部上拉电阻,驱动LED不方便。
关于延时函数,点灯不需要高精度,我这里是按简单的循环做了个粗糙延时。如果后续你需要精确延时,建议用定时器,初始化SysTick或者TIM,然后做一个基于中断的时基,这样整个系统的时间基准就统一了。
编译、下载后,板子上的LED应该开始600ms间隔交替闪烁。如果你在这里就卡住了,看第4章的排查表。
4. 实战中容易踩坑的典型问题与排查方法
4.1 编译阶段的报错处理
报错1:“fmd32f0xx.h: No such file or directory”。这个是最常见的,原因就是头文件路径没配好。回到Include Paths里检查,确认每一个用到库文件头文件的目录都被加进去了。注意Keil的路径分隔符是英文分号“;”,不要用中文输入法输入。
报错2:“...\core_cm0.h(29): error: #5: cannot open source input file "core_cmFunc.h"”。这个报错是启动文件和固件库中用到了CMSIS内核相关的头文件,但CMSIS目录没有被正确引用。检查一下工程里有没有把CMSIS的CoreSupport目录加到Include Paths,如果缺失,去Keil安装目录下的ARM/PACK/ARM/CMSIS里找一下,把这个路径加进去,或者直接从固件库包里的CMSIS文件夹引用。
报错3:“Error: L6218E: Undefined symbol SystemInit”。这个报错说明链接器找不到SystemInit函数。常见原因是你把启动文件添加了,但没有把system_fmd32f0xx.c添加到工程里,或者添加了源文件但头文件路径不对。解决方法是把固件库里的system_fmd32f0xx.c加入FWlib_Source分组,然后重新编译。
4.2 下载烧录阶段的故障排查
烧录不进去是整个过程中最让人抓狂的,我整理一个速查表:
| 故障现象 | 可能原因 | 解决方法 |
|---|---|---|
| Flash Download failed - Target DLL has been cancelled | Flash算法(编程算法)没有添加 | Debug -> Settings -> Flash Download,点击Add,选择FT32F030 Flash |
| Error: Flash Download failed - Target DLL has been cancelled | 芯片型号选错,选成了同系列但Flash内存大小不同的型号 | 在Device里重新选择与实际芯片匹配的型号 |
| No Target connected | SWD接口接线错误或者调试器没识别 | 检查SWDIO和SWCLK接线,确认调试器驱动已安装 |
| RDDI-DAP Error | SWD时钟频率太高 | 在Debug -> Settings -> Debug标签中把下载速率降到1MHz以下 |
| 下载成功但程序不运行 | BOOT引脚电平配置错误 | 检查BOOT0引脚电平,运行模式应该接低电平 |
我在实际项目中遇到一个比较隐蔽的问题:DFP装好了,工程也建好了,但下载时一直提示No Target connected。查了好久发现是STM32和辉芒微的SWD引脚定义虽然都是PA13和PA14,但是开发板上的丝印标注有差异,我把杜邦线接错了引脚位置,换过来就好了。所以拿到一块新板子,第一件事一定是对着原理图核对SWD引脚的物理位置,不要凭STM32的经验想当然。
还有一个高频问题:程序下载成功后,复位也不运行。后面排查发现是BOOT0引脚悬空导致的,芯片进入了串口下载模式而不是运行模式。把BOOT0接一个10K下拉电阻到GND,问题就解决了。很多山寨的最小系统板默认把BOOT0设计成悬空,这是个大坑。
4.3 时钟配置相关的注意事项
时钟是一切外设工作的基础,而这个部分最容易在移植的时候出错。辉芒微的库函数里,SystemInit()会在启动流程中自动调用,它会根据宏定义选择合适的时钟源。你可以再检查一下关于时钟初始化的配置,比如是否定义了FMD32F030x6,以及是否在SystemInit阶段就把系统时钟切换到外部晶振。
如果没有接外部晶振,而SystemInit却配置成HSE,芯片的时钟就会卡在那个等待超时的循环里,表现出来就是程序下进去后,一切功能都不正常。正确的做法是:确认你的板子有没有外部晶振,没有就保持默认的内部HSI(高速内部RC振荡器)时钟源即可,HSI的精度在常温下是±1%,对大多数量计时和通信场景够用。如果有外部晶振,确认频率值写入正确,别把8MHz写成12MHz,然后系统时钟倍频到72MHz。
5. 基于DFP 1.0.5开发流程的体会与后续扩展建议
5.1 芯片选型和开发流程设计的几点经验
用辉芒微32位MCU做了几个功能验证后,我最大的感受是:这颗料是真的为替代而生的。从Keil建工程到点灯,顺利的话不到十分钟就能搞定,对比很多国产芯片厂商要把一堆文档翻一遍才能把工程跑起来,辉芒微在开发体验上做得相当不错。
在选型上我的建议是,如果你现在用的是STM32F030系列,只要核对一下Flash/RAM容量和外设数量,很多项目可以直接切换到辉芒微,基本的代码都可以复用,硬件上大部分情况可以直接替换。这样做的好处是供应链上多了一个备选,价格和交期都更有保障。如果你用的是STM32F031或F072,也是类似的逻辑,同样要找对应型号做对照。
不过要提醒的是,32位MCU领域辉芒微还是后进入者,生态资料相比ST还是少很多,遇到问题可能需要更多自己去翻手册和源码。建议在项目评估阶段就下载好完整的参考手册和固件库,把关键引脚复用和时钟树大概过一遍,心里更有底。
5.2 从点灯到实际项目的扩展思路
点灯只是第一步,接下来可以按这个顺序逐步深入:
第一,把串口工程调通。串口是嵌入式调试的“眼睛”,把printf重定向到串口输出,后续所有调试都能省一大半力气。辉芒微库里面有完整的UART驱动,只需要配置好波特率,实现fputc函数即可。
第二,基于定时器的系统时基。把SysTick配置好,构建一个毫秒级时基,在此基础上可以实现软件定时器、超时判断、任务调度等机制,这是裸机项目结构化的基础。
第三,ADC采样与数据滤波。辉芒微的ADC模块支持12位采样,写一个周期采样DMA传输的代码,实际感受一下采样精度和稳定性。这个过程中注意参考电压引脚和采样保持时间的配置,这两点是最容易出问题的地方。
第四,如果需要低功耗应用,可以考虑把芯片跑在Stop模式,然后通过外部中断或定时器唤醒。Cortex-M0的功耗控制还是很灵活的,配合辉芒微在设计上的优化,整体待机功耗可以控制得很好。
5.3 多环境开发选项:fmd-ide与IAR等工具链
补充一个点:如果你的主力开发环境不是Keil,辉芒微也提供了其他路径。它家的fmd-ide v3.1.3是基于VSCode改装的一体化IDE,界面就是大家熟悉的那套VSCode操作逻辑,装好之后可以直接编辑、编译、下载。对于习惯GCC工具链的工程师,或者不想用盗版Keil的人,fmd-ide是很好的替代方案。
另一个选择是IAR for ARM,新版IAR对辉芒微FT32F系列也有支持,不过在DFP和工程模板的完善度上,还是Keil生态更成熟。我的建议是:团队如果都在用Keil,就统一用DFP方案;个人开发或者团队偏向开源工具链,可以试试fmd-ide。
5.4 电源、PCB和量产阶段容易被忽略的细节
最后聊聊DFP安装之外、但是做产品跑不掉的一些细节。辉芒微FT32F系列和所有MCU都一样,电源引脚附近一定要配去耦电容,典型配置是每个VDD引脚并联一个100nF陶瓷电容,最好再加一个4.7uF的钽电容或者电解电容。如果电源纹波大,ADC采样值会有明显跳动,这种硬件问题软件怎么滤波都只能缓解不能根治。
量产阶段还有一个不少人会忽略的地方:芯片虽然和STM32引脚兼容,但擦写次数、Flash编程电压这些参数并不完全一样。在做量产烧录和固件升级方案的时候,不要直接把为ST芯片设计的烧录器配置文件搬过来用,要用官方DFP里自带的Flash算法重新生成烧录文件。我自己在验证时发现,用ST的Flash算法去烧辉芒微的芯片,大概率会直接报错,就算侥幸烧进去,稳定性和可靠性也是没有保障的。
把这些坑都一一填平,辉芒微32位MCU用起来确实很顺手。从DFP安装一路走到量产烧录,整个闭环打通的体验比我想象中顺畅。这篇文章记录的踩坑过程,希望对准备入坑的朋友有一些帮助。我自己在实际操作中收获最大的一点是:永远不要凭经验想当然,即使是宣称兼容的芯片,也要在拿到样片后重新走一遍完整的开发流程验证,这既是对项目负责,也是对自己的时间负责。
本文还有配套的精品资源,点击获取