重定义/自定义printf到串口输出实现的三种方法(cubeide)

news2024/11/25 19:46:16

重定义/自定义printf到串口输出实现的三种方法(cubeide)


文章目录

  • 重定义/自定义printf到串口输出实现的三种方法(cubeide)
  • 1.重写_write函数
  • 2.重定义PUTCHAR_PROTOTYPE宏
  • 3.va_list自定义printf
  • 总结:


1.重写_write函数

注释掉syscalls.c文件中的_write函数
在这里插入图片描述
重写_write函数

__attribute__((weak)) int _write(int file, char *ptr, int len)
{
     if(HAL_UART_Transmit(&huart1,(uint8_t *)ptr,len,0xffff) != HAL_OK)
     {
         Error_Handler();
     }
     return len;
}

这段代码也是一个重定义的输出方法,用于重定向标准输出函数_write。通过使用__attribute__((weak))属性修饰,可以在用户自定义的函数中进行重定义。

具体分析如下:

函数的原型是int _write(int file, char *ptr, int len),表示重定义了标准输出函数_write。该函数接受三个参数,file表示文件描述符(在这里可以忽略),ptr表示要发送的数据指针,len表示要发送的数据长度。

在函数内部,使用HAL_UART_Transmit函数将数据指针ptr指向的内容通过UART进行传输。这里同样使用了名为huart1的UART句柄,您可能需要根据实际情况进行相应的修改。

如果UART传输过程中出现错误,通过调用Error_Handler函数进行错误处理。

最后,函数返回发送的数据长度len。

2.重定义PUTCHAR_PROTOTYPE宏

/* USER CODE BEGIN PFP */
#ifdef __GNUC__                                    //串口重定向
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif 
PUTCHAR_PROTOTYPE
{
    HAL_UART_Transmit(&huart1 , (uint8_t *)&ch, 1, 0xFFFF);
    return ch;
}
/* USER CODE END PFP */

这段代码是重定义了printf函数的输出方法,使用串口进行输出。它通过重定义PUTCHAR_PROTOTYPE宏来定义了一个名为__io_putchar(对于GCC编译器)或fputc(对于其他编译器)的函数。

首先,根据编译器类型,PUTCHAR_PROTOTYPE宏会被定义为__io_putchar或fputc。GCC编译器使用__io_putchar,而其他编译器使用fputc。

接下来,PUTCHAR_PROTOTYPE函数会被定义。它的返回类型是int,并接受一个字符参数ch。

在函数内部,使用HAL_UART_Transmit函数将字符ch通过UART进行传输。这里使用了名为huart1的UART句柄,你可能需要根据实际情况进行相应的修改。

最后,函数返回传输的字符ch。

3.va_list自定义printf

#define USART2_MAX_SEND_LEN        400
#pragma pack(8)
uint8_t USART1_TX_BUF[USART1_MAX_SEND_LEN];     //发送缓冲,最大USART2_MAX_SEND_LEN字节
#pragma pack()
void u1_printf(char* fmt,...)
{
    uint16_t i,j;
    va_list ap;
    va_start(ap,fmt);
    vsprintf((char*)USART1_TX_BUF,fmt,ap);
    va_end(ap);
    i=strlen((const char*)USART1_TX_BUF);//此次发送数据的长度
    for(j=0;j<i;j++)//循环发送数据
    {
        while((USART1->SR&0X40)==0);//循环发送,直到发送完毕
        USART1->DR=USART2_TX_BUF[j];
    }
}

这段代码是一个用于在串口1上实现重定义的printf函数的例子。

具体分析如下:

首先,定义了一个名为u1_printf的函数,用于重定义printf函数在串口2上的输出。

函数接受一个格式化字符串fmt作为参数,后面跟着可变参数列表…。

在函数内部,首先使用va_start宏和va_list类型的变量ap来初始化可变参数列表。

然后,使用vsprintf函数将格式化后的字符串保存到全局数组USART1_TX_BUF中。这里假设数组已经定义,并且长度足够容纳格式化后的字符串。vsprintf函数的使用类似于sprintf,但是可以处理可变参数列表。

使用va_end宏结束可变参数的处理。

接下来,计算格式化后的字符串的长度,并将其存储在变量i中。

然后,通过循环逐个发送数据。在每次发送之前,使用while循环等待串口2发送寄存器为空,即等待上一次发送完成。

最后,将字符逐个发送到串口2的数据寄存器USART1->DR中,以便通过串口进行发送。

如果文章对您有所帮助,点赞支持,感谢!!!

总结:

重写_write函数:通过重定义_write函数,将数据通过UART发送。在函数内部使用HAL_UART_Transmit函数将数据发送到UART。如果发送过程中出现错误,会调用Error_Handler函数进行错误处理。

重定义PUTCHAR_PROTOTYPE宏:通过重定义PUTCHAR_PROTOTYPE宏,定义了一个名为__io_putchar(对于GCC编译器)或fputc(对于其他编译器)的函数。这个函数将字符通过UART发送。

自定义printf函数:定义了一个名为u1_printf的函数,用于在串口1上实现重定义的printf函数。函数接受一个格式化字符串作为参数,使用vsprintf函数将格式化后的字符串保存到全局数组USART1_TX_BUF中。然后通过循环逐个发送数据到串口1的数据寄存器。

这些重定义的函数和宏都用于实现在特定的串口上进行输出,并使用UART进行数据传输。请确保在使用这些重定义函数之前已经正确初始化了相关的硬件资源(例如UART)以及引入了正确的头文件。
如果文章对您有所帮助,点赞支持,感谢!!!

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java中Map使用增强for循环和迭代器获取key和value

加油&#xff0c;新时代打工人&#xff01; java中List集合三种获取集合元素方式 本文运行代码使用 jdk1.8 for 语句比较简单&#xff0c;用于循环数据。 Java迭代器&#xff08;Iterator&#xff09;是 Java 集合框架中的一种机制&#xff0c;是一种用于遍历集合&#xff08…

非线程安全问题

目录 实例变量共享导致的“非线程安全问题” 如何解决这个问题&#xff1f; i--与System.out.println()出现引起的“非线程安全问题” 非线程安全主要是指多个线程对同一个对象中的同一个实例变量进行操作时会出现值被更改、值不同步的情况&#xff0c;进而影响程序的执行流…

科目一速通技巧笔记,简记

常规 累计积分制度&#xff08;12满&#xff09;周期12月 虚假材料1年&#xff0c;假1吊二撤三醉五逃终身 假1500 骗三2k以下 初次领证1年实习期、实习标志&#xff0c;18~70岁 拼装车、报废车&#xff0c;吊销 200~2k 没有中心线&#xff08;一条路&#xff09;城市道路3…

路径规划算法:基于白鲸优化的路径规划算法- 附代码

路径规划算法&#xff1a;基于白鲸优化的路径规划算法- 附代码 文章目录 路径规划算法&#xff1a;基于白鲸优化的路径规划算法- 附代码1.算法原理1.1 环境设定1.2 约束条件1.3 适应度函数 2.算法结果3.MATLAB代码4.参考文献 摘要&#xff1a;本文主要介绍利用智能优化算法白鲸…

Python、STK、MATLAB的连接和使用

写在前面 预备知识&#xff1a; Python通过命令行调用MATLAB的简单实现。这篇文章讲明了如何使用 Python 调用 MATLAB 的原理和过程&#xff0c;并给出相应代码。 STK、MATLAB、SQL的连接和使用。这篇文章讲明了STK 11.2、MATLAB 2014a、SQL 2019的安装过程&#xff0c;以及…

超越99%的程序员,chatgpt用C++写个线程安全无锁环形队列

​肝了一个周末&#xff0c;我们一起来欣赏chatgpt写的代码吧。让其用C为我们写一个线程安全的环形队列&#xff0c;并逐步提出一些需求。 先看带锁的实现。 带锁版本 我对chatgpt的需求是&#xff1a; 用C实现线程安全的环形队列&#xff0c;提供代码注释&#xff0c;以及g…

Meetup 报名|07.22 StarRocks Friends 与你相约广州

夏日炎炎&#xff0c;经历了杭州和上海两站的成功活动后&#xff0c;社区开发者的热情依旧如火如荼&#xff01;在更加炽热的七月&#xff0c;我们即将迎来 StarRocks & Friends 的第三站--广州&#xff01; 社区依旧秉持连接 StarRocks 社区专家与用户共同探讨大数据领域…

MySQL数据库 - 基本数据类型

目录 一、数据类型分类 二、数据类型 1、tinyint 类型 有符号 tinyint 范围测试 无符号 tinyint 范围测试 2、bit 类型 3、float 类型 有符号 float 范围测试 无符号 float 范围测试 4、decimal 类型 5、char 类型 6、varchar 类型 7、日期类型 8、enum类型、set类型…

Codeforces Round 739 (Div. 3)

A.Dislike of Threes AC代码&#xff1a; #include<iostream> #include<algorithm> #include<cstring> using namespace std; const int N2e510; int f[N]; int cnt; int main() {for(int i1;;i){if(i%3!0&&i%10!3) f[cnt]i;if(cnt>1000) break…

