华大单片机、STM32单片机如何做printf串口打印格式化输出

news2024/11/26 11:45:30

第一种方法:使用标准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_TXD
    stcGpioCfg.enDir = GpioDirOut;
    Gpio_Init(PORT_DEBUG_TXD,PIN_DEBUG_TXD,&stcGpioCfg);
    Gpio_SetAfMode(PORT_DEBUG_TXD,PIN_DEBUG_TXD,GpioAf2);//UART0_TXD

    ///< 端口方向配置 UART0_RXD
    stcGpioCfg.enDir = GpioDirIn;
    ///< 端口上下拉配置->上拉
    stcGpioCfg.enPu = GpioPuEnable;
    Gpio_Init(PORT_DEBUG_RXD,PIN_DEBUG_RXD,&stcGpioCfg);
    Gpio_SetAfMode(PORT_DEBUG_RXD,PIN_DEBUG_RXD,GpioAf2);//UART0_RXD

    Sysctrl_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 Init
    stcCfg.enRunMode        = UartMskMode1;                 ///<模式1
    stcCfg.enStopBit        = UartMsk1bit;                  ///<1bit停止位
    stcCfg.enMmdorCk        = UartMskDataOrAddr;            ///<多机模式时
    stcCfg.stcBaud.u32Baud  = 1000000;                      ///<波特率1000000
    stcCfg.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_TXD
    stcGpioCfg.enDir = GpioDirOut;
    Gpio_Init(PORT_DEBUG_TXD,PIN_DEBUG_TXD,&stcGpioCfg);
    Gpio_SetAfMode(PORT_DEBUG_TXD,PIN_DEBUG_TXD,GpioAf2);//UART0_TXD

    ///< 端口方向配置 UART0_RXD
    stcGpioCfg.enDir = GpioDirIn;
    ///< 端口上下拉配置->上拉
    stcGpioCfg.enPu = GpioPuEnable;
    Gpio_Init(PORT_DEBUG_RXD,PIN_DEBUG_RXD,&stcGpioCfg);
    Gpio_SetAfMode(PORT_DEBUG_RXD,PIN_DEBUG_RXD,GpioAf2);//UART0_RXD

    Sysctrl_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 Init
    stcCfg.enRunMode        = UartMskMode1;                 ///<模式1
    stcCfg.enStopBit        = UartMsk1bit;                  ///<1bit停止位
    stcCfg.enMmdorCk        = UartMskDataOrAddr;            ///<多机模式时
    stcCfg.stcBaud.u32Baud  = 1000000;                      ///<波特率1000000
    stcCfg.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();
}

总结:

要使用第一种还是第二种,看自己选择,大家好像选择第一种比较多。

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

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

相关文章

【项目日志】电商后台管理项目日志

技巧 对脚手架框架的梳理 使用脚手架建立项目后默认初始页面非空白&#xff0c;可以自行设置成空白页&#xff0c;将app.vue中的内容和样式清空即可router中的不必要的路由设置可以清除 如何右键打开powershell&#xff1f; 按住shift在空白处单击右键&#xff08;win10和2…

一个故事看懂CPU的SIMD技术

好久不见&#xff0c;我叫阿Q&#xff0c;是CPU一号车间的员工。我所在的CPU有8个车间&#xff0c;也就是8个核心&#xff0c;咱们每个核心都可以同时执行两个线程&#xff0c;就是8核16线程&#xff0c;那速度杠杠滴。 我所在的一号车间&#xff0c;除了负责执行指令的我&…

蓝牙5.4出来了,实现单个接入点与数千个终端节点双向通讯

蓝牙技术联盟最近发布了蓝牙5.4的核心规范&#xff0c;蓝牙5.4规范的主要改进之一就是实现了单个接入点与数千个终端节点进行双向无连接通信&#xff0c; 这一特性主要是针对电子货架标签市场。蓝牙5.4有哪些改进和新功能&#xff1f;蓝牙技术联盟最近发布了蓝牙5.4的核心规范&…

保姆级使用PyTorch训练与评估自己的EVA网络教程

文章目录前言0. 环境搭建&快速开始1. 数据集制作1.1 标签文件制作1.2 数据集划分1.3 数据集信息文件制作2. 修改参数文件3. 训练4. 评估5. 其他教程前言 项目地址&#xff1a;https://github.com/Fafa-DL/Awesome-Backbones 操作教程&#xff1a;https://www.bilibili.co…

【大数据处理与可视化】二 、Numpy科学计算库

【大数据处理与可视化】一 、大数据分析环境搭建&#xff08;安装 Anaconda 3 开发环境&#xff09;实验目的实验内容实验步骤1、创建一个值域范围从10到49的向量。2、创建一个 3x3 并且值从0到8的矩阵。3、创建一个 3x3 的单位矩阵。4、创建一个数组&#xff0c;数组的shape为…

第十四届蓝桥杯三月真题刷题训练——第 7 天

目录 第 1 题&#xff1a;三角回文数 问题描述 答案提交 运行限制 代码&#xff1a; 第 2 题&#xff1a;数数 问题描述 答案提交 运行限制 代码&#xff1a; 第 3 题&#xff1a;倍数问题_同余定理_分情况讨论 题目描述 输入描述 输出描述 输入输出样例 运行限…

Azure Portal 访问安全性增强

Azure Portal 访问安全性增强客户需求如何设置账号&#xff08;包括Admin&#xff09;定期修改密码&#xff0c;例如强制每90天必须修改密码如何设定账号密码的复杂性要求如何设定限制访问Azure Portal的源IP Address客户需求 为了增强访问Azure Portal的安全性&#xff0c;希…

