STM32利用C++语言重定向cout
STM32利用C语言重定向printft到Usart1。可利用printf函数实现打印功能,在串口调试助手上显示。
C语言代码为:
//加入以下代码,支持printf函数,不需要选择use MicroLIB(Option->Target->Use MicroLIB(勾选))
#if 1
#pragma import(__use_no_semihosting)
struct __FILE
{
int handle;
};
FILE __stdout;
_sys_exit(int x)
{
x = x;
}
int fputc(int ch, FILE *f)
{
while((USART1->SR&0X40)==0);
USART1->DR = (u8) ch;
return ch;
}
#endif
STM32利用C++语言重定向cout到Usart1。可利用cout对象实现打印功能,在串口调试助手上显示。
C++语言代码为:
#if 1
//非半主机模式
#pragma import(__use_no_semihosting_swi)
namespace std{
struct __FILE
{
int handle;
};
FILE __stdout;
FILE __stdin;
FILE __stderr;
//FILE *fopen(const char * __restrict /*filename*/,
// const char * __restrict /*mode*/)
// {
// usart1<<"\n\r fopen. \n\r";
// return NULL;
// }
int fputc(int ch, std::FILE *f)
{
while((USART1->SR&0X40)==0);//重定义fputc
USART1->DR = (u8) ch;
return ch;
}
// int fgetc(FILE *f) {
// /* Your implementation of fgetc(). */
// usart1<<"\n\r fgetc \n\r";
// return 0;
// }
int ferror(FILE *stream)
{
/* Your implementation of ferror(). */
return 0;
}
// long int ftell(FILE *stream){
// /* Your implementation of ftell(). */
// usart1<<"ftell\n\r";
// return 0;
// }
// int fclose(FILE *f){
// /* Your implementation of fclose(). */
// usart1<<"\n\r fclose \n\r";
// return 0;
// }
// int fseek(FILE *f, long nPos, int nMode){
// /* Your implementation of fseek(). */
// usart1<<"fseek\n\r";
// return 0;
// }
int fflush(FILE *f)
{
/* Your implementation of fflush(). */
return 0;
}
extern "C" void _sys_exit(int)
{
/* declared in <stdlib.h> */
abort();
while(1);
}
extern "C" void _ttywrch(int ch)
{
while((USART1->SR&0X40)==0);
USART1->DR = (u8) ch;
return ;
}
}
#endif
其中,注释的部分同样可以重定义。
重定向过程中,出现的部分问题:
1、加入上部分代码后,产生如下错误:
.\Objects\STM32C8T6.axf: Error: L6200E: Symbol __stderr multiply defined (by stdio_streams.o and usart.o).
.\Objects\STM32C8T6.axf: Error: L6200E: Symbol __stdout multiply defined (by stdio_streams.o and usart.o).
.\Objects\STM32C8T6.axf: Error: L6200E: Symbol fflush multiply defined (by fflush.o and usart.o).
.\Objects\STM32C8T6.axf: Error: L6200E: Symbol __stdin multiply defined (by stdio_streams.o and usart.o).
解决方法:勾选Use MicroLIB选项(Option->Target->Use MicroLIB)
2、勾选Use MicroLIB选项后,出现如下错误:
.\Objects\STM32C8T6.axf: Error: L6218E: Undefined symbol __fread_bytes_avail (referred from ios.o).
.\Objects\STM32C8T6.axf: Error: L6218E: Undefined symbol mbsinit (referred from ios.o).
.\Objects\STM32C8T6.axf: Error: L6218E: Undefined symbol wmemmove (referred from ios.o).
解决方法:在文件中加入如下代码:
#ifdef __cplusplus
extern "C" {
#endif
size_t __fread_bytes_avail(void *buf, size_t nbytes, FILE *stream)
/* Read a single character into buf[] using fgetc() */
{
*(char *)buf = (char)fgetc(stream);
return 1;
}
#include "wchar.h"
int mbsinit(const mbstate_t * ps)
{
return -1;
}
/// To suppress MDK-ARM Linker Error: L6218E: Undefined symbol mbsinit (referred from ios.o).
wchar_t *wmemmove(wchar_t * __restrict s1,const wchar_t * __restrict s2, size_t n) //__attribute__((__nonnull__(1,2)))
{
return NULL;
}
#ifdef __cplusplus
}
#endif
keil中可能会出现红叉,不用管它。
以下为测试代码及结果:
代码:
#include <iostream>
#include "stm32f10x.h"
#include "delay.h"
#include "usart.h"
using namespace std;
int main(void)
{
delay_init();
LED_Init();
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
uart_init(9600);
while(1)
{
cout<<"test"<<endl;
delay_ms(1000);
}
}
结果在串口调试助手中显示:
参考文献