【stm32f4 C++与C混合开发】建立keil5的ARM Compiler 6(AC6)标准库开发工程

这篇具有很好参考价值的文章主要介绍了【stm32f4 C++与C混合开发】建立keil5的ARM Compiler 6(AC6)标准库开发工程。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


前言

一:请先确保keil5的版本为5.30版本以上,笔者这里是5.36版本:
keil c/c++(ac6),stm32,c++,arm
二:F4标准库的pack包本版是2.9.0以上,笔者这里是2.15版本:
keil c/c++(ac6),stm32,c++,arm

上述资源可在https://zhuanlan.zhihu.com/p/262507061找到
keil c/c++(ac6),stm32,c++,arm
keil c/c++(ac6),stm32,c++,arm


提示:本工程创建用例基于正点原子的F407标准库例程

一、选择正点原子串口实验的工程

工程如下图所示:
keil c/c++(ac6),stm32,c++,arm

把工程拷贝一份新工程到纯英文路径下,新工程打开后,点击魔法棒发现编译器默认是ARM Compiler 5版本,此时能够正常编译工程
keil c/c++(ac6),stm32,c++,arm

keil c/c++(ac6),stm32,c++,arm

二、用AC6编译纯C语言代码

1.打开魔法棒选择default compiler version6

keil c/c++(ac6),stm32,c++,arm
keil c/c++(ac6),stm32,c++,arm

2.编译工程

不出意外的话,会有很多的错误:
keil c/c++(ac6),stm32,c++,arm

主要的错误应该是这个,也就是未定义vfpcc:
keil c/c++(ac6),stm32,c++,arm

3.更改包含头文件依赖

这里的解决主要是参考AC5编译器 转换到 AC6 编译器 错误 error: unknown register name vfpcc in asm的解决方法
这里有三种方法解决,要么更改头文件路径,要么把新版本CMSIS文件放到工程目录里面,要么是在keil的Mange Run-Time Environment里面选上CMSIS/CORE ,后两种比较适合工程移动到其他PC运行。
方法一:把工程头文件路径的\Core换成\keil_V5\packs\ARM\CMSIS\5.8.0\CMSIS\Core\Include
keil c/c++(ac6),stm32,c++,arm
比如我安装的是在D盘
keil c/c++(ac6),stm32,c++,arm
方法二:删除工程CORE里面的.h文件,
keil c/c++(ac6),stm32,c++,arm
再把\keil_V5\packs\ARM\CMSIS\5.8.0\CMSIS\Core\Include里的文件放到里面
(startup_stm32f40_41xxx.s不用动,因为我观察发现新旧版本的启动文件没有代码的变化,只是注释有变化)
keil c/c++(ac6),stm32,c++,arm
方法三:先把原工程包含文件目录的CORE路径删除
keil c/c++(ac6),stm32,c++,arm
然后点击Mange Run-Time Environment
keil c/c++(ac6),stm32,c++,arm
把CMSIS/CORE打勾
keil c/c++(ac6),stm32,c++,arm

4.修改旧版代码

此时重新编译会发现错误减少了,剩下的错误都是AC6不支持的语法代码了,我们要修改正点原子例程的代码来适配AC6
keil c/c++(ac6),stm32,c++,arm
错误有 #pragma import(__use_no_semihosting) 、__asm void WFI_SET(void)、__FILE,这些都是旧版编译器AC5的特定语法,新版AC6编译器已经不支持了,分别要把原代码报错的部分如下
keil c/c++(ac6),stm32,c++,arm

keil c/c++(ac6),stm32,c++,arm

修改成如下格式同时兼容AC5和AC6编译器,其中__CC_ARM是AC5编译器定义的标识,GNUC 和__clang__是AC6定义的标识,由此判断编译器版本,这里主要参考了
超级无敌让stm32的printf兼容MDK各种编译器的方法
[keil5]从AC5到AC6的转变

#if 1
#ifdef  __CC_ARM
#pragma import(__use_no_semihosting)
struct __FILE 
{ 
	int handle; 
}; 
#elif defined ( __GNUC__ ) || defined (__clang__)
__asm (".global __use_no_semihosting\n\t");   
#endif


