STM32调试手段:重定向printf串口

引言

       C语言中经常使用printf来输出调试信息,打印到屏幕。由于在单片机中没有屏幕,但是我们可以重定向printf,把数据打印到串口,从而在电脑端接收调试信息。这是除了debug外,另外一个非常有效的调试手段。


一、什么是printf的重定向

       我们知道 C 语言中printf 函数默认输出设备是控制台,如果要实现在串口或者 LCD 上显示,必须重定义C语言标准库函数里调用的与输出设备相关的函数。比如使用 printf 输出到串口,则需要将 fputc 里面的输出指向串口,这一过程就叫 重定向

二、怎么样重定向printf

       那么如何让 STM32 使用 printf 函数呢?很简单,只需要将 fputc 里面的输出指向 STM32 串口即可,fputc 函数有固定的格式,我们只需要在函数内操作STM32串口即可。

2.1 配置microLIB

       由于我们使用的开发环境或者说工具链是keil-MDK,而在KEIL-MDK开发环境中,本身是没有包含C语言的一些标准库函数,如stdio.h这种文件等。       

       在KEIL-MDK开发环境中,可以选择使用MicroLIB库。MicroLIB是一个高度优化的C库,适用于嵌入式应用程序。它的特点是代码体积小,但功能较少,不支持某些ISO C特性。当然这里重定向printf要使用的库函数已经够用了。

我们可以直接在【魔法棒】中勾选上即可完成它的配置


2.2 重定向fputc函数(寄存器实现)

在使用MicroLIB库时,需要重定向fputc函数。fputc函数的原型如下:

int fputc(int ch, FILE* stream)
{
USART_SendChar(USART1, (uint8_t)ch);
return ch;
}

        那么,本次我们将printf重定向到串口上,这里使用的串口是USART1,只需要编写一个发送单字符数据的函数,接着重新定义一下fputc函数即可实现printf的重定向。

       也就是说,只需要在usart.c中编写三个函数,分别是串口的初始化发送一个字符函数fputc函数重写即可。

参考代码如下:

1、usart.h

#ifndef __USART_H
#define __USART_H#include "stm32f10x.h"
#include <stdio.h>// 初始化
void USART_Init(void);// 发送一个字符
void USART_SendChar(uint8_t ch);#endif

2、usart.c

#include "usart.h"// 初始化
void USART_Init(void)
{// 1. 开启GPIO时钟 PA9 PA10RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;RCC->APB2ENR |= RCC_APB2ENR_USART1EN;// 2. 设置GPIO工作模式// PA9 TX 输出,复用推挽输出 MODE-11 CNF-10// PA10 RX 输入,浮空输入 MODE-00 CNF-01GPIOA->CRH |= GPIO_CRH_MODE9;GPIOA->CRH |= GPIO_CRH_CNF9_1;GPIOA->CRH &= ~GPIO_CRH_CNF9_0;GPIOA->CRH &= ~GPIO_CRH_MODE10;GPIOA->CRH &= ~GPIO_CRH_CNF10_1;GPIOA->CRH |= GPIO_CRH_CNF10_0;// 3. 串口配置// 3.1 设置波特率USART1->BRR = 0x271;         // 115.2 Kpbs// 3.2 开启模块及收发使能USART1->CR1 |= USART_CR1_UE;USART1->CR1 |= USART_CR1_TE;USART1->CR1 |= USART_CR1_RE;// 3.3 其他配置(字长、奇偶校验、停止位)USART1->CR1 &= ~USART_CR1_M;USART1->CR1 &= ~USART_CR1_PCE;USART1->CR2 &= ~USART_CR2_STOP;
}// 发送一个字符
void USART_SendChar(uint8_t ch)
{// 当发送的数据不为空时等待,TXE为1则可以继续写入数据while ((USART1->SR & USART_SR_TXE) == 0){}// 发送一个字符USART1->DR = ch;    
}// 重定向fputc函数
int fputc(int ch, FILE * file)
{USART_SendChar((uint8_t)ch);return (int)ch;
}

3、main.c

#include "usart.h"int main(void)
{// 初始化USART_Init();// printfint a = 100;printf("a = %d", a);// 死循环保持状态while(1){		}
}

2.3 重定向fputc函数(HAL库实现)

        然后我们在借助HAL库实现。其实也非常简单,其在STM32CubeMX中需要进行的配置和前面串口通讯轮询案例的HAL库实现需要的配置是一样的,因为本次作重定向主要就只是多重写一个fputc函数,即STM32CubeMX软件自动生成代码后我们再在usart.c中添加重写fputc函数的代码即可,非常简单。

