【STM32学习5】STM32使用printf函数 打印到电脑串口助手

这篇具有很好参考价值的文章主要介绍了【STM32学习5】STM32使用printf函数 打印到电脑串口助手。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


本文所使用的方法与代码参考自正点原子,如果想要详细了解这方面的知识,请阅读正点原子官方提供的文档。


一、背景

在开发STM32应用时,将一些信息通过串口打印到电脑上是常用的调试手段。C语言标准库中的printf函数是我们常用的打印函数。但是在STM32应用下一般无法直接使用这个函数,正点原子给出的解释如下,有兴趣可以详细了解一下。

标准库下的 printf 为调试属性的函数,如果直接使用,会使单片机进入半主机模式(semihosting),这是一种调试模式,直接下载代码后出现程序无法运行,但是在连接调试器进行 Debug 时程序反而能正常工作的情况。半主机是 ARM 目标的一种机制,用于将输入/输出请求从应用程序代码通信到运行调试器的主机。例如,此机制可用于允许 C 库中的函数(如 printf()和 scanf())使用主机的屏幕和键盘,而不是在目标系统上设置屏幕和键盘。这很有用,因为开发硬件通常不具有最终系统的所有输入和输出设备,如屏幕、键盘等。半主机是通过一组定义好的软件指令(如 SVC)SVC 指令(以前称为 SWI 指令)来实现的,这些指令通过程序控制生成异常。应用程序调用相应的半主机调用,然后调试代理处理该异常。调试代理(这里的调试代理是仿真器)提供与主机之间的必需通信。也就是说使用半主机模式必须使用仿真器调试。
如果想在独立环境下运行调试功能的函数,我们这里是 printf,printf 对字符 ch 处理后写入文件 f,最后使用 fputc 将文件 f 输出到显示设备。对于 PC 端的设备,fputc 通过复杂的源码,最终把字符显示到屏幕上。那我们需要做的,就是把 printf 调用的 fputc 函数重新实现,重定向fputc 的输出,同时避免进入半主模式。

目前想要在SMT32上使用printf有两种方法:

  1. 通过代码取消ARM的半主机工作模式,并重定向printf函数
  2. 使用微库MicroLib,并重定向printf函数。

由于微库裁剪了许多标准库的功能,如果注重功能完整性建议使用第一种方法。

二、取消ARM的半主机工作模式

添加stdio.h头文件,并在程序中加入以下代码段即可(代码引自正点原子)

/******************************************************************************************/

/* 在合适的位置引用下面头文件 */
#include <stdio.h>

/* 加入以下代码, 支持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
/***********************************************END*******************************************/

上面代码段使用的是串口1(USART1),可根据实际使用情况调整。

三、使用微库MicroLib

直接在Keil中的如下界面勾选使用微库
stm32 printf,STM32,嵌入式硬件,c语言,单片机,学习
并添加如下代码段重定向fputc

/* 在合适的位置引用下面头文件 */
#include <stdio.h>

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

微库由于裁剪掉了一些功能,有着如下特点:

  • 微库会优化代码空间,但会降低某些程序的执行效率(比如: memcpy()),效率换空间
  • 微库不支持浮点运算,所以在有FPU单元的MCU上,使用MicroLIB并开启FPU会让程序死机或跑飞
  • 微库不支持C++,在使用C++开发MCU时不能使用MicroLib
  • 微库不支持操作系统函数

更详细的讲解可参见博文STM32程序不运行与MicroLIB讲解

四、应用

采用了上面任意一种方法设置后,我们便可在程序中使用printf,并通过串口打印在电脑端的串口助手上。

		printf("123\r\n");
		
		HAL_Delay(500);

stm32 printf,STM32,嵌入式硬件,c语言,单片机,学习文章来源地址https://www.toymoban.com/news/detail-782748.html

