0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

使用MicroLIB+fputc的方式实现串口打印功能

GReq_mcu168 来源:玩转单片机 2020-08-05 10:52 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

常规打印方法

STM32的应用中,我们常常对printf进行重定向的方式来把打印信息printf到我们的串口助手。

在MDK环境中,我们常常使用MicroLIB+fputc的方式实现串口打印功能,即:

要实现fputc函数的原因是:printf函数依赖于fputc函数,重新实现fputc内部从串口发送数据即可间接地实现printf打印输出数据到串口。

不知道大家有没有看过正点原子裸机串口相关的例程,他们的串口例程里不使用MicroLIB,而是使用标准库+fputc的方式。相关代码如:

#if1 #pragmaimport(__use_no_semihosting) //标准库需要的支持函数 struct__FILE { inthandle; }; FILE__stdout; /** *@brief定义_sys_exit()以避免使用半主机模式 *@paramvoid *@returnvoid */ void_sys_exit(intx) { x=x; } intfputc(intch,FILE*f) { while((USART1->ISR&0X40)==0);//循环发送,直到发送完毕 USART1->TDR=(u8)ch; returnch; } #endif

关于这两种方法的一些说明可以查看Mculover666兄的《重定向printf函数到串口输出的多种方法》这篇文章。这篇文章中不仅包含上面的两种方法,而且也包含着在GCC中使用标准库重定向printf的方法。

自己实现一个打印函数

以上的几种方法基本上是改造C库的printf函数来实现串口打印的功能。其实我们也可以自己实现一个串口打印的功能。

printf本身就是一个变参函数,其原型为:

intprintf(constchar*__format,...);

所以,我们要重新封装的一个串口打印函数自然也应该是一个变参函数。具体实现如下:

1、基于STM32的HAL库

左右滑动查看全部代码>>>

#defineTX_BUF_LEN256/*发送缓冲区容量,根据需要进行调整*/ uint8_tTxBuf[TX_BUF_LEN];/*发送缓冲区*/ voidMyPrintf(constchar*__format,...) { va_listap; va_start(ap,__format); /*清空发送缓冲区*/ memset(TxBuf,0x0,TX_BUF_LEN); /*填充发送缓冲区*/ vsnprintf((char*)TxBuf,TX_BUF_LEN,(constchar*)__format,ap); va_end(ap); intlen=strlen((constchar*)TxBuf); /*往串口发送数据*/ HAL_UART_Transmit(&huart1,(uint8_t*)&TxBuf,len,0xFFFF); }

因为我们使用printf函数基本不使用其返回值,所以这里直接用void类型了。

自定义变参函数需要用到va_start、va_end等宏,需要包含头文件stdarg.h。关于变参函数的一些学习可以查看网上的一些博文,如:

https://www.cnblogs.com/wulei0630/p/9444062.html

这里我们使用的是STM32的HAL库,其给我们提供HAL_UART_Transmit接口可以直接把整个发送缓冲区的内容给一次性发出去。

2、基于STM32标准库

若是基于STM32的标准库,就需要一字节一字节的循环发送出去,具体代码如:

左右滑动查看全部代码>>>

#defineTX_BUF_LEN256/*发送缓冲区容量,根据需要进行调整*/ uint8_tTxBuf[TX_BUF_LEN];/*发送缓冲区*/ voidMyPrintf(constchar*__format,...) { va_listap; va_start(ap,__format); /*清空发送缓冲区*/ memset(TxBuf,0x0,TX_BUF_LEN); /*填充发送缓冲区*/ vsnprintf((char*)TxBuf,TX_BUF_LEN,(constchar*)__format,ap); va_end(ap); intlen=strlen((constchar*)TxBuf); /*往串口发送数据*/ for(inti=0;i< len; i++)   {  while(USART_GetFlagStatus(USART1, USART_FLAG_TC)==RESET);      USART_SendData(USART1, TxBuf[i]);   } }

测试结果:

我们也可以使用我们的MyPrintf函数按照上一篇文章:《C语言嵌入式中几个非常实用的宏技巧》的方式封装一个宏打印函数:

以上就是我们自定义方式实现的一种串口打印函数。

但是,我想说:对于串口打印的使用,我们没必要自己创建一个打印函数。

看到这,是不是有人想要打我了。。。。看了半天,你却跟我说没必要用。。。

哈哈,别急,我们不应用在串口打印调试方面,那可以用在其它方面呀。

(1)应用一:

比如最近我在实际应用中:我们的MCU跑的是我们老大自己写的一个小的操作系统+我们公司自己开发的上位机

我们MCU端与上位机使用的是串口通讯,MCU往上位机发送的数据有两种类型,一种是HEX格式数据,一种是字符串数据。

但是我们下位机的这两种数据,在通过串口发送之前都得统一把数据封包交给那个系统通信任务,然后再由通信任务发出去。

在这里,就不能用printf了。老大也针对他的这个系统实现了一个deb_printf函数用于打印调试。

但是,那个函数既复杂又很鸡肋,稍微复杂一点的数据就打印不出来了。

因此我利用上面的思路给它新封装了一个打印调试函数,很好用,完美地兼容了老大的那个系统。具体代码就不分享了,大体代码、思路如上。

(2)应用二:

我们在使用串口与ESP8266模块通讯时,可利用类似这样的方式封装一个发送数据的函数,这个函数的使用可以像printf一样简单。

