Keil4工程用Keil5继续开发,编译报错问题探究

        之前需要把在Keil4中建立的工程,继续在Keil5(Keil版本信息如图1所示)中进行开发,但通过Keil5打开其工程时弹出如图2的界面,因为打算后续就用Keil5进行开发,没有必要再去下载相应的遗留支持文件,因此选择了 “Migrate to Device Pack”;

Keil4工程用Keil5继续开发,编译报错问题探究_第1张图片

图 1

Keil4工程用Keil5继续开发,编译报错问题探究_第2张图片

图 2

        选择后,成功打开工程,但点击如图3的 “Build(F7)”,生成结果框显示如图4所示的错误,这就感到很奇怪了,在Keil4中是能够正常编译成功的,但为什么在Keil5中却有编译错误了?初步怀疑是软件Bug,于是乎便到网上去查找原因了。

图 3

Keil4工程用Keil5继续开发,编译报错问题探究_第3张图片

图 4

        果然,这个问题大家早就遇到了,然后提供的解决方法就是将如图5标记的“STM32F10X_HD”删除后,就可以编译成功了。

Keil4工程用Keil5继续开发,编译报错问题探究_第4张图片

图 5

        但如图4和图6所示,报错的原因是工程中的.c文件包含了stm32f10x.h,而stm32f103x.h中的typedef enum IRQn IRQn_Type构建有问题,可不是很能理解一个预编译的行为,为什么会影响typedef enum IRQn IRQn_Type的枚举类型名构建了,但因项目比较紧,当时就没有继续深究了。

Keil4工程用Keil5继续开发,编译报错问题探究_第5张图片

图 6

        然而,在秉着“知其然知其所以然”的学习态度,努力地减小自己的技术负债,最近得空后便又深究下了。

        仔细查看了下 tyepdef enum IRQn IRQn_Type;这个新类型名构造,以及结合以上的解决方法,那么如图7所示,DMA1_Channel17_IRQn = 17,应该是最后一个枚举常量值了,但实际程序中是还有引用如图8所示,USART1_IRQn,USART2_IRQn的。这就很奇怪了,从语法的角度来说引用的枚举常量USART1_IRQn,USART2_IRQn应该是不存在的,但程序为什么没有报错了?只能再从语法的角度推理,IRQn_Type这个枚举类型实际是包含枚举常量USART1_IRQn,USART2_IRQn,那就只能是某个芯片类型的条件预编译结果是真。因此通过删除如图7所示,”DMA1_Channel17_IRQn = 17,”后面的这个“,”果然发现了问题所在。

Keil4工程用Keil5继续开发,编译报错问题探究_第6张图片

图 7

Keil4工程用Keil5继续开发,编译报错问题探究_第7张图片

图 8

Keil4工程用Keil5继续开发,编译报错问题探究_第8张图片

图 9

        如图9所示,在该工程中”STM32F10X_MD”实际是在某个地方进行了预定义的。接下来,又进行了以下两种操作:1).通过将如图5中的“STM32F10X_HD”改成“STM32F10X_MD”; 2).或在将图5中“STM32F10X_HD”保留,并将”#ifdef STM32F10X_MD”改成“#ifdef aSTM32F10X_MD”;或将#ifdef STM32F10X_MD ……  #endif这段删除或屏蔽。在进行了以上两种操作的任何一种后,该工程也能在Keil5中编译通过。因此可以确定之前编译错误的原因是”STM32F10X_MD”已经在该工程中的某个地方进行了预定义,导致倘若再预定义“STM32F10X_HD”则会不可避免的出现错误。

        那么问题又来了,我们从没有主动预定义过“STM32F10X_MD”,这个预定义是从哪里来的呢?在整个工程中进行搜索(如图10所示),在预定义框中进行查看(如图11所示),均没有找到。这就很奇怪了。

图 10

Keil4工程用Keil5继续开发,编译报错问题探究_第9张图片

图 11

        又秉着“一个事物之前是好的,改变了某个部分后,突然不行了,那就只能是变动的那个地方有猫腻”的想法,借助SVN软件查看有改动的那些文件,最终在如图12所示的文件中,在如图13所示的文件内容中验证了该工程的确对“STM32F10X_MD”进行了预定义。那么还是之前那个问题——到底是在哪个地方对其进行预定义了?通过仔细查看如图13文件中的Command Line,发现预定义指令的前面是与头文件路径相关的指令,那么其可能就在包含文件路径设置栏的附近。

图 12

图 13

        果然如图14所示,在包含文件路径设置栏下面的Compiler control string中发现了跟如图13相同的指令,然后再将显示框往下滚动,如图15所示,奇迹出现了——“-DSTM32F10X_MD”。本想着将“-DSTM32F10X_MD”删除再验证下,却发现是一个只读显示框,不能进行修改的。

Keil4工程用Keil5继续开发,编译报错问题探究_第10张图片

图 14

Keil4工程用Keil5继续开发,编译报错问题探究_第11张图片

图 15

        然后又猜想是不是因为Keil4工程移植到Keil5工程导致的这个预定义,于是乎又重新用Keil5的MDK库(图16)和STM32CubeMX(图17)创建STM32F10x系列的工程,发现是都有预定义“-DSTM32F10X_MD”。

Keil4工程用Keil5继续开发,编译报错问题探究_第12张图片

图 16

Keil4工程用Keil5继续开发,编译报错问题探究_第13张图片

图 17

        至此,又出现了一个新的问题,为什么STM32F10x系列的Keil5工程要有编译控制命令“-DSTM32F10X_MD”?

        我想这个问题,只能有机会去问下Keil5这个IDE工具的开发人员了。当然若有知晓之人,欢迎进行补充分享。

你可能感兴趣的:(Keil,单片机,stm32,ide)