STM32-HAL-串口的printf重定向

news2024/11/17 16:37:05

一、C语言的格式化输出

C语言的printf是一个标准库函数,用于将格式化的数据输出到标准的输出设备(通常是终端)

  • 基本语法:
int printf(const char *format, ...);

其中的第一个参数const char *format表示输出格式,后面的参数是可变参数,用于填充格式化字符串中的占位符。

  • 字符输出原理:
  1. 格式化字符串处理:printf函数将第一个参数 const char *format 中的格式占位符解析出来,然后根据占位符的类型和顺序依次取可变参数中的值,将这些值转换为字符串,并将其按照格式化字符串中的顺序和样式组合成最终的输出字符串。
  2. 输出字符串存储:printf函数将格式化后的输出字符串存储在内存缓冲区中。
  3. 输出字符串显示:printf函数将内存缓冲区中的输出字符串显示到标准输出设备上,通常是终端。

在学习C语言的时候,在调用头文件#include "stdio.h"的时候,就可以使用printf函数进行格式化打印

#include <stdio.h>

int a = 10;
char str[] = "hello,world!";
int main(void)
{
    printf("%s\n",str);
    printf("a = %d",a);  
    return 0;
}

[result]

hello,world!
a = 10

但是在Keil中,在stm32的使用中是不能直接使用C语言的打印函数的,需要添加支持设置,即调用MDK的微库(MicroLib) 称之为printf的重定向。其实不仅仅可以把打印字符重定向,而且还可以将获取字符重定向。

二、开发准备

  • 基于STM32L431RCT6的小熊派开发板
    在这里插入图片描述

  • windows系统并安装Cubemx和Keil MDK的电脑

三、初始化片上外设

本次开发介绍的主要是串口的重定向,因此就是需要初始化串口外设。

设置串口通信为异步通信,波特率115200
在这里插入图片描述

生成代码,并选择keil-MDK打开该工程

四、设置重定向

4.1 点击魔术棒,然后勾选使用微库(Use MicroLIB)
在这里插入图片描述

针对MicroLIB的介绍:

​ MicroLIB是Keil公司提供的一个C标准库,专为嵌入式系统设计而开发。相对于标准C库,MicroLIB库更加轻量级,代码量更小,适用于嵌入式系统等资源受限的环境。MicroLIB库支持ISO/ANSI C标准的大部分函数,并增加了一些嵌入式系统常用的函数,例如串口通信、GPIO控制等。在MDK的工程中,开发者可以选择使用MicroLIB库来进行开发,以减小程序的代码大小和占用内存的空间。

​ 需要注意的是,MicroLIB库并不是一个完整的C标准库,它只实现了一部分的C标准函数,并且一些函数的实现与标准C库可能存在差异。如果需要使用标准C库的函数或者功能更加完整的C标准库,开发者需要使用其他的C标准库,例如GNU C Library(glibc)等。

4.2 添加串口重定向代码

在main函数中添加头文件:

#include “stdio.h"

/* USER CODE BEGIN 4 */内添加:

int fputc(int c,FILE *f)
{
    uint8_t ch;  //定义一个无符号8位整型变量ch 并将字符C赋值给它
    ch = c;
    HAL_UART_Transmit(&huart1,&ch,1,1000);
    // 调用HAL库的串口发送函数,将ch发送到USART1串口,等待时间为1000ms
    return c;
}

4.3 在主循环中添加代码

/* USER CODE BEGIN 2 */
	uint8_t str[] = "Hello GearLong!";
	uint8_t num1 = 10;
	float f = 3.1415926;
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
		printf("%s\r\n",str);
		printf("num = %d\r\n",num1);
		printf("f1 = %f\r\n",f);
		printf("f2 = %.2f\r\n",f);
		printf("f3 = %8.3f\r\n",f);
		HAL_Delay(1000);		
  }

4.4 编译、下载,然后打开串口调试助手查看执行

记得将AT开关拨到AT_MCU

在这里插入图片描述

4.5 不使用微库打印数据

下面的代码来自正点原子的HAL库代码中的串口打印 ,将代码复制到usart.c的代码添加处,并取消勾选微库,并移除上面已经设置的重定向代码。

/* 加入以下代码, 支持printf函数, 而不需要选择use MicroLIB */

#if 1
#if (__ARMCC_VERSION >= 6010050)                    /* 使用AC6编译器时 */
__asm(".global __use_no_semihosting\n\t");          /* 声明不使用半主机模式 */
__asm(".global __ARM_use_no_argv \n\t");            /* AC6下需要声明main函数为无参数格式,否则部分例程可能出现半主机模式 */

#else
/* 使用AC5编译器时, 要在这里定义__FILE 和 不使用半主机模式 */
#pragma import(__use_no_semihosting)