可以以很简单的方式把数据透传至服务端,比如我以前的毕设中就有这么应用:

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • STM32
    +关注

    关注

    2305

    文章

    11124

    浏览量

    371337
  • 函数
    +关注

    关注

    3

    文章

    4408

    浏览量

    66905
  • 串口打印
    +关注

    关注

    0

    文章

    11

    浏览量

    3313

原文标题:串口打印知多少?

文章出处:【微信号:mcu168,微信公众号:硬件攻城狮】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    什么是KEIL的微库(microlib)

    是以牺牲性能为代价的。为了减少容量,MicroLib去掉了一些函数功能,并对一些函数做了空间上的优化。那么Microlib都有哪些不一样呢? main()函数不能带参数,并且main()不能返回
    发表于 12-10 06:27

    使用Keil MicroLIB时自动设置堆大小

    Keil编译项目,如果使用微库MicroLIB,就可以使用malloc。微库内部位置一个堆管理模块。 芯片的RAM大小是固定了的,前面分为全局变量,后面分给堆和栈,这是一般开发方式。 但是我们在开发
    发表于 12-09 07:04

    【CPKCOR-RA8D1】基础串口打印测试

    本文将演示如何为瑞萨CPKCOR-RA8D1开发板配置串口功能,并实现最简单的“Hello World”数据打印串口是嵌入式开发中最常用、
    发表于 10-30 15:23

    【CPKCOR-RA8D1】+ 基础串口打印测试

    本文将演示如何为瑞萨CPKCOR-RA8D1开发板配置串口功能,并实现最简单的“Hello World”数据打印串口是嵌入式开发中最常用、
    发表于 10-30 09:40

    串口通信有哪些方式

    串口通信(Serial Communication)是一种通过串行方式逐位传输数据的通信方式,广泛应用于嵌入式系统、工业控制、仪器仪表等领域。其通信方式可根据不同的分类标准划分为多种类
    的头像 发表于 09-28 18:02 824次阅读

    【HarmonyOS 5】桌面快捷方式功能实现详解

    【HarmonyOS 5】桌面快捷方式功能实现详解 ##鸿蒙开发能力 ##HarmonyOS SDK应用服务##鸿蒙金融类应用 (金融理财# 一、前言 在移动应用开发中,如何让用户快速触达核心
    的头像 发表于 06-21 16:42 1900次阅读
    【HarmonyOS 5】桌面快捷<b class='flag-5'>方式</b><b class='flag-5'>功能</b><b class='flag-5'>实现</b>详解

    【RA4L1-SENSOR】+ RA4L1-SENSOR开发版之使用Jlink的RTT打印功能代替串口

    上一篇帖子中我已经实现了板子上的串口USART9进行输出打印,这篇帖子我采用另外一种串口打印实现
    发表于 06-09 09:03

    【RA4L1-SENSOR】+ RA4L1-SENSOR开发版串口打印功能printf实现

    很高兴收到瑞萨RA生态工作室给与试用的RA4L1-SENSOR开发板,本期就来讲解使用RA4L1-SENSOR开发板实现串口打印功能! 1。打开原理图 可以知道板载的USB
    发表于 06-08 15:01

    【RA-Eco-RA4M2开发板评测】使用Jlink的RTT来实现串口打印功能

    用。 但是在实际开发如果没有预留串口怎么办?其实我们的下载器是可以用来作为调试打印来用的,只是很多小伙伴不知道这个功能而已,今天就来说一下如何用调试器JLink来打印信息。 1、JLi
    发表于 04-30 12:19

    如何在热敏打印机中实现图片的灰阶打印效果吗?

    谁知道如何在热敏打印机中实现图片的灰阶打印效果。 现在基本上文字打印,图片打印功能都已开发结束,
    发表于 04-03 08:40

    STM32CubeIDE STM32H743XIH6串口无法重定向,且发送内容波特率不对乱码怎么解决?

    (\"0123rn\"), 100);为乱码。 但是相同的配置,使用STM32CubeMX+keil勾选MicroLIB完全没问题 波特率都是默认的115200,只是把引脚改为
    发表于 03-11 06:42

    【RA-Eco-RA2L1-48PIN-V1.0开发板试用】——使用串口输出打印printf实现

    上一篇我讲解了使用JINK RTT来实现串口输出打印printf函数功能, 本次测评我来讲解另外一种串口
    发表于 01-23 12:20

    【RA-Eco-RA2L1-48PIN-V1.0开发板试用】——使用Jlink的RTT实现串口打印功能

    能干瞪眼了?????? 当然不行啊,刚好JLINK自带的RTT就能弥补这个缺陷,它能进行串口printf打印的所有功能。 本期测评就让我来给大家讲解一下使用JLINK的RTT实现pri
    发表于 01-23 11:33

    串口与Wi-Fi的连接方式

    在现代通信技术中,串口和Wi-Fi是两种常见的数据传输方式串口通信以其简单、稳定的特性在工业控制、嵌入式系统等领域得到广泛应用。而Wi-Fi作为无线局域网技术,因其灵活性和便捷性在家庭、办公等环境
    的头像 发表于 12-27 10:10 1868次阅读

    串口通讯异常处理方法 串口设备连接方式

    串口通信异常处理方法 1. 异常检测 在串口通信中,首先需要能够检测到异常情况。异常检测可以通过以下几种方式实现: 硬件检测 :利用串口硬件
    的头像 发表于 12-27 09:53 5583次阅读