




版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
1、串口接收不定長度數據及數據粘包解析的實現1、如何讓串口接收不定長度數據想讓 Stm32 串口接收不定長度數據,這就需要我們開啟串口空閑中斷( IDLE)方式, 所謂串口空閑中斷指的是stm32 的數據總線在接收數據的過程中,如果總線在接收一個字節所需要的時間內沒有再接收到數據,單片機就會判定此時數據已經接收完成了,這時單片機會自動觸發空閑中斷IDLE標志位,引發空閑中斷, 我們只需要進入中斷取數據就可以了。使用 IDLE空閑中斷我們就可以用用口接 收任意長度的數據了。2、串口接收不定長度數據的實現思路我們實現串口接收不定長度數據的思路是:首先我們要定義一個接收數據的緩沖區, 一般用數組接收數據
2、,在串口初始化時要開啟串口的空閑中斷和接收中斷。 然后在有中斷產生時,我們需要在串口中斷函數里判斷是空閑中斷還是正常接收一個字節數據引起的接收中斷,如果是正常接收字節的中斷,那么我們需要把接收到的這個字節數據存放到緩沖數組中,如果是 IDLE空閑中斷,表示串口 數據已經接收完成了,我們需要在IDEL中斷處理函數中設置一個數據接收完成 標志位表示已經完整的接收到一幀數據了,如:RecFlag=1;3、數據粘包解析的實現思路數據粘包是多個數據包發送時由于線路延時,或者發送端發送多個數據包的時間延時很小,導致幾個數據包幾乎同時到達接收端(數據包到達接收端的時間間隔小于一個字節時間),這樣單片機接收數
3、據時就會將這幾個數據包當做一幀數據來接收存放。那么我們如何將這幾個數據包合成的一幀數據拆解成幾個數據包呢?其實,實現的方法也很簡單,這就需要我們在發送端和接收端的數據格式上做一個統一的約定,約定了統一的數據發送格式在發送數據時就嚴格按照這個格式來發送。一般來說約定的格式我們要明確規定數據頭 和 數據長度 。 然后我們再根據定義的數據頭是什么數據,在這一幀數據中逐個去判斷當前數據是不是數據頭, 如果是就說明這個是一個小數據包的開始位置,在根據數據長度就可以解析出一個數據包了。例如,我們約定發送的數據格式為:數據頭(2byte) +發送者ID(1byte)+接收者ID(1byte)+ 命令碼(1b
4、yte)+ 數據長度(1byte)+CRC校驗(2byte) 。這樣我們定義了標準的數據格式就容易拆包了。4、下面我們就根據約定的數據發送格式來定義具體的數據頭,例如我們定義一個數據包命令來查詢接收命令的單片機PH值傳感器1的數據是多少。數據包定義如下:數據頭:0xAA55發送者ID: 0x01接收者ID: 0x02命令碼:0x01 查詢PH值傳感器1命令 隨意約定命令代碼0x02 響應PH查詢命令0x03 設置傳感器PH值上限命令 0x10 / 設置成功數據長度:xxCRCK驗:0xB1B5 / CRC 16 Modbus那么發送端發送的查詢數據為: aa 55 01 02 01 00 b5
5、 b1接收查詢命令響應的數據發送格式也要按照約定的數據格式發送出去:響應數據為: aa 55 02 01 02 02 00 07 12 91如此約定了數據格式,如果真的發生粘包的情況,解析數據也很方便了,我們只需要找到數據頭的標志 0xAA55,然后讀取該數據包代表數據長度的字節存 放的存儲位置,就可以得到數據長度,比如數據包:aa 55 02 01 02 02 00 07 12 91數據長度的位置就在AA這個字節之后的第五個字節,假設此時AA字節在緩沖數組的位置為 RecBufi,那么長度字節存放的位置就是RecBufi+5,取出RecBufi+5沖的數據為2,說明該字節之后有2個字節的數據
6、,再加上 CRC的2 個字節,我們就需要在RecBufi+5之后還要取出4個字節的數據,才能完整的取 出這個小數據包:aa 5502 01 02 02 00 0712 91需要注意的是我們再拆包的過程中要重復考慮其中存在的問題,比如:數據長度錯誤時的數量,找不到數據頭時循環變量的修正等。5、基于cubemx HAL庫的實現方法(1)新建cubemx工程 選擇stm32f103ze芯片(2)開啟外部高速時鐘HSE配置好系統時鐘樹28Pinout & ConfigurationClock ConfigurationAdditional Softwarev PinoutRCC Mode an
7、d ConfigurationCatgorisA->ZModsSystem Core High Sp&ed Ckcg§E/|cystal/C&ramic Resonator ”Low Speed Dock (LSE» DisableDMA Master Clock OutputIWDGNV1CRCCSYSWWDG(3)配置串口 1 ,啟用DMA傳輸,使能中斷Pinout & Configurationr marsi_cn-i:ciri:Y'CAflFSMCI2C1I2C2yuiuSPI1SPE0 SPOUART4QART2U5ART1C
8、lack ConfigurationAdd it one I softwareUSAfiTI Mod* nd C&nfisw-iofiMed自Hardman F ow Control ;RS232| Disable INC SMI in g寡CmiR厚ir金。忖 DMA Selling Parimerter SettingsDMA R把que?MCh&rin 兇USART1 RX DK1A1 Chjn SART1 TX RMA1 ChflHPinout & ConfigurationGategari-s 分工三An* ng-rr -i -ComKliuily vCATJ
9、I2C1i?C2 &UIJ&PI15PI20 SPI3UARTJUART6LJSART1Pr7 Pl no i it GPIO SMtirg Usct ConstartsDireclionPiioriiyPcripflral To LewM*mnr Ta LowClock Cen figurationAddt c na SoftwareUSART1 Mude drid CorfiJUMt ullLindeModo |Asynchrano4JtHadvrar- Fl 談 Corflrcl (R52321fisse: Conffluralicn7 PinoutConfiqu舊 tM
10、 NV1C g.ling, 匚 I心,中 iig,# Paramstar Saltings: G PIC £旦小叫金 User Corsi:antsI4VIG Interrupt 丁日用甘I Qnau ed| Preempt oiPn onlyI'iMM -h innp|4 giohn irterrurflDLIA1 _h inolfi glnbfl m忡 rniptUSART1 gluhml1r印DMA接收配置成循環模式,數據位寬默認為8位DMA發送配置成正常模式,數據位寬默認為8位DMA Rsequ電好ChannelDirectionPriorityUSART1_RXDM
11、A1 Chamel 5Peripheial To MernoiyLawggAkH 1 0DMA1 Channel 4Memory To PenpheralLow l_h,r Const;nU NVT ,tlinjc GPID Settings DMA SeltingsDoIgt。ProjectCode GeneratorPyctCoce Generator(4)設置好工程名稱和保存位置,選擇自己用的開發工具和版本,然后生成工程代碼就可 以開始編寫我們自己的代碼了。Project SettingsProject MameRgueive nariable length dataProject Lo
12、cationC:Us erss & ntyD es kt&pcu brrucUjfiartApplication StructureBasic7 Do not generateToolchain Folder LocationC. U s ei與s e niy'D 6名 kt upkcu be rrixtu 壽總 rtlR t ue iy/ vaH abl e I en gt h d at n tToolchain / IDEMin VersionMDK-ARM7V576TM32Cube MCU packages anc embedded software packsC
13、opy all used libraries into the aroject folder® Copy unly the messary libidry file、O Add nec&ssa7 library fil&s as reference in the toolchain prcjed configuratjon file(Generated filesn Generate peripheral inicializioi as s pjir ofF c '' h' iiles par peripheral tJankup previo
14、usly genarstec tiles when re-generatingH Kfifrp User Cn when re-OPirating Deleie previously generated Iles when ncrt re-generated6、我們先看結果首先,我們先測試單個命令發送(沒有粘包)命令 1:查詢 PH 指令 aa 55 01 02 01 00 b5 bl收到查詢指令后,進行解析然后執行查詢命令,向主機返回 PH數據【返回數據】:aa 55 02 01 02 02 00 07 12 91 /返回PH值等于7|ft>, SSCOM V5J3,1生匚/網堵耍調記
15、;器作者大蝦J丁,2818058*通-三誤匚高口設置發送第字符W小工具都助質至忤者aPCB打串壽至每款5元腹聿色r可若雜色!【苕立創言網1 自解析第th包包據魚溫5【勤提頭正痛1工數據 1 : ai 6E 01 oe 01 00 t£ hi口距完成由靖麗-.1第髀據感器li送回:aa 55 02 01 02 02 DO 07 12 01翡蔻出口打開文件1發送文件1僖止著發射第字節4修關田串口(5更多串口設置r HEM顯示 保存數據搔收敏據到文件F HEJI發送I加時i颼和分包顯示印一M端口號1加1 USB-SERIAL CH34O球 55 01 口2 Q1 叩 15 blr RTS
16、r DTR 波恃率.11520U發送為了更好地發展居卬瞰件 請您注冊高立創晞尾客戶E升級到型CMT3】 PCE打樣降至每款6元"兔顏色費,咂豐包哪!提洪揖壩撈腓務口 *RT-TL | www, da J S:8R:22& COM 11 EfTTF 115200bps,8.1 ,NorePMone命令2:設置PH值上限指令 aa 55 01 02 03 02 00 0b 57 5b 設置PH上限為 11【返回數據】:aa 55 02 01 10 00 49 a5 /返回設置成功指令 0x10像558M V5J3J串口福轆庵調試器作者龍門1洞505昵斗” X通風諄口 串匚設置顯示
17、發送篆字符串小工具萍助聯系作杳A PCB打樣降至每款5元版三包吃可造雜色【矗立第官網】第03包隨- ! aaEE 頭正確1匚山龍后】:am 55 01 睥 C3 02 OO 0S 5? 51童感春I FK上限命會 觸凄眼 曲切口n力, 據】;aa 55 0E 0110nn發送文件停止II君發法e端口號|cmu VSB-SERIAL 出口 三I卷關曲器口 金盾多國口設置Ir RTS r DTR 波特率 I I M 二應工顯示 保存數據I廠楂收數指到文件F HEX發送I 廠加時間福和分包顯示.一所帚丁字節 aa 55 01 02 03 02 00 0L 57 5l為了更好地發展對珈軟件請您注冊嘉立
18、創F結尾客戶t升鼓至IJSSCONE 13.1 *FN打樣降至得款5元,免顏色費,順豐包郵!提供加貼片服考女RTThr S門。R:249 COM11 Kiff IISSOabpsl,None.None接下來,我們測試一下數據粘包的情況我們把之前的2個命令合在一起發送出去,紅色數據用來模擬有干擾的情況下,數據出錯了。a2 55 aa 55 01 02 01 00 b5 bl 32 15 8e 20 aa 55 01 02 03 02 00 0b 57 5b 68 21 結果如下:在串口收到這一幀數據后,調用拆包函數進行數據解析,按照數據頭逐個進行比較只要找到正確的數據頭,就按照約定的數據長度去取
19、數據,取到一個小包數據后進行 CRC校驗,校驗正確后才執行命令。第一個小包執行完成后接著去取下一個包,然后執行,直到把接收到的數據解析并執行完成。供 ££COM V5,13.1 空口福電期-能晶,惜:FTT.26做公則ee QQ蝌 S2M244g(HK. 匚 乂通訊口壬口漫皆顯示轆步手尋車小工具褶助既索忤吉上空口打博降至恒款5元哽工怛的可送京日.京文創官網】 一:-l-ul.;3215 :155as £應 :SQs ;歸駐而 頭正靦】np n? rw r? u si_經歷 01 02 03 OS 00 8 E7 協L5L恢覽止贓.J【新國汽成】話肆芾口打開文件|疾
20、法文件1停止1清發送區I廠最前Eng周 保存多制端口 Mjcwu 於l-iKI/Le厘口 - -關詡*口5尸口制r RTS r DTH 菽特率:plSZOD3 為了用好地送臍雙喃;件inF-sni 清里手腌立創rw用客。I回山Ir ieiie ,好m據一 部璉t鯉要件p回垢這匚典回泊 可 所 字節至怎二1拉松噎百加肥11謔制分包顯力.一互1 E*I 2 版 |" icn-ii055 叫囂 6 配C1。口 L£ ld|非IS . 00,田01無 必0由(口吟E7八603E那哥SHggi改用樣陣至席而,免顫國壽II肝包副提供如網日膀4 *RLmq由自中國&冊原憑器研用物
21、和Rt&a7COM11m打開115200bp加川吁忖口便中斷接收方式:采用中斷方式,只需要在宏定義#define UsartDMA 0/1配置成0就可以了,數據處理結果跟用DMA方式一樣,這里不再貼圖。7、代碼實現(1)編寫 myusart.h文件在myusart.h文件中我們主要定義串口數據接收的結構體類型#ifndef _MYUSART_H_#define _MYUSART_H_#include "main.h"#include "usart.h"#include "string.h"#include "stdi
22、o.h"#define UsartBufSize 512#define UsartDMA 1 / 是否啟用串口DMA 1 啟用 0 停止typedef struct uint8_t *ReadPtr;uint8_t RecFlag;uint8_t ProFinsh;/ 讀書節指針 / 接收標志 / 數據處理完成標志/ 數據緩沖區uint16_t InAllLen;uint16_t CFraLen;uint16_t ReadNBytes;UART_HandleTypeDef *huart;/ 緩沖區存放數據長度/ 當前幀長度最近接受的幀長度/ 需要讀取的字節數/串口號uint8_t R
23、ecBufUsartBufSize; NetDat_TypeDef;void NetDateRec(NetDat_TypeDef *NetDat);void My_Usart_Init(UART_HandleTypeDef *huart,NetDat_TypeDef *NetDat);#endif(2)編寫 myusart.c文件#include "myusart.h"#include "netdatpro.h"uint16_t temp,lastTemp=0;extern UART_HandleTypeDef huart1;extern DMA_Han
24、dleTypeDef hdma_usart1_rx;extern DMA_HandleTypeDef hdma_usart1_tx;NetDat_TypeDef Usart1_NetDate;/ 重定向 c 庫函數 printf 到 USARTxstruct _FILE /標準庫需要的支持函數int handle;int fputc(int ch, FILE *f) while(huart1.Instance->SR&0X40)=0);/ 循環發送,直到發送完畢huart1.Instance->DR = (uint8_t)ch ;return (ch);/ 網絡數據接收函數
25、void NetDateRec(NetDat_TypeDef *NetDat)#if UsartDMA = Enable/ static uint16_t temp=0,lastTemp=0;if(_HAL_UART_GET_FLAG(NetDat->huart,UART_FLAG_IDLE)處測是否有 IDE 中斷 NetDat->RecFlag = 1;/ 接受完成標志位置1/ HAL_UART_DMAStop(NetDat->huart);/ 停止 DMA 接收, 每次來新數據時都會從緩存 起始地址開始存放lastTemp=temp;temp = hdma_usart1
26、_rx.Instance->CNDTR;/ 獲取 DMA 中未傳輸的數據個數,NDTR寄存器分析見下面if(lastTemp=0&&temp=sizeof(NetDat->RecBuf)|lastTemp=temp)/lastTemp=temp 前 2 次都是一次接滿緩沖區NetDat->CFraLen=sizeof (NetDat->RecBuf);else if(lastTemp=0)/ 首次進入NetDat->CFraLen=sizeof (NetDat->RecBuf) - temp;/ 計算當前接收的幀長度elseNetDat-&g
27、t;CFraLen=lastTemp - temp;/ 計算當前接收的幀長度if(NetDat->CFraLen>sizeof (NetDat->RecBuf)/ 數據從緩沖區溢出NetDat->CFraLen=lastTemp+sizeof (NetDat->RecBuf)-temp;/ 有溢出了修正接收到的字節數 if(temp!=sizeof (NetDat->RecBuf)/ 緩存沒滿滿的時候temp 等于緩沖區大小NetDat->InAllLen =sizeof (NetDat->RecBuf) - temp;/ 總計數減去未傳輸的數據
28、個數, 得到已經接收的數據個數 elseNetDat->InAllLen =sizeof (NetDat->RecBuf);/ 緩存剛好滿時修正總數為緩存大小NetDat->ReadNBytes=NetDat->InAllLen;/ 計算需要讀取的字節數if(NetDat->InAllLen < NetDat->CFraLen)/ 接收總長度小于當前幀長度時緩沖區溢出NetDat->ReadNBytes=NetDat->InAllLen + sizeof (NetDat->RecBuf);/ 修正要需要讀取 的字節數HAL_UART_
29、Receive_DMA(NetDat->huart,NetDat->RecBuf,sizeof(NetDat->RecBuf);/ 開 啟 DMA 接收NetDat->ProFinsh=0;_HAL_UART_CLEAR_IDLEFLAG(NetDat->huart);精除標志位#elseuint8_t temp=0;static unsigned int num; / 接收計數static uint8_t RecTimes=0;/ 查詢是否發生了空閑中斷if(_HAL_UART_GET_FLAG(NetDat->huart,UART_FLAG_IDLE)!
30、=RESET&&_HAL_UART_GET_I T_SOURCE(NetDat->huart,UART_IT_IDLE)!=RESET)NetDat->CFraLen = num; /發生空閑中斷,將數據長度寫入到結構體NetDat->ReadNBytes = num; /發生空閑中斷,將數據長度寫入到結構體num=0;RecTimes=0;NetDat->RecFlag = 1;NetDat->ProFinsh=0;/ 待處理_HAL_UART_CLEAR_IDLEFLAG(NetDat->huart);清除空閑中斷else if(_HAL
31、_UART_GET_IT_SOURCE(NetDat->huart,UART_IT_RXNE)!=RESET/傳輸未完成,按字節接收#ifdef STM32F0_HAL_UART_CLEAR_IT(myuart->huart,UART_IT_RXNE);if(RecTimes=0 && myuart->recFlag=1)/ 如果上一幀數據未處理,新數據加在前一 幀末尾num = myuart ->RecLen;RecTimes+;if(num <= UsartBufSize )/ 緩沖區未滿myuart->UsartRxBufnum+=(u
32、int8_t)(myuart->huart->Instance->RDR); /F0 為 RDRelsetemp=(uint8_t)(myuart->huart->Instance->RDR);#elseif(RecTimes=0 && NetDat->ProFinsh=0)/ 如果上一幀數據未處理完成,新數據加在前一幀末尾num = NetDat->CFraLen;/ RecTimes+;if(num < sizeof (NetDat->RecBuf) )/ 緩沖區未滿NetDat->RecBufnum+=(u
33、int8_t)(NetDat->huart->Instance->DR); /F0 為 RD else if(num=sizeof (NetDat->RecBuf)/ 循環存放 num=0;NetDat->RecBufnum+=(uint8_t)(NetDat->huart->Instance->DR);#endif_HAL_UART_CLEAR_FLAG(NetDat->huart,UART_FLAG_RXNE); #endif / 串口和接收指針初始化 void My_Usart_Init(UART_HandleTypeDef *hua
34、rt,NetDat_TypeDef *NetDat) NetDat->huart=huart;NetDat->ReadPtr=NetDat->RecBuf;/ 讀數據指針賦值#if UsartDMA = EnableHAL_UART_Receive_DMA(huart,NetDat->RecBuf,sizeof(NetDat->RecBuf); 打開 DMA 接收, 數據存入Usart1_NetDate.RecBuf 數組中。#else_HAL_UART_ENABLE_IT(&huart1, UART_IT_RXNE); /使能接收中斷 #endif_HA
35、L_UART_ENABLE_IT(&huart1, UART_IT_IDLE);便能空閑中斷 (3)編寫 netdatpro.h文件#ifndef _NETDATPRO_H#define _NETDATPRO_H#include "crc16.h"#include "myusart.h"#include "stdlib.h"#include "string.h"#define MasterID 0x01#define SlaverID 0x02#define DateHead0xaa55#define He
36、ad10xaa#define Head20x55#define FrameMinByte 8 / 定義最小幀字節數當數據位為空時基本幀長度為最小幀字節數#define Max_Mess_LEN 100#ifndef Enable#define Enable 1 #endif#ifndef Disable#define Disable 0 #endif#define debug 1#define DebugPrint if(debug)printf typedef structunsigned char Head2;unsigned char SendDevID;unsigned char Re
37、cDevID;unsigned char Cmd;unsigned char len;unsigned char dataMax_Mess_LEN;NetPackge_Type;unsigned char NetDataUnpack(void *SavePackge ,NetDat_TypeDef *recdata);void NET_Data_Process(NetDat_TypeDef *netDat);void NET_Data_Package(uint8_t *sendData,uint8_t len);#endif(4)編寫 netdatpro.c文件#include "n
38、etdatpro.h"#include "stdio.h"#include "usart.h"#define RptrAddr (uint32_t)recdata->ReadPtrNetPackge_Type NET_data;extern uint8_t DebugFlag;extern NetDat_TypeDef Usart1_NetDate;NetPackge_Type SendDat=0;uint8_t DevID=0x02;/* 參數 : cmd 傳入指令datlen 數據長度,不是幀長度而是數據長度標識字節跟隨多少個字節數據
39、*date數據指針* 描述:將傳入數據按照協議封裝命令碼并計算CRC* 返回值:無*/*void NetDatePack(unsigned char cmd,unsigned char datlen,unsigned char *date) unsigned int CRC_Value=0;SendDat.Head0=Head1;SendDat.Head1=Head2;SendDat.SendDevID=DevID;if(DevID=MasterID)/ 主機發送數據時SendDat.RecDevID=SlaverID;else/從機發送數據時SendDat.RecDevID=MasterID
40、;SendDat.Cmd=cmd;SendDat.len=datlen;memcpy(&SendDat.data,date,datlen);CRC_Value = CRC16_Calculate(uint8_t*)&SendDat,datlen+6);6 是計算 CRC前的最小數 據包基本組成的字節數(數據字節為空,即沒有數據字節)/ DebugPrint("CRC_Value=%4xn",CRC_Value);SendDat.datadatlen = CRC_Value>>8;SendDat.datadatlen+1 = CRC_Value;/
41、* 函數名:NetDataUnpack(void *SavePackge ,NetDat_TypeDef *recdata)* 參數 : *SavePackge 解析后接收保存變量*recdata 待解析數據* 描述:按照協議頭將串口接收的數據進行拆包解析,解析后數據由*SavePackge 接收保存* 返回值:packgenum 0 數據包解析完成n 已經解析的數據包個數數據協議格式:協議頭(2byte) + 發送設備ID( 1byte) +接收設備ID( 1byte) + 信息碼 ( 1byte )+ 數 據 長 度 (1 byte )+ 數 據 ( n byte )+ 校 驗 碼 ( 2
42、byte )*/unsigned char NetDataUnpack(void *SavePackge ,NetDat_TypeDef *recdata)/ 拆分數據包,粘包處理unsigned char *p=SavePackge,*pa=SavePackge,*ptr;unsigned int i=0,DatHead=0;/static unsigned char packgenum=0;uint32_t bufBaseAddr=(uint32_t)recdata->RecBuf,HeadAddr=0;if(recdata->RecFlag=1 &&recda
43、ta->ProFinsh=0) / 收到新數據 printf("開始解析第1d】包數據n",packgenum);DatHead=(*recdata->ReadPtr+)<<8;/ 取數據頭0xaa 字節移到高位HeadAddr=RptrAddr;for(i=0;i<recdata->ReadNBytes-(HeadAddr-bufBaseAddr);i+)/RptrAddr-bufBaseAddr 之前已經讀取的個數printf(" 數據頭:%04xn",DatHead+*recdata->ReadPtr);i
44、f(DateHead=(DatHead+*recdata->ReadPtr)ptr=recdata->ReadPtr-1;/ 記錄找到數據頭時的指針起點DebugPrint(" 【數據頭正確】n");break; else DatHead=(*recdata->ReadPtr+)<<8; if(RptrAddr-bufBaseAddr>=sizeof (recdata->RecBuf)/ 指針溢出 recdata->ReadPtr=recdata->RecBuf;/ 修正指針位置到數組首位 recdata->Rea
45、dNBytes-=sizeof (recdata->RecBuf);/ 修正循環控制變量 if(DateHead=(DatHead+*recdata->ReadPtr)/0xaa55 packgenum+; if(*(ptr+5)>Max_Mess_LEN)/*(ptr+5) 是存放數據長度的位置 DebugPrint (" 信息長度大于%d , 已超出約定范圍! ! n",Max_Mess_LEN);recdata->ReadPtr+;讀指針增力口 到此處讀指針已經指向 0x55這個字節,退出函數后再次拆包時直接取下一個數進行判斷數據頭,因此讀指針
46、要+1if(RptrAddr-bufBaseAddr>=sizeof (recdata->RecBuf)/ 指針溢出 recdata->ReadPtr=recdata->RecBuf;/ 修正指針位置到數組首位 recdata->ReadNBytes-=sizeof (recdata->RecBuf);/ 修正讀字節數 return packgenum;for(i=0;i<*(ptr+5)+FrameMinByte;i+) / 接收一個數據包(小包)readbyte+5數據長度在0xaa 字節后 偏移 5 if(i=0)*p+ = *(recdata-
47、>ReadPtr-1);/0xaa else*p+ = *recdata->ReadPtr+; if(RptrAddr-bufBaseAddr>=sizeof (recdata->RecBuf)/ 指針溢出 recdata->ReadPtr=recdata->RecBuf;/ 修正指針位置到數組首位recdata->ReadNBytes-=sizeof (recdata->RecBuf);/ 修正讀字節數p=SavePackge;DebugPrint(" n ");DebugPrint(" 【數據】 : "
48、);for(i=0;i<*(pa+5)+FrameMinByte;i+)DebugPrint("%02x ",*p+);DebugPrint(" n ");if(RptrAddr-bufBaseAddr>recdata->ReadNBytes)/ 丟包了recdata->ReadPtr=&recdata->RecBufrecdata->ReadNBytes;/ 修正指針位置到實 際接收位置,并指向下一個待存數據內存單元if(RptrAddr-bufBaseAddr = recdata->ReadNByte
49、s)/ 讀完數據了printf ("n");printf (" 【拆包完成.】 n");printf ("n");recdata->ProFinsh=1;packgenum=0;#if UsartDMA = Disablerecdata->ReadPtr=recdata->RecBuf;/ 讀指針歸位#endifreturn packgenum;return 0;void NET_Data_Process(NetDat_TypeDef *netDat) / 網絡數據處理 extern uint16_t temp,la
50、stTemp,lastLen;uint16_t i=0,pack;uint8_t cmd,Date5,*p,a="test transmit IT"if(Usart1_NetDate.RecFlag=1)while(Usart1_NetDate.ProFinsh=0)/ 還沒拆完數據 NetDataUnpack(&NET_data,netDat); 拆包if(CRC16_Checkout(uint8_t*)&NET_data, NET_data.len+FrameMinByte)=CRC_OK) 校驗正確printf ("【CR或驗正確 】n&qu
51、ot;);cmd=NET_data.Cmd;switch(cmd) case 0x01:printf (" 收到查詢PH 傳感器 1 命令.n");printf ("向主機發送傳感器 1 PH值n");Date0=0x00;Date1=0x07;NetDatePack(0x02,0x02,Date);#if UsartDMA = DisableHAL_UART_Transmit(&huart1,(uint8_t*)&SendDat,SendDat.len+FrameMinByte,1000);#elseHAL_UART_Transmit_
52、DMA(&huart1,(uint8_t*)&SendDat,SendDat.len+FrameMinByte); #endifprintf (" 【返回數據】: ");p=(uint8_t*)&SendDat;for(i=0;i<SendDat.len+FrameMinByte;i+)printf ("%02x ",*p+);printf ("n");break;case 0x03:printf ("n");printf (" 收到設置傳感器1 PH 上限命令.n"
53、;);printf (" 設置傳感器1PH 上限.n");NetDatePack(0x10,0x00,Date);#if UsartDMA = DisableHAL_UART_Transmit(&huart1,(uint8_t*)&SendDat,SendDat.len+FrameMinByte,1000);#elseHAL_UART_Transmit_DMA(&huart1,(uint8_t*)&SendDat,SendDat.len+FrameMinByte); #endifprintf (" 返回設置成功命令.n")
54、;printf (" 【返回數據】: ");p=(uint8_t*)&SendDat;for(i=0;i<SendDat.len+FrameMinByte;i+)printf ("%02x ",*p+);printf ("nn");break;default :break;memset (&NET_data,0,sizeof (NET_data);#if UsartDMA = Enableprintf("n");printf("lastTemp=%dn",lastTemp)
55、;printf("temp=%dn",temp);printf("len=%dn",Usart1_NetDate.CFraLen);printf("alllen=%dn",Usart1_NetDate.InAllLen);#endifUsart1_NetDate.RecFlag=0;( 5)編寫crc16.h#ifndef _CRC16_H_#define _CRC16_H_/#include "sys_config.h"#include "main.h"/#define CRC16_LOW_B
56、ETY_AHEAD#define CRC_OK 0#define CRC_FAIL -1unsigned int CRC16_Calculate(unsigned char *pDate, unsigned int len );int CRC16_Checkout(unsigned char *pDate, unsigned char len);void CRC16_Pack(unsigned char *pDate, unsigned int *len);#endif( 6)編寫crc16.c/crc16 高字節在前驅動#include "crc16.h" /* 8位CRC驗表*/const unsigned char CRC16_HighByteTable256= 0x00 ,0xc1 ,0x81
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 天津市河西區實驗中學2024-2025學年高三年級第二次四校聯考物理試題含解析
- 江西省鷹潭市2025屆第二學期高三4月綜合測試(二)英語試題試卷含解析
- 寧波市鎮海區重點中學2025年初三中考熱身練習試題英語試題試卷含答案
- 蘭州工業學院《誤差理論與測量平差基礎》2023-2024學年第二學期期末試卷
- 江蘇省重點中學2025年普通高中高三第一次診斷性測試物理試題含解析
- 長沙航空職業技術學院《客戶關系管理》2023-2024學年第一學期期末試卷
- 遼寧省阜新二中2025年高三畢業生復習統一檢測試題生物試題含解析
- 山東省濟寧市市中學區2025屆初三下第二次測試(化學試題理)試題含解析
- 遼寧省盤錦市大洼區市級名校2024-2025學年初三中考沖刺預測卷(六)生物試題含解析
- 上海外國語大學《英語教學評價》2023-2024學年第二學期期末試卷
- 財務比率分析表模板
- 通用電子嘉賓禮薄
- 酒廠從業人員【安全教育培訓】課件
- 某地塊土壤污染狀況調查匯報PPT模板框架
- 術前停藥指南
- 新能源汽車充電樁項目可行性報告
- 水資源利用知到章節答案智慧樹2023年西安理工大學
- 靜脈給藥錯誤演練腳本
- IE動作MOD法培訓資料
- 一汽解放維修手冊說明書
- 禽流感人流感人間禽流感培訓課件
評論
0/150
提交評論