STM32使用UART发送字符串与printf输出重定向

        首先我们先看STM32F103C8T6的电路图

由图可知,其PA9和PA10引脚分别为UART的TX和RX(注意:这个电路图是错误的,应该是PA9是X而PA9是RX,我们看下图的官方文件可以看出),那么接下来我们应该找到该引脚的定义是什么,请参考STM32F103Cx手册,找到pin definitions。

        STM32系列集成了很多个UART接口,如UART1、UART2等,每个都可以独立配置和使用来与其他设备进行通信。UART1只是这些可用UART接口中的一个实例。

可以看到PA9和PA10使用的是UART1,配置外设第一件事情就是找所对应的时钟,因此接下来是根据接口来找对应的时钟。还是在手册中,查找"performance line block diagram",如下图:

        由图可知,USART1挂载在APB2总线上,因此如果我们需要该接口,则需要使能该时钟。根据STM32标准库手册,找到使能时钟所需的函数。

代码如下:

void Uart1_Configuration(void)
{GPIO_InitTypeDef GPIO_InitStructure;USART_InitTypeDef USART_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_USART1, ENABLE);// 配置PA9,作为TX,使用的是复用推挽输出GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_Init(GPIOA, &GPIO_InitStructure);// 配置PA10,作为RX,使用的是浮空输入,因为可能输入高电平也可能输入低电平GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;GPIO_Init(GPIOA, &GPIO_InitStructure);// 配置UARTUSART_InitStructure.USART_BaudRate = 115200;USART_InitStructure.USART_WordLength = USART_WordLength_8b;  // 数据位长度USART_InitStructure.USART_StopBits = USART_StopBits_1;USART_InitStructure.USART_Parity = USART_Parity_No;USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;USART_Init(USART1, &USART_InitStructure);USART_Cmd(USART1, ENABLE);
}

配置好端口后,那么就应该发送数据了,同样的发送数据也应该去标准库函数中找相应的函数。需要提醒的,我们主要是使用printf函数来测试uart接口的功能,, 而printf函数的标准输出设备是显示屏,因此需要将输出重定向到uart口上而不是显示屏上,就需要重写printf,但是,prinft只是一个函数宏,实际靠的还是fputc,所以总的来说还是要重写fputc。

代码如下:

// 输出从标准输出设备重定向到UART, 函数原型是int fputc (int c, FILE *fp)而不是int fputc (char c, File *fp)
// printf函数的一个个字符输出到UART
int fputc (int c, FILE *fp)
{while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) != SET); // TXE = Transmit Data Register EmptyUSART_SendData(USART1, c);while(USART_GetFlagStatus(USART1, USART_FLAG_TC) != SET); // TC = Transmission Completereturn 0;
}

配置好uart口以及进行输出重定向后,只要调用就可以实现printf输出到uart口了。

