华大单片机、STM32单片机如何做printf串口打印格式化输出
第一种方法:使用标准C库,但使用标准C库你必须关闭半主机模式
(1)添加下面代码就是关闭半主机模式
/* 告知连接器不从C库链接使用半主机的函数 */
#pragma import(__use_no_semihosting)/* 定义 _sys_exit() 以避免使用半主机模式 */
void _sys_exit(int x)
{x = x;
}/* 标准库需要的支持类型 */
struct __FILE
{int handle;
};FILE __stdout;
在独立应用程序中,不可能支持半主机操作。 因此,必须确保应用程序中没有链接 C 库半主机函数。
为确保没有从 C 库链接使用半主机的函数, 必须导入符号 __use_no_semihosting 。
可在工程的任何 C 或汇编语言源文件中执行此操作,如下所示:
在 C 模块中,使用 #pragma 指令:
#pragma import(__use_no_semihosting)
在汇编语言模块中,使用 IMPORT 指令:
IMPORT __use_no_semihosting
(2)串口重定向
将你要输出信息的串口添加到这句函数里面
///< 串口发送重定向
int fputc(int ch, FILE * file)
{Uart_SendDataPoll(M0P_UART0,ch); //调用库函数,通过UART0发送一个字母。return ch;
}
如果是不同型号的MCU,或者使用那个串口更改对应的串口号即可

接下来你就自己配置好对应的串口初始化就OK了
这里需要注意下:本文代码我采用华大HC32L系列的,它这个库函数Uart_SendDataPoll(M0P_UART0,ch)里面是有等待数据发送完毕的

如果你用的是STM32单片机,重定向函数应该这么写
//< 串口发送重定向
int fputc(int ch, FILE * file)
{USART_SendData(USART1,ch); while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);//等待发送结束return ch;
}
需要自己在添加一行代码来等待发送完毕,因为ST发送库函数里面没有等待语句

(3)下面是我自己完整的配置(我是使用串口0)
#include "BSP_GPIO.h"
#include "BSP_Uart.h"//#include "UFD.h"
uint8_t u8Rx0Data;/* 告知连接器不从C库链接使用半主机的函数 */
#pragma import(__use_no_semihosting)/* 定义 _sys_exit() 以避免使用半主机模式 */
void _sys_exit(int x)
{x = x;
}/* 标准库需要的支持类型 */
struct __FILE
{int handle;
};FILE __stdout;
///< 串口发送重定向
int fputc(int ch, FILE * file)
{Uart_SendDataPoll(M0P_UART0,ch); //调用库函数,通过UART0发送一个字母。return ch;
}
static void Uart0_PortInit(void)
{stc_gpio_cfg_t stcGpioCfg;///< 打开GPIO外设时钟门控Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio, TRUE);DDL_ZERO_STRUCT(stcGpioCfg);///< 端口方向配置 UART0_TXDstcGpioCfg.enDir = GpioDirOut;Gpio_Init(PORT_DEBUG_TXD,PIN_DEBUG_TXD,&stcGpioCfg);Gpio_SetAfMode(PORT_DEBUG_TXD,PIN_DEBUG_TXD,GpioAf2);//UART0_TXD///< 端口方向配置 UART0_RXDstcGpioCfg.enDir = GpioDirIn;///< 端口上下拉配置->上拉stcGpioCfg.enPu = GpioPuEnable;Gpio_Init(PORT_DEBUG_RXD,PIN_DEBUG_RXD,&stcGpioCfg);Gpio_SetAfMode(PORT_DEBUG_RXD,PIN_DEBUG_RXD,GpioAf2);//UART0_RXDSysctrl_SetFunc(SysctrlSWDUseIOEn, TRUE); /*Set SWD port to GPIO mode*/
}
static void Uart0_Init(void)
{stc_uart_cfg_t stcCfg;stc_uart_baud_t stcBaud;DDL_ZERO_STRUCT(stcCfg);DDL_ZERO_STRUCT(stcBaud);///< 打开UART0外设时钟门控Sysctrl_SetPeripheralGate(SysctrlPeripheralUart0,TRUE);///<UART InitstcCfg.enRunMode = UartMskMode1; ///<模式1stcCfg.enStopBit = UartMsk1bit; ///<1bit停止位stcCfg.enMmdorCk = UartMskDataOrAddr; ///<多机模式时stcCfg.stcBaud.u32Baud = 1000000; ///<波特率1000000stcCfg.stcBaud.enClkDiv = UartMsk8Or16Div; ///<通道采样分频配置stcCfg.stcBaud.u32Pclk = Sysctrl_GetPClkFreq(); ///</<获得外设时钟(PCLK)频率值Uart_Init(M0P_UART0, &stcCfg); ///<串口初始化///<UART中断使能Uart_ClrStatus(M0P_UART0,UartRC); ///<清接收请求Uart_ClrStatus(M0P_UART0,UartTC); ///<清接收请求Uart_EnableIrq(M0P_UART0,UartRxIrq); ///<使能串口接收中断EnableNvic(UART0_2_IRQn, IrqLevel3, TRUE); ///<系统中断使能
}void BSP_UartInit(void)
{Uart0_PortInit();Uart0_Init();
}
第二种方法:使用微库,因为使用微库的话 ,不会使用半主机模式,咱也就不用在写那几句关闭半主机模式的语句
(1)在Keil工程中“中勾选 ”Use MicroLIB

