实测Keil MDK v5.38 ,以及STM32CubeMX v6.8 ,本人踩过因库文件版本冲突致使工程编译报错两百多个这样的坑,新手只要跟着步骤逐个操作,便能够轻松避开这类常见问题。 ……
实测Keil MDK v5.38 ,以及STM32CubeMX v6.8 ,本人踩过因库文件版本冲突致使工程编译报错两百多个这样的坑,新手只要跟着步骤逐个操作,便能够轻松避开这类常见问题。
手动整合与HAL库自动整合到底选哪个
不少才刚开始接触的新手,从一开始就为此陷入纠结,究竟是完全借助CubeMX所生成的HAL库来得省事,还是依靠自己手动逐个将标准外设库文件放入工程更为可靠呢。我开展了两组用于对比的测试,得出的结论十分直白。
第一个小组进行测试:运用CubeMX默认的配置去生成一个针对F103C8T6的UART加上DMA并且还有ADC的工程,在生成代码之后直接开展编译,所耗费的时间大概是12秒,不存在报错的情况。然而生成的文件当中充斥着你根本就不会去使用的外设驱动,像是SPI、I2C、USB,工程的体积直接增大到4.2MB。
测试的第二组情况是,我从标准外设库3.5版本当中,仅仅是手动去拉取了stm32f10x_gpio.c,以及stm32f10x_usart.c,还有stm32f10x_adc.c,以及与之对应的头文件,另外还加上了核心的stm32f10x_rcc.c与misc.c,总共仅仅使用了6个源文件,工程大小被压缩到1.1MB,编译时间被缩短到7秒。
结论十分明晰:要是你的项目属于量产级的稳定固件,并且你明晰知道何种外设被采用、何种未被采用,那么手动整合库文件能够显著削减代码体积以及编译时间。然而要是你仍处于调试板子的阶段、频繁地更改外设配置,CubeMX自动整合会更加省心,毕竟它不会遗漏掉某个外设的时钟使能宏定义。
【新手需防】不管挑选哪一种途径,最为容易踏入的陷阱乃是头文件路径配置出现差错。我曾见识过有人将整个标准库的Inc目录一股脑地全部塞入工程之中,结果导致两个具有相同名称的头文件(诸如stm32f10x.h以及stm32f10x_conf.h)版本处在不一致的状况,编译时上报“redefinition of struct”。采取的解决方式为:始终仅仅留存一个核心头文件路径,且于Project->Options->C/C++->Include Paths那里进行手动指定,切勿采用“Add All Subfolders”这般的偷懒行为。
库文件版本冲突怎么一次性解决
1. 第一步:清空旧工程里的所有库文件
抵达至项目文件夹之处,以手动方式去删除Drivers目录以及Middlewares目录之中的所有内容,勿留存丝毫.c和.h文件。接着开启Keil工程管理器(Project->Manage->Project Items),将Groups里与外设具备相关联系的源文件尽数Remove。此步骤存在很多人因嫌麻烦而径直进行覆盖操作却并不选择删除,导致最终新旧文件混杂于一处,并由编译器随机进行调用,致使报错之时用户完全无法摸透其中缘由句号。
新手要避开大坑,当删除之后要是编译出现提示说“file not found”,那绝对是你忘掉了remove工程列表当中的旧文件索引。删除物理文件并不等同于删除工程引用,一定要去Project Items里把文件条目给删得干干净净。别来问我是怎么知道的,我就是因为这个卡了足足三个小时。
2. 第二步:从官方包重新提取统一版本的库文件
倘若是你运用HAL库,于CubeMX安装的那个文件夹里的Repository文件夹当中寻觅相对应芯片的官方包,就像STM32Cube_FW_F1_V1.8.5这般。将Drivers/STM32F1xx_HAL_Driver/Src之下的全部.c文件进行复制,放置到你工程的Drivers目录之内。留意,别把源于各异版本容器中的文档进行混杂取用,就像针对HAL库选用的是1.8.5版本,然而关于CMSIS核心文稿却是从1.8.0版本当中予以复制,如此这般便会致使底层里面专门针对寄存器位置的宏大界定出现对不上的状况。
【新手需防入坑】,我经历过的最为凄惨的一回报错状况乃是“undefined reference to HAL_GPIO_Init”,历经三天的查找之后发现,头文件版本属于 HAL 库 1.8.0 之中的,然而源文件却是 1.8.5 里的,在新版本里面 GPIO 初始化函数已然更改了参数结构体,而旧的头文件里面并未存在这个新结构体的定义。最后的解决方式是:将整个 Drivers 目录从同一个版本包里面重新全部拉取一遍,不要试图偷懒仅仅替换个别文件。
3. 第三步:统一修改主头文件中的模块开关宏
拿出stm32f1xx_hal_conf.h,将其中你不使用的外设宏统统进行注释,比如说你仅仅用到了GPIO,以及UART,还有DMA,再加上ADC,那么就只留存这四个模块的宏定义,其余的全部写成/ #define HAL_SPI_MODULE_ENABLED /。此步骤直接决定了编译器是否要编译那些你根本用不到的库文件,不进行注释就相当于往工程里塞了一连串垃圾代码。
【新手需防】就我所知,最为离谱的报错当属“HAL_I2C_MspInit重复定义”,其缘由在于,明明未曾使用I2C,然而conf.h之中却未将I2C的宏注释掉,与此同时,工程自身又编写了一个I2C的底层初始化函数,两个初始化函数因名称相同而产生冲突。解决的办法清晰而简便:conf.h里仅开启你实际运用的模块宏,其余的全部注释,如此便简洁明了。
这套借助手动清理并采用统一版本的办法,大体上能够处理百分之九十的库文件整合难题。假若你使用的乃是国产芯片像是GD32亦或是AT32,它们的库文件架构跟ST并非全然相同,这套办法就得予以调整——国产芯片的官方SDK里常常将外设驱动与芯片头文件混杂于一个大文件夹之内,无法径直依照ST的习惯去拆分。碰到这种情形,提议直接把他们官方的示例工程当作模板,仅仅替换你所需要的源文件,切莫自己从起始去构建文件夹架构。
微信扫一扫
还没有评论呢,快来抢沙发~