所以这里附上前面HAL库实现的串口通讯轮询案例的文章链接,可以直接去看看相关配置步骤USART_串口通讯轮询案例(HAL库实现)-CSDN博客https://blog.csdn.net/2301_79475128/article/details/145263748?spm=1001.2014.3001.5502

然后,根据上面所述原理,这里直接给上添加到usart.c中的参考代码如下:

/* USER CODE BEGIN 1 */int fputc(int ch, FILE * file)
{HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 1000);return ch;
}/* USER CODE END 1 */

      值得注意的是,keil中要勾选上【microLIB】代码中引入#include<stdio.h> ,否则会提示找不到printf函数。


三、测试

编译以后,我们烧录然后在串口助手中看效果

1、寄存器实现的测试

2、HAL库实现的测试

       显然,通过重定向printf,我们可以通过printf将一些信息打印发送到电脑上,使用串口助手进行查看。


以上便是本次文章的所有内容,欢迎各位朋友在评论区讨论,本人也是一名初学小白,愿大家共同努力,一起进步吧!

鉴于笔者能力有限,难免出现一些纰漏和不足,望大家在评论区批评指正,谢谢!

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

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

相关文章

设计模式:春招面试的关键知识储备

在之前的文章中&#xff0c;我们深入探讨了分布式事务&#xff0c;了解了它在分布式系统中的重要性以及常见的解决方案。而在软件开发领域&#xff0c;设计模式是提升代码质量、可维护性和可扩展性的关键要素。设计模式是对软件开发中反复出现的问题的通用解决方案&#xff0c;…

上位机知识篇---Linux的shell脚本搜索、查找、管道

文章目录 前言第一部分&#xff1a;什么是shell&#xff1f;1. 基本结构脚本声明注释命令和表达式例子 2.变量控制结构条件判断 3.函数输入输出重定向 4.执行命令5.实际应用 第二部分&#xff1a;Linux的搜索、查找、管道命令1.搜索命令2.查找命令3.管道操作 总结 前言 以上就…

利用飞书机器人进行 - ArXiv自动化检索推荐

相关作者的Github仓库 ArXivToday-Lark 使用教程 Step1 新建机器人 根据飞书官方机器人使用手册&#xff0c;新建自定义机器人&#xff0c;并记录好webhook地址&#xff0c;后续将在配置文件中更新该地址。 可以先完成到后续步骤之前&#xff0c;后续的步骤与安全相关&…

混合专家模型MoE的全面详解

什么是混合专家&#xff08;MoE&#xff09;&#xff1f; 混合专家&#xff08;MoE&#xff09;是一种利用多个不同的子模型&#xff08;或称为“专家”&#xff09;来提升LLM质量的技术。 MoE的两个主要组成部分是&#xff1a; 专家&#xff1a;每个前馈神经网络&#xff08…

基于Arcsoft的人脸识别

目录 一、前言 二、使用方法 三、获取SDK 四、人脸检测/人脸识别 五、代码实现 一、前言 face++,百度ai,虹软,face_recognition,其中除了face_recognition是python免费的一个库安装好响应的库直接运行就好,另外三个需要填入相关申请的信息id和key。 分别对应着相应的人…

电梯系统的UML文档13

5.2.6 CarPositionControl 的状态图 图 24: CarPositionControl 的状态图 5.2.7 Dispatcher 的状态图 图 25: Dispatcher 的状态图 5.3 填补从需求到状态图鸿沟的实用方法 状态图能对类的行为&#xff0c;一个用例&#xff0c;或系统整体建模。在本文中&#xff0c;状态图…

自动化运维在云环境中的完整实践指南

随着云计算的普及,越来越多的企业将业务迁移到云上。云环境的高动态性和复杂性使得传统的手动运维方式难以应对,自动化运维成为提升效率、降低成本、保障系统稳定性的关键。本文将详细介绍如何在云环境中实施自动化运维,涵盖工具选择、实施步骤和最佳实践。 © ivwdcwso…

性能测试丨分布式性能监控系统 SkyWalking

软件测试领域&#xff0c;分布式系统的复杂性不断增加&#xff0c;如何保证应用程序的高可用性与高性能&#xff0c;这是每一个软件测试工程师所面临的重大挑战。幸运的是&#xff0c;现在有了一些强大的工具来帮助我们应对这些挑战&#xff0c;其中之一便是Apache SkyWalking。…

Ollama windows安装

Ollama 是一个开源项目&#xff0c;专注于帮助用户本地化运行大型语言模型&#xff08;LLMs&#xff09;。它提供了一个简单易用的框架&#xff0c;让开发者和个人用户能够在自己的设备上部署和运行 LLMs&#xff0c;而无需依赖云服务或外部 API。这对于需要数据隐私、离线使用…

