【STM32單片機】#10.5 串口數據包

主要參考學習資料:

B站@江協科技

STM32入門教程-2023版 細致講解 中文字幕

開發資料下載鏈接:https://pan.baidu.com/s/1h_UjuQKDX9IpP-U1Effbsw?pwd=dspb

單片機套裝:STM32F103C8T6開發板單片機C6T6核心板 實驗板最小系統板套件科協

實驗:

  • 串口收發HEX數據包
  • 串口收發文本數據包

目錄

  • 數據包
    • HEX數據包
    • 文本數據包
  • 數據包收發流程
    • HEX數據包
    • 文本數據包
  • 實驗22 串口收發HEX數據包
    • 接線圖
    • Serial驅動
    • 主程序
  • 實驗23 串口收發文本數據包
    • 接線圖
    • Serial驅動
    • 主程序

數據包

數據包的作用是進行多字節的數據通信,將屬于同一批的數據進行打包和分割,以便接收方識別。打包和分割的方法可以自行設計。

HEX數據包

HEX數據包直接傳輸十六進制數據,本實驗規定使用FF作為包頭、FE作為包尾的方式打包和分割數據包。

針對包頭包尾和載荷數據重復的問題,一種解決方法是限制載荷數據的范圍,在發送時對數據進行限幅,使其不會重復;第二種方法是盡量使用固定長度的數據包,只要通過包頭包尾對齊了數據,就可以嚴格知道哪個數據時包頭包尾,哪個數據是載荷數據;第三種方法是增加包頭包尾的數量,并讓盡量使用載荷數據不會出現的狀態,例如用FF、FE作為包頭,FD、FC作為包尾。

包頭和包尾并非都需要,可以只保留包頭,刪除包尾,但載荷與包頭重復的問題也會更嚴重。

文本數據包

在文本數據包中,每個字節經過了一層編碼和譯碼,以文本格式表現。字符在包頭包尾的選擇中可以有效避免與載荷數據重復的問題,本實驗規定以@作為包頭,以換行字符\r\n作為包尾。載荷數據接收為字符串,軟件通過對字符串判斷和操作可以實現各種指令控制功能。

HEX數據包的優點是傳輸直接,解析簡單,適合陀螺儀、傳感器等模塊發送原始數據,缺點是靈活性不足,載荷容易和包頭包尾重復。文本數據包的優點是數據直觀易理解,非常靈活,適合通過指令進行人機交互的場合,缺點是解析效率低。

數據包收發流程

數據包發送的過程很簡單,只需定義數組,填充數據并發送。此處主要介紹接收流程。

HEX數據包

在接收數據中,針對包頭、數據載荷和包尾三種狀態需要不同的處理邏輯,因此我們使用狀態機思維設計程序,通過一個能記住不同狀態的機制,在不同狀態執行不同的操作,同時還要進行狀態的合理轉移。上圖為接收固定包長含包頭包尾的HEX數據包的狀態轉移圖,變量S標志不同的狀態,在滿足相應的條件時跟隨箭頭方向轉移。

文本數據包

實驗22 串口收發HEX數據包

接線圖

Serial驅動

在實驗21的基礎上更改。

Serial.h

#ifndef __SERIAL_H
#define __SERIAL_H#include <stdio.h>//允許外部調用發送和接收數據包
extern uint8_t Serial_TxPacket[];
extern uint8_t Serial_RxPacket[];void Serial_Init(void);
void Serial_SendByte(uint8_t Byte);
void Serial_SendArray(uint8_t *Array, uint16_t Length);
void Serial_SendString(char *String);
void Serial_SendNumber(uint32_t Number, uint8_t Length);
void Serial_Printf(char *format, ...);
void Serial_SendPacket(void);
uint8_t Serial_GetRxFlag(void);#endif

Serial.c

只展示更改部分:

//在驅動中暫存接受數據包
uint8_t Serial_TxPacket[4];
uint8_t Serial_RxPacket[4];
uint8_t Serial_RxFlag;//新增發送數據包函數
void Serial_SendPacket(void)
{//發送包頭Serial_SendByte(0xFF);//發送數據載荷Serial_SendArray(Serial_TxPacket, 4);//發送包尾Serial_SendByte(0xFE);
}//刪去Serial_GetRxData函數
//更改中斷函數
void USART1_IRQHandler(void)
{//狀態變量static uint8_t RxState = 0;//指示數據接收到第幾個static uint8_t pRxPacket = 0;if(USART_GetITStatus(USART1, USART_IT_RXNE)){//接收單個字節uint8_t RxData = USART_ReceiveData(USART1);//根據狀態不同進入不同的處理程序switch(RxState){//等待包頭case 0://收到包頭轉移狀態if(RxData == 0xFF)RxState = 1;break;//接收數據case 1:Serial_RxPacket[pRxPacket] = RxData;pRxPacket ++;//接收滿4個數據if(pRxPacket >= 4){RxState = 2;pRxPacket = 0;}break;//等待包尾case 2://收到包尾if(RxData == 0xFE){RxState = 0;//置接收標志位Serial_RxFlag = 1;}break;}USART_ClearITPendingBit(USART1, USART_IT_RXNE);}
}