(2)重定向输出(这个跟第一种方法一样)
//< 串口发送重定向
int fputc(int ch, FILE * file)
{Uart_SendDataPoll(M0P_UART0,ch); //调用库函数,通过UART0发送一个字母。return ch;
}
(3)下面是我自己完整的配置(我是使用串口0)

#include "BSP_GPIO.h"
#include "BSP_Uart.h"//#include "UFD.h"
uint8_t u8Rx0Data;//< 串口发送重定向
int fputc(int ch, FILE * file)
{Uart_SendDataPoll(M0P_UART0,ch); //调用库函数,通过UART0发送一个字母。return ch;
}
static void Uart0_PortInit(void)
{stc_gpio_cfg_t stcGpioCfg;///< 打开GPIO外设时钟门控Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio, TRUE);DDL_ZERO_STRUCT(stcGpioCfg);///< 端口方向配置 UART0_TXDstcGpioCfg.enDir = GpioDirOut;Gpio_Init(PORT_DEBUG_TXD,PIN_DEBUG_TXD,&stcGpioCfg);Gpio_SetAfMode(PORT_DEBUG_TXD,PIN_DEBUG_TXD,GpioAf2);//UART0_TXD///< 端口方向配置 UART0_RXDstcGpioCfg.enDir = GpioDirIn;///< 端口上下拉配置->上拉stcGpioCfg.enPu = GpioPuEnable;Gpio_Init(PORT_DEBUG_RXD,PIN_DEBUG_RXD,&stcGpioCfg);Gpio_SetAfMode(PORT_DEBUG_RXD,PIN_DEBUG_RXD,GpioAf2);//UART0_RXDSysctrl_SetFunc(SysctrlSWDUseIOEn, TRUE); /*Set SWD port to GPIO mode*/
}
static void Uart0_Init(void)
{stc_uart_cfg_t stcCfg;stc_uart_baud_t stcBaud;DDL_ZERO_STRUCT(stcCfg);DDL_ZERO_STRUCT(stcBaud);///< 打开UART0外设时钟门控Sysctrl_SetPeripheralGate(SysctrlPeripheralUart0,TRUE);///<UART InitstcCfg.enRunMode = UartMskMode1; ///<模式1stcCfg.enStopBit = UartMsk1bit; ///<1bit停止位stcCfg.enMmdorCk = UartMskDataOrAddr; ///<多机模式时stcCfg.stcBaud.u32Baud = 1000000; ///<波特率1000000stcCfg.stcBaud.enClkDiv = UartMsk8Or16Div; ///<通道采样分频配置stcCfg.stcBaud.u32Pclk = Sysctrl_GetPClkFreq(); ///</<获得外设时钟(PCLK)频率值Uart_Init(M0P_UART0, &stcCfg); ///<串口初始化///<UART中断使能Uart_ClrStatus(M0P_UART0,UartRC); ///<清接收请求Uart_ClrStatus(M0P_UART0,UartTC); ///<清接收请求Uart_EnableIrq(M0P_UART0,UartRxIrq); ///<使能串口接收中断EnableNvic(UART0_2_IRQn, IrqLevel3, TRUE); ///<系统中断使能
}void BSP_UartInit(void)
{Uart0_PortInit();Uart0_Init();
}
总结:
要使用第一种还是第二种,看自己选择,大家好像选择第一种比较多。
相关文章:

华大单片机、STM32单片机如何做printf串口打印格式化输出
第一种方法:使用标准C库,但使用标准C库你必须关闭半主机模式(1)添加下面代码就是关闭半主机模式/* 告知连接器不从C库链接使用半主机的函数 */ #pragma import(__use_no_semihosting)/* 定义 _sys_exit() 以避免使用半主机模式 */…...

unity 面试汇总
1、什么是协同程序?答:在主线程运行时同时开启另一段逻辑处理,来协助当前程序的执行。换句话说,开启协程就是开启一个可以与程序并行的逻辑。可以用来控制运动、序列以及对象的行为。2、Unity3D中的碰撞器和触发器的区别ÿ…...

Spring SpringBoot中使用Mybatis-plusDemo1
官网:https://baomidou.com GitHub:GitHub - baomidou/mybatis-plus: An powerful enhanced toolkit of MyBatis for simplify development Gitee:mybatis-plus: mybatis 增强工具包,简化 CRUD 操作。 文档 http://baomidou.com低代码组件库 http://aizuda.com My…...

【18.04Ubuntu中解决无法识别显示屏】
【18.04Ubuntu中解决无法识别外接显示屏】1. 问题来源2. 检查Ubuntu是否识别出外接显示器3. 解决没有识别出外接显示器问题4. 显示器扩展屏幕设置1. 问题来源 实验室的一个dell显示器,通过HDMI连接电脑后,在Windows上连接上就直接可以使用了。由于我电脑…...

Python 协程详解,都在这里了
什么是协程 协程(co-routine,又称微线程、纤程) 是一种多方协同的工作方式。 协程不是进程或线程, 其执行过程类似于 Python 函数调用, Python 的 asyncio 模块实现的异步IO编程框架中, 协程是对使用 asy…...

百家号如何写文章赚钱,百家号写文章真的赚钱?
随着互联网的快速发展,越来越多的人开始关注到写文章赚钱这个领域。而在众多写作平台中,头条号无疑是最受欢迎的一个。那么,百家号写文章赚钱是真的吗?如何写文章赚钱呢?下面我们就来一一解答。 首先,百家号…...
【HDFS】datanodeReport RPC优化
cat datanodeReport.txt | awk ‘{print $8}’ | sort | uniq | wc -l 结果15,说明我们有15个router。 每15秒一个router8次调用这个rpc。15秒是我们的监控采集间隔。 看下router为什么要调用这个rpc。 顺着这个配置项去寻找:dfs.federation.router.dn-report.time-out 一…...

【数据结构】研究链表带环问题
💯💯💯💯 本篇主要研究的是链表带环问题,快慢指针的应用,分析不同解法对带环链表的处理,梳理完本篇你将对链表的理解更加透彻Ⅰ.研究链表带环问题Ⅱ.扩展带环问题1.为什么慢指针和快指针一定会相…...

数据仓库的设计思想
数据仓库设计 知识点01:设计大纲与学习目标 #内容大纲1、数据仓库基础知识(回顾)什么是数仓为什么有数仓数仓的特点是什么OLTP和OLAP系统区别(数据库和数仓的区别)2、数仓系统的架构与核心流程核心1:ETL核…...