留学生scratch计算机haskell函数ocaml编程ruby语言prolog作业VB

您列出了一系列编程语言和技术&#xff0c;这些可能是您在留学期间需要学习或完成作业的内容。以下是对每个项目的简要说明和它们可能涉及的领域或用途&#xff1a; Scratch&#xff1a; Scratch是一种图形化编程语言&#xff0c;专为儿童和初学者设计&#xff0c;用于教授编程…

C++二叉树进阶

1.二叉搜索树 1.1二叉搜索树概念 二叉搜索树又称二叉排序树&#xff0c;它或者是一颗空树&#xff0c;或者具有以下性质的二叉树 若它的左子树不为空&#xff0c;则左子树上所有结点的值小于根节点的值若它的右子树不为空&#xff0c;则右子树上所有节点的值都大于根节点的值…

亲测有效!解决PyCharm下PyEMD安装报错 ModuleNotFoundError: No module named ‘PyEMD‘

解决PyCharm下PyEMD安装报错 PyEMD安装报错解决方案 PyEMD安装报错 PyCharm下通过右键自动安装PyEMD后运行报错ModuleNotFoundError: No module named ‘PyEMD’ 解决方案 通过PyCharm IDE python package搜索EMD-signal&#xff0c;选择版本后点击“install”执行安装

2. Java-MarkDown文件解析-工具类

2. Java-MarkDown文件解析-工具类 1. 思路 读取markdown文件的内容&#xff0c;根据markdown的语法进行各个类型语法的解析。引入工具类 commonmark 和 commonmark-ext-gfm-tables进行markdown语法解析。 2. 工具类 pom.xml <!-- commonmark 解析markdown --> <d…

常用符号的英语表达

plus 加号&#xff1b;正号 -  minus 减号&#xff1b;负号  plus or minus 正负号  is multiplied by 乘号  is divided by 除号 &#xff1d; is equal to 等于号 ≠ is not equal to 不等于号 ≡ is equivalent to 全等于号 ≌ is equal to or approximatel…

青少年编程与数学 02-008 Pyhon语言编程基础 02课题、基础概念

青少年编程与数学 02-008 Pyhon语言编程基础 02课题、基础概念 一、标识符二、关键字三、字面量四、变量五、运算符1. 算术运算符2. 比较运算符3. 逻辑运算符4. 赋值运算符5. 成员运算符6. 身份运算符 六、表达式七、语句八、注释单行注释多行注释文档字符串&#xff08;Docstr…

lanqiaoOJ 2145:求阶乘 ← 二分法

【题目来源】 https://www.lanqiao.cn/problems/2145/learning/ 【题目描述】 满足 N&#xff01;的末尾恰好有 K 个 0 的最小的 N 是多少&#xff1f; 如果这样的 N 不存在输出 -1。 【输入格式】 一个整数 K。 【输出格式】 一个整数代表答案。 【输入样例】 2 【输出样…

vs2013 使用 eigen 库编译时报 C2059 错的解决方法

&#xff08;个人感觉&#xff09;vs2013 就不能使用版本大于等于 3.4 的 eigen&#xff0c;使用 3.3.9 就可以了&#xff0c;再不行就用 3.3.8 另一个博主也遇到过用 vs2013 的时候不能编译 3.4 的 eigen 的问题&#xff0c;不过我用的是 win11&#xff0c;所以感觉跟操作系统…

U盘打开提示格式化:深度解析与数据恢复全攻略

在数字化时代&#xff0c;U盘作为便捷的数据存储和传输工具&#xff0c;广泛应用于各个领域。然而&#xff0c;当我们满怀期待地插入U盘&#xff0c;却遭遇“U盘打开提示格式化”的尴尬局面时&#xff0c;那份焦虑与无助感油然而生。本文将全面剖析U盘打开提示格式化的原因、应…

智能工厂能耗管理:Python助力节能增效

智能工厂能耗管理:Python助力节能增效 在工业4.0时代,工厂能耗管理已成为制造企业降本增效的重要一环。传统的能耗管理方式往往依赖人工统计和经验决策,导致能源浪费严重。而借助人工智能与Python的强大能力,我们可以实现智能化、数据驱动的能耗优化方案。今天,我们就来聊…

MyBatis 框架:简化 Java 数据持久化的利器

Java学习资料 Java学习资料 Java学习资料 一、引言 在 Java 企业级应用开发中&#xff0c;数据持久化是一个至关重要的环节&#xff0c;它涉及到将应用程序中的数据保存到数据库&#xff0c;以及从数据库中读取数据供应用程序使用。传统的 JDBC 编程虽然可以实现数据持久化&…