struct __FILE
{
    int handle;
    /* Whatever you require here. If the only file you are using is */
    /* standard output using printf() for debugging, no file handling */
    /* is required. */
};

#endif

/* 不使用半主机模式,至少需要重定义_ttywrch\_sys_exit\_sys_command_string函数,以同时兼容AC6和AC5模式 */
int _ttywrch(int ch)
{
    ch = ch;
    return ch;
}

/* 定义_sys_exit()以避免使用半主机模式 */
void _sys_exit(int x)
{
    x = x;
}

char *_sys_command_string(char *cmd, int len)
{
    return NULL;
}

/* FILE 在 stdio.h里面定义. */
FILE __stdout;

/* 重定义fputc函数, printf函数最终会通过调用fputc输出字符串到串口 */
int fputc(int ch, FILE *f)
{
    while ((USART1->ISR & 0X40) == 0);               /* 等待上一个字符发送完成 */
    
    USART1->TDR = (uint8_t)ch;                       /* 将要发送的字符 ch 写入到DR寄存器 */	
    return ch;
}
#endif

需要注意的是在使用Cubmex生成的HAL库代码中,USART1的相关寄存器变成了ISR和TDR

4.6 打印输出的结果是一致的
在这里插入图片描述

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

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

相关文章

Kubernetes核心组件及资源介绍

文章目录 一、Kubernetes架构二、Kubernetes核心组件三、Kubernetes核心资源四、拓展1、Service和Ingress的区别是什么&#xff1f;2、Replicaset和Deployment的区别是什么&#xff1f;3、Deployment和Statefulset的区别是什么&#xff1f;4、Job和Cronjob的区别是什么&#xf…

【FAQ】统一扫码服务常见问题及解答

1.隐私政策是怎么样的&#xff1f;收集哪些信息&#xff1f; 关于Scan Kit的隐私政策及收集的信息&#xff0c;请查看SDK隐私安全说明。 Android&#xff1a;SDK隐私安全说明 iOS&#xff1a;SDK隐私安全说明 2.如何使用多码识别&#xff1f;多码模式下如何实现指定条码&am…

vue生命周期的理解?

目录标题 一、什么是生命周期&#xff1f;二、生命周期的流程图&#xff1a; 一、什么是生命周期&#xff1f; Vue 实例有一个完整的生命周期&#xff0c;也就是从开始创建、初始化数据、编译版、挂载Dom ->染、更新 ->渲染、卸载 等一系列过程&#xff0c;称这是Vue的生…

简单清晰了解B树和B+树

一.学习背景 在MySQL的学习中,我们了解到了索引的知识,而关于MySQL索引背后的数据结构,我们在这里进行学习. 首先,我们要了解到的是,MySQL的索引用到的数据结构为B树. 使用B树是因为,在数据量大的时候,内存不够用&#xff0c;大部分数据只能存放在磁盘上&#xff0c;只有需要…

【Linux命令行与Shell脚本编程】第七章 Linux文件权限

Linux命令行与Shell脚本编程 第七章 Linux文件权限 文章目录 Linux命令行与Shell脚本编程七,Linux文件权限7.1,Linux的安全性7.1.1,用户信息 /etc/passwd文件7.1.2,用户密码 /etc/shadow文件7.1.3,useradd 添加新用户7.1.4,userdel 删除用户7.1.5, 修改用户1,usermod2,passwd…

Hystrix Dashboard图形化监控

&#x1f449;&#x1f3fb; SpringCloud 入门实战系列不迷路 &#x1f448;&#x1f3fb;&#xff1a; SpringCloud 入门实战&#xff08;一&#xff09;什么是SpringCloud&#xff1f;SpringCloud 入门实战&#xff08;二&#xff09;-SpringCloud项目搭建SpringCloud 入门实…

【云计算•云原生】1.什么是云计算?它为什么这么火?

文章目录 1.云计算基础什么是云计算云计算的分类开源软件、自由软件、免费软件 2.云计算机制云基础设施机制云管理机制云安全机制基本云架构 3.虚拟化技术服务器虚拟化服务器虚拟化技术CPU虚拟化内存虚拟化设备和I/O虚拟化存储虚拟化网络虚拟化桌面虚拟化 KVM 4.网络与存储基础…

90后,第一批接棒白酒的“年轻人”

【潮汐商业评论/原创】 又到了每月的公司团建&#xff0c;“团建必喝酒”似乎已经成为了大家的共识。 但在酒水的选择上&#xff0c;有红的、啤的、洋的&#xff0c;还有低度果酒&#xff0c;唯独不见听谁说聚会喝白的。当Jason询问为什么没有白酒时&#xff0c;得到了几乎一…

C语言函数大全-- o 开头的函数

