STM32基于HAL库串口printf使用和接收

news2024/9/24 5:30:22



我们这里使用HAL库直接用cubemx生成代码配置串口

1.打开cubemx,选择MCU型号

2.我这里使用的是STM32F103C8T6,根据自己的型号选择,这里不限制型号

3.选择时钟源

4.系统设置

5时钟配置


5.选择和配置串口




5.配置中断和中断优先级

6.工程设置

7.代码生成设置



cubemx代码生成注意事项

添加代码


/* USER CODE BEGIN Prototypes */

#define RX_BUFFER_SIZE 256

typedef struct {
    uint8_t RxBuffer[RX_BUFFER_SIZE];
    uint8_t RxData;
    uint16_t RxDataCnt;
}UART_RxTypeDef;

extern UART_RxTypeDef Uart1Rx;   // 为UART1声明外部结构体变量

/* USER CODE END Prototypes */


 

/* USER CODE BEGIN 0 */

UART_RxTypeDef Uart1Rx = {{0}, 0, 0};  // 为UART1初始化结构体

// 重定向c库函数printf到huart1
int fputc(int ch, FILE *f) {
    HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xFFFF);
    return ch;
}
int fgetc(FILE *f)
{
  uint8_t ch = 0;
  HAL_UART_Receive(&huart1, &ch, 1, 0xffff);
  return ch;
}
/* USER CODE END 0 */

/* USER CODE BEGIN Includes */
	
#include <stdio.h>
#include <string.h>

#include "usart.h"
/* USER CODE END Includes */

关键的一点,如果不勾选这个选项,那么是无法运行printf代码,整个代码无法运行



然后我们如果不想每次烧录后都要按下复位键




然后我们就测试一下代码是否可以正常运行

主函数while循环
 

  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
	  printf("Hello World!\r\n");
	  HAL_Delay(1000);
  }
  /* USER CODE END 3 */

烧录后,打开我们的串口工具
我这里用的是正点原子的xcom串口助手


现在说明我们的串口发送是可以的了

然后我们需要串口接收
之前我们已经配置好了NVIC中断向量了
已经使能了串口中断
在HAL库中,串口如果发送中断会进入中断服务函数,然后在这个函数中他帮我们处理了很多东西,我们只需要调用一个回调函数,这个回调函数是弱定义,我们可以重新定义

在usart.c最下面添加代码:
 

/* USER CODE BEGIN 1 */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	if (huart->Instance == USART1)
    {

		Uart1Rx.RxBuffer[Uart1Rx.RxDataCnt++] = Uart1Rx.RxData;   //接收数据转存
	
		if(Uart1Rx.RxDataCnt > RX_BUFFER_SIZE) 
		{
			memset(Uart1Rx.RxBuffer,0x00,sizeof(Uart1Rx.RxBuffer));
			Uart1Rx.RxDataCnt = 0;
		}
		
		if((Uart1Rx.RxBuffer[Uart1Rx.RxDataCnt - 2] == '\r' && Uart1Rx.RxBuffer[Uart1Rx.RxDataCnt - 1] == '\n')) //判断结束位
		{
			HAL_UART_Transmit(&huart1, (uint8_t *)&Uart1Rx.RxBuffer, Uart1Rx.RxDataCnt,0xFFFF); //将收到的信息发送出去
            while(HAL_UART_GetState(&huart1) == HAL_UART_STATE_BUSY_TX);//检测UART发送结束
			Uart1Rx.RxDataCnt = 0;
			memset(Uart1Rx.RxBuffer,0x00,sizeof(Uart1Rx.RxBuffer)); //清空数组
		}
	
	HAL_UART_Receive_IT(&huart1, (uint8_t *)&Uart1Rx.RxData, 1);   //再开启接收中断

	}
}
/* USER CODE END 1 */

这样子还不够,还需要在代码初始化时,先开启接收一次数据

  /* USER CODE BEGIN 2 */
	HAL_UART_Receive_IT(&huart1, (uint8_t *)&Uart1Rx.RxData, 1);
  /* USER CODE END 2 */

烧录测试


补充
1.为什么使用printf需要在编译软件中勾选Use MicroLIB?
答:MicroLIB是一个针对ARM Cortex-M系列处理器优化的C库,相比标准C库,它更适用于资源有限的嵌入式系统,提供了更高效的空间和速度性能

资源优化:MicroLIB经过优化,更适合嵌入式系统的资源限制。