【JavaSE】数组的定义与使用详解
目录 1.数组的基本概念 1.1数组的好处 1.2什么是数组 1.3数组的定义及初始化 1.3.1数组的创建 1.3.2数组的初始化 1.4数组的使用 1.4.1访问数组中的元素 1.4.2遍历数组 2.数组的类型 2.1认识JVM的内存分布 2.2基本类型变量与引用类型变量 2.3认识null 3.数组的应…...

Kubernetes14:Helm为了部署像微服务这种的大型项目
Kubernetes14:Helm介绍(为了部署像微服务这种的大型项目) 1、Helm的引入 (1)之前方式部署应用基本过程 编写yaml文件 1、deployment kubectl create deployment nginx --imagenginx --dryrun -o yaml > nginx.yaml2、Service kubect…...

2.3操作系统-存储管理:页式存储、逻辑地址、物理地址、物理地址逻辑地址之间的地址关系、页面大小与页内地址长度的关系、缺页中断、内存淘汰规则
2.3操作系统-存储管理:页式存储、逻辑地址、物理地址、物理地址逻辑地址之间的地址关系、页面大小与页内地址长度的关系、缺页中断、内存淘汰规则页式存储逻辑地址、物理地址如何判断物理地址和逻辑地址它们之间的地址关系?页面大小与页内地址长度的关系…...

设计模式3——结构型模式
结构型模式描述如何将类或对象按某种布局组成更大的结构,它分为类结构型和对象结构型模式,前者采用继承机制来组织接口和类,后者采用组合或聚合来组合对象。 由于组合关系或聚合关系比继承关系耦合度低,满足“合成复用原则”&…...

css——图片缩放,拉伸,变形的解决办法
你的图片即将变得超级丝滑图片为什么会拉伸变形?怎么解决?css的object-fit属性object-fit属性有什么用介绍一下object-position举个小栗子图片为什么会拉伸变形? 前端布局时,图片会出现拉伸、缩放和变形的原因可能有多种: 1.例如图…...

【工具使用】STM32CubeMX-基础使用篇
一、概述 无论是新手还是大佬,基于STM32单片机的开发,使用STM32CubeMX都是可以极大提升开发效率的,并且其界面化的开发,也大大降低了新手对STM32单片机的开发门槛。 本文主要面向初次接触STM32CubeMX的同学,大…...

面试题解-理解cookie、session和token
项目vuespringboot 1、token 用户填写密码账号发送至后端,由后端生成token,返回给前端,前端把它存放起来,如放在cookie或者localStorage里面 前端向服务器发起请求时在请求头携带token,判断用户身份给与反应。 //后…...

Buuctf [GUET-CTF2019]number_game 题解
目录 一.主函数逻辑 二.level_stor()函数 三.mid_stor函数 四.operate函数 五.judge2函数 六.求解flag 一.主函数逻辑 ①先输入一个字符串,然后judge1()函数遍历它,判断字符是否在[0,4]区间范围内 ②将输入的字符串用层次遍历的方式存储为一个二叉树root ③再将二叉树r…...
OsgEarth配置.earth文件支持wms服务
<!-- 参考 http://vmap0.tiles.osgeo.org/wms/vmap0?LAYERSbasic&SERVICEWMS&VERSION1.1.1&REQUESTGetMap&STYLES&FORMATimage%2Fjpeg&SRSEPSG%3A4326&BBOX-90,45,-45,90&WIDTH256&HEIGHT256 --> <!-- 可用 2023.03.09--> …...

【数据结构】详解空间复杂度
Yan英杰的博客 悟已往之不谏 知来者之可追 目录 空间复杂度 案例1:计算BubbleSort的空间复杂度? 案例2:计算斐波那契额数列的前N项的空间复杂度 案例3:计算阶乘递归Fac的空间复杂度? 案例4:F1和F2两函数是否使用的同一块空间 案例5:计算该…...

