在嵌入式系统中实现串口重定向(将标准输出如 printf 函数输出重定向到串口)通常有以下几种常用方法,下面结合具体代码示例和适用场景进行说明:

1. 重写 fputc 函数(最常见、最基础的方法)

通过重写标准库中的 fputc 函数,将字符通过串口发送出去,从而实现 printf 等函数的串口输出:

#include "stdio.h"
#include "stm32f1xx_hal.h" // 根据实际MCU型号调整头文件// 假设使用USART1
extern UART_HandleTypeDef huart1;int fputc(int ch, FILE *f) {HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, HAL_MAX_DELAY);return ch;
}
  • 适用场景:裸机(无操作系统)环境,使用标准C库或HAL库。
  • 优点:实现简单,兼容性好。
  • 缺点:阻塞式发送,占用CPU资源。
  • 串口重定向的本质是:通过重写 fputc 将标准库的字符输出请求转发到硬件驱动函数(如 HAL_UART_Transmit)。
    这种设计充分利用了标准库的灵活性和HAL库的硬件抽象能力,是嵌入式开发中非常高效且通用的调试手段。

2. 使用 MicroLIB 库(Keil 环境推荐)

在 Keil 中勾选 Use MicroLIB 选项,并重写 fputc 函数:

#include "stdio.h"
#include "stm32f1xx_hal.h"int fputc(int ch, FILE *f) {HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, HAL_MAX_DELAY);return ch;
}
  • 适用场景:Keil 开发环境,资源受限的MCU。
  • 优点:代码体积小,运行效率高。
  • 缺点:MicroLIB 不完全兼容标准C库,部分功能受限。

3. 使用 RTOS 设备驱动(FreeRTOS 等)

在 RTOS 中,通过设备驱动框架将串口注册为标准输出设备,支持多任务并发访问:

// 假设使用FreeRTOS和串口驱动
void vLoggingTask(void *pvParameters) {while (1) {// 从队列中获取日志数据并通过串口发送// 使用非阻塞或DMA方式发送}
}
  • 适用场景:带 RTOS 的复杂系统。
  • 优点:支持异步输出,避免阻塞任务。
  • 缺点:实现较复杂,需额外资源。

4. 直接寄存器操作(裸机、极致性能优化)

直接操作串口寄存器,适用于无库函数依赖的裸机环境:

#define USART1_DR (*(volatile uint32_t *)0x40013804) // STM32F1示例
#define USART1_SR (*(volatile uint32_t *)0x40013800)void usart_putc(char ch) {while (!(USART1_SR & (1 << 7))); // 等待发送缓冲区空USART1_DR = ch;
}
  • 适用场景:对性能要求极高的裸机程序。
  • 优点:零依赖,执行速度最快。
  • 缺点:代码可读性差,移植性低。

5. Linux 系统下的串口重定向(嵌入式Linux)

在嵌入式Linux中,可通过以下方式将标准输出重定向到串口设备文件:

# 在终端中执行
./your_program > /dev/ttyS0 2>&1

或通过代码实现:

#include <stdio.h>
int main() {freopen("/dev/ttyS0", "w", stdout);printf("Hello, Serial Port!\n");return 0;
}
  • 适用场景:运行Linux的嵌入式设备(如树莓派、BeagleBone等)。
  • 优点:利用系统标准机制,简单易用。
  • 缺点:依赖Linux系统环境。

总结与建议:

  • 裸机开发:优先选择重写 fputc 函数(方法1),若使用Keil可结合MicroLIB(方法2)。
  • RTOS系统:建议通过RTOS设备驱动框架实现(方法3),支持异步和并发。
  • 极致性能:直接寄存器操作(方法4),但需谨慎维护。
  • Linux系统:直接使用系统重定向机制(方法5)。

以上方法可根据实际硬件平台、开发环境和性能需求灵活选择。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/90240.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/90240.shtml
英文地址,请注明出处:http://en.pswp.cn/diannao/90240.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

static补充知识点-代码