重定向支持:通过MicroLIB,可以更容易地实现printf等标准输出函数的重定向,方便开发者使用这些函数输出调试信息到串口。

2.什么是重定向?
在编程中,重定向是指改变一个操作(比如输入输出)的默认行为,将其指向另一个方向或者设备。例如,将标准输出(通常是屏幕)重定向到打印机或文件。在STM32等嵌入式设备上,将printf的输出重定向到串口通讯,使得通过串口可以发送调试或其他信息到外部设备,如电脑终端。

printf通常不能直接使用来输出信息,因为标准的printf函数是用于在计算机上向终端或文件输出信息的,而微控制器一般使用串口(UART)作为与外界通信的手段。为了能够在串口上使用printf输出调试或其他信息,需要将printf重定向到串口,这就是“重定向”的含义。
 

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

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

相关文章

ElasticSearch 集群的索引别名管理

一、索引别名 &#xff08;一&#xff09;添加索引别名 1.给单个索引添加别名 POST http://10.0.0.101:9200/_aliases{"actions":[{"add":{"index":"yedu-linux85","alias":"Linux容器运维"} },{"add&q…

Xinstall赋能,H5与App完美融合,打造极致用户体验

随着移动互联网的迅猛发展&#xff0c;App已经成为我们日常生活中不可或缺的一部分。然而&#xff0c;在App推广和运营的过程中&#xff0c;推广者们常常面临着一个难题&#xff1a;如何将H5网页上的用户顺利引导至App内&#xff0c;实现用户增长和活跃度提升&#xff1f;今天&…

ShenNiusModularity项目源码学习(3:用户登录)

第一篇文章中搞错了一件事&#xff0c;ShenNiusModularity项目启动并非需要同时启动ShenNius.Admin.Mvc和ShenNius.Admin.Hosting两个项目&#xff0c;仅需启动前者即可登录后台管理系统&#xff0c;而后者是支持前后端分离的API宿主项目&#xff0c;供其它前后端分离的项目调用…

uniapp组件中的emit声明触发事件

emit解析 在 uniapp 中&#xff0c;emit 主要用于组件间通信&#xff0c;特别是在子组件需要向父组件或者其他组件发送消息的时候。具体用途包括&#xff1a; 子传父数据&#xff1a;子组件通过 $emit 触发一个事件&#xff0c;并携带参数&#xff0c;父组件监听这个事件并对参…

uniapp 封装uni.login 实现全局调用

封装utils app.vue中 使用globalData 注册 utils 页面中使用方法 定义app 调用方法

GAMES202——作业3 Screen Space Ray Tracing

任务 为场景实现屏幕空间的全局光照效果 1.直接光照&#xff1a; 实现ssrFragmentShader中的EvalDiffuse(wi, wo, uv) 和EvalDirectionalLight(uv) 函数&#xff0c;并在 main 函数中实现直接光照的效果。 2.屏幕空间光线求交&#xff1a;实现RayMarch(ori, dir, out hitPos) …

Open3D mesh 网格简化(顶点聚类)

目录 一、概述 1.1原理 1.2实现步骤 1.3应用场景 二、代码实现 2.1关键函数 2.2完整代码 三、实现效果 3.1原始mesh 3.2聚类后的mesh Open3D点云算法汇总及实战案例汇总的目录地址&#xff1a; Open3D点云算法与点云深度学习案例汇总&#xff08;长期更新&#xff0…

开源 AI 智能名片 O2O 商城小程序:引入淘汰机制,激发社交电商新活力

摘要&#xff1a;本文深入探讨在社交电商领域中&#xff0c;开源 AI 智能名片 O2O 商城小程序如何通过设置淘汰机制&#xff0c;实现“良币驱逐劣币”&#xff0c;激励士气&#xff0c;为社交电商企业注入新的活力。通过分析缺乏淘汰机制的弊端以及设置淘汰机制的优势&#xff…

sickos 靶机渗透(wolf cms 渗透,squid 代理)

靶机信息 vulnhub靶机 主机发现 192.168.50.152 为靶机Ip ┌──(kali㉿kali)-[~/testSickos] └─$ sudo nmap -sn 192.168.50.0/24 [sudo] password for kali: Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-08-30 09:56 CST Nmap scan report for 192.168.50.1 …

Linux 下查找运行中的 Java 进程及 .jar 文件位置

