ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

STM32CubeMX从入门到精通:图形化配置、HAL库与FreeRTOS实战指南

STM32CubeMX从入门到精通:图形化配置、HAL库与FreeRTOS实战指南 嵌入式开发这行干久了你会发现一个很有意思的现象十年前大家还在为寄存器配置和启动文件里那一堆汇编代码头疼现在刚入行的新人直接打开一个图形化工具鼠标点几下就能把时钟树、外设引脚、中断优先级全部配好代码框架自动生成。这个工具就是STM32CubeMXST官方推出的图形化配置工具。它把芯片选型、引脚分配、时钟树配置、外设初始化、中间件集成这些原本需要翻几百页参考手册才能搞定的活儿变成了可视化操作。不管你用的是F1、F4还是最新的H7、G0系列只要装了对应的固件包都能在同一个界面里完成配置。这篇文章我打算把STM32CubeMX从下载安装到实际项目配置的完整流程拆开讲一遍包括中文界面怎么设置、HAL库代码怎么生成、FreeRTOS怎么集成、SPI读写W25Q64这类典型外设怎么配以及我在实际使用中踩过的那些坑。适合刚接触STM32的新手也适合想从标准库转到HAL库的老玩家参考。1. 这个工具到底解决什么问题1.1 从寄存器配置到图形化生成的演进逻辑早些年开发STM32流程是这样的先翻数据手册确认引脚复用功能再翻参考手册找到对应寄存器的位定义然后手动写RCC配置、GPIO初始化、NVIC设置。一个简单的串口通信光初始化代码就得写几十行还得反复核对时钟使能有没有漏、引脚模式有没有配错。更麻烦的是换芯片的时候比如从STM32F103换到STM32F407引脚分布变了、时钟树结构变了、外设寄存器地址也变了之前写的初始化代码基本要推倒重来。STM32CubeMX的核心价值就在于把这套流程标准化了。它内置了ST全系列芯片的数据库每颗芯片的外设资源、引脚复用表、时钟树结构、电气参数都在里面。你选好芯片型号之后工具会自动限制可配置的选项比如某个引脚不支持SPI功能你在配置SPI的时候就不会看到这个引脚出现在可选列表里。这种约束机制从源头上避免了很多低级错误。另一个关键点是HAL库的配套。CubeMX生成的代码是基于HAL库的HAL库把寄存器操作封装成了函数调用比如HAL_GPIO_WritePin()、HAL_UART_Transmit()。这样做的好处是代码可移植性大幅提升同一套应用逻辑在不同STM32系列之间迁移的时候底层驱动基本不用改。代价是代码体积变大、执行效率比直接操作寄存器略低但对于大多数应用场景来说这点开销完全可以接受。1.2 哪些人适合用CubeMX哪些场景不建议用CubeMX最适合的场景是快速原型开发和中低复杂度项目。比如你要做一个数据采集板需要用到ADC、SPI、UART、定时器用CubeMX配置一遍可能也就十几分钟换成手动写初始化代码至少半天。对于教学场景来说CubeMX能让学生把精力集中在应用逻辑上而不是耗在底层驱动的调试上。但有些场景我是不建议用CubeMX的。一是对代码体积极其敏感的项目比如用STM32F030F4这种只有16KB Flash的芯片HAL库占用的空间可能就吃掉一大半这时候用LL库或者直接寄存器操作更合适。二是对实时性要求极高的场景HAL库的函数调用层级比较深中断响应延迟比直接操作寄存器要大一些。三是需要深度定制底层驱动的项目比如你要自己实现一套DMA链式传输机制HAL库的抽象层反而会碍事。不过话说回来CubeMX也支持生成LL库代码LL库比HAL库更接近寄存器层代码效率更高API也更简洁。在CubeMX的Project Manager里可以选HAL还是LL或者两者混用。这个后面会详细说。2. 下载安装与环境准备2.1 软件下载渠道与版本选择STM32CubeMX的官方下载地址在ST官网的开发者工具页面。直接搜STM32CubeMX download就能找到。下载之前需要注册一个ST账号这个账号是免费的用邮箱注册就行。注册完之后登录选择对应操作系统的安装包。Windows版本有exe安装包和zip免安装包两种Linux版本是.run文件macOS版本是.dmg。版本选择上我建议用最新的稳定版。CubeMX的版本更新比较频繁新版本通常会支持更多芯片型号、修复已知bug、改进界面交互。但也不是越新越好有些新版本刚发布的时候可能会有一些兼容性问题。我一般会等新版本发布一两个月之后再升级看看社区反馈再说。安装包下载下来之后Windows版直接双击运行一路下一步就行。安装路径建议不要带中文和空格虽然新版本对中文路径的支持已经好很多了但为了避免一些莫名其妙的编译问题还是用纯英文路径比较稳妥。安装过程中会提示是否安装ST-Link驱动如果你用ST-Link下载器的话就勾上用J-Link或者DAP-Link的话可以不装。2.2 固件包的安装与管理CubeMX本体安装完之后还需要安装对应芯片系列的固件包。固件包里包含了HAL库源码、LL库源码、中间件FreeRTOS、FatFS、USB库等、例程代码、芯片描述文件。没有固件包CubeMX就没法生成代码。安装固件包有两种方式。一种是在CubeMX启动后的主界面点击Install/Remove Packages然后从列表里选择需要的芯片系列。比如你用的是STM32F4系列就找到STM32F4对应的固件包点击Install。固件包比较大F4系列的完整包大概有1GB左右下载时间取决于网速。另一种方式是手动下载固件包然后导入。在ST官网的CubeMX页面可以找到各个系列的固件包下载链接下载下来是一个zip文件。在CubeMX的Install/Remove Packages界面里点击From Local按钮选择下载好的zip文件就能导入。这种方式适合网络环境不太好或者需要离线安装的情况。固件包安装路径默认在用户目录下的STM32Cube/Repository文件夹里。如果你C盘空间紧张可以在CubeMX的Updater Settings里修改Repository路径到其他盘。我一般会把它放到D盘或者E盘因为随着你用的芯片系列越来越多固件包占用的空间会越来越大十几个系列全装下来可能十几个GB就没了。注意固件包版本和CubeMX版本之间有兼容性要求。新版本的CubeMX通常能兼容旧版本的固件包但反过来不一定行。如果你升级了CubeMX之后发现某个固件包用不了要么降级CubeMX要么升级固件包。2.3 中文界面设置与汉化方法CubeMX从6.0版本开始内置了多语言支持包括简体中文。设置方法很简单打开CubeMX点击菜单栏的Help然后选择Updater Settings在弹出的窗口里找到User Language选项下拉选择Chinese或者中文重启软件之后界面就变成中文了。不过说实话我不太建议用中文界面。原因有两个一是中文翻译有些地方不太准确特别是一些专业术语的翻译反而容易造成理解偏差二是网上大部分教程和文档都是基于英文界面的你用中文界面的话对照教程找选项的时候会比较费劲。我个人的做法是保持英文界面但把一些常用操作的英文术语记熟这样查资料和看官方文档的时候更顺畅。如果你确实需要中文界面除了上面说的官方设置方法之外网上还有一些第三方汉化包。但我不推荐用第三方汉化包一是可能引入安全风险二是CubeMX版本更新之后汉化包可能失效导致界面显示异常。官方自带的中文支持已经够用了。3. 新建工程与芯片选型3.1 从芯片型号还是从开发板入手打开CubeMX之后主界面会看到三个入口New Project新建工程、Load Project加载工程、Example Selector例程选择。新建工程有两种方式一种是通过MCU/MPU Selector按芯片型号筛选另一种是通过Board Selector按官方开发板筛选。按芯片型号筛选的话你可以在搜索框里输入具体的型号比如STM32F103C8然后从结果列表里选中对应的芯片。列表里会显示芯片的封装、Flash大小、RAM大小、主频等关键参数。选中之后点击Start Project就进入配置界面了。按开发板筛选的话CubeMX内置了ST官方开发板的配置文件比如Nucleo系列、Discovery系列、Evaluation系列。选中开发板之后工具会自动帮你配好板载的外设比如LED、按键、串口、ST-Link接口等。这种方式适合用官方板子做开发的场景能省去一些手动配置的工作。如果你用的是第三方开发板或者自己画的板子那就按芯片型号来选。选芯片的时候要注意封装是否匹配比如STM32F103C8T6是LQFP48封装STM32F103C8T6TR是同一个芯片的卷带包装功能上没区别。但如果是STM32F103C8U6就是QFN封装了引脚数量和排列都不一样。3.2 引脚分配与冲突检查进入配置界面之后你会看到一个芯片的俯视图上面标注了所有引脚的编号和默认功能。左侧是外设列表包括Analog、Timers、Connectivity、Computing、Multimedia、Security等分类。中间是芯片引脚图右侧是配置面板。配置外设的时候比如你要用USART1就在左侧的Connectivity里找到USART1点击它旁边的下拉框选择Mode为Asynchronous异步模式。这时候芯片图上对应的引脚通常是PA9和PA10会变成绿色表示已经被分配了。如果你之前已经把PA9分配给了别的功能CubeMX会弹出冲突提示告诉你这个引脚已经被占用需要先释放或者换一个引脚。引脚分配这块有个很实用的功能叫Pinout View可以切换成List View模式用表格的形式显示所有引脚的状态。哪些引脚被占用了、哪些还空闲、每个引脚当前配置成什么功能一目了然。在配置复杂项目的时候我一般会先列一个引脚分配表把每个外设用到的引脚都规划好然后在CubeMX里一次性配完避免反复修改。实操心得配置引脚的时候尽量把同一组外设的引脚放在相邻位置比如SPI1的SCK、MISO、MOSI尽量用PA5、PA6、PA7这一组不要东一个西一个。这样画PCB的时候走线会方便很多也减少信号交叉干扰的风险。3.3 时钟树配置的核心逻辑时钟树配置是CubeMX里最核心也最容易出错的部分。STM32的时钟系统比较复杂有HSI内部高速时钟、HSE外部高速时钟、LSI内部低速时钟、LSE外部低速时钟四个时钟源还有PLL锁相环、多个分频器和多路选择器。配置时钟树的时候先要确定时钟源。如果板子上有外部晶振一般用HSE精度比HSI高很多。HSE的频率常见的有8MHz、12MHz、25MHz等具体看你的硬件设计。选好HSE之后在时钟树图上找到HSE的输入路径然后在PLL配置区域设置倍频系数。以STM32F407为例假设外部晶振是8MHz目标主频是168MHz。配置流程是这样的HSE输入8MHz经过M分频器设为8得到1MHz的PLL输入频率然后经过N倍频器设为336得到336MHz的VCO输出频率再经过P分频器设为2得到168MHz的系统时钟。同时PLLQ分频器设为7得到48MHz的USB时钟。这些参数在CubeMX的时钟树界面里直接输入就行工具会自动计算并显示最终频率。时钟树配置有个原则PLL输入频率建议在1MHz到2MHz之间VCO输出频率建议在100MHz到432MHz之间不同系列范围不同这样PLL的抖动和锁定时间比较理想。CubeMX会在你输入参数的时候实时检查是否超出范围如果超了会标红提示。配置完时钟树之后还要注意各个总线的分频系数。AHB总线、APB1总线、APB2总线的最高频率限制不一样。比如F407的APB1最高42MHzAPB2最高84MHz。如果你的外设挂在APB1上而APB1的分频系数设得太小导致频率超过42MHz外设可能工作不正常。CubeMX会自动检查这些限制但你自己也要心里有数。4. 外设配置与代码生成4.1 GPIO与中断配置的实操细节GPIO配置看起来简单但里面有不少细节。在CubeMX里点击某个引脚会弹出配置菜单可以设置引脚模式输入、输出、复用、模拟、上下拉电阻、输出速度、用户标签等。输出模式一般用于驱动LED、继电器等。输出速度有Low、Medium、High、Very High四档速度越高功耗越大、EMI辐射也越大。驱动LED的话Low就够了驱动高速信号比如SPI的SCK才需要High或Very High。上下拉电阻的选择要看具体电路比如按键输入一般用上拉按键按下时接地产生下降沿。中断配置在NVIC Settings里。勾选Enabled使能对应的中断然后设置抢占优先级和响应优先级。STM32的中断优先级数值越小优先级越高。抢占优先级决定能不能打断正在执行的中断服务函数响应优先级决定同一抢占优先级下的排队顺序。注意FreeRTOS对中断优先级有特殊要求。使用了FreeRTOS之后优先级高于configMAX_SYSCALL_INTERRUPT_PRIORITY的中断不能调用FreeRTOS的API函数。在CubeMX里配置FreeRTOS的时候工具会自动设置这个阈值但你自己加的中断要注意不要超过这个限制。4.2 用SPI接口读写W25Q64的完整配置W25Q64是一颗8MB的SPI Flash芯片很多项目用它来存储字库、图片、日志数据。用CubeMX配置SPI读写W25Q64的流程是这样的首先在Connectivity里找到SPI接口选择一个可用的SPI比如SPI1。Mode选择Full-Duplex Master全双工主机模式。Hardware NSS Signal选择Disable因为W25Q64的片选信号我们用自己的GPIO控制不用SPI硬件片选。参数配置方面Clock PolarityCPOL设为LowClock PhaseCPHA设为1 Edge这是W25Q64支持的SPI模式0。Data Size设为8 BitsFirst Bit设为MSB First。Prescaler分频系数根据你的SPI时钟要求来设W25Q64最高支持80MHz但实际布线质量一般的话建议先设低一点比如4分频或者8分频调通了再往上提。然后分配一个GPIO作为片选信号比如PA4配置为GPIO_Output初始电平设为High片选无效。在代码里操作W25Q64的时候先把PA4拉低然后调用HAL_SPI_Transmit()和HAL_SPI_Receive()发送命令和数据操作完之后再把PA4拉高。W25Q64的常用命令包括0x06写使能、0x05读状态寄存器、0x03读数据、0x02页编程、0x20扇区擦除、0xC7整片擦除。读数据的时候先发0x03命令然后发24位地址接着连续读取数据。写数据之前必须先发写使能命令然后发页编程命令每次最多写256字节超过一页的要分多次写。// W25Q64读数据示例 void W25Q64_Read(uint32_t addr, uint8_t *buf, uint16_t len) { uint8_t cmd[4]; cmd[0] 0x03; cmd[1] (addr 16) 0xFF; cmd[2] (addr 8) 0xFF; cmd[3] addr 0xFF; HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET); HAL_SPI_Transmit(hspi1, cmd, 4, 100); HAL_SPI_Receive(hspi1, buf, len, 1000); HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET); }4.3 FreeRTOS集成与任务配置CubeMX集成了FreeRTOS中间件可以在Middleware里找到FREERTOS选项。选择Enabled之后会出现一堆配置项包括任务创建、队列、信号量、定时器等。创建任务的时候需要设置任务名称、优先级、栈大小、入口函数。任务优先级数值越大优先级越高空闲任务的优先级是0所以用户任务的优先级至少要是1。栈大小以字为单位STM32是32位机一个字4字节所以栈大小设128的话实际是512字节。栈大小要根据任务里局部变量和函数调用深度来估算拿不准的话先设大一点跑起来之后用uxTaskGetStackHighWaterMark()查看栈使用峰值再调整。CubeMX生成的FreeRTOS代码默认使用CMSIS-RTOS v2封装层API函数以os开头比如osThreadNew()、osDelay()、osMessageQueuePut()。这种封装的好处是代码可移植性更好换到其他RTOS的时候上层逻辑改动小。如果你习惯用原生FreeRTOS的API可以在配置里把Use CMSIS-RTOS v2关掉这样生成的就是xTaskCreate()、vTaskDelay()这些原生函数。实操心得CubeMX生成FreeRTOS代码的时候默认会把SysTick和HAL的时间基准都交给FreeRTOS管理。这时候HAL_Delay()会失效因为SysTick中断被FreeRTOS接管了。解决办法是在CubeMX的SYS配置里把Timebase Source从SysTick改成其他定时器比如TIM6或者TIM7。这个坑我踩过好几次生成的代码里HAL_Delay()一直卡死查了半天才发现是这个问题。5. 工程管理与代码结构5.1 Project Manager的关键设置配置完外设之后切换到Project Manager标签页这里设置工程名称、存储路径、工具链类型等。Toolchain/IDE选项里可以选MDK-ARMKeil、STM32CubeIDE、IAR、Makefile等。选好之后生成的工程文件格式会对应变化。Code Generator这一页有几个重要选项。Copy only necessary library files会把用到的HAL库文件复制到工程目录里这样工程是自包含的换电脑也能编译。Add necessary library files as reference则是引用固件包安装目录里的库文件工程体积小但换电脑可能找不到库文件。我一般选前者虽然占空间但省心。Generate peripheral initialization as a pair of .c/.h files per peripheral这个选项建议勾上这样每个外设的初始化代码会单独生成一个文件比如spi.c、usart.c代码结构更清晰。不勾的话所有初始化代码都堆在main.c里项目大了之后很难维护。Keep User Code when re-generating这个选项一定要勾上。它的作用是在你重新生成代码的时候保留你在/* USER CODE BEGIN */和/* USER CODE END */之间写的代码。如果不勾每次重新生成代码你写的东西都会被覆盖掉。5.2 生成代码的结构解析点击GENERATE CODE之后CubeMX会生成完整的工程文件。以Keil工程为例目录结构大概是这样的Project/ ├── Core/ │ ├── Inc/ │ │ ├── main.h │ │ ├── gpio.h │ │ ├── spi.h │ │ ├── usart.h │ │ ├── FreeRTOSConfig.h │ │ └── ... │ ├── Src/ │ │ ├── main.c │ │ ├── gpio.c │ │ ├── spi.c │ │ ├── usart.c │ │ ├── stm32f4xx_it.c │ │ ├── stm32f4xx_hal_msp.c │ │ └── ... │ └── Startup/ │ └── startup_stm32f407xx.s ├── Drivers/ │ ├── STM32F4xx_HAL_Driver/ │ └── CMSIS/ ├── Middlewares/ │ └── Third_Party/ │ └── FreeRTOS/ └── MDK-ARM/ └── Project.uvprojxmain.c是主程序文件里面包含了SystemClock_Config()、MX_GPIO_Init()、MX_SPI1_Init()等初始化函数的调用以及while(1)主循环。每个外设的初始化函数在对应的.c文件里实现比如MX_SPI1_Init()在spi.c里。stm32f4xx_it.c是中断服务函数文件CubeMX会自动生成SysTick、HardFault、外设中断的处理函数框架。你需要在对应的中断服务函数里添加自己的处理逻辑注意要写在/* USER CODE BEGIN */和/* USER CODE END */之间。stm32f4xx_hal_msp.c是MCU支持包文件里面是HAL库的外设底层初始化函数比如GPIO时钟使能、NVIC配置、DMA配置等。这些函数由CubeMX自动生成一般不需要手动修改。5.3 用户代码保护区的正确使用CubeMX重新生成代码的时候只会保留/* USER CODE BEGIN */和/* USER CODE END */之间的内容。这个保护区在文件里有很多处比如main.c里的/* USER CODE BEGIN Includes */ // 在这里添加头文件包含 /* USER CODE END Includes */ /* USER CODE BEGIN 0 */ // 在这里添加全局变量或函数声明 /* USER CODE END 0 */ /* USER CODE BEGIN 2 */ // 在这里添加初始化完成后的代码 /* USER CODE END 2 */ /* USER CODE BEGIN WHILE */ while (1) { /* USER CODE BEGIN 3 */ // 在这里添加主循环代码 /* USER CODE END 3 */ } /* USER CODE END WHILE */把代码写在保护区里重新生成的时候就不会丢。但要注意保护区的注释标记不能删掉或改掉否则CubeMX识别不出来。另外如果你在保护区外面改了代码重新生成的时候会被覆盖这个要特别注意。常见问题有时候重新生成代码之后发现Keil工程里新加的文件没有自动包含进去。这是因为CubeMX只更新它自己生成的文件你手动添加到工程里的文件需要手动在Keil里重新添加。解决办法是在Keil的工程选项里把新文件所在的文件夹路径加到Include Paths里然后把文件添加到对应的Group里。6. 常见问题与排查技巧6.1 生成代码编译报错的典型原因CubeMX生成的代码编译报错最常见的原因有这么几个第一个是固件包版本和CubeMX版本不匹配。比如你用CubeMX 6.10生成了基于F4固件包1.27的代码但你的Keil工程里引用的还是旧版本的HAL库文件就会报一堆未定义符号的错误。解决办法是确保CubeMX里选的固件包版本和工程里实际引用的库文件版本一致。第二个是Keil的编译器版本问题。CubeMX生成的代码默认使用AC5编译器如果你用的是AC6有些语法可能不兼容比如__weak关键字、内联汇编等。解决办法是在Keil的Target选项里把编译器切回AC5或者手动修改代码适配AC6。第三个是头文件路径没配全。CubeMX生成的工程里头文件分布在多个目录下如果Keil的Include Paths里漏了某个路径就会报找不到头文件的错误。检查方法是看报错信息里缺的是哪个头文件然后找到它所在的目录把路径加到Include Paths里。6.2 外设不工作的排查思路外设配置好了但就是不工作这种问题最让人头疼。我一般按这个顺序排查先查时钟。用示波器或者逻辑分析仪测一下外设对应的时钟引脚有没有波形。如果没有检查时钟树配置是否正确、外设时钟使能有没有打开。CubeMX生成的代码里外设时钟使能是在HAL_XXX_MspInit()函数里做的确认这个函数被调用了。再查引脚。确认引脚配置是否正确有没有被其他功能占用。用万用表测一下引脚电平看是不是预期的状态。如果是复用功能引脚还要确认复用映射是否正确。然后查配置参数。比如串口通信波特率、数据位、停止位、校验位是否和对方设备匹配。SPI通信CPOL、CPHA、数据位顺序是否和从设备匹配。I2C通信从设备地址是否正确。最后查中断。如果外设用了中断确认NVIC里中断使能了、优先级配置正确、中断服务函数里清了中断标志位。有时候中断只触发一次就不再触发了就是因为中断标志位没清。6.3 常见问题速查表问题现象可能原因排查方法解决方案编译报错找不到头文件Include Paths配置不全查看报错信息缺哪个头文件把对应目录加到Include PathsHAL_Delay()卡死SysTick被FreeRTOS接管检查Timebase Source设置改用TIM6/TIM7作为时间基准串口乱码波特率不匹配核对双方波特率设置统一波特率检查时钟配置SPI读不到数据CPOL/CPHA配置错误对照从设备手册确认SPI模式调整CPOL和CPHA参数中断只触发一次中断标志位未清除检查中断服务函数在中断处理中清除标志位重新生成代码后用户代码丢失代码写在保护区外检查USER CODE标记把代码移到保护区内工程换电脑后编译报错库文件路径引用问题检查库文件是否存在改用Copy方式复制库文件FreeRTOS任务不调度优先级配置错误检查任务优先级设置确保用户任务优先级大于06.4 版本升级与工程迁移注意事项CubeMX版本升级之后打开旧工程可能会提示固件包版本不匹配。这时候可以选择升级固件包或者保持旧版本。升级固件包的话HAL库的API可能有变化需要检查代码里用到的函数是否还在、参数是否变了。比如HAL库从1.24升级到1.27的时候某些函数的返回值类型从void改成了HAL_StatusTypeDef如果你的代码里没接收返回值编译不会报错但逻辑可能有问题。工程迁移到不同芯片系列的时候比如从F103迁移到F407不能直接改芯片型号因为外设资源、时钟树结构、引脚分布都不一样。正确的做法是新建一个F407的工程把外设配置重新做一遍然后把应用层代码移植过去。HAL库的API在不同系列之间基本一致所以应用层代码改动量不大主要是底层初始化部分需要重新配置。实操心得我习惯在每次CubeMX配置完成、生成代码之后把.ioc文件单独备份一份。这个文件记录了所有的配置信息以后需要修改配置的时候直接打开.ioc文件就行不用从头再配一遍。如果配置改坏了还可以回退到备份的版本。7. 进阶技巧与效率提升7.1 用脚本自动化重复配置如果你经常需要创建相似配置的工程比如每个项目都要配一遍USART1、SPI1、几个GPIO可以考虑用CubeMX的命令行模式来自动化。CubeMX支持通过脚本文件.cubemx脚本来批量配置不过这个功能用得人不多文档也比较少。更实用的做法是维护一个模板工程。把常用的外设配置、FreeRTOS设置、工程选项都配好存成一个.ioc文件。新项目开始的时候复制这个模板文件改一下芯片型号和项目名称重新生成代码就行。这样能省去大量重复配置的时间。7.2 结合版本管理工具管理工程CubeMX生成的工程文件建议纳入Git管理。但要注意Drivers目录下的HAL库文件、Middlewares目录下的FreeRTOS源码这些第三方文件如果每个工程都提交一份的话仓库会变得很大。我的做法是在.gitignore里排除这些目录只提交Core目录下的用户代码和.ioc配置文件。换电脑的时候先用CubeMX打开.ioc文件重新生成一遍库文件然后再编译。.ioc文件是文本格式的Git可以很好地追踪它的变化。每次修改配置之后.ioc文件的diff能清楚地显示改了哪些选项方便回溯和review。7.3 从CubeMX到CubeIDE的平滑过渡STM32CubeIDE是ST推出的免费IDE基于Eclipse框架集成了CubeMX的配置功能。如果你不想用Keil或者IAR可以直接用CubeIDE。CubeIDE里新建工程的时候可以直接在IDE内部完成CubeMX的所有配置操作不需要在CubeMX和IDE之间来回切换。从CubeMXKeil迁移到CubeIDE的话把CubeMX生成的工程导入CubeIDE就行。CubeIDE会自动识别工程结构把源文件、头文件路径、编译选项都配好。不过CubeIDE的编译器和Keil不一样有些Keil特有的语法或者内联汇编需要改。另外CubeIDE的调试体验和Keil也有差异需要适应一下。我个人现在的做法是用CubeMX做配置和代码生成用Keil做编译和调试。CubeIDE偶尔用来做代码静态分析因为它集成的CubeMX配置界面确实方便改配置不用切来切去。7.4 固件包瘦身与工程体积优化CubeMX生成的工程里HAL库文件是全部复制过来的但实际上你的项目可能只用了其中几个外设。比如你只用了GPIO和USART但Drivers/STM32F4xx_HAL_Driver/Src目录下有几十个.c文件编译的时候全部参与编译导致编译时间长、生成的hex文件大。优化方法是在Keil的工程里把没用到的HAL库文件从编译列表里移除。具体操作是在Project窗口里找到对应的.c文件右键选择Options for File把Include in Target Build的勾去掉。这样编译的时候就不会编译这些文件生成的代码体积也会小很多。不过要注意有些HAL库文件之间有依赖关系移除的时候要确认没有其他文件引用它。比如stm32f4xx_hal_rcc.c是时钟配置相关的基本上所有外设都依赖它这个不能移除。stm32f4xx_hal_spi.c如果你没用SPI就可以移除。另外在CubeMX的Project Manager里可以设置Minimum Heap Size和Minimum Stack Size根据实际需要调整。堆和栈的大小直接影响RAM占用设得太小可能导致运行时出错设得太大又浪费RAM。一般堆设0x200到0x400栈设0x400到0x800就够用了。我在实际项目里还发现一个细节CubeMX生成的main.c里SystemClock_Config()函数在main()一开始就被调用但如果你在main()之前有全局对象的构造函数C项目这些构造函数会在时钟配置之前执行可能导致依赖时钟的外设初始化失败。解决办法是把全局对象的初始化放到main()里手动调用或者用指针延迟创建。这个坑在C项目里比较常见纯C项目一般不会遇到。最后再分享一个小技巧CubeMX的.ioc文件可以用文本编辑器打开里面记录了所有配置项。有时候在界面上找不到某个配置选项可以直接在.ioc文件里搜索对应的参数名手动修改。比如你想改FreeRTOS的tick频率在界面上可能要点好几层菜单才能找到直接在.ioc文件里搜FREERTOS.TICK_RATE就能定位到。改完之后用CubeMX重新打开.ioc文件配置就生效了。这个方法在批量修改配置的时候特别高效但要注意改之前先备份改错了可能导致工程打不开。
返回列表