C语言函数大全 本篇介绍C语言函数大全-- o 开头的函数 1. obstack_init&#xff0c;obstack_free&#xff0c;obstack_alloc&#xff0c;obstack_blank&#xff0c;obstack_grow 1.1 函数说明 函数声明函数功能void obstack_init(struct obstack *obstack_ptr);它是 POSIX …

Python采集某网站小sp内容, m3u8内容下载

前言 嗨喽~大家好呀&#xff0c;这里是魔王呐 ❤ ~! 环境使用: Python 3.8 Pycharm 模块使用: import requests >>> pip install requests import re 正则表达式 解析数据 import json 本次案例所用知识点: python基础语法: 字典创建/取值 print输出函数使用…

【人工智能概论】 RNN、LSTM、GRU简单入门与应用举例、代码耗时计算

【人工智能概论】 RNN、LSTM、GRU简单入门与应用举例、代码耗时计算 文章目录 【人工智能概论】 RNN、LSTM、GRU简单入门与应用举例、代码耗时计算一. RNN简介1.1 概念简介1.2 方法使用简介 二. 编码层embedding2.1 embedding的参数2.2 embedding的理解 三. Linear层与CrossEnt…

全景图像算法简述

全景图像拼接是一种将多个图像合成为一个大型全景图像的技术。这种技术广泛应用于虚拟现实、游戏开发、文化遗产保护等领域。本文将介绍三种主流的全景图像拼接算法&#xff0c;并对它们进行综合比较。 一、基于特征点匹配的拼接算法 特征点匹配是全景图像拼接中最常用的一种算…

深入讲解ARMv8 异常处理简介

内核稳定性问题复杂多样&#xff0c;最常见的莫过于“kernel panic”&#xff0c;意为“内核恐慌&#xff0c;不知所措”。这种情况下系统自然无法正常运转&#xff0c;只能自我结束生命&#xff0c;留下死亡信息。诸如&#xff1a; “Unable to handle kernel XXX at virtual …

直播系统开发中哪些技术架构是必不可少的

在当今数字化时代&#xff0c;直播已成为一种极其受欢迎的娱乐和营销方式。由于直播应用的复杂性&#xff0c;架构师在直播系统的开发和设计中扮演着至关重要的角色。本文将介绍直播系统开发中技术架构师所必不可少的技术和工具。 什么是直播系统&#xff1f; 直播系统是一种通…

uni-app入门到实战

&#x1f37f;*★,*:.☆(&#xffe3;▽&#xffe3;)/$:*.★* &#x1f37f; &#x1f35f;欢迎来到前端初见的博文&#xff0c;本文主要讲解uni-app入门到实战&#x1f35f; &#x1f468;‍&#x1f527; 个人主页 : 前端初见 &#x1f95e;喜欢的朋友可以关注一下&#xff…

【Linux】浏览器写代码!部署code-server远程vscode网页

部署code-server远程vscode网页&#xff0c;在浏览器上写代码&#xff01; 参考文档 https://developer.aliyun.com/article/876967#slide-7 本文首发于 慕雪的寒舍 1.什么是code-server&#xff1f; 注意&#xff0c;这不是在linux系统上安装vscode软件&#xff08;和windo…

虹科分享 | 如何主动保护个人信息 | 网络安全评级

网上报税和支付越来越流行&#xff0c;针对毫无防备的纳税人的税务欺诈也越来越频繁。以下是一些需要避免的常见网上税务骗局&#xff1a; 网络钓鱼诈骗 骗子利用电子邮件、短信或电话伪装成相关机构或报税软件提供商&#xff0c;诱骗人们提供他们的个人信息&#xff0c;或点击…

走进梦龙冰淇淋的生产线 揭晓“灯塔工厂”背后的秘密

作为一家积极履行社会责任的公司&#xff0c;联合利华和路雪在今年3月携手京东“青绿计划”&#xff0c;推出了包含梦龙、可爱多、千层雪、和路雪等多款可持续组合装产品&#xff0c;这一助力实现双碳目标的举措也引发了消费者的关注。其实&#xff0c;自联合利华太仓食品生产基…

我们都被 ChatGPT 给骗了?

引言&#xff1a; 用过 ChatGPT 的人都知道&#xff0c;当你与 chatgpt 对话的时候&#xff0c;它是“逐字输出”的&#xff0c;就像真的有个人在跟你打字一样。其实&#xff0c;这种技术并没有那么神奇&#xff0c;这种技术叫做“实时文本生成”或“逐字输出”技术&#xff0…

分布式事务Seata-AT模式

承接上文分布式事务-二阶段提交 Seata是开源的分布式事务解决方案&#xff0c;提供高性能和简单易用的分布式事务服务&#xff0c;包含AT、TCC、 SAGA、XA四种事务模式&#xff0c;为用户打造一站式的分布式解决方案。 Seata提供的4种事务模式都是由2PC&#xff08;二阶段提交…