public class Student {private static int age;//静态的变量private double score;//非静态的方法public void run(){}public static void go(){}public static void main(String[] args) {new Student().run();Student.go();} } public class Person {//2 &#xff1a; 赋初始…

使用泛型<T>,模块化,反射思想进行多表数据推送

需求&#xff1a;有13个表&#xff0c;其中一个主表和12细表&#xff0c;主表用来记录推送状态&#xff0c;细表记录12种病例的详细信息&#xff0c;现在需要把这12张病例表数据进行数据推送&#xff1b;普通方法需要写12个方法分别去推送数据然后修改状态&#xff1b;现在可以…

光流 | RAFT光流算法如何改进提升

RAFT(Recurrent All-Pairs Field Transforms)作为ECCV 2020最佳论文,已成为光流估计领域的标杆模型。其通过构建4D相关体金字塔和GRU迭代优化机制,在精度与泛化性上实现了突破。但针对其计算效率、大位移处理、跨场景泛化等问题,研究者提出了多维度改进方案,核心方向可系…

linux/ubuntu日志管理--/dev/log 的本质与作用

文章目录 **一、基本概念****二、技术细节:UNIX域套接字****三、在不同日志系统中的角色****四、应用程序如何使用 `dev/log`****五、查看和验证 `/dev/log`****六、总结 `/dev/log` 的核心作用**一、基本概念 /dev/log 是一个 UNIX域套接字(Unix Domain Socket),是Linux系…

EMC整改案例之(1):汽车NFC进入模块BCI整改

EMC整改案例(1):汽车NFC进入模块BCI整改 在汽车电子系统中,NFC(Near Field Communication)进入模块用于实现无钥匙进入功能,但它在电磁兼容(EMC)测试中常面临挑战。本案例聚焦于BCI(Bulk Current Injection)测试整改,该测试模拟大电流注入对设备的影响。以下是基于…

2025年INS SCI2区,灵活交叉变异灰狼算法GWO_C/M+集群任务调度,深度解析+性能实测

目录1.摘要2.灰狼算法GWO原理3.灵活交叉变异灰狼算法GWO_C/M4.结果展示5.参考文献6.代码获取7.算法辅导应用定制读者交流1.摘要 随着云计算的快速发展&#xff0c;受自然现象启发的任务调度算法逐渐成为研究的热点。灰狼算法&#xff08;GWO&#xff09;因其强大的收敛性和易于…

Java常用加密算法详解与实战代码 - 附可直接运行的测试示例

&#x1f337; 古之立大事者&#xff0c;不惟有超世之才&#xff0c;亦必有坚忍不拔之志 &#x1f390; 个人CSND主页——Micro麦可乐的博客 &#x1f425;《Docker实操教程》专栏以最新的Centos版本为基础进行Docker实操教程&#xff0c;入门到实战 &#x1f33a;《RabbitMQ》…

2025开发者工具链革命:AI赋能的效率跃迁

目录引言&#xff1a;效率焦虑下的开发者生存现状一、智能代码编辑器&#xff1a;从辅助到主导的进化1.1 GitHub Copilot&#xff1a;全能型AI助手1.2 Cursor Pro&#xff1a;极致编码体验1.3 飞算JavaAI&#xff1a;垂直领域颠覆者二、版本控制革命&#xff1a;Git的AI进化论2…

“虚空”的物理、哲学悖论

一、虚空并非“完全真空”&#xff1a;量子场论揭示的“真空不空” 物理真空的本质 现代物理学中的“真空”并非绝对的空无一物&#xff0c;而是量子场的基态&#xff08;能量最低状态&#xff09;。根据量子场论&#xff1a; 虚粒子涨落&#xff1a;真空中持续发生量子涨落&am…

CSP-S模拟赛二总结(实际难度大于CSP-S)

T1 很简短&#xff0c;也很好做&#xff0c;第一题直接场切。 我的方法 首先要明确一件事&#xff1a;就是如果选了 ax,ya_{x,y}ax,y​&#xff0c;那么就必然要选 ay,xa_{y,x}ay,x​&#xff0c;所以第一步就在 ax,ya_{x,y}ax,y​ 的基础上加上 ay,xa_{y,x}ay,x​。 然后我…

旋转屏幕优化

1.问题背景 从google原生算法&#xff0c;可以知道其有2个比较大的缺陷&#xff1a; 1) 通过重力传感器传来的x&#xff0c;y&#xff0c;z轴的加速度合成之后只有一个垂直往下的加速度&#xff0c;如果此时用户在别的方向上有加速度&#xff0c;那么通过反余弦、反正切等计算…

Java---day2

七、IDEA开发工具 &#x1f4e6; 一、下载 IntelliJ IDEA 官网地址&#xff1a; &#x1f517; IntelliJ IDEA – the IDE for Pro Java and Kotlin Development 版本选择&#xff1a; 版本说明Community Edition (CE)免费开源版本&#xff0c;适合 Java、Kotlin、Android…

RAL-2025 | 清华大学数字孪生驱动的机器人视觉导航!VR-Robo:面向视觉机器人导航与运动的现实-模拟-现实框架

作者&#xff1a; Shaoting Zhu, Linzhan Mou, Derun Li, Baijun Ye, Runhan Huang, Hang Zhao单位&#xff1a;清华大学交叉信息研究院&#xff0c;上海期智研究院&#xff0c;Galaxea AI&#xff0c;上海交通大学电子信息与电气工程学院论文标题&#xff1a;VR-Robo: A Real-…

碰一碰发视频 + 矩阵系统聚合平台源码搭建,支持OEM

随着短视频生态与多平台运营需求的融合&#xff0c;“碰一碰发视频 矩阵系统” 聚合平台成为内容创作者与企业营销的新基建。这类系统需实现近场交互触发、多平台内容分发、数据聚合分析的全流程闭环&#xff0c;其源码搭建与定制开发需突破硬件交互与软件矩阵的技术壁垒。核心…

缓存雪崩、缓存穿透、缓存预热、缓存更新、缓存降级

1. 缓存雪崩&#xff08;Cache Avalanche&#xff09;定义&#xff1a;缓存雪崩是指大量缓存中的数据在同一时间过期&#xff0c;导致大量请求同时访问数据库&#xff0c;造成数据库压力骤增&#xff0c;甚至可能导致数据库崩溃。原因&#xff1a;多个缓存的 key 在同一时间过期…

【unity实战】Unity手搓脚本工具实现合并网格功能

注意:考虑到实战的内容比较多,我将该内容分开,并全部整合放在【unity实战】专栏里,感兴趣的小伙伴可以前往逐一查看学习。 文章目录 前言实战1、简单的合并网格实现2、设置统一的材质3、设置不同的多种材质4、多材质网格合并方案专栏推荐完结前言 有许多单独的网格对象会影…

ThreadPoolTaskExecutor 的使用案例

ThreadPoolTaskExecutor 的使用案例 1. 依赖说明 <!-- Spring Retry&#xff08;用于任务重试&#xff09; --> <dependency><groupId>org.springframework.retry</groupId><artifactId>spring-retry</artifactId><version>1.3.1<…

0.3mg硝酸甘油舌下片:冠心病预防中的“消防员”

冠状动脉疾病&#xff08;CAD&#xff09;如同一颗定时炸弹&#xff0c;即使在成功进行血运重建或药物治疗后&#xff0c;心绞痛急性发作的风险依然如影随形。在冠心病管理的漫长战役中&#xff0c;二级预防的核心目标不仅仅是延缓疾病进展&#xff0c;更是预防致命性心脏事件复…

【Spring源码学习系列】基础架构和环境搭建

一直以来都把精力花在中间件的研究和系统设计上&#xff0c;忽略了离我最近的spring&#xff0c;最近开始学习spring的源码了&#xff0c;为了学习到成体系的spring知识和提高学习效率&#xff0c;想要找了一本书看&#xff0c;最终选的是郝佳的《Spring源码深度解析&#xff0…

C++十大排序详解(包括变种优化)

排序**基础排序算法**1. **冒泡排序&#xff08;Bubble Sort&#xff09;**冒泡排序优化**1. 提前终止优化&#xff08;标志位优化&#xff09;****原理**&#xff1a;**实现示例**&#xff08;以C为例&#xff09;&#xff1a;**优点**&#xff1a;**2. 双向冒泡排序&#xff…