想了很久,不知道该标题起的是否合适,该篇Blog用于记录在使用HAL库的USART模块时实际遇到的一个涉及发送方式的问题,用于提醒自身同时也希望能帮到各位。

程序问题叙述

         先来看一段代码:

void CusUSART_SendByte_IT( uint8_t Byte )
{  while((husart1.State != HAL_USART_STATE_READY));HAL_USART_Transmit_IT(&husart1, &Byte, 1);
}void test_task( void )
{for( ; ; ){HAL_USART_Transmit_IT(&husart1, "TEST RUNNING.\n", strlen("TEST RUNNING.\n"));vTaskDelay(1000);CusUSART_SendByte_IT( 0x42 );  // ASCII: 0x42  BvTaskDelay(1000);}
}

        上述代码展示了一个示例RTOS任务,间隔一秒向串口发送字符串"TEST RUNNING.\n",和字符'B'。理想情况下,串口接收到的数据应该如下所示:

TEST RUNNING.
B

        但将程序烧入芯片后,串口接收到的数据如下图所示:

        可以看到发送的顺序不仅出现错误,发送的字符数据也出现了错误。

原因

        在这里需要先知道HAL_USART_Transmit_ITHAL_USART_Transmit方法的本质区别.

  • HAL_USART_Transmit

本质是以阻塞方式通过 USART 发送数据。也就是说该方法会将指定的数据缓冲区中的数据通过 USART 发送出去,且CPU 会一直等待直到所有数据都发送完成才会返回。

  • HAL_USART_Transmit_IT

该方法本质是以非阻塞方式通过USART发送数据。也就是说该方法只是将缓冲区地址和大小设置好,启动USART传输后会立即返回,实际的传输由后台硬件中断完成,并不会等待USART发送完成再返回!。数据传输完成后,HAL 库会调用回调函数(HAL_USART_TxCpltCallback)通知传输完成。

        了解了两种方法的区别之后,问题就很明显了:

void CusUSART_SendByte_IT( uint8_t Byte )
{  while((husart1.State != HAL_USART_STATE_READY));HAL_USART_Transmit_IT(&husart1, &Byte, 1);
}

        在该函数中,待发送的字节 Byte局部变量,由外部传入。作为局部变量,当调用栈结束后即被销毁。当Transmit_IT方法调用后,将局部变量Byte的地址传入,将传输请求提交给后台后便返回。此时,字符 Byte 的传输并未真正开始抑或是开始了并未完成传输。而此时在HAL_USART_Transmit_IT返回后,该函数(Cus)已经结束,Byte已经被销毁。进而后台真正开始发送时,访问的地址是已经被销毁了的,自然发送的就是错误数据。

        知晓问题之后,对其作如下修改:

void CusUSART_SendByte_IT( uint8_t Byte )
{  while((husart1.State != HAL_USART_STATE_READY));HAL_USART_Transmit_IT(&husart1, &Byte, 1);for(uint32_t i = 0; i < 5000; i++){ }  // 简单阻塞延时.
}

只要保证在发送完毕前变量不被销毁即可。当然这种修改方式并不好,我们做如下修改。

void CusUSART_SendByte_IT( uint8_t Byte )
{  static uint8_t temp;while((husart1.State != HAL_USART_STATE_READY));temp = Byte;HAL_USART_Transmit_IT(&husart1, &temp, 1);
}

此时,再将程序烧入,即可得到串口接收到的数据如下:

至于乱序问题,我先把初始化代码贴出:

void CusUSART_Init( uint32_t baudrate )
{.......HAL_USART_Transmit_IT(&husart1, "USART Init OK!", strlen("USART Init OK!"));
}

        在该初始化函数中,有一行关键代码HAL_USART_Transmit_IT(&husart1, "USART Init OK!", strlen("USART Init OK!"));

        初始化函数被调用后,紧接着就启动USART任务开始传输. 而初始化函数末尾使用了Transmit_IT方法发送初始化完毕信息,但是要注意!该方法是非阻塞的!当任务启动开始运行后:

void test_task( void )
{for( ; ; ){// 此处距离初始化函数中的异步IT发送方法的时间间隔太近了!HAL_USART_Transmit_IT(&husart1, "TEST RUNNING.\n", strlen("TEST RUNNING.\n"));vTaskDelay(1000);CusUSART_SendByte_IT( 0x42 );vTaskDelay(1000);}
}

  "USART Init OK!"还在发送过程中时就进入了任务中,"TEST RUNNING.\n"再次发出传输请求,但是由于后台仍在处理"USART Init OK!",因此此次传输请求便被取消了,这也是为什么会先输出B的关键原因所在!

知道了原因,那修改自然不难:

最简单的便是在问题处代码前直接加入延时。

vTaskDelay(1000);HAL_USART_Transmit_IT(&husart1, "TEST RUNNING.\n", strlen("TEST RUNNING.\n"));

亦或是在提交发送请求后进行检查

void test_task( void )
{for( ; ; ){while(HAL_USART_Transmit_IT(&husart1, (uint8_t *)"TEST RUNNING.\n", strlen("TEST RUNNING.\n")) != HAL_OK){vTaskDelay(1);}vTaskDelay(1000);CusUSART_SendByte_IT( 0x42 );vTaskDelay(1000);}
}

 只要前后留出一定的时间裕度即可。运行结果如下:

     

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

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

相关文章

CUDA默认流的同步行为

默认流 对于需要指定 cudaStream_t参数的 cuda API&#xff0c;如果将 0作为实参传入&#xff0c;则视为使用默认流&#xff1b;对于不需要指定 cudaStream_t参数的 cuda API&#xff0c;则也视为使用默认流。 在 cuda中&#xff0c;默认流有两种类型&#xff0c;一种是 legacy…

「数据获取」《中国电力统计年鉴》(1993-2024)(含中国电力年鉴)

01、数据简介一、《中国电力统计年鉴》作为全面系统反映中国电力领域发展状况的权威性年度统计资料&#xff0c;涵盖了电力建设、生产、消费及供需等全链条关键信息。其编制工作有着深厚的历史积淀&#xff0c;可追溯至 20 世纪 50 年代&#xff0c;历经数十年的积累与完善&…

《AI大模型应知应会100篇》第68篇:移动应用中的大模型功能开发 —— 用 React Native 打造你的语音笔记摘要 App

&#x1f4f1; 第68篇&#xff1a;移动应用中的大模型功能开发 —— 用 React Native 打造你的语音笔记摘要 App &#x1f3af; 核心目标&#xff1a;零门槛集成大模型&#xff0c;5步开发跨平台智能功能 &#x1f9e9; 适用人群&#xff1a;前端开发者、产品经理、独立开发者 …

FPGA ad9248驱动

ad9248的最高时钟频率65mhz&#xff0c;采用cmos3.3v电压的并行io接口&#xff0c;做成电子模块后一般为双通道adc&#xff0c;有两个对外输出时钟cha_clk与chb_clk&#xff0c;一个并行输入端口&#xff0c;14分辨率的ddr_data&#xff0c;其模块逻辑如下&#xff0c;首先向ad…

Spring MVC 处理请求的流程

Spring MVC 处理请求的流程流程步骤详解第1步&#xff1a;发起请求 (HTTP Request)第2步&#xff1a;映射处理器 (Handler Mapping)第3步&#xff1a;获取适配器 (Handler Adapter)第4步&#xff1a;执行拦截器前置处理 (Interceptors - preHandle)第5步&#xff1a;真正调用处…

敏捷scrum管理实战经验总结

1.敏捷 敏捷的构成 敏捷由实践来源、应用场景、组织文化、领导力、团队、需求、管理、技术、质量、度量、交付、过程改进、大型项目组合管理以及受监管行业中的敏捷等构成 敏捷开发的特点 短发布周期小批量的方式、开展从需求到实现的开发工作高层级的预先规划结合详细的即时规…

南科大适应、协同与规划的完美融合!P³:迈向多功能的具身智能体

作者&#xff1a;Shengli Zhou1^{1}1, Xiangchen Wang1^{1}1, Jinrui Zhang1^{1}1, Ruozai Tian2^{2}2, Rongtao Xu2,3^{2,3}2,3, Feng Zheng1,2^{1,2}1,2单位&#xff1a;1^{1}1南方科技大学&#xff0c;2^{2}2时空智能&#xff0c;3^{3}3穆罕默德本扎耶德人工智能大学论文标题…

自动化流水线

import React, { useState, useEffect } from ‘react’; import { ChevronRight, CheckCircle, Circle, AlertCircle, Clock, Play, Pause, Settings, Code, Server, Shield, Database, Globe, Zap, FileText, Users, GitBranch, Package, Monitor, ChevronDown } from ‘luci…

【高等数学】第十一章 曲线积分与曲面积分——第三节 格林公式及其应用

上一节&#xff1a;【高等数学】第十一章 曲线积分与曲面积分——第二节 对坐标的曲线积分 总目录&#xff1a;【高等数学】 目录 文章目录1. 格林公式2. 平面上曲线积分与路径无关的条件3. 二元函数的全微分求积4. 曲线积分的基本定理1. 格林公式 单连通与复连通区域 设 DDD …

Boost电路:平均状态空间建模

电路特征介绍如图所示是一个非理想情况下的boost电路&#xff0c;其中L1L_{1}L1​和RL1R_{L1}RL1​是分别是电感和串联电阻&#xff1b;C1C_{1}C1​和RC1R_{C1}RC1​是输出电容和串联电阻&#xff1b;Q1Q_{1}Q1​是MOS管&#xff0c;其导通电阻是RonR_{on}Ron​&#xff1b;D1D…

免费网站模板/网站模板建站的优势/如何下载网站模板搭建网站?

在网站建设领域&#xff0c;“网站模板” 是降低技术门槛、提升建站效率的核心工具&#xff0c;尤其适合非专业开发者或追求低成本、快上线的需求场景。下面从定义、核心优势两方面展开详细解析&#xff0c;帮助你全面理解其价值。 一、什么是网站模板&#xff1f; 网站模板&am…

【MATLAB例程】平面上的组合导航例程,使用EKF融合IMU和GNSS数据,8维状态量和2维观测量,附代码下载链接

文章目录程序详解概述系统架构核心数学模型性能评估算法特点运行结果MATLAB源代码程序详解 概述 本代码实现基于扩展卡尔曼滤波器&#xff08;EKF&#xff09;的二维组合导航系统&#xff0c;融合IMU&#xff08;惯性测量单元&#xff09;和GNSS&#xff08;全球导航卫星系统…

react生命周期,详细版本

React 组件的生命周期分为三个阶段:挂载(Mounting)、更新(Updating) 和 卸载(Unmounting)。以下是类组件生命周期的详细说明(基于 React 16.3+ 版本): 一、挂载阶段(Mounting) 组件实例被创建并插入 DOM 时的流程: constructor(props) ○ 用途:初始化状态(this…

腾讯最新开源HunyuanVideo-Foley本地部署教程:端到端TV2A框架,REPA策略+MMDiT架构,重新定义视频音效新SOTA!

一、模型介绍HunyuanVideo-Foley 是腾讯混元团队在2025年8月底开源的一款端到端视频音效生成模型。它旨在解决AI生成视频“有画无声”的痛点&#xff0c;通过输入视频和文本描述&#xff0c;就能自动生成电影级别的同步音效&#xff0c;显著提升视频的沉浸感。它是专为视频内容…

计算机原理(二)

计算机原理系列 欢迎大家关注「海拉鲁知识大陆」 多交流不迷路 计算机原理&#xff08;一&#xff09; 继续上一篇计算机原理&#xff08;一&#xff09;深入了解程序执行部分&#xff0c;进一步说说程序在冯诺依曼模型上如何执行。如果没有了解的童鞋可以查看我上一篇文章。…

【设计模式】 工厂方法模式

系列文章目录 文章目录系列文章目录需要了解工厂制造细节吗&#xff1f;简单工厂模式实现工厂方法模式的实现简单方法&#xff1f; 工厂方法&#xff1f;总结需要了解工厂制造细节吗&#xff1f; 我们在前面的文章中为大家介绍了简单工厂模式&#xff0c;我们知道 简单工厂模式…

详解 Java 中的 CopyOnWriteArrayList

目录 【1】CopyOnWriteArrayList 简介 【2】核心原理 1.底层数据结构 2.写时复制机制 【3】CopyOnWriteArrayList常用方法及实例 1.添加元素方法 add () 2.获取元素方法 get () 3.删除元素方法remove() 【4】优缺点分析 【5】适用场景 【6】总结 【1】CopyOnWriteAr…

新手SEO优化快速起步教程

本教程专为SEO新手设计&#xff0c;帮助您快速上手优化工作。我们将一步步带您了解基础概念&#xff0c;包括高效挖掘关键词的方法、内容优化的核心技巧&#xff0c;以及网站基础设置的关键步骤。后续还会讲解提升排名的实用策略、如何监控效果并进行调整&#xff0c;确保您能系…

Minecraft图片搜索技巧

以下是更多专注 Minecraft 内容的高质量社区平台&#xff0c;涵盖建筑展示、模组/材质分享、实机截图、艺术创作等方向&#xff0c;按类型分类整理&#xff1a;---一、国际知名综合社区平台 特点 链接 CurseForge 模组/材质/数据包第一仓库&#xff0c;作者更新快&#xff0c;支…

数学建模-非线性规划(NLP)

1-理论知识介绍应用2-基于matlab实现非线性规划1&#xff09;例1% 清除工作台和命令行 clear;clc; x0[0 0 0]; A [-1 1 -1]; b 0; [x,value] fmincon(f1,x0,A,b,[],[],[],[],nonlfun1) function f f1(x)f x(1)^2x(2)^2x(3)^28; end function [c,ceq] nonlfun1(x)c [x(1)…