串口HAL庫發送問題

????????想了很久,不知道該標題起的是否合適,該篇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.敏捷 敏捷的構成 敏捷由實踐來源、應用場景、組織文化、領導力、團隊、需求、管理、技術、質量、度量、交付、過程改進、大型項目組合管理以及受監管行業中的敏捷等構成 敏捷開發的特點 短發布周期小批量的方式、開展從需求到實現的開發工作高層級的預先規劃結合詳細的即時規…

南科大適應、協同與規劃的完美融合!P3:邁向多功能的具身智能體

作者&#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)…