LJgibbs · 2021年05月12日

STM32 HAL库学习小计:如何解决编译出现大量未定义错误

转载自:知乎
作者:ljgibbs

原创:STM32 HAL库学习小计与经验分享:添加c文件后,如何解决编译出现大量未定义错误(identifier xxx isundefined)

image.png
题图来自网络


最近在学习STM32 HAL库的使用,使用的芯片型号是F407。之前在使用F103时,一直使用的是标准库,而使用HAL库最简单的动机就是ST官方为了推广HAL库的使用,不再提供标准库的下载,而只提供官方的HAL库。(至少在F4 F7 以及一些较新的型号上)

根据我这两三天的使用,初步的感觉是HAL库相较于标准库在使用外设的库函数时,并没有太大的区别。但HAL库提供更高的抽象程度,个人感觉进一步消除了各个型号芯片之间的差异。搭配STM32CubeMX工程生成软件,能够在非常短的时间内,上手STM32系列的芯片。

稍开脑洞,假设单片机行业有统一的硬件抽象标准,那么是不是就能像开发x86桌面软件,或者安卓APP一样,屏蔽硬件层的厂商差异,开发ARM内核的单片机。不过我觉得最大的问题应该还是在于各家公司的商业考虑。


言归正传,这篇文章想给大家分享遇到的一个错误和解决的过程,也体会了STM32 HAL库和标准库的一些差异。网上有关STM32标准库的资料铺天盖地 ,有关HAL库的相对少很多,希望能帮到有需要的朋友。

我遇到问题是在练习写入读取片上flash的实验中,我的小实验参照的是正点原子F429HAL库版手册,大家可以去网上找找,是很好的学习HAL库的资料。如果找不到的话可以联系我。我首先使用cube创建了工程,将有关flash的函数放到自己添加的flash.c/h中。因为读取和写入片上flash需要调用HAL库中的函数,所以我想遵循我使用标准库时的流程,引入相应的库文件的头函数,在HAL库中有关flash的是两个库文件_stm32f4xx\_hal\_flash.h_,_stm32f4xx\_hal\_flash\_ex.h_。如下

图我最早引入了3个库文件,还引入了_stm32f4xx\_hal.h_文件(当时没注释)

在编写完我自己的flash.c以及相应的头文件后,编译之后出现了一大堆的错误

可以看到这些错误都出现在于flash.c文件本身无关的其他文件中,且都是未定义错误,这里分享一个基本的调试心得,出现了许多和新添加的c文件无关的未定义错误的根源一般在于新添加的文件重复include。当时在做上一个使用f103的项目中最早遇到这个问题,最简单的解决方法是使用#ifndef标签,我们随便打开一个库文件的头文件就可以看到避免重复定义的方法:

如果头文件被第一次调用,尚未定义\_\_STM32F4xx\_HAL\_SPI\_H变量,则继续复制接下来的定义到执行include的文件中(对复制有疑问的同学可以了解一下#include的工作原理)。如果有文件第二次调用头文件,因为变量已经被定义,#ifndef标签会阻止重复复制下方的定义文件。

变量的名称是自己取的,只要注意前后一致和避免与其他文件中的变量重名即可,这里推荐大家学习ST库文件中的定义 :两个下划线打头,大写的头文件文件名,其中以下划线代替“.”

整个h文件结构如下

#ifndef __STM32F4xx_HAL_SPI_H
#define __STM32F4xx_HAL_SPI_H

…..头文件中的定义…

#endif

我自信地给我的flash.h文件增加了上述防止重复定义的语句,然后。。

哈罗,老朋友

又见到了老朋友:Error limit reached。。。 我们还是没解决这个问题。

之后的调试过程就进入了东改一点西改一点的过程,但问题还在于重复定义,也是从这个角度找问题。最后问题解决是我分析了cube生成的标准spi.h文件,我发现

Spi.c中调用了对应库函数_stm32f4xx\_hal\_spi.h_中定义的初始化函数,但却并没有include这个文件,只include了_stm32f4xx\_hal.h_

查看_stm32f4xx\_hal.h_的include,如下:

再打开唯一include的_stm32f4xx\_hal\_conf.h_文件,读到如下的语句时,谜底一下揭开了

_stm32f4xx\_hal\_conf.h_会根据外设是否使用,引入被用到的外设头文件。这个工作我推测是由cube完成的,所以我们如果要在当前工程自己添加外设,需要到这里去除相应外设的注释

所以flash的模块也被启用了,conf.h已经include了相应的flash模块,我们在自己的头文件中再include
flash的头文件自然重复引用了

所以当我把flash.h改成如下:

一切问题都解决了,世界都太平了。

编译是没问题了 但问题的根源出在哪,为什么标准库和HAL库之间会出现这个差异?换句话说如果_stm32f4xx\_hal\_flash.h_文件按照之前我们学习的_stm32f4xx\_hal.h_的方式使用#ifnedef方式进行防止重复定义,那么我们就算重复include stm32f4xx\_hal\_flash.h 不也不会出现问题么?

问题出在_stm32f4xx\_hal\_flash.h_ 真的没有采用这种方式,这点我也比较奇怪,不知道ST是不是有更深层次的考虑。

至此,至少大量未定义报错的问题解决了,也对出错的原因稍稍进行了分析。总之,出现大量与新添加的c文件无关的未定义错误,问题一般出在错误的include上,希望这篇文章能帮助到刚刚接触STM32或者HAL库的朋友。毕竟这个错误也是属于很多人最初都会遇到的。


写在最后,我玩单片机的时间不长,对于C语言的理解也谈不上深,文章中可能会有不少错误,理解上会有偏差,欢迎斧正。特别是对HAL库的看法,因为我也是刚刚接触HAL库,看法难免片面。

推荐阅读

更多招聘及面经请关注云上招聘
推荐阅读
关注数
10512
内容数
513
FPGA Logic 二三事
目录
极术微信服务号
关注极术微信号
实时接收点赞提醒和评论通知
安谋科技学堂公众号
关注安谋科技学堂
实时获取安谋科技及 Arm 教学资源
安谋科技招聘公众号
关注安谋科技招聘
实时获取安谋科技中国职位信息