到了这里,关于【STM32学习5】STM32使用printf函数 打印到电脑串口助手的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • stm32 ->HAL库重定向printf,实现串口打印

    在CubeMX中初始化uart引脚 包含printf函数的头文件 stdio.h 重定义printf函数 勾选 Use MicroLIB 编译烧录

    2024年02月16日
    浏览(42)
  • stm32---在keil 5中使用printf函数输出到串口USART(printf函数的移植方法)以及补充窗口printf函数输出汉字

    在串口函数初始化的c文件中加上#include stdio.h 重写fputc函数 (fputc是printf函数的底层,printf就是不断调用fputc函数一个个打印,把fputc函数重定向到串口,这样子printf自然就输出到串口) 在主函数main.c编写如下代码后直接运行. 引入#include stdarg.h  对sprintf进行可变参数的函数封装 在主

    2024年02月05日
    浏览(49)
  • STM32 F103C8T6学习笔记3:串口配置—串口收发—自定义Printf函数

    今日学习使用STM32 C8T6的串口,我们在经过学习笔记2的总结归纳可知,STM32 C8T6最小系统板上有三路串口,如下图:  今日我们就着手学习如何配置开通这些串口进行收发,这里不讲串口通信概念与基础,可以自行网上查找,本文直接开始介绍库函数与编程实现:          

    2024年02月10日
    浏览(38)
  • STM32CubeIDE串口printf函数输出中文乱码(配置教程+解决方法)

    目录 前言 平台环境 软件:STM32CubeIDE 硬件:STM32H7A3ZIT6Q 一、串口配置 二、printf重定向 三、中文乱码解决方案 步骤 效果 四、总结 本文主要讲述在使用CubeIDE配置串口通信的过程中,如何 重定向printf() 函数,以及如何解决在 串口打印中文时输出乱码 的情况。         

    2024年02月07日
    浏览(64)
  • stm32之12.如何使用printf打印输出

      主函数增加这些代码即可实现printf打印输出  需要添加头文件 #include \\\"stdio.h\\\" --------------- 源码 struct __FILE { int handle; /* Add whatever you need here */ }; FILE __stdout; FILE __stdin; int fputc(int c, FILE *f)  {     /* 发送一个字节 */     USART_SendData(USART1,c);     /* 等待发送完毕 */     while(

    2024年02月11日
    浏览(48)
  • STM32使用串口printf乱码问题解决方法

    使用stm32系列单片机串口打印问题,在使用HAL库重新定义printf为串口输出后,输出的内容全都是乱码,试了网上的方法后还是乱码。  像这样的    最后发现是串口调试助手和keil的文字编码方式不同, keil中是GB 2312,串口调试助手是UFT_8,所以打印出来才会乱码  将串口调试助

    2024年02月11日
    浏览(37)
  • STM32使用printf函数

    正点原子学习笔记 1,printf函数输出流程 2,printf的使用 3,printf函数支持 1)用户调用 printf() 2)编译器从 stdio.h 里解析 3)最终由 fputc() 实现输出 由此用户需要根据最终输出的硬件重新定义该函数,此过程称为: printf重定向 1,printf(\\\"Hello World!rn\\\"); 2,printf(\\\"%drn\\\",121);          

    2024年02月07日
    浏览(108)
  • 在STM32中使用printf函数

        利用printf函数使得输出打印到串口中。     我们在C语言中为什么能够调用printf函数打印数据到控制台中,那是因为printf函数又调用了fputc()函数。那么我们我们可不可以说printf函数之所以能够打印数据到控制台中几乎都是fput()函数的功劳呢?答案是显而易见的。

    2024年02月16日
    浏览(42)
  • 【基础】STM32中如何使用printf()函数

    在STM32串口通信程序中使用printf发送数据,非常的方便。可在刚开始使用的时候总是遇到问题,常见的是硬件访真时无法进入main主函数,其实只要简单的配置一下就可以了。 下面就说一下使用printf需要做哪些配置。 有两种配置方法: 一、对工程属性进行配置,详细步骤如下

    2024年04月24日
    浏览(45)
  • STM32使用printf函数的步骤和注意事项

    1,在KEIL中勾选 Use MicroLIB . 即使用微库. 2, 在代码中添加 如下代码 (目的是为了调用stdio库中的print 函数) 3,在uart.c 填加如下代码 (目的是为了重定向 stdio库中的print 函数 ) 1, 在代码中添加 如下代码 (目的是为了调用stdio库中的print 函数) 2, 关闭半主机模式,并重定向printf 想要明白

    2023年04月08日
    浏览(59)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包