最近想开发一段单片机的代码,代码本身有很多的重复元素,这重复定义的一些结构体使用起来有些繁琐,所以就想用C++开发,C++的继承模板类可以很容易的解决这些问题。因为在单片机运行,习惯用MDK或者IAR这些软件。但是这些软件都是默认C开发的,用C++开发需要重新配置,有些麻烦。但是我还是试了试,做了一个小demo供大家参考。

代码文件我传到我的github中去了,大家有兴趣可以参考一下

https://github.com/conscience-still/MDK-Cplusplus--LED

一、STM32CubeMX生成底层代码

因为是做一个demo,不需要很复杂,就用cubemx生成了一个简单的串口和IO控制的MDK代码,用了精简的LL库,具体实现就不讲了。

二、进行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的,很简单,但却是非常关键的一步,就是这么一回事啦。

CSDN:回忆浅离

我按照他的操作然后程序就可以正常运行了,下载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++中内存以及代码扩增一些基础知识需要熟悉,负责很容易代码膨胀,导致我们的程序无法在单片机使用。

1.今年,嵌入式系统技术关注热点是什么?

2.深度:单片机到底是如何软硬件结合的?

3.看完此文,就知道如何选择RTOS了!

4.抓住工业互联网新风口,抢滩智能家居万亿市场

5.对国产嵌入式操作系统,你了解多少?

6.用RISC-V微控制器开发难不难?行人搜索AI框架新突破~

免责声明:本文系网络转载,版权归原作者所有。如涉及作品版权问题,请与我们联系,我们将根据您提供的版权证明材料确认版权并支付稿酬或者删除内容。

如何用C++开发STM32?相关推荐

  1. 如何用node开发自己的cli工具

    如何用node开发自己的cli工具 灵感 写这个工具的灵感以及场景源于youtube的一次闲聊 github 地址 blog首发 使用场景 原本我们写博客展示shell,例如:安装运转docker,一 ...

  2. rust做嵌入式开发_Rust 嵌入式开发 STM32 amp; RISC-V

    Rust 嵌入式开发 STM32 & RISC-V 发布于 2020-04-03 11:07:06 本帖最后由 wuhanstudio 于 2020-4-3 11:58 编辑 更新地址: [m ...

  3. python stm32-尝试一下使用Python来开发STM32

    MicroPython是什么 微信图片_20200508183121.jpg (26.41 KB, 下载次数: 0) 2020-5-8 18:39 上传 程序猿中有句俗语: 人生苦短,我用Python ...

  4. 如何用VC++开发读取网卡MAC地址的程序

    如何用VC++开发读取网卡MAC地址的程序 实际的应用系统中,我们往往会需要在程序运行时获取当前机器的网卡的MAC地址,以便作为某种标识之用,如控制程序的合法性等.下文就如何用Microsoft Vi ...

  5. ARM Keil MDK开发STM32工程模板

    使用Keil MDK开发STM32的工程模板 源代码工程 https://github.com/chenhaifeng2016/Band

  6. 使用EmBitz开发STM32项目开发环境配置

     一.EmBitz软件获取与安装 1.EmBitz软件的获取 EmBitz原名Em::Blocks,是基于Code::Blocks开发的,面向嵌入式的C/C++集成开发环境.支持J-Link和ST ...

  7. stm32烧录软件_使用华为LiteOS Studio开发STM32物联网工程1

    本节介绍如何使用HUAWEI LiteOS Studio 开发STM32开发板工程.开源LiteOS工程,支持STM32F429IG.STM32L431RC.STM32F769NI等STM32系列开发 ...

  8. stm32 python界面开发_【STM32开发】使用Qt Creator 开发STM32

    在之前的文章中我们介绍了如何使用VSCode去构建一个STM32的单片机项目,今天我们来说一下使用 Qt Creator 来开发STM32单片机. 0x01: 开发环境准备 PlatformIO Co ...

  9. vscode 暂停运行_用VS Code开发STM32(三)——调试

    2020年7月26日更新: 增加了Jlink GDB Server的支持,可以使用J-Scope 和 SEGGER RTT了. 2020年7月3日更新: 改为了使用Cortex-Debug插件来进行调 ...

最新文章

  1. java队列_如何彻底搞懂 Java 数据结构?CSDN 博文精选
  2. CentOS7安装笔记:minio分布式集群搭建
  3. c语言的32个关键词
  4. MyBatis 源码分析-技术分享
  5. layui 传递前端请求_前端请求后端,后端查询完毕传到前端 ,用layui 将 数据分页...
  6. PyTorch实战福利从入门到精通之八——深度卷积神经网络(AlexNet)
  7. arcgis sample代码之SOE示例代码PageLayout REST Server Object Extension 的源码分析
  8. Keras学习---数据预处理篇
  9. Django重新整理3
  10. java static 可见性_java可重入锁可见性分析
  11. 所有子线程全部结束的判断
  12. mac上好看的时钟屏保
  13. 简单易用的运动控制卡(八):直线插补和手轮运动
  14. gabor滤波器matlab实现,使用matlab实现Gabor滤波器
  15. 单片机“左移右移理论”,详解
  16. 华为2020年鸿蒙系统发布会,2021年6月2日华为发布会内容是什么?将正式发布鸿蒙手机操作系统...
  17. 拓嘉辰丰:拼多多店铺装修有哪几个部分
  18. 403 Forbidden vs 401 Unauthorized HTTP 响应
  19. threejs加载3D模型
  20. 把握趋势,把握未来 —- 小评《只有偏执狂才能生存》

热门文章

  1. pycocotools报错 if type(resFile) == str or type(resFile) == unicode: NameError: name ‘unicode‘ is
  2. IEC 61850 Compatible OpenPLC for Cyber Attack Case Studies on Smart Substation Systems
  3. grep -v grep的作用
  4. mysql 查询名字包括下划线_Python 之 MySql 每日一练 329——查询名字中含有风字的学生信息...
  5. matlab 功率谱密度 汉宁窗_【转】功率谱密度相关方法的MATLAB实现
  6. 计算机的逻辑电路是什么意思,CMOS逻辑电路,CMOS逻辑电路是什么意思
  7. php path separator,php_DIRECTORY_SEPARATOR 和 PATH_SEPARATOR
  8. janus的官网介绍
  9. 展示一下用thinker做小软件的UI
  10. Rust、D、Go三者的Pk1