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

news2025/1/30 15:22:35

引言

       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 PA10
    RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;
    RCC->APB2ENR |= RCC_APB2ENR_USART1EN;

    // 2. 设置GPIO工作模式
    // PA9 TX 输出,复用推挽输出 MODE-11 CNF-10
    // PA10 RX 输入,浮空输入 MODE-00 CNF-01
    GPIOA->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();

	// printf
	int 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.coloradmin.cn/o/2284996.html

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

相关文章

基于Flask的哔哩哔哩评论数据可视化分析系统的设计与实现

【Flask】基于Flask的哔哩哔哩评论数据可视化分析系统的设计与实现&#xff08;完整系统源码开发笔记详细部署教程&#xff09;✅ 目录 一、项目简介二、项目界面展示三、项目视频展示 一、项目简介 该系统可以搜索查看作者、播放量、评论等相关信息&#xff0c;并将相关的分析…

YOLO目标检测4

一. 参考资料 《YOLO目标检测》 by 杨建华博士 本篇文章的主要内容来自于这本书&#xff0c;只是作为学习记录进行分享。 二. 环境搭建 (1) ubuntu20.04 anaconda安装方法 (2) 搭建yolo训练环境 # 首先&#xff0c;我们建议使用Anaconda来创建一个conda的虚拟环境 conda cre…

​ONES 春节假期服务通知

ONES 春节假期服务通知 灵蛇贺岁&#xff0c;瑞气盈门。感谢大家一直以来对 ONES 的认可与支持&#xff0c;祝您春节快乐&#xff01; 「2025年1月28日 &#xff5e; 2025年2月4日」春节假期期间&#xff0c;我们的值班人员将为您提供如下服务 &#xff1a; 紧急问题 若有紧急问…

Redis部署方式全解析:优缺点大对比

Redis部署方式全解析&#xff1a;优缺点大对比 一、引言 Redis作为一款高性能的内存数据库&#xff0c;在分布式系统、缓存、消息队列等众多场景中都有着广泛的应用。选择合适的Redis部署方式&#xff0c;对于系统的性能、可用性、可扩展性以及成本等方面都有着至关重要的影响…

【新春不断更】数据结构与算法之美:二叉树

Hello大家好&#xff0c;我是但凡&#xff01;很高兴我们又见面啦&#xff01; 眨眼间已经到了2024年的最后一天&#xff0c;在这里我要首先感谢过去一年陪我奋斗的每一位伙伴&#xff0c;是你们给予我不断前行的动力。银蛇携福至&#xff0c;万象启新程。蛇年新春之际&#xf…

Linux环境基础开发工具的使用(apt, vim, gcc, g++, gbd, make/Makefile)

什么是软件包 在Linux下安装软件, 一个通常的办法是下载到程序的源代码, 并进行编译, 得到可执行程序. 但是这样太麻烦了, 于是有些人把一些常用的软件提前编译好, 做成软件包(可以理解成windows上的安 装程序)放在一个服务器上, 通过包管理器可以很方便的获取到这个编译好的…

渗透测试之WAF规则触发绕过规则之规则库绕过方式

目录 Waf触发规则的绕过 特殊字符替换空格 实例 特殊字符拼接绕过waf Mysql 内置得方法 注释包含关键字 实例 Waf触发规则的绕过 特殊字符替换空格 用一些特殊字符代替空格&#xff0c;比如在mysql中%0a是换行&#xff0c;可以代替空格 这个方法也可以部分绕过最新版本的…

Harmony Next 跨平台开发入门

ArkUI-X 官方介绍 官方文档&#xff1a;https://gitee.com/arkui-x/docs/tree/master/zh-cn ArkUI跨平台框架(ArkUI-X)进一步将ArkUI开发框架扩展到了多个OS平台&#xff1a;目前支持OpenHarmony、Android、 iOS&#xff0c;后续会逐步增加更多平台支持。开发者基于一套主代码…

小阿卡纳牌

小阿卡纳牌 风&#xff1a;热湿 火&#xff1a;热干 水&#xff1a;冷湿 土&#xff1a;冷干 火风&#xff1a;温度相同&#xff0c;但是湿度不同&#xff0c;二人可能会在短期内十分热情&#xff0c;但是等待热情消退之后&#xff0c;会趋于平淡。 湿度相同、温度不同&#x…

【现代深度学习技术】深度学习计算 | 参数管理

