采用STM32CubeMX生成的keil工程,默认是采用V5编译的,V5版本编译器只支持C。
就目前来说,使用C++开发嵌入式的程序员还是比较少,就我个人认为原因是一方面KEIL / MDK对C++程序的支持还不够全面,另一方面则是C++程序的体量相较于C程序过于庞大,对于小型的应用来说没有必要。
作为一个嵌入式和智能终端都有一点接触的程序员来说,我当然是更希望我的代码能够更容易地移植,最重要的一点则是C++兼容了C,我们要在原始的C工程上面,进行修改,使得我们的工程变得可以支持C++。
一、KEIL / MDK 配置修改
KEIL / MDK是支持C++编程方式的,我们先打开原先的keil工程,当然这个工程原本是可以编译通过的。
如下图,打开Project -- Options for Target,打开Target选项卡:
1、选择Version 6
因为KEIL / MDK V5版本只支持C编译,V6版本才支持C++编译。
2、去掉Use MicorLIB的勾选
microlib 是缺省 C 库的备选库;
它用于必须在极少量内存环境下运行的深层嵌入式应用程序;
microlib 进行了高度优化以使代码变得很小。 它的功能比缺省 C 库少,并且根本不具备某些 ISO C 特性。
microlib支持printf,
但是不支持C++编译,所以这里要去掉,后面我们会采用其他方式来支持printf。
如下图,选择C/C++(AC6)选项卡
OK,配置完成
二、std标准库 重定向
因为microlib已经去掉,需要对部分标准库方法进行重定向编写,既将输入输出流重定向至STM32的串口端。而Retarget.c里面就实现了相关的方法。
我们从keil的安装路径里找到Retarget.c文件,复制到我们的工程目录下,然后进行修改如下:
/******************************************************************************/
/* RETARGET.C: 'Retarget' layer for target-dependent low level functions */
/******************************************************************************/
/* This file is part of the uVision/ARM development tools. */
/* Copyright (c) 2005 Keil Software. All rights reserved. */
/* This software may only be used under the terms of a valid, current, */
/* end user licence from KEIL for a compatible version of KEIL software */
/* development tools. Nothing else gives you the right to use this software. */
/******************************************************************************/
#include <rt_sys.h>
#include "usart.h"
#ifdef __cplusplus
extern "C" {
#endif
extern int sendchar(int ch);
extern int getkey(void);
int fputc(int ch, FILEHANDLE *f) {
return (sendchar(ch));
}
int fgetc(FILEHANDLE *f) {
return (sendchar(getkey()));
}
FILEHANDLE _sys_open(const char * name, int openmode)
{
return 1;
}
int _sys_close(FILEHANDLE fh)
{
return 0; //return success
}
int _sys_write(FILEHANDLE fh, const unsigned char * buf,
unsigned len, int mode)
{
return 0;
}
int _sys_read(FILEHANDLE fh, unsigned char * buf,
unsigned len, int mode)
{
return 0;
}
void _ttywrch(int ch)
{
}
int _sys_istty(FILEHANDLE fh)
{
return 1; // no interactive device present
}
int _sys_seek(FILEHANDLE fh, long pos)
{
return -1; // error
}
int _sys_ensure(FILEHANDLE fh)
{
return 0; // success
}
long _sys_flen(FILEHANDLE fh)
{
return 0;
}
int _sys_tmpnam(char * name, int sig, unsigned maxlen)
{
return 0; // fail, not supported
}
void _sys_exit(int returncode)
{
while(1) {};
}
#ifdef __cplusplus
}
#endif
然后在其他文件里,比如你的串口读写的C文件里实现
sendchar函数和getkey函数
例如:
int sendchar(int ch)
{
if (ch == '\n') {
HAL_UART_Transmit(&huart1, (void *)"\r", 1,30000);
}
HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xFFFF);
}
int getkey(void){
/* Place your implementation of fgetc here */
/* e.g. readwrite a character to the USART2 and Loop until the end of transmission */
uint8_t ch = 0;
//uint32_t recv_size;
HAL_UART_Receive(&huart1, &ch, 1,30000);
return ch;
}
三、从C调用C++
建立一个C++文件,加入到我们工程中,或者将我们之前的一个c文件直接修改为cpp文件
要调用c++里的函数, 需要将被调用的函数声明为``extern "C"''
如
extern "C" void application_entry(void *arg);
可以添加
std::cout << "hello world" << std::endl;
进行测试了。
串口已能正常打印输出。
至此,我们就可以任意
随心所欲地进行C++程序编写了。