STM32-HAL-串口的printf重定向

这篇具有很好参考价值的文章主要介绍了STM32-HAL-串口的printf重定向。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、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的小熊派开发板
    hal_uart_transmit printf,STM32,BearPi,stm32,单片机,嵌入式硬件

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

三、初始化片上外设

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

设置串口通信为异步通信,波特率115200
hal_uart_transmit printf,STM32,BearPi,stm32,单片机,嵌入式硬件

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

四、设置重定向

4.1 点击魔术棒,然后勾选使用微库(Use MicroLIB)
hal_uart_transmit printf,STM32,BearPi,stm32,单片机,嵌入式硬件

针对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.c函数中添加头文件:

#include "stdio.h"

main.c函数的/* 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

hal_uart_transmit printf,STM32,BearPi,stm32,单片机,嵌入式硬件

4.5 不使用微库打印数据

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

usart.c函数中添加头文件:

#include "stdio.h"

usart.c函数/* USER CODE BEGIN 1 */内添加下面代码即可:

/* 加入以下代码, 支持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->SR & 0X40) == 0);               /* 等待上一个字符发送完成 */
    
    USART1->DR = (uint8_t)ch;                       /* 将要发送的字符 ch 写入到DR寄存器 */	
    return ch;
}
#endif

注意在使用Cubmex生成的HAL库代码中,USART1的相关寄存器可能随着不同型号的MCU会发生变化,如果编译不通过及时修改即可。

4.6 打印输出的结果是一致的
hal_uart_transmit printf,STM32,BearPi,stm32,单片机,嵌入式硬件文章来源地址https://www.toymoban.com/news/detail-676032.html

到了这里,关于STM32-HAL-串口的printf重定向的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 关于STM32 hal printf重定向 “FILE“ is undefined

    关于STM32 hal printf重定向,及报错。“FILE” is undefined 增加以下内容:

    2024年02月13日
    浏览(39)
  • STM32-HAL库-printf函数重定向(简单易懂亲测有效)

    由于STM32cubemx生成的HAL库代码没有printf,为了让这个函数能实现打印功能,我们必须要把这个函数重定向,让它重定向到串口中,把要输出的内容打印到串口中。 配置好时钟后,选择你的串口,生成代码。 进入到STM32xxxhal.c中,加入如下两条语句,你的huart是数字几,后面就修

    2024年02月05日
    浏览(39)
  • STM32 HAL库串口重映射printf

    添加代码 keil设置 microlib 是缺省 C 库的备选库。 它旨在与需要装入到极少量内存中的深层嵌入式应用程序配合使用。 这些应用程序不在操作系统中运行。 microlib 进行了 高度优化以使代码变得很小 。 它的功能比缺省 C 库少,并且根本不具备某些 ISO C 特性。 某些库函数的运

    2024年02月16日
    浏览(36)
  • STM32+HAL库调试printf串口打印

    目录 1 新建cubemx工程  2 配置系统时钟 3 配置串口引脚 4 生成keil工程 5 补充代码 5.1 重定向printf 5.2 main函数 6 编译烧录 7 实验现象         选择对应芯片         主频为64MHz         对应给到usart2的时钟也为64MHz            查阅原理图,可知usart2引脚连接了USB串口      

    2024年02月09日
    浏览(40)
  • stm32(HAL库)使用printf函数打印到串口

    目录 1、简介 2.1 基础配置 2.1.1 SYS配置  2.1.2 RCC配置 2.2 串口外设配置  2.3 项目生成  3、KEIL端程序整合   4、效果测试 在HAL库中,常用的printf函数是无法使用的。本文通过重映射实现在HAL库中进行printf函数。 2.1.1 SYS配置  2.1.2 RCC配置 在usart.c函数最下方复制如下代码 接着在

    2024年02月14日
    浏览(38)
  • STM32 HAL库 STM32CubeMx -- 串口的使用(USART/UART)

    在上一篇博客里面写了串口通信的理论知识,在这一篇中将讲述串口通信在STM32CubeMx里面的配置,以及在函数里面怎么使用。 对于串口发送信息,分为三种方法: 串口阻塞方式收发 、 串口中断方式收发 、 串口DMA方式收发 。(DMA方式在之后的DMA章节讲解) 关于STM32CubeMx的基

    2024年02月06日
    浏览(64)
  • 【STM32】HAL库三步实现串口重定向(代码复制可用)

    目录 第一步:添加标准输入输出头文件 第二步:重写fputc()函数 第三步:重写fgetc()函数 代码汇总(直接复制使用)-需要直接来复制 在PC上进行C语言程序开发时,我们可以利用C语言的格式化输出函数 printf()将程序的运行结果发送到显示屏上显示,也可以利用格式化输人函数

    2024年02月05日
    浏览(36)
  • 【13】STM32·HAL库-正点原子SYSTEM文件夹 | SysTick工作原理、寄存器介绍 | printf函数使用、重定向

      下面函数都是以sys_开头,定义在sys.c中。正点原子函数现阶段命名规则如果是在led.c中,则以led_开头。在F7/H7系列中会存在Cache配置函数,I-Cache中存储指令,D-Cache中存储数据。   SysTick,即系统滴答定时器,包含在M3/4/7内核里面,核心是一个24位的递减计数器( 最大计

    2024年02月15日
    浏览(38)
  • (stm32之HAL库)UART工作在DMA模式要打开串口中断吗?

    最近学习了stm32(F4xx)的串口在DMA模式下的使用,期间以ST官方提供的例程进行参考学习,发现其初始化过程中是打开了UART的中断的,而且HAL库中stm32f4xx_hal_uart.c文件中的DMA模式使用说明里也有这么一句话: 即在非循环模式下(也就是发完一次数据就停止的常用模式)需要配置

    2024年02月12日
    浏览(30)
  • 【STM32】HAL库UART含校验位的串口通信配置BUG避坑

    【STM32】HAL库UART含校验位的串口通信配置BUG避坑 UART通过一条线就能完成数据的发送 另外一条线则完成数据的接收 所以一共是两条线 TX RX UART在空闲时为低电平 时钟周期由波特率确定 通常是115200bit/s UART协议由四个部分组成: 起始位: 固定低电平 1个时钟周期 数据域: 通常

    2024年01月20日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包