FILE __stdout;       
//定义_sys_exit()以避免使用半主机模式    
void _sys_exit(int x) 
{ 
	x = x; 
} 
//重定义fputc函数 
int fputc(int ch, FILE *f)
{ 	
	while((USART1->SR&0X40)==0);//循环发送,直到发送完毕   
	USART1->DR = (u8) ch;      
	return ch;
}

#endif

#ifdef  __CC_ARM
__asm void WFI_SET(void)
{
	WFI;		  
}
//关闭所有中断(但是不包括fault和NMI中断)
__asm void INTX_DISABLE(void)
{
	CPSID   I
	BX      LR	  
}
//开启所有中断
__asm void INTX_ENABLE(void)
{
	CPSIE   I
	BX      LR  
}
//设置栈顶地址
//addr:栈顶地址
__asm void MSR_MSP(u32 addr) 
{
	MSR MSP, r0 			//set Main Stack value
	BX r14
}
#elif defined ( __GNUC__ ) || defined (__clang__)
void WFI_SET(void)
{
    __ASM volatile("WFI");
}

//关闭所有中断(但是不包括fault和NMI中断)
void INTX_DISABLE(void)
{
	__ASM volatile("CPSID   I");
	__ASM volatile("BX      LR");  
}
//开启所有中断
void INTX_ENABLE(void)
{
	__ASM volatile("CPSIE   I");
	__ASM volatile("BX      LR");
}
//设置栈顶地址
//addr:栈顶地址
void MSR_MSP(u32 addr) 
{
	__ASM volatile("MSR MSP, r0"); 			//set Main Stack value
	__ASM volatile("BX r14");
}
#endif

5.重新编译

此时可以看到编译已经通过了,可以烧到F407探索者板子里看效果了,因为我手头上还没有板子,就不演示了
keil c/c++(ac6),stm32,c++,arm

6.烧录程序并查看效果

把程序烧进板子后可看到MCU已经通过串口发送数据了
keil c/c++(ac6),stm32,c++,arm

三、用C++编写代码

1.选择C++方式编译

之前我们做的只是把工程从AC5编译器更换到AC6,因为要体验完整的现代C++功能必须要升级到ARM Compiler 6,那么接下来我们就要把工程用C++编译了。
先右键main.c文件设置一下属性,选择Options for File ‘main.c’
keil c/c++(ac6),stm32,c++,arm

然后改成C++文件
keil c/c++(ac6),stm32,c++,arm

2.修改代码并编译

此时直接编译会有如下报错:
keil c/c++(ac6),stm32,c++,arm

因为原工程都是按照C语言方式编写代码,所以要添加C语言的兼容性处理如下图所示:
keil c/c++(ac6),stm32,c++,arm
keil c/c++(ac6),stm32,c++,arm
keil c/c++(ac6),stm32,c++,arm
然后重新编译就无报错了。
keil c/c++(ac6),stm32,c++,arm

这里会有一个空循环的warning,虽然目前程序有无影响,但我尝试了更新了标准库版本,但还是有warning,不过既然没影响那就忽略,想了解怎么更换新版本标准库的,可参考下面的注意2.更换新版本的STD库

3.用C++重写printf重定向

按上图所示,此时虽然工程可以正常编译,但一旦在主函数中添加了iostream等库,会报错说__stdout重定义了
keil c/c++(ac6),stm32,c++,arm
这是因为ac6里的BUG,具体原因我也不知道,大概是C++的iostream和stdio有冲突,所以必须要重写重定向函数,具体的解决方法我这里参考了STM32 C++编程系列2.5:让Keil MDK工程支持现代C++特性及填坑
打开Mange Run-Time Environment,进入Compiler->I/O,将里面的STDERR、STDIN、STDOUT勾选上,如下图所示:
keil c/c++(ac6),stm32,c++,arm

然后在usart.c代码里重写半主机模式的重定义函数:

#if 1
#ifdef  __CC_ARM
#pragma import(__use_no_semihosting)
struct __FILE 
{ 
	int handle; 
}; 

FILE __stdout;       
//定义_sys_exit()以避免使用半主机模式    
void _sys_exit(int x) 
{ 
	x = x; 
} 
#elif defined ( __GNUC__ ) || defined (__clang__)
//__asm (".global __use_no_semihosting\n\t");   
#endif

