华大单片机、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游戏服务器/云主机租用配置价格表
用于游戏业务的服务器和普通云服务器和主机空间是不同的,游戏服务器对于硬件的配置、网络带宽有更大的要求,一般游戏服务器根据不同的配置和适用场景会有十几元一小时到几十元一小时,而且可以根据不同的按量计费。而普通的云服务器可能需要几…...
突破不可导策略的训练难题:零阶优化与强化学习的深度嵌合
强化学习(Reinforcement Learning, RL)是工业领域智能控制的重要方法。它的基本原理是将最优控制问题建模为马尔可夫决策过程,然后使用强化学习的Actor-Critic机制(中文译作“知行互动”机制),逐步迭代求解…...
连锁超市冷库节能解决方案:如何实现超市降本增效
在连锁超市冷库运营中,高能耗、设备损耗快、人工管理低效等问题长期困扰企业。御控冷库节能解决方案通过智能控制化霜、按需化霜、实时监控、故障诊断、自动预警、远程控制开关六大核心技术,实现年省电费15%-60%,且不改动原有装备、安装快捷、…...
linux arm系统烧录
1、打开瑞芯微程序 2、按住linux arm 的 recover按键 插入电源 3、当瑞芯微检测到有设备 4、松开recover按键 5、选择升级固件 6、点击固件选择本地刷机的linux arm 镜像 7、点击升级 (忘了有没有这步了 估计有) 刷机程序 和 镜像 就不提供了。要刷的时…...
Matlab | matlab常用命令总结
常用命令 一、 基础操作与环境二、 矩阵与数组操作(核心)三、 绘图与可视化四、 编程与控制流五、 符号计算 (Symbolic Math Toolbox)六、 文件与数据 I/O七、 常用函数类别重要提示这是一份 MATLAB 常用命令和功能的总结,涵盖了基础操作、矩阵运算、绘图、编程和文件处理等…...
tree 树组件大数据卡顿问题优化
问题背景 项目中有用到树组件用来做文件目录,但是由于这个树组件的节点越来越多,导致页面在滚动这个树组件的时候浏览器就很容易卡死。这种问题基本上都是因为dom节点太多,导致的浏览器卡顿,这里很明显就需要用到虚拟列表的技术&…...
Typeerror: cannot read properties of undefined (reading ‘XXX‘)
最近需要在离线机器上运行软件,所以得把软件用docker打包起来,大部分功能都没问题,出了一个奇怪的事情。同样的代码,在本机上用vscode可以运行起来,但是打包之后在docker里出现了问题。使用的是dialog组件,…...
免费PDF转图片工具
免费PDF转图片工具 一款简单易用的PDF转图片工具,可以将PDF文件快速转换为高质量PNG图片。无需安装复杂的软件,也不需要在线上传文件,保护您的隐私。 工具截图 主要特点 🚀 快速转换:本地转换,无需等待上…...
【C++特殊工具与技术】优化内存分配(一):C++中的内存分配
目录 一、C 内存的基本概念 1.1 内存的物理与逻辑结构 1.2 C 程序的内存区域划分 二、栈内存分配 2.1 栈内存的特点 2.2 栈内存分配示例 三、堆内存分配 3.1 new和delete操作符 4.2 内存泄漏与悬空指针问题 4.3 new和delete的重载 四、智能指针…...
Web中间件--tomcat学习
Web中间件–tomcat Java虚拟机详解 什么是JAVA虚拟机 Java虚拟机是一个抽象的计算机,它可以执行Java字节码。Java虚拟机是Java平台的一部分,Java平台由Java语言、Java API和Java虚拟机组成。Java虚拟机的主要作用是将Java字节码转换为机器代码&#x…...
毫米波雷达基础理论(3D+4D)
3D、4D毫米波雷达基础知识及厂商选型 PreView : https://mp.weixin.qq.com/s/bQkju4r6med7I3TBGJI_bQ 1. FMCW毫米波雷达基础知识 主要参考博文: 一文入门汽车毫米波雷达基本原理 :https://mp.weixin.qq.com/s/_EN7A5lKcz2Eh8dLnjE19w 毫米波雷达基础…...