【作者主页】Francek Chen 【专栏介绍】 ⌈ ⌈ ⌈PyTorch深度学习 ⌋ ⌋ ⌋ 深度学习 (DL, Deep Learning) 特指基于深层神经网络模型和方法的机器学习。它是在统计机器学习、人工神经网络等算法模型基础上&#xff0c;结合当代大数据和大算力的发展而发展出来的。深度学习最重…

c++ 定点 new

&#xff08;1&#xff09; 代码距离&#xff1a; #include <new> // 需要包含这个头文件 #include <iostream>int main() {char buffer[sizeof(int)]; // 分配一个足够大的字符数组作为内存池int* p new(&buffer) int(42); // 使用 placement new…

宫本茂的游戏设计思想:有趣与风格化

作为独立游戏开发者之一&#xff0c;看到任天堂宫本茂20年前的言论后&#xff0c;深感认同。 游戏研发思想&#xff0c;与企业战略是互为表里的&#xff0c;游戏是企业战略的具体战术体现&#xff0c;虚空理念的有形载体。 任天堂长盛不衰的关键就是靠简单有趣的游戏&#xf…

【AI论文】扩散对抗后训练用于一步视频生成总结

摘要&#xff1a;扩散模型被广泛应用于图像和视频生成&#xff0c;但其迭代生成过程缓慢且资源消耗大。尽管现有的蒸馏方法已显示出在图像领域实现一步生成的潜力&#xff0c;但它们仍存在显著的质量退化问题。在本研究中&#xff0c;我们提出了一种在扩散预训练后针对真实数据…

在线可编辑Excel

1. Handsontable 特点&#xff1a; 提供了类似 Excel 的表格编辑体验&#xff0c;包括单元格样式、公式计算、数据验证等功能。 支持多种插件&#xff0c;如筛选、排序、合并单元格等。 轻量级且易于集成到现有项目中。 具备强大的自定义能力&#xff0c;可以调整外观和行为…

【javaweb项目idea版】蛋糕商城(可复用成其他商城项目)

该项目虽然是蛋糕商城项目&#xff0c;但是可以复用成其他商城项目或者购物车项目 想要源码的uu可点赞后私聊 技术栈 主要为&#xff1a;javawebservletmvcc3p0idea运行 功能模块 主要分为用户模块和后台管理员模块 具有商城购物的完整功能 基础模块 登录注册个人信息编辑…

langchain基础(三)

Chain&#xff1a; 关于三个invoke&#xff1a; 提示模板、聊天模型和输出解析器都实现了langchain的runnable接口&#xff0c; 都具有invoke方法&#xff08;因为invoke方法是Runnable的通用调用方法&#xff09; 所以可以一次性调用多次invoke直接得到最终结果&#xff1a;…

Kafka 深入服务端 — 时间轮

Kafka中存在大量的延迟操作&#xff0c;比如延时生产、延时拉取和延时删除等。Kafka基于时间轮概念自定义实现了一个用于延时功能的定时器&#xff0c;来完成这些延迟操作。 1 时间轮 Kafka没有使用基于JDK自带的Timer或DelayQueue来实现延迟功能&#xff0c;因为它们的插入和…

一文掌握ADB的安装及使用

文章目录 一、什么是ADB&#xff1f;二、 安装ADB2.1 下载ADB2.2 配置环境变量 三、连接Android设备四、 常用ADB命令五、ADB高级功能5.1 屏幕截图和录制5.2 模拟按键输入5.3 文件管理5.4 系统设置管理5.5 系统操作指令5.6 日志操作指令5.7 APK操作指令5.8 设备重启和恢复 六、…

Linux系统下速通stm32的clion开发环境配置

陆陆续续搞这个已经很久了。 因为自己新电脑是linux系统无法使用keil&#xff0c;一开始想使用vscode里的eide但感觉不太好用&#xff1b;后面想直接使用cudeide但又不想妥协&#xff0c;想趁着这个机会把linux上的其他单片机开发配置也搞明白&#xff1b;而且非常想搞懂cmake…

OpenCSG月度更新2025.1

1月的OpenCSG取得了一些亮眼的成绩 在2025年1月&#xff0c;OpenCSG在产品和社区方面继续取得了显著进展。产品方面&#xff0c;推出了AutoHub浏览器自动化助手&#xff0c;帮助用户提升浏览体验&#xff1b;CSGHub企业版功能全面升级&#xff0c;现已开放试用申请&#xff0c…