stm32 HAL库 串口DMA接收不定长度数据及粘包处理

上传人:zou****hua 文档编号:181743468 上传时间:2023-01-16 格式:DOCX 页数:24 大小:302.94KB
返回 下载 相关 举报
stm32 HAL库 串口DMA接收不定长度数据及粘包处理_第1页
第1页 / 共24页
stm32 HAL库 串口DMA接收不定长度数据及粘包处理_第2页
第2页 / 共24页
stm32 HAL库 串口DMA接收不定长度数据及粘包处理_第3页
第3页 / 共24页
点击查看更多>>
资源描述
串口接收不定长度数据及数据粘包解析的实现1、如何让串口接收不定长度数据想让Stm32串口接收不定长度数据,这就需要我们开启串口空闲中断(IDLE) 方式,所谓串口空闲中断指的是stm32的数据总线在接收数据的过程中,如果总 线在接收一个字节所需要的时间内没有再接收到数据,单片机就会判定此时数据 已经接收完成了,这时单片机会自动触发空闲中断IDLE标志位,引发空闲中断, 我们只需要进入中断取数据就可以了。使用IDLE空闲中断我们就可以用串口接 收任意长度的数据了。2、串口接收不定长度数据的实现思路我们实现串口接收不定长度数据的思路是:首先我们要定义一个接收数据的 缓冲区,一般用数组接收数据,在串口初始化时要开启串口的空闲中断和接收中 断。然后在有中断产生时,我们需要在串口中断函数里判断是空闲中断还是正常 接收一个字节数据引起的接收中断,如果是正常接收字节的中断,那么我们需要 把接收到的这个字节数据存放到缓冲数组中,如果是 IDLE 空闲中断,表示串口 数据已经接收完成了,我们需要在 IDEL 中断处理函数中设置一个数据接收完成 标志位表示已经完整的接收到一帧数据了,如:RecFlag=1;3、数据粘包解析的实现思路数据粘包是多个数据包发送时由于线路延时,或者发送端发送多个数据包的 时间延时很小,导致几个数据包几乎同时到达接收端(数据包到达接收端的时间 间隔小于一个字节时间),这样单片机接收数据时就会将这几个数据包当做一帧 数据来接收存放。那么我们如何将这几个数据包合成的一帧数据拆解成几个数据 包呢?其实,实现的方法也很简单,这就需要我们在发送端和接收端的数据格式 上做一个统一的约定,约定了统一的数据发送格式在发送数据时就严格按照这个 格式来发送。一般来说约定的格式我们要明确规定数据头和数据长度。然后我们 再根据定义的数据头是什么数据,在这一帧数据中逐个去判断当前数据是不是数 据头,如果是就说明这个是一个小数据包的开始位置,在根据数据长度就可以解 析出一个数据包了。例如,我们约定发送的数据格式为:数据头(2byte) +发送 者 ID (Ibyte) + 接收者 ID (Ibyte) + 命令码(Ibyte)+ 数据长度(Ibyte)+CRC 校验(2byte)。这样我们定义了标准的数据格式就容易拆包了。4、下面我们就根据约定的数据发送格式来定义具体的数据头,例如我们定义一 个数据包命令来查询接收命令的单片机 PH 值传感器 1 的数据是多少。数据包定义如下:数据头:0XAA55发送者 ID: 0x01接收者 ID: 0X02命令码: 0X01 /查询 PH 值传感器 1 命令 随意约定命令代码0X02/响应 PH 查询命令0x03 设置传感器PH值上限命令0X10 /设置成功数据长度: xxCRC 校验: 0xB1B5 / CRC 16 Modbus 那么发送端发送的查询数据为: aa 55 01 02 01 00 b5 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个字节的数据,再加上CRC的2 个字节,我们就需要在RecBufi+5之后还要取出4个字节的数据,才能完整的取 出这个小数据包: aa 5502 0102 0200 0712 91 需要注意的是我们再拆包的过程中要重复考虑其中存在的问题,比如: 数据长度错误时的数量,找不到数据头时循环变量的修正等。5、基于 cubemx HAL 库的实现方法(1) 新建cubemx工程 选择stm32f103ze芯片(2) 开启外部高速时钟HSE,配置好系统时钟树QRCC Master Glock OutputMAGROIWDGNVICR.CC Mode anZSystem Core vHi-gh Speed CI u風日垂日IJCe日mi%sWWDG3)配置串口 1 ,启用 DMA 传输,使能中断Pinout & ConfigurationClock ConfigurationPrAddit cnal Sofhvarev PinoutUSART1 Made and CnnfiguratiDnMode AsynchrcnousMc-deKXConnecti/ityCAN FSf/lCI2C1I2C2 SDIOSPI1SPI20 SPI3UART4UART6USART1Hardware Flov/ Control (R.S232) D也;aMeCo nfigu ration NVIC Settings* DMA Sellings GPIO Settings | Paramatgr SellingsS User Constants1Resei ConfiguralianN VIC Interupt Table|lnaUEdl|P弋七mptiun PriuntyDMA1 channel global interruptDMA1 channels global interruptUSART1 global inierruptDMA 接收配置成循环模式,数据位宽默认为8 位ConfiguralionReset Configuration Parameter Sett ngs User Constants NVIC Settings DMA Settings GRID SettingsDMA RequestChannelDirectionPriorityDMA1 Channel 5Peripheral To MemoryLowUSART1_7IDMA1 Channel 4MemcryTo PeripheralLowAdd DeleteDMA 发送配置成正常模式,数据位宽默认为8 位DMA Requ&stChannelDir&ctionPriorityUSART1_RXMA1 Charnel 5Peripheral To MemoryL&w型hi匸iqMAJ CharnelMemory To PeripheralLow-DMA Request SettingsPeripheralMemoryModeIncrement Addrsss| Parameter Settings User Constants NVIC Settings DMA Ssitings GPIO SettingsData Widt h(4)设置好工程名称和保存位置,选择自己用的开发工具和版本,然后生成工程代码就可以开始编写我们自己的代码了。6、我们先看结果首先,我们先测试单个命令发送(没有粘包)命令 1:查询 PH 指令 aa 55 01 02 01 00 b5 bl收到查询指令后,进行解析然后执行查询命令,向主机返回PH数据【返回数据】aa 55 02 010202 00 07 12 91 /返回PH值等于7lit:, SSCOM V5.13.1串口f网翔逛谓试器作者:大1FT丁尼閃805Hq通腿口串口设員显示岌送寧字符串小工具輩助联磊作者土 PCB打样降至每款5元呱丰包邮可选杂色】【嘉立创盲网】【数据】: aa E5 U1 02 U1 00 LE bl【拆包長咸 】912r_u 希02 J 命 T551- 1- D!l.wiEr:=L .a: 馨机回 CRT到嘉端口号 |COMU USE-SEEIAL CH340厂HE1显示 保存数据|厂接收數据到文件盛HE1芨送 厂加时间戳和分包显示,固ms第厂字节兰关诃串口更參昂口设畫厂 RTS r DTFI 波特率:1115200 口豳 55 01 02 01 00 b5 bl为了更好地总展出匚呻件若R 洁佩Hflft宜订浏F结屋客A 互更【升级到羁WMB.IEU】 *FCE打样降至每款吕兀,免颜色费,顺丰包邮!提供SMT贴片朋务。*肌-丁咕www.da3cia.co-m :3R:22&| COW 11 已打开 11 予 ZOObp 巳&1 ,Mon 巳 Ncmm青碟裔口 I打开文件|岌送文件命令2:设置PH值上限指令aa 55 01 02 03 02 00 0b 57 5b 设置PH上限为11【返回数据】aa 55 02 011000 49 a5 /返回设置成功指令0x10瞧SSCOM V5.13.1串口/网樹据潟试器.作者;大虾T丁2619O58q,“-通讯端口串口设置显示跪送窑字符串小工具群的麻聿作青 量PCE打祥降至每款5元顺丰包M可选杂色!嘉立创盲网】【数据】:獰 55 01 02 03 02 00 Ob 57 51)【拆包宾成 1【匚毗校验正确.囂感器1 FH上限命令fe : aa 55 OZ 011000 43aS发注文件青踪窗口打开艾件|端口号 |cmi USB-SERIAL CH340工r HM显示 保存埶据I r接收数据到文件刚HEX发注 厂加时间謎和分包显处20论用厂宇节飆关ifl串口总更參串口设劃厂RTS厂DTR液特率:1朽2如 Baa 55 01 02 03 02 00 0b 57 5t茄了更好地岌展跖CON软件 若 崔: 请您注册嘉立创F结屋客户发匡【升级到SSC0H5. 13. 1 *FCE打样隆至每款5元,免颜色游,顺丰包由记提拱如贴片服势。*RT-Thiwuvw.daxia.Gom S;10R;249COIM11 已打开 IISOObps.flJ.Ncrne.None接下来,我们测试一下数据粘包的情况我们把之前的2 个命令合在一起发送出去,红色数据用来模拟有干扰的情况下,数据出错了a2 55 aa 55 01 02 01 00 b5 b132 15 8e 20aa 55 01 02 03 02 00 0b 57 5b68 21 结果如下:在串口收到这一帧数据后,调用拆包函数进行数据解析,按照数据头逐个进行比较只要 找到正确的数据头,就按照约定的数据长度去取数据,取到一个小包数据后进行CRC校验, 校验正确后才执行命令。第一个小包执行完成后接着去取下一个包,然后执行,直到把接收 到的数据解析并执行完成。鳩SSCOM V5.13.1串Zl/R率娠湄弍纯作者:大虾T丁,261S058qq.cam. QQ群;5巧02445諭丘”,- 匚通汛端口串口设苴駅示发送苓芋符吕-4T耳碉匿垂作咅APCBm降至毎款5云顺丰包邮可选杂色!【扁立创宣网】皋煞倉盘Lii 55 01 32 Cl 30 15 J|【颓堀.】S 吧 95 01 0 03 02 00 DL_57 阳Llkl- JS3B5 02 01 10QU 49舌徐窗口 tJHJir |去迂戈片|停止丨鸽左迂区I厂Sil厂tnjk.保存至埶端二号 | :awil JEI-E:ERI?L CKE-1D删显示 血逊J厂 齡曲腔应件 加旳軀和分包显走超打垃旧:巨胡P HEI发送OTitZ: 130 mJ文厂 l踽关碑口 |出瞽串口绘弟|1 &斗至|末扣刘沙呼工厂RTG T DTR寂特率,1免叩-I梓:C:C Cl 0: 01 0C L: ll|32 1C 芸 20 近 C3 01 D2 C: 32 CO L C7 Cl C3 21対了更好地岌展551:喩件晋h I请您注结屋容户.应氐1lESSCME.13 i】*FO打样降至馬窗,免倾色藝II辟句邮!提供皿贴剛臍。*RT-Hu沁竦自中国的开頑免畏商用物晞w/ |S:2BR:587COM11 巳扫开 115200bps.SJjNone,None中断接收方式:采用中断方式,只需要在宏定义 #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 stdio.h #define UsartBufSize 512#define UsartDMA 1 /是否启用串口 DMA 1启用0停止typedef structuint8_t *ReadPtr;uint8_t RecFlag;uint8_t ProFinsh;uint8_t RecBufUsartBufSize;uint16_t InAllLen;uint16_t CFraLen;uint16_t ReadNBytes;UART_HandleTypeDef *huart;/读书节指针/接收标志/数据处理完成标志/数据缓冲区/缓冲区存放数据长度/当前帧长度 最近接受的帧长度/需要读取的字节数/串口号 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_HandleTypeDef hdma_usart1_rx; extern DMA_HandleTypeDef hdma_usart1_tx;NetDat_TypeDef Usart1_NetDate;/重定向c库函数printf到USARTx struct _FILE /标准库需要的支持函数int handle;int fputc(int ch, FILE *f)while(huart1.lnstance-SR&0X40)=0); 循环发送,直到发送完毕 huart1.Instance-DR = (uint8_t)ch ;return (ch);/网络数据接收函数 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_rx.InstanceCNDTR;获取 DMA 中未传输的数据个数,NDTR 寄存器分析见下面if(lastTemp=0&temp=sizeof(NetDat-RecBuf)|lastTemp=temp)/lastTemp=temp 前 2 次都是一次接满缓冲区NetDat-CFraLen=sizeof (NetDat-RecBuf);else if(lastTemp=O)首次进入NetDat-CFraLen=sizeof (NetDat-RecBuf)- temp;/计算当前接收的帧长度elseNetDat-CFraLen=lastTemp- temp;/计算当前接收的帧长度if(NetDat-CFraLensizeof (NetDat-RecBuf) 数据从缓冲区溢出NetDat-CFraLen=lastTemp+sizeof (NetDat-RecBuf)-temp;有溢出了 修正接收到的 字节数if(temp!=sizeof (NetDat-RecBuf)缓存没满 满的时候temp等于缓冲区大小 NetDat-InAllLen =sizeof (NetDat-RecBuf) - temp;/总计数减去未传输的数据个数, 得到已经接收的数据个数elseNetDat-InAllLen =sizeof (NetDat-RecBuf);缓存刚好满时修正总数为缓存大小 NetDat-ReadNBytes=NetDat-InAllLen; 计算需要读取的字节数 if(NetDat-InAllLen CFraLen)接收总长度小于当前帧长度时 缓冲区溢出NetDat-ReadNBytes=NetDat-InAllLen + sizeof (NetDat-RecBuf);修正要需要读取 的字节数HAL_UART_Receive_DMA(NetDat-huart,NetDat-RecBuf,sizeof(NetDat-RecBuf);/ 开 启 DMA接收NetDat-ProFinsh=O;_HAL_UART_CLEAR_IDLEFLAG(NetDat-huart);/ 清除标志位#elseuint8_t temp=O;static unsigned int num; /接收计数static uint8_t RecTimes=O;/查询是否发生了空闲中断if(_HAL_UART_GET_FLAG(NetDat-huart,UART_FLAG_IDLE)!=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_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 UsartRxBufnum+=(uint8_t)(myuart-huart-Instance-RDR); /F0 为 RDR elsetemp=(uint8_t)(myuart-huart-Instance-RDR);#elseif(RecTimes=0 & NetDat-ProFinsh=0)如果上一帧数据未处理完成,新数据 加在前一帧末尾num = NetDat-CFraLen;/RecTimes+;if(num RecBuf) )/缓冲区未满 NetDat-RecBufnum+=(uint8_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 *huart,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_HAL_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 DateHead 0xaa55#define Head1 0xaa#define Head2 0x55#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)printftypedef structunsigned char Head2;unsigned char SendDevID;unsigned char RecDevID;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 netdatpro.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 数据长度,不是帧长度而是数据长度标识字节 跟随多少个字节数据 *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(DevlD=MasterlD)主机发送数据时SendDat.RecDevID=SlaverID;else/从机发送数据时SendDat.RecDevlD=MasterlD;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_Value8;SendDat.datadatlen+1 = CRC_Value;* 函数名: NetDataUnpack(void *SavePackge ,NetDat_TypeDef *recdata)* 参数:*SavePackge 解析后接收保存变量*recdata 待解析数据* 描述:按照协议头将串口接收的数据进行拆包解析,解析后数据由 *SavePackge 接收保存* 返回值: packgenum 0 数据包解析完成 n 已经解析的数据包个数数据协议格式:协议头(2byte) +发送设备ID (Ibyte) +接收设备ID (Ibyte) +信息 码 ( 1byte ) + 数 据 长 度 ( 1 byte ) + 数 据 ( n byte ) + 校 验 码 ( 2byte )*/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 &recdata-ProFinsh=0) /收到新数据printf(开始解析第【d】包数据.n,packgenum);DatHead=(*recdata-ReadPtr+)8;取数据头 Oxaa 字节移到高位 HeadAddr=RptrAddr;for(i=O;iReadNBytes-(HeadAddr-bufBaseAddr);i+)/RptrAddr-bufBaseAddr 之前已经读取的个数printf(数据头:%04xn,DatHead+*recdata-ReadPtr); if(DateHead=(DatHead+*recdata-ReadPtr)ptr=recdata-ReadPtr-1;记录找到数据头时的指针起点DebugPrint(【数据头正确】n); break;else DatHead=(*recdata-ReadPtr+)=sizeof (recdata_RecBuf) 指针溢出recdata-ReadPtr=recdata-RecBuf; 修正指针位置到数组首位 recdata-ReadNBytes-=sizeof (recdata-RecBuf);修正循环控制变量if(DateHead=(DatHead+*recdata-ReadPtr)/0xaa55packgenum+;if(*(ptr+5)Max_Mess_LEN)/*(ptr+5)是存放数据长度的位置 DebugPrint (信息长度大于%d ,已超出约定范围! ! !n,Max_Mess_LEN); recdata-ReadPtr+;读指针增加到此处读指针已经指向0x55这个字节,退出函数后再次拆包时直接取下一个数进行判断数据头,因此读指针要 +1if(RptrAddr-bufBaseAddr=sizeof (recdata-RecBuf)/指 针溢出recdata-ReadPtr=recdata-RecBuf; 修正指针位置到数组首位 recdata-ReadNBytes-=sizeof (recdata-RecBuf); 修正读字节数return packgenum;for(i=0;iReadPtr-1);/0xaaelse*p+ = *recdata-ReadPtr+;if(RptrAddr-bufBaseAddr=sizeof (recdata-RecBuf)/指 针溢出recdata-ReadPtr=recdata-RecBuf; 修正指针位置到数组首位recdata-ReadNBytes-=sizeof (recdata-RecBuf); 修正读字节数p=SavePackge;DebugPrint( n );DebugPrint(【数据】:);for(i=0;irecdata-ReadNBytes)丢 包了recdata-ReadPtr=&recdata-RecBufrecdata-ReadNBytes; 修 正指针位置到实际接收位置,并指向下一个待存数据内存单元if(RptrAddr-bufBaseAddr = recdata-ReadNBytes)读完数据了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,lastTemp,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 (【CRC 校验正确.】n);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 = Disable/HAL_UART_Transmit(&huart1,(uint8_t*)&SendDat,SendDat.len+FrameMinByte,1000);/ #else/ HAL_UART_Transmit_DMA(&huart1,(uint8_t*)&SendDat,SendDat.len+FrameMinByte);/ #endifprintf (【返回数据】:);p=(uint8_t*)&SendDat;for(i=0;iSendDat.len+FrameMinByte;i+)printf (%02x ,*p+);printf (n);break;case 0x03:printf (n);printf (收到设置传感器1 PH上限命令.n);printf (设置传感器1PH上限.n);NetDatePack(0x10,0x00,Date);/#if UsartDMA = Disable/ HAL_UART_Transmit(&huart1,(uint8_t*)&SendDat,SendDat.len+FrameMinByte,1000);/ #else/HAL_UART_Transmit_DMA(&huart1,(uint8_t*)&SendDat,SendDat.len+FrameMinByte);/ #endifprintf (返回设置成功命令.n); printf (【返回数据】:); p=(uint8_t*)&SendDat;for(i=0;iSendDat.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); 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_BETY_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 ,0x40 ,0x01 ,0xc0 ,0x80 ,0x41 ,0x01 ,0xc0 ,0x80 ,0x41 ,0x00 ,0xc1 ,0x81 ,0x40 , 0x01 ,0xc0 ,0x80 ,0x41 ,0x00 ,0xc1 ,0x81 ,0x40 ,0x00 ,0xc1 ,0x81 ,0x40 ,0x01 ,0xc0 ,0x80 ,0x41 , 0x01 ,0xc0 ,0x80 ,0x41 ,0x00 ,0xc1 ,0x81 ,0x40 ,0x00 ,0xc1 ,0x81 ,0x40 ,0x01 ,0xc0 ,0x80 ,0x41 , 0x00 ,0xc1 ,0x81 ,0x40 ,0x01 ,0xc0 ,0x80 ,0x41 ,0x01 ,0xc0 ,0x80 ,0x41 ,0x00 ,0xc1 ,0x81 ,0x40 , 0x01 ,0xc0 ,0x80 ,0x41 ,0x00 ,0xc1 ,0x81 ,0x40 ,0x00 ,0xc1 ,0x81 ,0x40 ,0x01 ,0xc0 ,0x80 ,0x41 , 0x00 ,0xc1 ,0x81 ,0x40 ,0x01 ,0xc0 ,0x80 ,0x41 ,0x01 ,0xc0 ,0x80 ,0x41 ,0x00 ,0xc1 ,0x81 ,0x40 , 0x00 ,0xc1 ,0x81 ,0x40 ,0x01 ,0xc0 ,0x80 ,0x41 ,0x01 ,0xc0 ,0x80 ,0x41 ,0x00 ,0xc1 ,0x81 ,0x40 , 0x01 ,0xc0 ,0x80 ,0x41 ,0x00 ,0xc1 ,0x81 ,0x40 ,0x00 ,0xc1 ,0x81 ,0x40 ,0x01 ,0xc0 ,0x80 ,0x41 , 0x01 ,0xc0 ,0x80 ,0x41 ,0x00 ,0xc1 ,0x81 ,0x40 ,0x00 ,0xc1 ,0x81 ,0x40 ,0x01 ,0xc0 ,0x80 ,0x41 , 0x00 ,0xc1 ,0x81 ,0x40 ,0x01 ,0xc0 ,0x80 ,0x41 ,0x01 ,0xc0 ,0x80 ,0x41 ,0x00 ,0xc1 ,0x81 ,0x40 , 0x00 ,0xc1 ,0x81 ,0x40 ,0x01 ,0xc0 ,0x80 ,0x41 ,0x01 ,0xc0 ,0x80 ,0x41 ,0x00 ,0xc1 ,0x81 ,0x40 , 0x01 ,0xc0 ,0x80 ,0x41 ,0x00 ,0xc1 ,0x81 ,0x40 ,0x00 ,0xc1 ,0x81 ,0x40 ,0x01 ,0xc0 ,0x80 ,0x41 , 0x00 ,0xc1 ,0x81 ,0x40 ,0x01 ,0xc0 ,0x80 ,0x41 ,0x01 ,0xc0 ,0x80 ,0x41 ,0x00 ,0xc1 ,0x81 ,0x40 , 0x01 ,0xc0 ,0x80 ,0x41 ,0x00 ,0xc1 ,0x81 ,0x40 ,0x00 ,0xc1 ,0x81 ,0x40 ,0x01 ,0xc0 ,0x80 ,0x41 , 0x01 ,0xc0 ,0x80 ,0x41 ,0x00 ,0xc1 ,0x81 ,0x40 ,0x00 ,0xc1 ,0x81 ,0x40 ,0x01 ,0xc0 ,0x80 ,0x41 , 0x00 ,0xc1 ,0x81 ,0x40 ,0x01 ,0xc0 ,0x80 ,0x41 ,0x01 ,0xc0 ,0x80 ,0x41 ,0x00 ,0xc1 ,0x81 ,0x40 , ;/*低 8 位 CRC 校验表*/const unsigned char CRC16_LowByteTable 256= 0x00 ,0xc0 ,0xc1 ,0x01 ,0xc3 ,0x03 ,0x02 ,0xc2 ,0xc6 ,0x06 ,0x07 ,0xc7 ,0x05 ,0xc5 ,0xc4 ,0x04 , 0xcc ,0x0c ,0x0d ,0xcd ,0x0f ,0xcf ,0xce ,0x0e ,0x0a ,0xca ,0xcb ,0x0b ,0xc9 ,0x09 ,0x08 ,0xc8 , 0xd8 ,0x18 ,0x19 ,0xd9 ,0x1b ,0xdb ,0xda ,0x1a ,0x1e ,0xde ,0xdf ,0x1f ,0xdd ,0x1d ,0x1c ,0xdc , 0x14 ,0xd4 ,0xd5 ,0x15 ,0xd7 ,0x17 ,0x16 ,0xd6 ,0xd2 ,0x12 ,0x13 ,0xd3 ,0x11 ,0xd1 ,0xd0 ,0x10 , 0xf0 ,0x30 ,0x31 ,0xf1 ,0x33 ,0xf3 ,0xf2 ,0x32 ,0x36 ,0xf6 ,0xf7 ,0x37 ,0xf5 ,0x35 ,0x34 ,0xf4 , 0x3c ,0xfc ,0xfd ,0x3d ,0xff ,0x3f ,0x3e ,0xfe ,0xfa ,0x3a ,0x3b ,0xfb ,0x39 ,0xf9 ,0xf8 ,0x38 , 0x28 ,0xe8 ,0xe9 ,0x29 ,0xeb ,0x2b ,0x2a ,0xea ,0xee ,0x2e ,0x2f ,0xef ,0x2d ,0xed ,0xec ,0x2c , 0xe4 ,0x24 ,0x25 ,0xe5 ,0x27 ,0xe7 ,0xe6 ,0x26 ,0x22 ,0xe2 ,0xe3 ,0x23 ,0xe1 ,0x21 ,0x20 ,0xe0 , 0xa0 ,0x60 ,0x61 ,0xa1 ,0x63 ,0xa3 ,0xa2 ,0x62 ,0x66 ,0xa6 ,0xa7 ,0x67 ,0xa5 ,0x65 ,0x64 ,0xa4 , 0x6c ,0xac ,0xad ,0x6d ,0xaf ,0x6f ,0x6e ,0xae ,0xaa ,0x6a ,0x6b ,0xab ,0x69 ,0xa9 ,0xa8 ,0x68 , 0x78 ,0xb8 ,0xb9 ,0x79 ,0xbb ,0x7b ,0x7a ,0xba ,0xbe ,0x7e ,0x7f ,0xbf ,0x7d ,0xbd ,0xbc ,0x7c , 0xb4 ,0x74 ,0x75 ,0xb5 ,0x77 ,0xb7 ,0xb6 ,0x76 ,0x72 ,0xb2 ,0xb3 ,0x73 ,0xb1 ,0x71 ,0x70 ,0xb0 , 0x50 ,0x90 ,0x91 ,0x51 ,0x93 ,0x53 ,0x52 ,0x92 ,0x96 ,0x56 ,0x57 ,0x97 ,0x55 ,0x95 ,0x94 ,0x54 , 0x9c ,0x5c ,0x5d ,0x9d ,0x5f ,0x9f ,0x9e ,0x5e ,0x5a ,0x9a ,0x9b ,0x5b ,0x99 ,0x59 ,0x58 ,0x98 , 0x88 ,0x48 ,0x49 ,0x89 ,0x4b ,0x8b ,0x8a ,0x4a ,0x4e ,0x8e ,0x8f ,0x4f ,0x8d ,0x4d ,0x4c ,0x8c , 0x44 ,0x84 ,0x85 ,0x45 ,0x87 ,0x47 ,0x46 ,0x86 ,0x82 ,0x42 ,0x43 ,0x83 ,0x41 ,0x81 ,0x80 ,0x40 , ;/* brief CRC16_Calculate CRC16 值计算* param pDate 待计算的数组 len 数组长度* retval 16 位校验值
展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 建筑环境 > 机械电气


copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!