腾讯云GPU游戏服务器/云主机租用配置价格表
用于游戏业务的服务器和普通云服务器和主机空间是不同的,游戏服务器对于硬件的配置、网络带宽有更大的要求,一般游戏服务器根据不同的配置和适用场景会有十几元一小时到几十元一小时,而且可以根据不同的按量计费。而普通的云服务器可能需要几…...

UE5 学习系列(二)用户操作界面及介绍
这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…...

智慧工地云平台源码,基于微服务架构+Java+Spring Cloud +UniApp +MySql
智慧工地管理云平台系统,智慧工地全套源码,java版智慧工地源码,支持PC端、大屏端、移动端。 智慧工地聚焦建筑行业的市场需求,提供“平台网络终端”的整体解决方案,提供劳务管理、视频管理、智能监测、绿色施工、安全管…...

练习(含atoi的模拟实现,自定义类型等练习)
一、结构体大小的计算及位段 (结构体大小计算及位段 详解请看:自定义类型:结构体进阶-CSDN博客) 1.在32位系统环境,编译选项为4字节对齐,那么sizeof(A)和sizeof(B)是多少? #pragma pack(4)st…...
线程同步:确保多线程程序的安全与高效!
全文目录: 开篇语前序前言第一部分:线程同步的概念与问题1.1 线程同步的概念1.2 线程同步的问题1.3 线程同步的解决方案 第二部分:synchronized关键字的使用2.1 使用 synchronized修饰方法2.2 使用 synchronized修饰代码块 第三部分ÿ…...

(二)TensorRT-LLM | 模型导出(v0.20.0rc3)
0. 概述 上一节 对安装和使用有个基本介绍。根据这个 issue 的描述,后续 TensorRT-LLM 团队可能更专注于更新和维护 pytorch backend。但 tensorrt backend 作为先前一直开发的工作,其中包含了大量可以学习的地方。本文主要看看它导出模型的部分&#x…...

CentOS下的分布式内存计算Spark环境部署
一、Spark 核心架构与应用场景 1.1 分布式计算引擎的核心优势 Spark 是基于内存的分布式计算框架,相比 MapReduce 具有以下核心优势: 内存计算:数据可常驻内存,迭代计算性能提升 10-100 倍(文档段落:3-79…...
系统设计 --- MongoDB亿级数据查询优化策略
系统设计 --- MongoDB亿级数据查询分表策略 背景Solution --- 分表 背景 使用audit log实现Audi Trail功能 Audit Trail范围: 六个月数据量: 每秒5-7条audi log,共计7千万 – 1亿条数据需要实现全文检索按照时间倒序因为license问题,不能使用ELK只能使用…...

【SQL学习笔记1】增删改查+多表连接全解析(内附SQL免费在线练习工具)
可以使用Sqliteviz这个网站免费编写sql语句,它能够让用户直接在浏览器内练习SQL的语法,不需要安装任何软件。 链接如下: sqliteviz 注意: 在转写SQL语法时,关键字之间有一个特定的顺序,这个顺序会影响到…...

高等数学(下)题型笔记(八)空间解析几何与向量代数
目录 0 前言 1 向量的点乘 1.1 基本公式 1.2 例题 2 向量的叉乘 2.1 基础知识 2.2 例题 3 空间平面方程 3.1 基础知识 3.2 例题 4 空间直线方程 4.1 基础知识 4.2 例题 5 旋转曲面及其方程 5.1 基础知识 5.2 例题 6 空间曲面的法线与切平面 6.1 基础知识 6.2…...

跨链模式:多链互操作架构与性能扩展方案
跨链模式:多链互操作架构与性能扩展方案 ——构建下一代区块链互联网的技术基石 一、跨链架构的核心范式演进 1. 分层协议栈:模块化解耦设计 现代跨链系统采用分层协议栈实现灵活扩展(H2Cross架构): 适配层…...