在 Linux 环境中&#xff0c;有时我们需要查找正在运行的 Java 进程以及它们对应的 .jar 文件位置。本文将介绍如何使用命令行工具来实现这一目标。 前言 在 Linux 系统中&#xff0c;我们经常需要监控正在运行的应用程序&#xff0c;特别是在出现问题时&#xff0c;了解应用程…

使用API有效率地管理Dynadot域名,添加账户中的联系人信息

前言 Dynadot是通过ICANN认证的域名注册商&#xff0c;自2002年成立以来&#xff0c;服务于全球108个国家和地区的客户&#xff0c;为数以万计的客户提供简洁&#xff0c;优惠&#xff0c;安全的域名注册以及管理服务。 Dynadot平台操作教程索引&#xff08;包括域名邮箱&…

Android 移除最近任务列表展示

Android 设置应用在最近任务列表不展示 android 中想要实现在最近任务列表中不展示,实现的方式很简单. 在Mainifests的MainActivity中添加: android:excludeFromRecents“true” 如下所示: <activity android:name".MainActivity"android:excludeFromRecents&…

Nvidia股价前景引投资者情绪波动:杠杆ETF数据透视市场风向

一、Nvidia业绩前瞻&#xff1a;看跌情绪升温 随着Nvidia&#xff08;NVDA&#xff09;季度业绩发布日的临近&#xff0c;市场中的投资者情绪似乎正经历着微妙的变化。据多家发行杠杆型交易所交易基金&#xff08;ETF&#xff09;的机构数据显示&#xff0c;投资者对看跌Nvidia…

【机器学习】支持向量机(SVM)的对偶性、核方法以及核技巧

引言 在SVM中&#xff0c;通过引入拉格朗日乘子&#xff0c;可以将原始问题转化为对偶问题&#xff0c;这种转换具有几个重要的优点&#xff0c;包括简化计算和提供更直观的优化问题的解释 文章目录 引言一、支持向量机&#xff08;SVM&#xff09;的对偶性1.1 原始问题&#x…

【知识库系列】MPR/多模态方向观察:图像视频与3D生成

多模态背后的backbone会长成什么样&#xff1f; 各种模态到梯度下降到最后会不会都差不多&#xff1f; Sora 是不是已经被追上了? 我们真的把视频数据都用好了吗&#xff1f; 知识库完整文档&#xff1a; MPR/多模态方向观察&#xff1a;图像视频与3D生成&#xff1a;https…

【Unity3D优化】优化内置shader的内存占用

一、性能分析 监控项目线上的崩溃情况&#xff0c;绝大多数崩溃都是因为低端设备&#xff0c;运行时内存不足&#xff0c;在运行过程中申请开辟新的内存时Crash了。因此&#xff0c;不定期继续优化内存占用。 性能分析首先主要靠Unity3d的Memory Profiler监控一些可追踪到的内存…

初识redis:学习Java客户端

Redis服务器在官网公开了使用的协议&#xff0c;叫做RESP。任何一个第三方都可以通过上述的协议&#xff0c;来实现出一个和redis服务器通信的客户端程序。 Java生态中&#xff0c;封装好了RESP协议&#xff0c;实现的redis客户端是有很多的&#xff0c;此处使用的是jedis&…

操作系统:实验三进程间通信实验

一、实验目的 1、了解什么是信号。 2、熟悉LINUX系统中进程之间软中断通信的基本原理。 3、理解进程的同步关系。 4、掌握用信号实现进程间的同步操作。 5、了解什么是管道。 6、熟悉UNIX/LINUX支持的管道通信方式。 二、实验内容 1、阅读下列程序&#xff0c;执行程序…

【js逆向专题】1.js语法基础

小节目标: 逆向工具准备熟悉 逆向的基本过程熟悉 JavaScript语法 一.前期准备 1. 技术准备 python基础语法爬虫基础功底JavaScript基础语法知识(可以自己偷偷的学习一些) 2. 工具准备 node解释器 官网地址:https://nodejs.org/zh-cn (推荐安装版本16版本) 把提供的软件…

网络层 IV(ARP、DHCP、ICMP)【★★★★★★】

&#xff08;★★&#xff09;代表非常重要的知识点&#xff0c;&#xff08;★&#xff09;代表重要的知识点。 一、地址解析协议&#xff08;ARP&#xff09;&#xff08;★★&#xff09; 在局域网中&#xff0c;由于硬件地址已固化在网卡上的 ROM 中&#xff0c;因此常常将…