JavaWeb--ListenerAjaxaxiosjson

Listener&Ajax&axios1 Listener1.1 概述1.2 分类1.3 代码演示2 Ajax2.1 概述2.1.1 作用2.1.2 同步和异步2.2 快速入门2.2.1 服务端实现2.2.2 客户端实现2.2.3 测试2.3 案例2.3.1 分析2.3.2 后端实现2.3.3 前端实现2.4 测试3 axios3.1 基本使用3.2 快速入门3.2.1 后端实…

32*4VKL128 LQFP44超低功耗/超低工作电流/抗干扰LCD液晶段码驱动IC/LCD驱动芯片(IC) 适用于激光/红外线测距仪

产品型号&#xff1a;VKL128产品品牌&#xff1a;永嘉微电/VINKA封装形式&#xff1a;LQFP44产品年份&#xff1a;新年份原厂&#xff0c;工程服务&#xff0c;技术支持&#xff01;VKL128概述:VKL128是一个点阵式存储映射的LCD驱动器&#xff0c;可支持最大128点&#xff08;3…

BSN-DDC基础网络详解(五):接入DDC网络(1)

BSN-DDC基础网络推出已经一年了&#xff0c;得到了行业应用方和广大开发者的高度认可。一年中BSN产品技术团队也在根据市场业务需求不断更新功能服务&#xff0c;我们将通过本系列文章为大家系统化介绍DDC网络的功能和使用&#xff0c;为感兴趣的朋友提供学习帮助。01支持DDC的…

PACS系统源码 PACS源码 三维重建PACS源码

一、系统概述&#xff1a; ​基于VC MSSQL开发的一套三甲医院医学影像PACS系统源码&#xff0c;集成3D影像后处理功能&#xff0c;包括三维多平面重建、三维容积重建、三维表面重建、三维虚拟内窥镜、最大/小密度投影、心脏动脉钙化分析等功能。系统功能强大&#xff0c;代码…

pcx文件丢失原因和三种恢复方法

你是否在使用设备过程中出现pcx文件丢失现象呢&#xff1f;对于丢失的pcx文件你是如何恢复的呢&#xff1f;您可以尝试本文推荐的三种方法。关于pcx格式文件pcx是一种图像文件格式&#xff0c;是由ZSOFT公司开发的经过压缩、支持256种彩色的图像文件格式&#xff0c;pcx是在pc机…

无线网络设置

5.在广州分公司的内网创建无线的 SSID 为 Test-GZ_XX(XX 现场提供)&#xff0c;WLAN ID 为 1&#xff0c;AP-Group 为 GZ。在吉林分公司的内网中创建无线 SSID 为 Test-JL_XX(XX 现场提供)&#xff0c;WLAN ID 为 2&#xff0c;AP-Group 为 JL。在北京总部内网 中创建无线的 SS…

NoneBot2,基于Python的聊天机器人

NoneBot2&#xff0c;基于Python的聊天机器人第一步&#xff0c;配置python第二步&#xff0c;配置[go-cqhttp](https://github.com/Mrs4s/go-cqhttp)第三步&#xff0c;配置[NoneBot](https://61d3d9dbcadf413fd3238e89--nonebot2.netlify.app/)NoneBot2 是一个现代、跨平台、…

日读300篇文献的技巧

感觉自己看文章很慢&#xff0c;有时候也抓不住重点。 如果是英文文献的话&#xff0c;可能还要有点难度&#xff0c;毕竟英语渣渣还是需要有中文-》英文的转换过程。 最近在搞毕业论文的时候&#xff0c;发现了一个非常好玩的东西&#xff0c;大大提升了我看文章搞科研&#x…

idea maven:Unable to import maven project /idea maven工程加载报错

文章目录前言一、报错截图二、设置maven三、更换maven版本前言 idea工具中导入maven工程有时候会遇到Unable to import maven project的报错&#xff0c;并且pom依赖中的依赖包没有加载出来&#xff0c;这里总结一下我遇到的问题与解决方法。 系统环境&#xff1a;jdk 1.8 m…

Docker的可视化界面工具

Docker的可视化界面工具1. Portainer1.1 Introduction1.1.1 Official1.2 Download And Deploy1.3 Dashboard1.3.1 Dashboard2. Shipyard2.1 Introduction2.1.1 Character2.1.2 Official2.2 Download And Deploy2.2.1 脚本下载镜像2.2.2 执行脚本2.2.2 查看下载的镜像2.3 Dashbo…

【学习Docker(八)】Docker Canal的安装与卸载

座右铭&#xff1a;《坚持有效输出&#xff0c;创造价值无限》 最近想了解下canal&#xff0c;自行搭建并完成数据同步。经过了几天的踩坑之旅&#xff0c;今天终于搭建成功了。 环境&#xff1a;canalv1.1.5、MySQL8.0、JDK1.8 安装MySQL 创建存放目录 mkdir /docker-localm…

蓝桥杯单片机第九届省赛编程题(深夜学习——单片机)

一、根据硬件框图初始化好要使用的外设推测出外设类型&#xff1a;PCF8591、矩阵按键、AT24C02、LED、数码管&#xff08;定时器&#xff09;创建工程模板&#xff1a;&#xff08;1&#xff09;主函数&#xff1a;#ifndef PBBLIC_H #define PBBLIC_H#include <STC15F2K60S2…

SpaceNet 建筑物检测

SpaceNet 建筑物检测 该存储库提供了一些 python 脚本和 jupyter 笔记本来训练和评估从SpaceNet卫星图像中提取建筑物的卷积神经网络。 用法