//重定义fputc函数 
int fputc(int ch, FILE *f)
{ 	
	while((USART1->SR&0X40)==0);//循环发送,直到发送完毕   
	USART1->DR = (u8) ch;      
	return ch;
}

#endif

其实就是把半主机模式删除了,因为官方已经自动添加进官方版本的重定向代码,我们只用保留重定向调用的fputc函数就行了,然后就能成功编译了,烧进板子里面可看到同样的效果。
keil c/c++(ac6),stm32,c++,arm


注意

1.AC6工程不要用中文路径

Arm compiler 6对中文路径支持不够友好,如果工程建立在中文路径下,编译后右键点击Go To Definition of "xxxx"会无法跳转到相应函数的位置,必须要把工程建立在纯英文路径下。

2.更换新版本的STD库

如上面所说,当工程编译通过后会有个空循环的warning,这里我也不知道要不要处理,不知道对工程效果有没有影响
keil c/c++(ac6),stm32,c++,arm
我怀疑是正点原子用的F4 pack包比较旧,以为他们用的是V1.4.0 固件库包的固件包:
keil c/c++(ac6),stm32,c++,arm
现在已经更新到了V1.9.0版本了,所以从官网下载最新固件(可参考STM32标准外设库(标准库)官网下载方法,附带2021最新标准固件库下载链接)后把新版本标准库里面文件覆盖原工程源码里面(具体操作可参考正点原子的STM32F4开发指南-库函数版本_V1.2.pdf里面的3.32节新建模板工程
keil c/c++(ac6),stm32,c++,arm
我在这里也简单说一下,因为只是替换成新文件,不像新建工程那样麻烦
①STM32F4xx_DSP_StdPeriph_Lib_V1.9.0\Project\STM32F4xx_StdPeriph_Templates,把如图的四个文件覆盖到原工程的USER里面
keil c/c++(ac6),stm32,c++,arm
②再进入STM32F4xx_DSP_StdPeriph_Lib_V1.9.0\Libraries\CMSIS\Device\ST\STM32F4xx\Include里把system_stm32f4xx.hstm32f4xx.h覆盖到原工程
keil c/c++(ac6),stm32,c++,arm
③确保这六个文件都覆盖了之后
keil c/c++(ac6),stm32,c++,arm
再进入标准库的STM32F4xx_DSP_StdPeriph_Lib_V1.9.0\Libraries\STM32F4xx_StdPeriph_Driver文件夹,把新的inc和src文件夹取代原工程的inc和src文件夹,这里建议先把原工程的文件夹里面的内容清空
keil c/c++(ac6),stm32,c++,arm
④此时编译会有一个error
keil c/c++(ac6),stm32,c++,arm
处理方法正点原子的教程里也有说明,先注释keil c/c++(ac6),stm32,c++,armmain.h头文件,然后再注释TimingDelay_Decrement()函数keil c/c++(ac6),stm32,c++,arm
⑤再把PLL 第一级分频系数 M 修改为 8
keil c/c++(ac6),stm32,c++,arm

⑥重新编译(Rebuild)后warning更多了,而且原来的空循环还存在
keil c/c++(ac6),stm32,c++,arm
keil c/c++(ac6),stm32,c++,arm
对此我也不知道为什么,也不知道对程序功能有没有影响,我会放出原工程供大家参考一下,有搞得原由的可评论区说一下
keil c/c++(ac6),stm32,c++,arm

3.更多AC5转换到AC6的代码对应,可参考下图

(来自https://blog.csdn.net/weixin_43644424/article/details/125048889)
keil c/c++(ac6),stm32,c++,arm

工程下载链接

stm32f4标准库C++与C混合开发工程文章来源地址https://www.toymoban.com/news/detail-607817.html

到了这里,关于【stm32f4 C++与C混合开发】建立keil5的ARM Compiler 6(AC6)标准库开发工程的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 2023最新版本~KEIL5使用C++开发STM32

    ▬▬▬▬▬▶用C++开发Keil◀▬▬▬▬▬ 因为是第一次写这个配置教程 我会尽量详细些 打开一个Keil工程 移除本地core 添加在线core 第一次编译代码 不会有报错 修改main.c文件类型为C++ 点击魔术棒 把ARM编译器修改为V6 第二次编译会报错语法不兼容 我把汇编部分的这些代码做了

    2024年02月12日
    浏览(19)
  • STM32(HAL库) CubeMX+Keil5 建立工程

    菜单栏 File 新建工程 打开工程 退出软件 Window 输出窗口的开启 软件字体设置 Help 软件帮助文档 检查软件更新 管理MCU 已存在工程(Existing Projects) 最近打开过的工程(Recent Opened Project) 打开其他已经存在的工程(Other Project) 新建工程(New Project) 基于芯片(Start My Project from MCU) 基于

    2024年01月19日
    浏览(34)
  • MDK Keil5 创建Stm32工程-理论篇(这里以Stm32F103Zet6为例)

    整个工程可以粗略的划分为几个文件夹: BSP 底层驱动比如GPIOTimer等驱动文件 CMSIS 内核相关的文件 Firmware 生成的固件下载文件 Mycode 用户编写的相关文件,主要编写的文件都在这个文件夹里 Project 工程文件 startup 芯片启动文件 STM32F10x_FWLib 标准库文件 USER 主函数等文件 readm

    2023年04月24日
    浏览(48)
  • STM32F7xx Keil5 RTX RL-TCPnet DP83822移植

    暂时全部默认配置,DHCP已打开 修改RTE_Device.h ETH配置 修改DP83822驱动 去掉文件只读属性,之后需要修改,添加到工程 修改DP83822 ID RTE创建tcp server例程,参考该例程,进行修改 修改后的TCP_Socket_server.c ping Tcp client 可以PING通,但client无法连接,后来发现是netInitialize以及server相关

    2024年02月08日
    浏览(18)
  • Keil5 开发 STM32 工程创建

    打开Keil5软件,点Project菜单的的下来选项New uVision Project…,然后选择工程文件夹放置的目录,新建项目目录,如:LED闪烁 点击OK后,会弹出配置运行时环境的选项框,关闭即可,该方法使用手动配置。 完成后,如下图: 打开项目目录,分别创建3个文件夹:Library, Start, User,

    2024年02月16日
    浏览(23)
  • (STM32基础)STM32用keil5开发前准备

    1)Keil5安装MDK-ARM版本后,需要安装对应芯片器件库,否则新建工程无芯片可选项。  查看设备管理器  stlink 是否驱动正常,如果是感叹号则需要装驱动  2、插入STLINK后,在keil安装目录下找到安装驱动程序,安装STLINK驱动。 3、插入usb转串口模块后,安装驱动程序(资料文件

    2024年02月03日
    浏览(24)
  • keil5使用c++编写stm32控制程序

    想着搞个新奇的玩意玩一玩来着,想用c++编写代码来控制stm32,结果在keil5中,把踩给我踩闷了,这里简单记录一下。注意一定要按照如下流程进行操作,一步都不要跟丢了。 所需要的一些文件放在百度网盘了。 先把最新的库函数和CMSIS安装好。 我这里为了方便就直接安装在

    2023年04月25日
    浏览(23)
  • 解决keil5.38编译stm32报四个错误问题,无需更换ARM5编译器

     以上为错误截图,一下为错误信息 Start/core_cm3.c(445): error: non-ASM statement in naked function is not supported   uint32_t result=0;   ^ Start/core_cm3.c(442): note: attribute is here uint32_t __get_PSP(void) __attribute__( ( naked ) );                                           ^ Start/core_cm3.c(465): error: paramet

    2024年02月11日
    浏览(38)
  • 基于STM32F4开发的智能台灯

    写这篇博客的目的有2个,首先是记录一下学习STM32大半年来的第一个自己动手开发的项目,整理一下开发过程和思路;其次也是希望可以和更多的同行交流开发经验,有什么问题可以多多讨论,集思广益,共同进步~ 开发的智能台灯功能有2个: 1.手动模式:可通过按键调节

    2024年02月05日
    浏览(16)
  • STM32——01-开发软件Keil5及STM32CubeMX的安装

    1.1开发环境的安装  编程语言:C语言 需要安装的软件有两个:Keil5和STM32CubeMX 安装         安装包(不需要太新,以 MDK324 为例,最新的 MDK327 有问题)         安装过程一路下一步即可(建议不要安装在 C 盘)         安装路径一定不要有中文或空格!!(重要

    2024年02月08日
    浏览(19)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包