第一阶段-第六章 Python的数据容器

目录 一、数据容器入门  1.学习目标  2.为什么要学习数据容器  3.什么是数据容器  4.本小节的总结 二、数据容器&#xff1a;list&#xff08;列表&#xff09;  2.1列表的定义  1.学习目标  2.为什么需要列表  3.列表的定义  4.本节的代码演示  5.本小节的…

【Java练习题汇总】《第一行代码JAVA》面向对象基础篇,汇总Java练习题——面向对象:特性、类与对象、数组、String、内部类... ~

Java练习题 面向对象基础篇 1️⃣ 面向对象基础篇 1️⃣ 面向对象基础篇 一、填空题 面向对象的三大特征&#xff1a;_______ 、_______ 、_______。类由_______和_______组成。运算符_______的作用是根据对象的类型分配内存空间。当对象拥有内存空间时&#xff0c;会自动调…

oceanbase基础

与mysql对比 分布式一致性算法 paxos 存储结构&#xff08;引擎&#xff09;用的是两级的 数据库自动分片功能&#xff0c;提供独立的obproxy路由写入查询等操作到对应的分片 多租户 方便扩展 存储层 http://www.hzhcontrols.com/new-1391864.html LSM tree&#xff0c;is very…

CnOCR 使用教程

目录 一、 简介二、使用教程三、效果展示 一、 简介 CnOCR 是 Python 3 下的文字识别&#xff08;Optical Character Recognition&#xff0c;简称OCR&#xff09;工具包&#xff0c;支持简体中文、繁体中文&#xff08;部分模型&#xff09;、英文和数字的常见字符识别&#…

[COCI2010-2011#6]STEP

目录 1.题目&#xff1a; 题目描述 输入格式 输出格式 2.思路 1.ans数组的维护 2.L and R 的维护 3.ne数组与pr数组的维护 4.len数组&#xff1a; 3.代码&#xff1a; 1.有注释版&#xff1a; 2.copy版&#xff1a; 1.题目&#xff1a; 题目描述 给定一个长度为N的…

Java设计模式-责任链(Chain of Responsibility)模式

介绍 Java责任链&#xff08;Chain of Responsibility&#xff09;设计模式是指很多处理对象构成一个链&#xff0c;链中前一个对象指向后一个对象。请求在链中传递&#xff0c;一个请求可以被一个或者多个对象处理。调用方&#xff08;即客户端&#xff09;不知道请求会被链中…

【UniApp开发小程序】项目创建+整合UI组件(FirstUI和uView)

创建项目 下图为初始化的项目的文件结构 引入组件 俗话说&#xff1a;“工欲善其事&#xff0c;必先利其器”&#xff0c;为了更加方便地开发出页面较为美观的小程序&#xff0c;我们先引入成熟的UI组件&#xff0c;再开始开发之旅。&#xff08;如果你是前端高手&#xff0…

ardupilot IMU陀螺仪方向的重要性

目录 文章目录 目录摘要1.简介---BMI088 方向2.控制摘要 本节主要记录IMU陀螺仪方向的重要性,欢迎批评指正!!! 1.简介—BMI088 方向 注意这个BMI088 的IMU方向,特别是是那个左上角的黑色点点,他的坐标系满足右手坐标系,但是我们无人机坐标系是北东地坐标系,因此需要把…

Cobalt Strike实战实例

客户端 初始化界面如下&#xff1a; 可以多个客户端同时连接&#xff0c;可以聊天。 msg 指定id 文字。 msg 文字。 创建监听器 这里出现了&#xff0c;监听设置不成功。原因是服务端的CS4.0报错了。我重新下载就可以了。如果这里有问题&#xff0c;可联系我。我帮你。这里解…

python+requests接口自动化测试

原来的web页面功能测试转变成接口测试&#xff0c;之前大多都是手工进行&#xff0c;利用postman和jmeter进行的接口测试&#xff0c;后来&#xff0c;组内有人讲原先web自动化的测试框架移驾成接口的自动化框架&#xff0c;使用的是java语言&#xff0c;但对于一个学java&…

Feign远程调用组件

Feign Feign是Netfix开发的一个轻量级REstFul的HTTP服务客户端,是以java接口注解的方式调用HTTP请求,而不用像java中通过封装HTTP请求报文的方式直接调用,可以帮助我们更加便捷,优雅的调用HTTP API Feign RestTemplate Ribbon Hystrix 本质:封装了HTTP调用流…