MDK中用C++开发STM32
作者:良知犹存
转载授权以及围观:欢迎添加微信:Allen-Iverson-me-LYN
前言
最近想开发一段单片机的代码,代码本身有很多的重复元素,这重复定义的一些结构体使用起来有些繁琐,所以就想用C++开发,C++的继承 模板类可以很容易的解决这些问题。因为在单片机运行,习惯用MDK或者IAR这些软件。但是这些软件都是默认C开发的,用C++开发需要重新配置,有些麻烦。但是我还是试了试,做了一个小demo供大家参考。
代码文件我传到我的github中去了,大家有兴趣可以参考一下
https://github.com/conscience-still/MDK-Cplusplus--LED
一、STM32CubeMX生成底层代码
因为是做一个demo,不需要很复杂,就用cubemx生成了一个简单的串口和IO控制的MDK代码,用了精简的LL库,具体实现就不讲了,详细操作可以看我博客CubeMX配置的一些文章。我的博客名是:良知犹存
二、进行IDE的C++配置(去掉C环境的配置)
1.首先打开MDK软件,去掉use microlib 勾选,这个一个C的依赖库,但比标准的库小,它可以减少C代码的大小。CubeMX生成的文件默认选择此项。因为这个精简库不支持C++,所以我们需要去掉此项功能。
2.Options for Target 再点C/C++ 在下边的Misc Controls 中输入—cpp
3.去掉C99 mode选项
三、代码中C++的编写注意
1. IDE中的编译器的这个工程时候,当文件后缀是C的时候IDE会使用C编译器进行编译,如果文件后缀是CPP则IDE使用C++编译器进行编译,工程包含的头文件是使用C++编译器进行编译的,不过头文件声明的还是C文件的符号,所以IDE会无法正确编译链接。此时我们应该将头文件所有声明C符号的部分用预编译宏加extern "C" { }的形式包含起来,告诉编译器该段要使用C编译器进行编译。只包含需要进行C编译的部分即可
#ifndef __MAIN_H
#define __MAIN_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "stm32f0xx_ll_crs.h"
#include "stm32f0xx_ll_rcc.h"
#include "stm32f0xx_ll_bus.h"
#include "stm32f0xx_ll_system.h"
#include "stm32f0xx_ll_exti.h"
#include "stm32f0xx_ll_cortex.h"
#include "stm32f0xx_ll_utils.h"
#include "stm32f0xx_ll_pwr.h"
#include "stm32f0xx_ll_dma.h"
#include "stm32f0xx_ll_usart.h"
#include "stm32f0xx_ll_gpio.h"
#ifdef __cplusplus
}
#endif
2.设置需要C++编译的文件,这时候有两种方法实现。
1>.在代码文件的界面,选择文件右击选择Option for Files "你点击的文件",然后设置file type为需要的C++
2>.直接将文件改为.cpp文件,重新添加,此时候IDE自动进行C++编译
第二种方法简单快捷,但是第一种方法虽然麻烦,但是有个好处,我们不需要修改文件名称,这样STM32CubeMX下一次生成代码就不会在生成相应名称的C代码了。
3.将中断服务函数添加 extern "C" 的标识,因为C++中无法直接识别中断函数,所以用C的方法进行设备编译。而在Cpp文件中引入C的部分代码,需要进行extern "C" { }进行修饰,否则不能通过编译链接。
四、C++实现时候遇到的情况
1.写了个类没有注意到写成了虚函数,其他处也没有继承定义这个虚函数,导致编译错误,为什么把这个问题写出来呢,就是因为MDK中C++的报错没怎么遇到过,我查了挺长时间,才发现这个问题的。
c++test\c++test.axf: Error: L6218E:Undefined symbol vtable for STM32_TEST::TestGPIO (referred from main.o).
把类中的虚函数改为定义好的函数即可。
2.因为我把串口初始化都放在类中实现,我想进行类的构造的时候进行串口数据的打印,但是网上查询得知,MDK不支持std的流打印输出,所以我就用sub和super补丁函数,进行系统main函数执行前进行串口的初始化。
这是一种特殊模式:用于有一个已经存在且不能被改变的函数 的情况。使用这两个模式可以帮原函数打补丁。如存在一个函数foo();
$Sub$ $foo :定义的新功能函数,在foo()函数之前/后使用$Sub$$foo 可以添加一些新的程序代码。
$Super$ $foo :就是原始的未修补的foo函数,使用这个$Super$ $foo函数将直接跳转到foo()函数。
具体教程可以看ARM官网的资料学习哈,http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0377g/pge1362065967698.html。
因为super与sub函数属于c所以我们在cpp文件下需要添加extern“C”进行编译才行,否则就要出现如下问题了,这些我都遇到过,给大家把雷趟了一遍。
3.最后的一个bug,STDIO的初始化。
本来一个简单的C++程序就写完了,主要就是运行环境,但是程序收录进去之后无法工作,并且在硬件调试下明显看到系统到了__main之后不知道跑哪里去了,F5全速执行几次程序才有机会正常运行,这就很奇怪了,后来在网上找资料,终于找到问题所在了,在以为博主的文章看到,他最后找到问题原来是:
事实上本人也找了近两天的时间才找到解决办法,一开始认为是heap和stack没有初始化好,尝试了好久均未成功,后来在网上得到启发,这个问题是出在STDIO初始化上。
如果要使用C/C++标准库就要对其STDIO进行Retarget的,很简单,但却是非常关键的一步,就是这么一回事啦。
我按照他的操作然后程序就可以正常运行了,下载ARM官方的retarget文件,并加入到工程当中。下载链接:
http://infocenter.arm.com/help/topic/com.arm.doc.faqs/attached/3844/retarget.c
然后将里面的串口读写按照我现有的硬件需求进行重写就可以了。如下代码所示:
char UART_read(void);
void UART_write(char ch);
char UART_read(void)
{
return 0;
}
void UART_write(char ch)
{
while(!(USART2->ISR & USART_ISR_TXE)){};
USART2->TDR = ch;
}
五、最后测试的一些体验与感想
刚开始想用C++在MDK中开发是因为,有些个需求的功能C++特别符合,但是在调试这个demo过程中,发现使用的单片机容量太小,一个<iostream>头文件的包含就让一个只有串口加几组IO控制的最小程序代码膨胀到了32K,而去掉该头文件,代码缩小到了5K。
代码过大是c++的依赖项过多,而C++ 中模板类 、虚拟继承 、STL库等精华由于依赖的问题都不建议在单片机中用,代码膨胀的时候单片机吃不住。所以C++虽好,可不一定适合小容量的单片机,大家需要按照自己的功能进行有效的使用C++,精简使用的依赖,这个可以通过每次编译的生成的.map文件进行增该删,其次对于C++中内存以及代码扩增一些基础知识需要熟悉,负责很容易代码膨胀,导致我们的程序无法在单片机使用。
这就是我分享的在MDK用C++开发的demo,里面代码是实践过的,如果大家有什么更好的思路,欢迎分享交流哈。
更多分享,扫码关注我
微信:Allen-Iverson-me-LYN
MDK中用C++开发STM32的更多相关文章
- Jlink V7在MDK下使用Cortex-M3-Jlink模式开发STM32的说明
Jlink V7在MDK下使用Cortex-M3-Jlink模式开发STM32的说明 开发环境:STM32F103RB(128K Flash 20K RAM)+MDK3.50+JLINK V7(v ...
- 免费的EmBitz可替代Keil MDK开发STM32、NXP项目
一.背景 由于使用之前开发STM32是基于Keil MDK编译环境开发的,由于该软件是收费的,想用个免费开源的软件来替代Keil,EmBitz编译器是免费的,可以完全替代开发.下载程序支持J-Link ...
- Linux下开发STM32单片机
一开始学习51单片机就是用的MDK这个IDE软件,IDE软件虽然看起来直观好像更加容易入门(因为有界面看起来很形象),但是实际上IDE却是向我们这些入门人员隐藏了背后真实存在的过程,让我们以为编译就是 ...
- 使用EmBitz开发STM32项目的环境配置
一.EmBitz软件获取与安装 1.EmBitz软件的获取 EmBitz原名Em::Blocks,是基于Code::Blocks开发的,面向嵌入式的C/C++集成开发环境.支持J-Link和ST-Li ...
- 在Mac OS X中使用VIM开发STM32(4)
本文原创于http://www.cnblogs.com/humaoxiao,非法转载者请自重! 在上三篇文章中,我们基本搭建好了开发STM32的IDE环境,当然vim.ctags.tagl ...
- 在Mac OS X中使用VIM开发STM32(2)
本文原创于http://www.cnblogs.com/humaoxiao,非法转载者请自重! 在我先前的博文⎣在Mac OS X中使用VIM开发STM32(1)⎤中,我们安装完成了MACVIM,这一 ...
- 基于MDK的ARM-GCC开发环境建立及新唐M0的HID类设备的C++开发
一,下载安装测试arm-none-eabi-gcc编译工具链 1,查看arm-none-eabi-gcc编译工具版本 打开网页:https://sourcery.mentor.com/G ...
- MDK建立STM32F103*开发模板
一.整体流程 1.获取ST库--STM32F10x_StdPeriph_Lib_V3.5.0 2.新建文件夹并加载文件 3.新建工程 4.给工程添加组 5.设置"Target Option& ...
- 在vs2012中用C#开发Android应用Xamarin环境搭建
Xamarin是Mono创始人Miguel de Icaza创建的公司,旨在让开发者可以用C#编写iOS, Android, Mac应用程序,也就是跨平台移动开发. 简介 Xamarin是基于Mono ...
随机推荐
- [ABP教程]第二章 图书列表页面
Web应用程序开发教程 - 第二章: 图书列表页面 关于本教程 在本系列教程中, 你将构建一个名为 Acme.BookStore 的用于管理书籍及其作者列表的基于ABP的应用程序. 它是使用以下技术开 ...
- 【JavaWeb】JSTL 标签库
JSTL 标签库 简介 JSTL(JSP Standard Tag Library),即 JSP 标准标签库.标签库是为了替换代码脚本,使得整个 jsp 页面变得更加简洁. JSTL 有五个功能不同的 ...
- 常用的N个网站建议收藏
类型网站路径学习资源及博客论坛网站 书栈网:https://www.bookstack.cn 52 download: http://www.52download.cn/wpcourse/ 菜鸟教程: ...
- 5.1中repair table
mysql> repair table xs;+---------+--------+----------+----------+| Table | Op | Msg_type | Msg_te ...
- 【高级排序算法】1、归并排序法 - Merge Sort
归并排序法 - Merge Sort 文章目录 归并排序法 - Merge Sort nlogn 比 n^2 快多少? 归并排序设计思想 时间.空间复杂度 归并排序图解 归并排序描述 归并排序小结 参 ...
- apiAutoTest: 接口自动化测试的数据清洗(备份/恢复)处理方案
接口自动化测试之数据清洗/隔离/备份/恢复 在得到QQ:1301559180 得代码贡献之后,想到了通过ssh连接上服务器,然后进行数据库备份,数据库恢复, 主要使用了 paramiko库 最终效果 ...
- ctfhub技能树—文件上传—无验证
打开靶机 查看页面信息 编写一句话木马 <?php echo "123"; @eval(@$_POST['a']); ?> 上传木马 上传成功,并拿到相对路径地址 查看 ...
- oracle可传输表空间测试
使用RMAN在恢复表空间的时候,表空间数据文件DBID和恢复数据库的数据文件DBID必须相同 可传输表空间不需要这样,也就是可以快速的把这个表空间插入另一个数据库使用 可传输表空间内的对象必须不依赖与 ...
- Py编程方法,尾递归优化,map函数,filter函数,reduce函数
函数式编程 1.面向过程 把大的问题分解成流程,按照流程来编写过程 2.面向函数 面向函数编程=编程语言定义的函数+数学意义上的函数先弄出数学意义上的方程式,再用编程方法编写这个数学方程式注意面向函数 ...
- 小白也能看懂的ACID与隔离级别
前言 现如今JAVA开发工程师的数量越来越多,但大多数工程师平时做的工作都是简单的CRUD,当你一直处于这种舒适的环境中不追求进步的时候,如果哪一天你突然想要改变环境,换个工作,去与面试官当面聊技术的 ...