stm32-hal库(5)--usart串口通信三种模式(主从通信)(关于通信失败和串口不断发送数据问题的解决)
问题:
最近发现,stm32cubemx最新版本f1系列的hal库(1.85版本)生成的hal库,其中stm32f1xx_hal_uart.c的库文件中,其串口发送接收存在一些问题:
1.没有使用 __HAL_LOCK 和 __HAL_UNLOCK 宏,锁机制。
2.pdata8bits 和 pdata16bits 未初始化为 NULL,可能会导致未定义行为。
3.在遇到超时错误时,没有恢复 huart->RxState 状态。
这样子会出现什么问题呢?
1.串口中断进不去,主机发送消息,从机无回应
2.轮询模式下,打开串口,其会不断给电脑串口发信息,直到几千几万条后溢出。
(也有可能是我没理解到位,如果知道原因的大佬,可以在评论区给点意见)
解决方法:
我将stm32cubemx的hal库版本进行了修改,改成了1.81版本,进行通信,实验成功。
步骤如下:
1.点击库管理

2.找到自己芯片库

如果你是1.85版本,如果前面框为绿色,选中然后下面点击移除就行。

点击1.81版本,进行安装。下图2框取消勾选,3框选择1.81。

其他配置和上篇文章一致:
STM32-hal库学习(4)--usart/uart通信 (单向通信)(同时显示在oled)-CSDN博客
1.轮询模式
什么是轮询模式?
轮询模式利用阻塞模式收发数据
HAL_UART_Transmit():串口发送数据,使用超时管理机制
HAL_UART_Receive(): 串口接收数据,使用超时管理机制
其用于在没有中断机制或DMA机制的情况下,主动等待并处理外设的状态变化。在轮询模式下,CPU不断地检查外设的状态寄存器,以确定是否有数据可供处理。这种方式简单易用,但效率较低,因为CPU在等待期间不能处理其他任务。
程序:
main.c中加入
#include "stdio.h"
uint8_t RxDate[256];
因为oled函数里面没有显示hex类型函数,所以编写oled.c的hex显示函数:
void OLED_ShowHexArray(uint8_t x, uint8_t y, uint8_t *numArray, uint8_t Length, uint8_t size2, uint8_t Color_Turn)
{uint8_t i;uint8_t highNibble, lowNibble;for (i = 0; i < Length; i++){highNibble = (numArray[i] >> 4) & 0x0F;lowNibble = numArray[i] & 0x0F;// 显示高半字节if (highNibble < 10){OLED_ShowChar(x + (size2 / 2) * (2 * i), y, highNibble + '0', size2, Color_Turn);}else{OLED_ShowChar(x + (size2 / 2) * (2 * i), y, highNibble - 10 + 'A', size2, Color_Turn);}// 显示低半字节if (lowNibble < 10){OLED_ShowChar(x + (size2 / 2) * (2 * i + 1), y, lowNibble + '0', size2, Color_Turn);}else{OLED_ShowChar(x + (size2 / 2) * (2 * i + 1), y, lowNibble - 10 + 'A', size2, Color_Turn);}}
}
在oled.h加入:
void OLED_ShowHexArray(uint8_t x, uint8_t y, uint8_t *numArray, uint8_t Length, uint8_t size2, uint8_t Color_Turn);
在main.c实现轮询,
#include "string.h"
#include "stdio.h"
uint8_t RxDate[256];
unsigned int num = 0;
while(1)加入
switch(HAL_UART_Receive(&huart1, RxDate, 200, 1)){case HAL_OK:HAL_Delay(1);HAL_UART_Transmit(&huart1, RxDate, 200, 1);break;case HAL_TIMEOUT:if (huart1.RxXferCount != 200-1){HAL_UART_Transmit(&huart1, RxDate, 200-1 - huart1.RxXferCount, 1);}else{HAL_Delay(1);}break;case HAL_ERROR:// 错误处理逻辑,可以根据需要添加// 例如,重置 UART 或重新初始化huart1.RxState = HAL_UART_STATE_READY;__HAL_UNLOCK(&huart1);break;case HAL_BUSY:// 处理 UART 忙碌状态的逻辑// 可以选择等待一段时间再重试HAL_Delay(1);break;default:break;}OLED_ShowHexArray(48, 4, RxDate,1, 16, 0); // len 设置为 8,具体根据显示需求调整}
代码解释:HAL_UART_Receive接收huart1句柄的数据,RxDate,长度为200,等待时间为0xffff(也就是1)。若接收完毕,返回HAL_OK,则发送数据回电脑。
测试:


2.中断模式:
USART的中断模式是一种数据传输方式,在这种模式下,当特定事件(如接收到一个字符或发送完一个字符)发生时,会触发中断请求,中断服务程序(ISR)负责处理这些事件。使用中断模式可以提高系统效率,因为在等待数据的过程中,CPU可以执行其他任务,而不需要不断轮询USART状态。
.中断模式收发数据
HAL_UART_Transmit_IT():串口中断模式发送
HAL_UART_Receive_IT(): 串口中断模式接收
HAL_StatusTypeDef HAL_UART_Transmit_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);
这个函数的目的是启动UART传输并以非阻塞的方式发送一定数量的数据。
参数说明:中断方式的收发函数只有三个参数
第一个参数是要使用的串口句柄地址
第二个参数是发送缓冲区的首地址,用于存放要发送的数据
第三个参数是发送缓冲区长度
HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);
参数说明与发送函数类似,只是把第二个和第三个参数变为了接收缓冲区
程序:
main.c加入
uint8_t TxDate[64], RxDate[64];
uint8_t rxstate;
int main加入
HAL_UART_Receive_IT(&huart1,RxDate,1);
接收中断函数,我这里将长度设为了1,表示接收到一个字节,便接收完毕,返回一个字节,比如0x11 是一个十六进制数,表示的是一个字节(8位)数据。在计算机系统中,十六进制数 0x11 对应的二进制数是 00010001,占用一个字节的存储空间。因此,0x11 占用1个字节。
while(1)加入
if(rxstate == 1)
{rxstate = 0;HAL_UART_Transmit_IT(&huart1,TxDate,1);
}
当接收标志位为1,则表示接收完成,如果标志位为1,便发送数据
最下面加上
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{if(huart->Instance == USART1){memcpy(TxDate,RxDate,1);rxstate = 1;HAL_UART_Receive_IT(&huart1,RxDate,1);}
}
void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
{if(huart->Instance == USART1){}
}
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{if(huart->Instance == USART1){}
memcpy(TxDate, RxDate, 1);:将接收到的一个字节的数据从RxDate复制到TxDate。这里假设RxDate是接收缓冲区,TxDate是发送缓冲区。memcpy函数用于内存拷贝,将RxDate中的一个字节数据复制到TxDate中。- 拷贝完成,标志位变成1
测试:


3.DMA模式:
什么是dma模式?
DMA(Direct Memory Access,直接内存访问)是一种计算机系统中用于数据传输的机制。它允许数据在外设和内存之间直接传输,而不需要CPU的介入,从而减轻了CPU的负担,提高了数据传输的效率。
举个例子:
想象一下我们搬家的场景:你要把家里的一些东西从旧房子搬到新房子。在传统的情况下,你可能要亲自搬每一箱东西,把它们从旧房子搬到新房子。这就相当于CPU传统地处理数据传输的方式。
现在,有一支搬家队,他们专门负责搬家。你只需要告诉他们从哪里搬,搬到哪里,然后他们就会自己完成这项任务。而你可以利用这段时间去做其他事情,不需要亲自动手。这就有点类似于DMA的工作原理。
在计算机中,CPU通常会处理数据的传输工作,就像你亲自搬家一样。但有了DMA,就好比有了一支专门负责数据传输的队伍。CPU只需要告诉DMA从哪里搬,搬到哪里,然后就可以去处理其他任务了。DMA负责在外设和内存之间直接传输数据,而不需要CPU一直参与。
简而言之,DMA就像是一支搬家队伍,负责在不需要CPU亲自操劳的情况下完成数据传输任务,从而提高了系统的效率。
DMA模式的优势
- 效率高:DMA能够以较高的效率传输数据,因为传输过程不需要经过CPU。
- 释放CPU资源:在数据传输过程中,CPU可以执行其他任务,避免了CPU因数据传输而被阻塞。
- 传输速度快:由于DMA控制器专门用于数据传输,其速度通常比通过CPU进行传输要快。
DMA模式的工作原理
- 配置DMA控制器:在使用DMA模式之前,需要配置DMA控制器,包括源地址、目的地址、传输数据的大小等。
- 启动DMA传输:配置完成后,启动DMA传输。DMA控制器将接管数据传输任务。
- 传输完成中断:在传输完成后,DMA控制器会生成一个中断,通知CPU传输已经完成。
DMA发送函数
HAL_StatusTypeDef HAL_UART_Transmit_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);
参数类型和中断模式发送函数相同
DMA接收函数
HAL_StatusTypeDef HAL_UART_Receive_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);
参数类型和中断模式接收函数相同
HAL_UART_Transmit_DMA();串口DMA模式发送
HAL_UART_Transmit_DMA();串口DMA模式接收
HAL_UART_DMAPause() 暂停串口DMA
HAL_UART_DMAResume();恢复串口DMA
HAL_UART_DMAStop(); 结束串口DMA
因为比较多,关于代码部分,在日后文章中将具体写一下
相关文章:
stm32-hal库(5)--usart串口通信三种模式(主从通信)(关于通信失败和串口不断发送数据问题的解决)
问题: 最近发现,stm32cubemx最新版本f1系列的hal库(1.85版本)生成的hal库,其中stm32f1xx_hal_uart.c的库文件中,其串口发送接收存在一些问题: 1.没有使用 __HAL_LOCK 和 __HAL_UNLOCK 宏&…...
一文学会LVS:概念、架构、原理、搭建过程、常用命令及实战案例
引言 随着互联网技术的飞速发展,服务器负载均衡技术变得越来越重要。LVS(Linux Virtual Server)作为一种高效的负载均衡解决方案,广泛应用于各大企业的生产环境中。本文将深入探讨LVS的概念、架构、工作原理,详细讲解其…...
[Go 微服务] Kratos 使用的简单总结
文章目录 1.Kratos 简介2.传输协议3.日志4.错误处理5.配置管理6.wire 1.Kratos 简介 Kratos并不绑定于特定的基础设施,不限定于某种注册中心,或数据库ORM等,所以您可以十分轻松地将任意库集成进项目里,与Kratos共同运作。 API -&…...
【unity实战】使用旧输入系统Input Manager 写一个 2D 平台游戏玩家控制器——包括移动、跳跃、滑墙、蹬墙跳
最终效果 文章目录 最终效果素材下载人物环境 简单绘制环境角色移动跳跃视差和摄像机跟随效果奔跑动画切换跳跃动画,跳跃次数限制角色添加2d物理材质,防止角色粘在墙上如果角色移动时背景出现黑线条方法一方法二 墙壁滑行实现角色滑墙不可以通过移动离开…...
【实战】EasyExcel实现百万级数据导入导出
文章目录 前言技术积累实战演示实现思路模拟代码测试结果 前言 最近接到一个百万级excel数据导入导出的需求,大概就是我们在进行公众号API群发的时候,需要支持500w以上的openid进行群发,并且可以提供发送openid数据的导出功能。可能有的同学…...
Graalvm配置文件与Feature和Substitute机制介绍
GraalVM介绍 GraalVM提前将Java应用程序编译成独立与机器码二进制文件(可执行文件、动态库文件),如windows系统中的exe文件和dll文件。与在Java虚拟机(JVM)上运行的应用程序相比,这些二进制文件更小,启动速…...
Appium adb 获取appActivity
方法一(最简单有效的方法) 通过cmd命令,前提是先打开手机中你要获取包名的APP adb devices -l 获取连接设备详细信息 adb shell dumpsys activity | grep mFocusedActivity 有时获取到的不是真实的Activity 方法二 adb shell monkey -p …...
调整分区失败致盘无法访问:深度解析与数据恢复全攻略
调整分区失败盘打不开的困境 在计算机的日常维护与管理中,调整磁盘分区是常见的操作之一,旨在优化存储空间布局、提升系统性能或满足特定应用需求。然而,当这一操作未能如预期般顺利进行,反而导致分区调整失败,进而使…...
试用笔记之-汇通计算机等级考试软件一级Windows
首先下载汇通计算机等级考试软件一级Windows http://www.htsoft.com.cn/download/htwork.rar...
Java的NIO体系
目录 NIO1、操作系统级别下的IO模型有哪些?2、Java语言下的IO模型有哪些?3、Java的NIO应用场景?相比于IO的优势在哪?4、Java的IO、NIO、AIO 操作文件读写5、NIO的核心类 :Buffer(缓冲区)、Channelÿ…...
自下而上的选股与自上而下的选股
一起学习了《战胜华尔街》,不知道大家有没有这么一种感受:林奇的选股方法是典型的自下而上的选股方法。虽然这一点没有单独拎出来讨论过,但在《从低迷中寻找卓越》《如何通过财务指标筛选股票?》《边逛街边选股?》《好…...
Tech Talk:智能电视eMMC存储的五问五答
智能电视作为搭载操作系统的综合影音载体,以稳步扩大的市场规模走入越来越多的家庭,成为人们生活娱乐的重要组成部分。存储部件是智能电视不可或缺的组成部分,用于保存操作系统、应用程序、多媒体文件和用户数据等信息。智能电视使用eMMC作为…...
scikit-learn教程
scikit-learn(通常简称为sklearn)是Python中最受欢迎的机器学习库之一,它提供了各种监督和非监督学习算法的实现。下面是一个基本的教程,涵盖如何使用sklearn进行数据预处理、模型训练和评估。 1. 安装和导入包 首先确保安装了…...
CentOS 7 搭建rsyslog日志服务器
CentOS 7 搭建rsyslog日志服务器 前言一、IP地址及主机名称规划1.修改主机名 二、配置rsyslog日志服务器1.安装rsyslog服务2.编辑/etc/rsyslog.conf 文件3.启动并启用rsyslog服务4.验证端口是否侦听 三、在rsyslog日志服务器上配置firewalld防火墙四、配置rsyslog日志客户端1.编…...
使用Spring Boot Actuator监控应用健康状态
使用Spring Boot Actuator监控应用健康状态 大家好,我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编,也是冬天不穿秋裤,天冷也要风度的程序猿!今天我们将探讨如何利用Spring Boot Actuator来监控和管理应用程序的…...
leetcode刷题:vector刷题
🔥个人主页:guoguoqiang. 🔥专栏:leetcode刷题 1.只出现一次的数字 这道题很简单,我们只需要遍历一次数组即可通过异或运算实现。(一个数与自身异或结果为0,任何数与0异或还是它本身) class Solut…...
CGI面试题及参考答案
什么是CGI?它在Web服务器与应用程序之间扮演什么角色? CGI(Common Gateway Interface) 是一种标准协议,它定义了Web服务器与运行在服务器上的外部程序(通常是脚本或应用程序)之间的通信方式。简单来说,CGI充当了一个桥梁,使得Web服务器能够将用户的请求传递给后端程序…...
论文调研_物联网漏洞检测综述
A Review of IoT Firmware Vulnerabilities and Auditing Techniques 研究背景:物联网设备在工业、消费类等各个领域得到了广泛应用,实现了更高的自动化和生产率。然而,这些连网设备的高度依赖也带来了一系列网络安全威胁,特别是…...
Java学习【IO流:深入理解与应用(上)】
Java学习【IO流:深入理解与应用(上)】 🍃1.IO流体系结构🍃2.FileOutputStream🍁2.1FileOutputStream写数据的三种方式🍁2.2换行和续写 🍃3.FileInputStream🍁3.1每次读取…...
干货系列:SpringBoot3第三方接口调用10种方式
环境:SpringBoot.3.3.0 1、简介 在项目中调用第三方接口是日常开发中非常常见的。调用方式的选择通常遵循公司既定的技术栈和架构规范,以确保项目的一致性和可维护性。无论是RESTful API调用、Feign声明式HTTP客户端、Apache HttpClient等调用方式&…...
UE5 学习系列(二)用户操作界面及介绍
这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…...
conda相比python好处
Conda 作为 Python 的环境和包管理工具,相比原生 Python 生态(如 pip 虚拟环境)有许多独特优势,尤其在多项目管理、依赖处理和跨平台兼容性等方面表现更优。以下是 Conda 的核心好处: 一、一站式环境管理:…...
线程同步:确保多线程程序的安全与高效!
全文目录: 开篇语前序前言第一部分:线程同步的概念与问题1.1 线程同步的概念1.2 线程同步的问题1.3 线程同步的解决方案 第二部分:synchronized关键字的使用2.1 使用 synchronized修饰方法2.2 使用 synchronized修饰代码块 第三部分ÿ…...
SpringBoot+uniapp 的 Champion 俱乐部微信小程序设计与实现,论文初版实现
摘要 本论文旨在设计并实现基于 SpringBoot 和 uniapp 的 Champion 俱乐部微信小程序,以满足俱乐部线上活动推广、会员管理、社交互动等需求。通过 SpringBoot 搭建后端服务,提供稳定高效的数据处理与业务逻辑支持;利用 uniapp 实现跨平台前…...
BCS 2025|百度副总裁陈洋:智能体在安全领域的应用实践
6月5日,2025全球数字经济大会数字安全主论坛暨北京网络安全大会在国家会议中心隆重开幕。百度副总裁陈洋受邀出席,并作《智能体在安全领域的应用实践》主题演讲,分享了在智能体在安全领域的突破性实践。他指出,百度通过将安全能力…...
Python基于历史模拟方法实现投资组合风险管理的VaR与ES模型项目实战
说明:这是一个机器学习实战项目(附带数据代码文档),如需数据代码文档可以直接到文章最后关注获取。 1.项目背景 在金融市场日益复杂和波动加剧的背景下,风险管理成为金融机构和个人投资者关注的核心议题之一。VaR&…...
免费PDF转图片工具
免费PDF转图片工具 一款简单易用的PDF转图片工具,可以将PDF文件快速转换为高质量PNG图片。无需安装复杂的软件,也不需要在线上传文件,保护您的隐私。 工具截图 主要特点 🚀 快速转换:本地转换,无需等待上…...
[ACTF2020 新生赛]Include 1(php://filter伪协议)
题目 做法 启动靶机,点进去 点进去 查看URL,有 ?fileflag.php说明存在文件包含,原理是php://filter 协议 当它与包含函数结合时,php://filter流会被当作php文件执行。 用php://filter加编码,能让PHP把文件内容…...
Golang——9、反射和文件操作
反射和文件操作 1、反射1.1、reflect.TypeOf()获取任意值的类型对象1.2、reflect.ValueOf()1.3、结构体反射 2、文件操作2.1、os.Open()打开文件2.2、方式一:使用Read()读取文件2.3、方式二:bufio读取文件2.4、方式三:os.ReadFile读取2.5、写…...
Python环境安装与虚拟环境配置详解
本文档旨在为Python开发者提供一站式的环境安装与虚拟环境配置指南,适用于Windows、macOS和Linux系统。无论你是初学者还是有经验的开发者,都能在此找到适合自己的环境搭建方法和常见问题的解决方案。 快速开始 一分钟快速安装与虚拟环境配置 # macOS/…...
