嵌入式系统重定向printf的三种方法 |
您所在的位置:网站首页 › 两种重定向 › 嵌入式系统重定向printf的三种方法 |
对printf()进行重定向的三种方法
方法1: 使用MircoLib并重定义fputc方法2: 停用半主机模式,在MDK中使用标准库重定向printf()方法3: 在Gcc中使用标准库重定向printf
1. MDK使用MircoLib并重定义fputc
printf()函数实际上是调用了fputc()根据 format 字符串给出的格式打印输出到 stdout(标准输出)中。这两个函数都定义在中: int printf(const char *format, ...); ... int fputc(int ch, FILE *stream);fputc() 函数写入字符 ch 到给定输出流 stream,printf()函数在调用fputc() 时,会向stream参数传入stdout从而打印数据到标准输出。 KEIL-MDK中有一个Use MicroLIB选项,MicroLib是缺省c库的备选库,它可装入少量内存中,与嵌入式应用程序配合使用,且这些应用程序不在操作系统中运行。MicroLib提供了一个有限的stdio子系统,它仅支持未缓冲的stdin、stdout和stderr。 所以我们只需要勾选Use MicroLIB选项,并重写fputc() 函数就可以将printf()从串口输出了。 int fputc(int ch, FILE* f) { USART_SendData(USART1, (unsigned char) ch); while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET) { } return ch; } 2. 在MDK中使用标准库重定向printf()如果不想使用MicroLib,也可以使用标准库,但是需要停用半主机模式。下面我们提供另外一种重定义fputc()的写法。 STM32或者其他类似的ARM芯片(比如航顺HK32系列)的USART串口外设有一个 ISR 寄存器,全名 Interrupt and status register, 用来指示当前串口的状态,可以通过判断该位来判断串口当前是否处于发送状态,代码如下: while((USART1->ISR & 0X40) == 0);为了提高发送效率,直接使用寄存器来操作串口发送字符ch: USART1->TDR = (uint8_t) ch; #include /* 告知连接器不从C库链接使用半主机的函数 */ #pragma import(__use_no_semihosting) /* 定义 _sys_exit() 以避免使用半主机模式 */ void _sys_exit(int x) { x = x; } /* 标准库需要的支持类型 */ struct __FILE { int handle; }; FILE __stdout; /*重定义fputc的另外一种方式*/ int fputc(int ch, FILE *stream) { /* 堵塞判断串口是否发送完成 */ while((USART1->ISR & 0X40) == 0); /* 串口发送完成,将该字符发送 */ USART1->TDR = (uint8_t) ch; return ch; } 3. 在Gcc中使用标准库重定向printf()如果你不使用MDK而是Gcc来编译项目,那么上述两种方法不可行。 那么需要怎么做呢: 在使用Gcc编译器的时候,需要重新定义_write函数而不是fputs()函数。只能使用标准库,因为Gcc中没有MicroLib。 代码如下: #include int _write(int fd, char *ptr, int len) { HAL_UART_Transmit(&huart1, (uint8_t*)ptr, len, 0xFFFF); return len; } |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |