找回密码
 立即注册
查看: 184|回复: 21

printf能直接通过串口1打印出数据

[复制链接]
  • 打卡等级:初来乍到
  • 打卡总天数:6
  • 最近打卡:2025-04-29 08:53:52
已绑定手机

8

主题

47

回帖

144

积分

注册会员

积分
144
发表于 2025-4-17 09:33:27 | 显示全部楼层 |阅读模式
printf("APP_Version: %s\r\n", APP_Version);
为什么这个能直接通过串口1打印出数据呢??
这是怎么实现的?? 编译器将标准输出挂在到了串口1上面了么??




看不到stdio.c, 后台是怎么实现的?? 有谁知道么??
截图202504170930121576.jpg
截图202504170930335372.jpg
截图202504170930439622.jpg
回复

使用道具 举报 送花

3

主题

1160

回帖

1031

积分

等待验证会员

积分
1031
发表于 2025-4-17 09:38:00 | 显示全部楼层
在嵌入式系统中,printf函数通常用于格式化输出数据。默认情况下,printf函数会将数据输出到标准输出设备(通常是控制台)。然而,在嵌入式系统中,标准输出设备可能并不存在,或者需要通过特定的硬件接口(如串口)进行输出。因此,开发者需要将printf函数的输出重定向到特定的硬件接口,例如串口1。

1. printf函数的工作原理
printf函数是C标准库中的一个函数,用于格式化输出数据。它的底层实现依赖于putchar或write等函数,这些函数负责将字符逐个输出到标准输出设备。在嵌入式系统中,标准输出设备通常被重定向到串口或其他硬件接口。

2. 重定向printf到串口1
在嵌入式系统中,将printf函数的输出重定向到串口1通常需要以下步骤:

2.1 实现putchar或write函数
为了将printf的输出重定向到串口1,开发者需要实现一个自定义的putchar或write函数,该函数将字符发送到串口1。例如:
  1. c
  2. int ioputchar(int ch) {
  3.     // 将字符发送到串口1
  4.     UARTSendData(UART1, (uint8t)ch);
  5.     while (UARTGetFlagStatus(UART1, UARTFLAGTXE) == RESET);
  6.     return ch;
  7. }
复制代码

2.2 重定向标准输出
在实现putchar或write函数后,开发者需要将标准输出重定向到该函数。这通常通过修改ioputchar函数的定义或使用特定的库函数来实现。例如,在某些开发环境中,可以通过以下方式重定向标准输出:
  1. c
  2. int write(int file, char ptr, int len) {
  3.     int DataIdx;
  4.     for (DataIdx = 0; DataIdx < len; DataIdx++) {
  5.         ioputchar(ptr++);
  6.     }
  7.     return len;
  8. }
复制代码

2.3 初始化串口1
在重定向标准输出之前,开发者需要确保串口1已经正确初始化。这通常包括配置串口的波特率、数据位、停止位和校验位等参数。例如:
  1. c
  2. void UART1Init(void) {
  3.     // 配置串口1的波特率、数据位、停止位和校验位
  4.     UARTInitTypeDef UARTInitStruct;
  5.     UARTInitStruct.BaudRate = 115200;
  6.     UARTInitStruct.WordLength = UARTWORDLENGTH8B;
  7.     UARTInitStruct.StopBits = UARTSTOPBITS1;
  8.     UARTInitStruct.Parity = UARTPARITYNONE;
  9.     UARTInitStruct.Mode = UARTMODETXRX;
  10.     UARTInitStruct.HwFlowCtl = UARTHWCONTROLNONE;
  11.     UARTInitStruct.OverSampling = UARTOVERSAMPLING16;
  12.     UARTInit(UART1, &UARTInitStruct);
  13.     UARTCmd(UART1, ENABLE);
  14. }
复制代码

3. 编译器的作用
编译器在编译过程中并不会自动将标准输出重定向到串口1。重定向标准输出是开发者在代码中显式实现的。编译器的作用是将printf函数的调用转换为对底层输出函数(如putchar或write)的调用。因此,开发者需要确保这些底层输出函数能够正确地将数据发送到串口1。

4. 后台实现
在嵌入式系统中,printf函数的后台实现通常涉及以下几个步骤:

1. 格式化字符串:printf函数首先根据格式化字符串和参数生成输出字符串。
2. 调用底层输出函数:生成的字符串通过putchar或write函数逐个字符地输出。
3. 硬件接口发送:putchar或write函数将字符发送到串口1,串口1再将字符发送到外部设备。

5. 总结
在嵌入式系统中,printf函数能够直接通过串口1打印出数据,是因为开发者将标准输出重定向到了串口1。这通常通过实现自定义的putchar或write函数,并确保串口1正确初始化来实现。编译器在编译过程中并不会自动完成这一重定向,开发者需要在代码中显式地实现这一功能。

通过这种方式,开发者可以方便地使用printf函数进行调试和信息输出,而无需关心底层的硬件接口细节。

[本文内容由国芯人工智能辅助生成,仅供参考]
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:6
  • 最近打卡:2025-04-29 08:53:52
已绑定手机

8

主题

47

回帖

144

积分

注册会员

积分
144
发表于 2025-4-17 09:44:27 | 显示全部楼层
用户没有主动增加这部分程序,这个是怎么实现的?? 编译器??还是库函数中自带的??
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:6
  • 最近打卡:2025-04-17 09:50:59

17

主题

91

回帖

755

积分

高级会员

积分
755
发表于 2025-4-17 09:50:59 | 显示全部楼层
王*** 发表于 2025-4-17 09:44
用户没有主动增加这部分程序,这个是怎么实现的?? 编译器??还是库函数中自带的??
...

你这个明显是某个 RTOS系统,RTOS替你重定向了,仔细找,应该能找到

点评

没有用,裸机程序  发表于 2025-4-17 10:00
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:423
  • 最近打卡:2025-05-01 07:10:25
已绑定手机

76

主题

4833

回帖

8343

积分

超级版主

DebugLab

积分
8343
发表于 2025-4-17 10:00:25 | 显示全部楼层
用了库函数?
DebugLab
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:6
  • 最近打卡:2025-04-29 08:53:52
已绑定手机

8

主题

47

回帖

144

积分

注册会员

积分
144
发表于 2025-4-17 10:01:41 | 显示全部楼层
纯裸机程序,没有用操作系统
截图202504171001157465.jpg
截图202504171001281422.jpg
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:6
  • 最近打卡:2025-04-29 08:53:52
已绑定手机

8

主题

47

回帖

144

积分

注册会员

积分
144
发表于 2025-4-17 10:02:24 | 显示全部楼层

用了,标准库的printf

点评

libc没有操作串口的程序,给SBUF赋值的语句在哪里?  详情 回复 发表于 2025-4-17 10:09
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:6
  • 最近打卡:2025-04-17 09:50:59

17

主题

91

回帖

755

积分

高级会员

积分
755
发表于 2025-4-17 10:04:02 | 显示全部楼层
你的日志信息,谁给你实现的?
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:423
  • 最近打卡:2025-05-01 07:10:25
已绑定手机

76

主题

4833

回帖

8343

积分

超级版主

DebugLab

积分
8343
发表于 2025-4-17 10:05:31 | 显示全部楼层
我写的串口printf程序供参考:
https://www.stcaimcu.com/thread-4598-1-1.html
https://www.stcaimcu.com/thread-16321-1-1.html

可以改为snprintf,避免缓冲区溢出
截图202504171005258743.jpg


DebugLab
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:6
  • 最近打卡:2025-04-17 09:50:59

17

主题

91

回帖

755

积分

高级会员

积分
755
发表于 2025-4-17 10:06:01 | 显示全部楼层
王*** 发表于 2025-4-17 10:02
用了,标准库的printf

标准 printf 的fputc 是可以自己定义的


/* 重定义fputc函数, printf函数最终会通过调用fputc输出字符串到串口 */
int fputc(int ch, FILE *f)
{
    while ((USART_UX->ISR & 0X40) == 0);    /* 等待上一个字符发送完成 */

    USART_UX->TDR = (uint8_t)ch;            /* 将要发送的字符 ch 写入到DR寄存器 */
    return ch;
}
写这样一个名字的函数,编译时printf 就会替换原来的输出

你搜索这个函数
回复 支持 反对

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|小黑屋|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2025-5-1 21:57 , Processed in 0.134648 second(s), 109 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表