主程序

#include "stm32f10x.h" 
#include "Delay.h"
#include "OLED.h"
#include "Serial.h"
#include "Key.h"uint8_t KeyNum;int main(void)
{OLED_Init();Key_Init();Serial_Init();OLED_ShowString(1, 1, "TxPacket");OLED_ShowString(3, 1, "RxPacket");//初始化待發送數據包Serial_TxPacket[0] = 0x01;Serial_TxPacket[1] = 0x02;Serial_TxPacket[2] = 0x03;Serial_TxPacket[3] = 0x04;while(1){KeyNum = Key_GetNum();//每次按下按鍵使發送數據包加一并發送if(KeyNum){Serial_TxPacket[0] ++;Serial_TxPacket[1] ++;Serial_TxPacket[2] ++;Serial_TxPacket[3] ++;Serial_SendPacket();OLED_ShowHexNum(2, 1, Serial_TxPacket[0], 2);OLED_ShowHexNum(2, 4, Serial_TxPacket[1], 2);OLED_ShowHexNum(2, 7, Serial_TxPacket[2], 2);OLED_ShowHexNum(2, 10, Serial_TxPacket[3], 2);}//判斷標志位接收數據包if(Serial_GetRxFlag()){OLED_ShowHexNum(4, 1, Serial_RxPacket[0], 2);OLED_ShowHexNum(4, 4, Serial_RxPacket[1], 2);OLED_ShowHexNum(4, 7, Serial_RxPacket[2], 2);OLED_ShowHexNum(4, 10, Serial_RxPacket[3], 2);}	}
}

實驗23 串口收發文本數據包

實現功能:使用串口發送文本指令控制LED亮滅。

接線圖

Serial驅動

在實驗22的基礎上修改。

Serial.h

#ifndef __SERIAL_H
#define __SERIAL_H#include <stdio.h>extern char Serial_RxPacket[];
//聲明標志位為外部可調用
extern uint8_t Serial_RxFlag;void Serial_Init(void);
void Serial_SendByte(uint8_t Byte);
void Serial_SendArray(uint8_t *Array, uint16_t Length);
void Serial_SendString(char *String);
void Serial_SendNumber(uint32_t Number, uint8_t Length);
void Serial_Printf(char *format, ...);#endif

Serial.c

只展示更改部分:

//接收數據類型改為char,上限100個字符
char Serial_RxPacket[100];
uint8_t Serial_RxFlag;
//刪除發送數據包函數和獲取標志位函數
void USART1_IRQHandler(void)
{static uint8_t RxState = 0;static uint8_t pRxPacket = 0;if(USART_GetITStatus(USART1, USART_IT_RXNE)){uint8_t RxData = USART_ReceiveData(USART1);switch(RxState){case 0://更改包頭//為防止程序處理數據包不及時導致數據包錯位//需判斷接收標志位清零后再接收下一個數據包if(RxData == '@' && !Serial_RxFlag){RxState = 1;pRxPacket = 0;}break;case 1://判斷包尾是否到來if(RxData == '\r')RxState = 2;else{Serial_RxPacket[pRxPacket] = RxData;pRxPacket ++;}//無需檢測數據數量break;case 2://等待第二個包尾if(RxData == '\n'){RxState = 0;//添加字符串結束標志Serial_RxPacket[pRxPacket] = '\0';Serial_RxFlag = 1;}break;}USART_ClearITPendingBit(USART1, USART_IT_RXNE);}
}

主程序

#include "stm32f10x.h" 
#include "Delay.h"
#include "OLED.h"
#include "Serial.h"
#include "LED.h"
//判斷字符串的官方庫
#include <string.h>int main(void)
{OLED_Init();LED_Init();Serial_Init();OLED_ShowString(1, 1, "TxPacket");OLED_ShowString(3, 1, "RxPacket");while(1){if(Serial_RxFlag){//由于字符串長度不確定,需擦除顯示行再覆寫下一個字符串OLED_ShowString(4, 1, "                ");OLED_ShowString(4, 1, Serial_RxPacket);//字符串相等返回0//開燈指令if(!strcmp(Serial_RxPacket, "LED_ON")){LED1_ON();//回傳反饋Serial_SendString("LED_ON_OK\r\n");OLED_ShowString(2, 1, "                ");OLED_ShowString(2, 1, "LED_ON_OK");}//關燈指令else if(!strcmp(Serial_RxPacket, "LED_OFF")){LED1_OFF();Serial_SendString("LED_OFF_OK\r\n");OLED_ShowString(2, 1, "                ");OLED_ShowString(2, 1, "LED_OFF_OK");}//錯誤指令else{Serial_SendString("ERROR_COMMAND\r\n");OLED_ShowString(2, 1, "                ");OLED_ShowString(2, 1, "ERROR_COMMAND");				}//清空標志位Serial_RxFlag = 0;}}
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/77610.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/77610.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/77610.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

百度暑期實習崗位超3000個,AI相關崗位占比87%,近嶼智能攜AIGC課程加速人才輸出

今年3月&#xff0c;百度重磅發布3000暑期實習崗位&#xff0c;聚焦大模型、機器學習、自動駕駛等AI方向的崗位比例高達87%。此次實習崗位涉及技術研發、產品策劃、專業服務、管理支持、政企解決方案等四大類別&#xff0c;覆蓋超300個崗位細分方向。值得一提的是&#xff0c;百…

vue3 + element-plus中el-dialog對話框滾動條回到頂部

對話框滾動條回到頂部 1、需要對話框顯示后 2、使用 nextTick 等待 Dom 更新完畢 3、通過開發者工具追查到滾動條對應的標簽及class“el-overlay-dialog” 4、設置屬性 scrollTop 0 或者 執行方法 scrollTo(0, 0) // 對話框顯示標識 const dialogVisible ref(false); //…

C++學習之游戲服務器開發十一DOCKER的基本使用

目錄 1.多實例部署方案 2.容器的概念 3.docker初識 4.docker倉庫 5.docker鏡像 6.docker容器 7.docker和虛擬機的區別 8.docker命令解釋 9.dockerfile構建鏡像 10.離線分發鏡像 1.多實例部署方案 redis 命令&#xff08; redis-cli XXXX &#xff09; set key value:…

2025.4.21總結

工作&#xff1a;開了一場關于大模型版本的會議&#xff0c;回歸一個問題單&#xff0c;提了兩個單&#xff0c;把用例都執行完。如今都四月中旬了&#xff0c;上班年快要結束了&#xff0c;該到了沖刺KPI的時候了。 今日思考&#xff1a;刷到了jack叔叔的視頻&#xff0c;講了…

vite安裝及使用

沒特殊要求的項目,還是怎么簡單怎么來╮(╯▽╰)╭ 一、Vite 基礎知識 1. 什么是 Vite? Vite 是一個前端構建工具,專注于開發服務器速度和優化構建過程。特點: 快速冷啟動:利用 ES 模塊的原生支持,實現快速的開發服務器啟動。即時熱更新:在開發過程中,修改代碼后可以…

ubuntu下gcc/g++安裝及不同版本切換

1. 查看當前gcc版本 $ gcc --version# 查看當前系統中已安裝版本 $ ls /usr/bin/gcc*2. 安裝新版本gcc $ sudo apt-get update# 這里以版本12為依據&#xff08;也可以通過源碼方式安裝&#xff0c;請自行Google&#xff01;&#xff09; $ sudo apt-get install -y gcc-12 g…

cdq 系列 題解

從二維數點&#xff08;二維偏序&#xff09;到三維偏序。 用 cdq 分治可以解決二維數點問題。 1.洛谷 P1908 逆序對 題意 求所有數對 ( i , j ) (i,j) (i,j) 的個數&#xff0c;滿足 i < j i<j i<j 且 a i > a j a_i>a_j ai?>aj?。 1 ≤ n ≤ 5 1…

計算機組成與體系結構:內存接口(Memory Interface)

目錄 什么是內存接口 &#xff1f; 為什么需要特別設計“接口”&#xff1f; 什么是 MIPS&#xff1f;為什么它和內存接口有關&#xff1f; 內存接口的兩種訪問方式 串行訪問&#xff08;Serial Access Model&#xff09; 并行訪問&#xff08;Parallel Access Model&…

Java面試(2025)—— Spring MVC

什么是Spring MVC Spring MVC 是 Spring 框架的一個 基于 Java 的 Web 開發模塊&#xff0c;它實現了 MVC&#xff08;Model-View-Controller&#xff09;架構模式&#xff0c;用于構建靈活、松耦合的 Web 應用程序。 它是 Spring 生態的核心組件之一&#xff0c;通過簡化 HTT…

天翼云手機斷開連接2小時關機

2025-04-21 天翼云手機斷開連接2小時自動 天翼云手機 4元1個月 天翼云手機永不關機 天翼云手機不休眠 天翼云手機斷開連接時&#xff0c;界面顯示&#xff1a;離線運行&#xff0c;2小時后自動關機 電腦每小時自動連接一次 手機每小時自動連接一次

Redis——數據結構

目錄 1.動態字符串SDS 1.1SDS底層源碼 1.2 SDS動態擴容 1.3動態字符串SDS優點 2.IntSet 2.1底層結構 2.2有序性 2.3.IntSet結構擴容 2.4總結 3.Dict 3.1底層結構 3.2.Dict擴容 3.3Dict收縮 3.4.Dict的rehash 1.分配空間 2. 設置 rehashidx 3. 漸進式 rehash…

C++ GPU并行計算開發實戰:利用CUDA/OpenCL加速粒子系統與流體模擬

&#x1f9d1; 博主簡介&#xff1a;CSDN博客專家、CSDN平臺優質創作者&#xff0c;高級開發工程師&#xff0c;數學專業&#xff0c;10年以上C/C, C#, Java等多種編程語言開發經驗&#xff0c;擁有高級工程師證書&#xff1b;擅長C/C、C#等開發語言&#xff0c;熟悉Java常用開…

LeetCode算法題(Go語言實現)_54

題目 給你兩個正整數數組 spells 和 potions &#xff0c;長度分別為 n 和 m &#xff0c;其中 spells[i] 表示第 i 個咒語的能量強度&#xff0c;potions[j] 表示第 j 瓶藥水的能量強度。 同時給你一個整數 success 。一個咒語和藥水的能量強度 相乘 如果 大于等于 success &a…

內網穿透快解析免費開放硬件集成SDK

一、行業問題 隨著物聯網技術的發展&#xff0c;符合用戶需求的智能硬件設備被廣泛的應用到各個領域&#xff0c;而智能設備的遠程運維管理也是企業用戶遇到的問題 二、快解析內網穿透解決方案 快解析是一款內網穿透產品&#xff0c;可以實現內網資源在外網訪問&#xff0c;…

Python+Word實現周報自動化的完整流程

一、技術方案概述 自動化報表解決方案基于以下技術組件&#xff1a; Python 作為核心編程語言python-docx 庫用于處理 Word 文檔pandas 庫用于數據處理和分析matplotlib 或 plotly 庫用于數據可視化Word 模版作為報表的基礎格式 這種方案的優勢在于&#xff1a;保留了 Word 文…

elastic/go-elasticsearch與olivere/elastic

在 Go 語言中&#xff0c;與 Elasticsearch 交互的客戶端庫有多種選擇&#xff0c;其中 github.com/elastic/go-elasticsearch/v8 和 github.com/olivere/elastic/v7 是兩個常用的庫。這兩個庫的功能和用途有一些差異&#xff0c;以下是它們的詳細對比&#xff1a; 1. github.c…

deepseek + kimi制作PPT

目錄 一、kimi簡介二、deepseek生成內容三、生成PPT四、編輯PPT 一、kimi簡介 kimi是一款只能ppt生成器&#xff0c;擅長將文本內容生成PPT。 在這里&#xff0c;??DeepSeek 負責內容生成與邏輯梳理??&#xff0c;??Kimi 優化表達與提供設計建議??。 二、deepseek生…

【八大排序】冒泡、直接選擇、直接插入、希爾、堆、歸并、快速、計數排序

目錄 一、排序的介紹二、排序算法的實現2.1 直接插入排序2.2 希爾排序2.3 直接選擇排序2.4 堆排序2.5 冒泡排序2.6 快速排序2.7 歸并排序2.8 比較排序算法的性能展示2.9 計數排序 個人主頁<— 數據結構專欄<— 一、排序的介紹 我們的生活中有很多排序&#xff0c;比如像…

linux 查詢目錄文件大小

? 在 Linux 系統中&#xff0c;準確地掌握目錄和文件的大小對于磁盤空間管理至關重要。?本文將詳細介紹如何使用 du&#xff08;disk usage&#xff09;命令逐層查看目錄和文件的大小&#xff0c;并結合 sort 命令對結果進行排序&#xff0c;以便有效地識別和管理占用…

如何簡單幾步使用 FFmpeg 將任何音頻轉為 MP3?

在多媒體處理領域&#xff0c;FFmpeg 以其強大的功能和靈活性而聞名。無論是視頻編輯、音頻轉換還是流媒體處理&#xff0c;它都是專業人士和技術愛好者的首選工具之一。在這篇文章中簡鹿辦公將重點介紹如何使用 FFmpeg 進行音頻格式轉換&#xff0c;提供一些常用的轉換方式&am…