#include "bsp_SysTick.h"
#include "bsp_uart.h"int main(void)
{int i = 0;SysTick_Configuration();Uart1_Configuration();while(1){printf("Hello world\n");printf("i = %d\n", i++);Delay_us(1000000); // 等待1秒,该函数是通过cortex的SysTick来编写的,这里的主要作用就只是延迟而已}
}

需要特别注意的是,如果你使用调试器进行Download,也就是下图这个东西,那么使用的将是半主机模式。

下面简单介绍什么是半主机模式:

启用半主机模式:

        单片机上的程序遇到I/O调用时(比如printf),会通过调试接口将这些请求转发给宿主机上的调试器处理。


关闭半主机模式:

        单片机上的程序必须自己处理所有的I/O操作,或者通过预定义的硬件接口与其他设备通信。

因此,我们如果使用调试器(或者叫做仿真器)进行测试调试代码的话,想要有数据从单片机的uart口输出,那么我们应该关闭半主机模式。

如何关闭:

这样应该就可以解决串口助手看不到数据的问题了。

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

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

相关文章

Kotlin在医疗大健康域的应用实例探究与编程剖析(下)

四、Kotlin医疗编程实例分析 4.1 移动医疗应用实例 4.1.1 患者健康监测应用 在当今数字化医疗时代,患者健康监测应用为人们提供了便捷的健康管理方式。利用Kotlin开发的患者健康监测应用,能够实时采集患者的各类生理数据,如心率、血压、血氧饱和度等,并通过直观的可视化…

探索数据之美,Plotly引领可视化新风尚

在数据如潮的今天,如何精准捕捉信息的脉搏,让数据说话?Plotly,这款强大的数据可视化工具,正以其卓越的性能和丰富的功能,成为数据分析师、科学家及工程师们的得力助手。 Plotly不仅仅是一个绘图库&#xf…

Redis 5设计与源码分析读书笔记

目录 引言Redis 5.0的新特性Redis源码概述Redis安装与调试 简单动态字符串数据结构基本操作创建字符串释放字符串拼接字符串扩容策略 其余API 本章小结兼容C语言字符串、保证二进制安全sdshdr5的特殊之处是什么SDS是如何扩容的 跳跃表简介跳跃表节点与结构跳跃表节点跳跃表结构…

Golang学习历程【第五篇 复合数据类型:数组切片】

Golang学习历程【第五篇 复合数据类型:数组&切片】 1. 数组(Array)1.1 数组的定义1.2 初始化数组1.3 数据的循环遍历1.4 多维数组 2. 切片(Slice)2.1 切片声明、初始化2.2 基于数组创建切片2.2 切片的长度(len)和容…

【Unity】 HTFramework框架(五十七)通过Tag、Layer批量搜索物体

更新日期:2024年12月30日。 Github源码:[点我获取源码] Gitee源码:[点我获取源码] 索引 问题再现通过Tag搜索物体(SearchByTag)打开SearchByTag窗口搜索标记指定Tag的所有物体批量修改Tag搜索Undefined状态的所有物体 …

基于feapder爬虫与flask前后端框架的天气数据可视化大屏

# 最近又到期末了,有需要的同学可以借鉴。 一、feapder爬虫 feapder是国产开发的新型爬虫框架,具有轻量且数据库操作方便、异常提醒等优秀特性。本次设计看来利用feapder进行爬虫操作,可以加快爬虫的速率,并且简化数据入库等操作…

PCL点云库入门——PCL库点云滤波算法之统计滤波(StatisticalOutlierRemoval)

1、算法原理 统计滤波算法是一种利用统计学原理对点云数据进行处理的方法。它主要通过计算点云中每个点的统计特性,如均值、方差等,来决定是否保留该点。算法首先会设定一个统计阈值,然后对点云中的每个点进行分析。如果一个点的统计特性与周…

CentOS7 解决ping:www.baidu.com 未知的名称或服务

CentOS7 解决ping:www.baidu.com“未知的名称或服务 在VM查看网络配置 查看虚拟网络编辑器 编辑网络配置文件 vi /etc/sysconfig/network-scripts/ifcfg-ens33注意:不同机器的配置文件名可能不相同,通过 ip addr 命令查看 将 ONBOOT 从 no 改…

aws(学习笔记第二十一课) 开发lambda应用程序

aws(学习笔记第二十一课) 开发lambda应用程序 学习内容: lambda的整体概念开发lambda应用程序 1. lambda的整体概念 借助AWS Lambda,无需预置或管理服务器即可运行代码。只需为使用的计算时间付费。借助 Lambda,可以为几乎任何类型的应用进…

【Leetcode】3280. 将日期转换为二进制表示

文章目录 题目思路代码复杂度分析时间复杂度空间复杂度 结果总结 题目 题目链接🔗 给你一个字符串 date,它的格式为 yyyy-mm-dd,表示一个公历日期。 date 可以重写为二进制表示,只需要将年、月、日分别转换为对应的二进制表示&a…

docker compose部署kafka集群

先部署zookeeper集群,启动 参考:docker compose部署zookeeper集群-CSDN博客 再部署kafka集群 networks: net: external: true services: kafka1: restart: always image: wurstmeister/kafka:2.13_2.8.1 container_name: kafka1 …

拆解 | 公募REITs:发售上市流程及细节

Hi,围炉喝茶聊产品的新老朋友好,在国庆假期写了两篇有关公募REITs的文章,先简单回顾下,以达到温故知新的效果。 第一篇:一起探索:公募REITs,它从本质、背景、概念等维度较系统介绍了公募REITs,如:明明是“不动产基金”,为什么叫REITs?说到底,投资REITs的实质是什么…

作业:C高级:Day4

第一题 思维导图 第二题 test的指令(整数判断、字符串判断、文件判断) 结果 第三题 题目 终端输入一个C源文件名(.c结尾)判断文件是否有内容,如果没有内容删除文件,如果有内容编译并执行改文件。 代码 三种情形的结果&#xff1…

(推荐)【通用业务分发架构】1.业务分发 2.rpc调用 3.Event事件系统

一.Reflections和SpringUtil完成扫描包的(反射缓存) 二.id与class的映射泛型上下文(玩家是否登录,rpc调用SeqId,class类名)反射调用 1.netty层的 AccountMsgParam // 登录前 OnlineMsgParam // 登录后 SceneMsgParam // 发到场景层的 2.跨进程rpc调用的…

FristiLeaks_1.3靶场渗透

目录 环境搭建 开始渗透 扫一下存活(也就是扫描一下靶机IP) ​编辑 扫描端口 扫描服务 查看80端口 扫描一下目录 查看robots 再看一下images,没啥用 回头看主页面,说多喝点FRISTI,我们试试看 尝试admin和万能密码 查看源…

OpenCV的TickMeter计时类

OpenCV的TickMeter计时类 1. TickMeter是一个计时的类1.1 计算耗时1.2 计算循环的平均耗时和FPS1.3 function 2. 案例 1. TickMeter是一个计时的类 https://docs.opencv.org/4.x/d9/d6f/classcv_1_1TickMeter.html#details 1.1 计算耗时 TickMeter tm;tm.start();// do some…

logback之pattern详解以及源码分析

目录 (一)pattern关键字介绍 (二)源码分析 (一)pattern关键字介绍 %d或%date:表示日期,可配置格式化%d{yyyy-MM-dd HH:mm:ss} %r或%relative:也是日期,不过…

【专题】2024年出口跨境电商促销趋势白皮书报告汇总PDF洞察(附原数据表)

原文链接:https://tecdat.cn/?p38722 在当今全球化加速演进、数字经济蓬勃发展的大背景下,跨境电商行业正以前所未有的态势重塑国际贸易格局,成为各方瞩目的焦点领域。 根据亚马逊发布的《2024年出口跨境电商促销趋势白皮书》,…

primevue的<Menu>组件

1.使用场景 2.代码 1.给你的menu组件起个引用名 2.<Menu>组件需要一个MenuItem[] 3.你要知道MenuItem[ ]的特殊的数据格式&#xff0c;就像TreeNode[ ]一样&#xff0c;数据格式不对是不渲染的。。。。 常用的属性就这几种&#xff0c;js语言和java不一样&#xff0c;J…

NVR小程序接入平台EasyNVR使用FFmpeg取流时提示错误是什么原因呢?

在视频监控系统中&#xff0c;FFmpeg常用于从各种源&#xff08;如摄像头、文件、网络流等&#xff09;获取流媒体数据&#xff0c;这个过程通常称为“取流”。 在EasyNVR平台中&#xff0c;使用FFmpeg取流是一种常见的操作。FFmpeg作为一款强大的开源多媒体处理工具&#xff…