版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
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. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 电力系统故障排除与预防措施手册
- 2026年剧本杀运营公司员工法律法规培训管理制度
- 2026年剧本杀运营公司新运营模式研发管理制度
- 2026年剧本杀运营公司剧本供应商筛选与评估管理制度
- 2026年零售行业创新报告及新零售模式发展趋势分析报告001
- 2026年自动驾驶在物流运输中创新报告
- 2025 小学三年级思想品德之班级卫生值日检查管理课件
- 2026年游戏行业元宇宙创新报告及虚拟现实技术应用报告
- 2026年游戏行业电竞产业报告及未来五至十年电竞赛事报告
- 人工智能赋能下的教育公平:区域教育均衡发展的实践模式构建教学研究课题报告
- 2026年甘肃省兰州市皋兰县兰泉污水处理有限责任公司招聘笔试参考题库及答案解析
- 2025年全国高压电工操作证理论考试题库(含答案)
- 居间合同2026年工作协议
- 2025-2026学年(通*用版)高二上学期期末测试【英语】试卷(含听力音频、答案)
- 翻车机工操作技能水平考核试卷含答案
- 员工宿舍安全培训资料课件
- 化工设备培训课件教学
- 舞台灯光音响控制系统及视频显示系统安装施工方案
- 2025福建省能源石化集团有限责任公司秋季招聘416人参考考试试题及答案解析
- 煤矿三违行为界定标准及处罚细则
- 服装厂安全生产责任制度制定
评论
0/150
提交评论