嵌入式系统重定向printf的三种方法
2023-09-11 14:21:25 时间
对printf()进行重定向的三种方法
- 方法1: 使用MircoLib并重定义fputc
- 方法2: 停用半主机模式,在MDK中使用标准库重定向printf()
- 方法3: 在Gcc中使用标准库重定向printf
1. MDK使用MircoLib并重定义fputc
printf()
函数实际上是调用了fputc()
根据 format
字符串给出的格式打印输出到 stdout
(标准输出)中。这两个函数都定义在<stdio.h>
中:
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 <stdio.h>
/* 告知连接器不从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 <stdio.h>
int _write(int fd, char *ptr, int len)
{
HAL_UART_Transmit(&huart1, (uint8_t*)ptr, len, 0xFFFF);
return len;
}
相关文章
- springboot支持三种嵌入式servlet容器:tomcat(默认),jetty,undertow
- 《安富莱嵌入式周报》第250期:2022.01.24--2022.01.30
- 《安富莱嵌入式周报》第217期:2021.06.14--2021.06.20
- 嵌入式新闻早班车-第4期
- 【STM32H7】第1章 当前主流的小型嵌入式网络协议栈
- SAP UI5 本地开发如何实现 XML 和 JavaScript 代码的自动完成和嵌入式 API 文档自动显示试读版
- 如何在Eclipse自带的嵌入式Maven和外部安装的Maven之间切换
- linux驱动开发重点关注内容--摘自《嵌入式Linux驱动模板精讲与项目实践》
- 嵌入式linux开发,抓包工具tcpdump使用方法
- 嵌入式linux开发,单网卡绑定多IP,实现多网段的访问
- 嵌入式linux开发,linux命令之cp
- 嵌入式linux开发,uboot命令行黏贴内容显示乱码,linux系统下显示正常
- 嵌入式Linux系统中ARM汇编语言的使用方法
- 嵌入式单片机及外设(硬件)知识基础一