在做毕设过程中,用到了八个相同的传感器,传感器的通信协议都是一样的,固然直接搞八个差不多的文件来驱动传感器是没问题的,但是有一种更简洁的方式,那就是使用C++,来复用通信程序;
参考:https://zhuanlan.zhihu.com/p/115068898
环境说明
使用的单片机芯片是STM32F103C6T6;
Keil编译器版本为AC6;
Keil的配置如下:
![]() |
|---|
![]() |
然后是将C++源文件配对的头文件改为使用C++编译器进行编译;
![]() |
|---|
![]() |
源码编写
注意把main文件的后缀也改为.cpp,否则会出错;
头文件:
1 | /* |
源文件:
1 | /* |
要注意其中的
extern "C"的用法;
Main中调用:
注意main文件也是cpp后缀;
1 | void main(void) |
其他
可执行文件的大小比较
实现相同功能的情况下,生成的bin文件的大小比较:
| 使用C编写 |
|---|
![]() |
| 使用C++编写 |
![]() |
C:
| Total RO Size (Code + RO Data) | 14016 (13.69kB) |
|---|---|
| Total RW Size (RW Data + ZI Data) | 2040 (1.99kB) |
| Total ROM Size (Code + RO Data + RW Data) | 14464 ( 14.13kB) |
C++:
| Total RO Size (Code + RO Data) | 11780 (11.50kB) |
|---|---|
| Total RW Size (RW Data + ZI Data) | 2864 (2.80kB) |
| Total ROM Size (Code + RO Data + RW Data) | 12220 ( 11.93kB) |
相比较而言C用的ROM比较多一些,C++用的RAM比较多一些;
可见在某些情况下,使用C++编写代码可以有效缩减代码体积,且代码更易懂;
microlib
使用C++编译的话,就没法再使用MicroLIB,因为MicroLIB为非标准的精简库,会与标准C++产生冲突;
中断服务程序
如果中断服务程序是异常的,因为stm32的中断入口矢量是按C的方式进入的,因此需要在整个文档的头部和末尾加上extern “C”{}用大括号把整个代码段扩住,这样中断就可以正常的进入了;
Cubemx
Cubemx在生成头文件中已经加入了:
1 |
|
所以在不是其生成的文件中要注意extern "C"的使用;
当需要使用有C++特性的头文档时可以直接用cpp后缀,没有用到C++特性的可以C后缀也可以以CPP后缀了;
printf的实现
半主机模式是ARM的一种机制,实现将来ARM应用程序代码的输入/输出请求传送至运行着调试器的主机。例如设置使用半主机模式下的ARM应用程序,可以使用printf()和scanf()来使用主机的显示器和键盘,而不需要在ARM系统上搭配显示器和键盘。
半主机通过一组定义好的软件指令(如SVC)来实现的,这些指令在程序控制下产生异常,ARM应用程序调用半主机对应的异常处理函数,然后调试代理处理该异常。
第二段话感觉理解起来有点模糊,但是第一段还是懂它在讲什么的。一般的ARM应用程序中并不需要半主机操作,在这里为确保ARM应用程序中没有链接MicroLib的半主机相关函数,我们要取消ARM的半主机工作模式。
实现代码:
在工程中加上如下代码:
1 | // 取消ARM的半主机工作模式 |
然后就可以愉快的使用printf打印日志了;





