/********************************************************************************************************** 建立头文件"transport.h" **********************************************************************************************************/ #ifndef __TRANSPORT_H #define __TRANSPORT_H #include "stm8_macro.h" /********************************************************* 接收数据帧: 1.结构 : 2字节帧头 + 1字节长度信息 + 数据 + 1字节校验码 2.移植 : 1).IC层,数据的接收中断与发送函数。 2).CRC_Calculation(u8* ),校验码计算 3.OUTPUT: 1).调用DataFrame_Receive()将接收到的原始数据经过处理、CRC校验, 将得到的有效数据帧存放于RcvFrameCache.Cache[]中,数据 不包含帧头。 2).接收数据超时:调用DataFrame_Receive()接收一帧数据的过程中, 超过(TIME_OUT)次扫描未接收到数据则输出超时Cmd_TimeOut。 3).调用getDataFrame(u8* buffer)从RcvFrameCache.Cache[]中获取数据帧 *********************************************************/ //////////////////////// 参数配置 //////////////////////// // 长度信息计算方法: // 0: 长度 = 长度信息本身字节数 + 数据 + 校验码 // 1: 长度 = 长度信息本身字节数 + 数据 // 2: 长度 = 数据 + 校验码 // 3: 长度 = 数据 #define LENGTH_METHOD (0L) #define FRAME_HEAD1 (0XFFul)//帧头1 #define FRAME_HEAD2 (0xF0ul)//帧头2 #define FRAME_LENGTH_MIN (5ul) //一帧数据的最小长度 #define FRAME_LENGTH_MAX (20ul) //一帧数据的最大长度 #define ROW_DATA_SIZE (100ul) // 接收到的原始数据缓存大小 #define FRAME_CACHE_SIZE (200ul) // 接收到的帧数据缓存大小 #define TIMEOUT_MECHANISMS_ENABLE 1 //超时处理机制 0:失能 1:使能 #if TIMEOUT_MECHANISMS_ENABLE != 0 #define TIME_OUT (500ul) //接收一帧数据超时的时间阈值, //单位:调用Command_Receive()函数的周期 #endif ////////////////////////////////////////////////////////// typedef enum { Cmd_NoCmd = 0, //未收到完整数据包 Cmd_OK, //接收成功 Cmd_TimeOut, //接收超时 Cmd_LEN_Wrong, //接收到的数据包错误(长度不在范围内) Cmd_CRC_Wrong //CRC校验错误 } _frameRes_; void Uart_Init(u32 baudrate); void UartSendData(u8 *ptr, u8 len); u8 UartSendStr(u8 *str); u8 CRC_Calculation(u8* pbuf); _frameRes_ DataFrame_Receive(void); _frameRes_ getDataFrame(u8 *buffer); u8 framePakage(u8 *buffer, const u8 cmdDataLen, ...); #endif /*__TRANSPORT_H*/ /********************************************************************************************************** 建立源文件"transport.c" ***********************************************************************************************************/ #include "transport.h" #include "stdarg.h" #include "stm8s.h" //从接收到的数据帧中获取 总长度 = 长度 + 数据 + 校验码 //len : 长度信息 #if LENGTH_METHOD == 0 #define GET_TOTAL_LENGTH(len) (len) #elif LENGTH_METHOD == 1 #define GET_TOTAL_LENGTH(len) (len+1) #elif LENGTH_METHOD == 2 #define GET_TOTAL_LENGTH(len) (len+1) #elif LENGTH_METHOD == 3 #define GET_TOTAL_LENGTH(len) (len+2) #else #error "wrong define LENGTH_METHOD !" #endif typedef enum{ FINDING_HEAD1 = 0, FINDING_HEAD2, NEED_LENGTH, GETTING_DATA, GETTING_CHECKSUM } RcvStatus_TypeDef; volatile struct{ u8 Reg[ROW_DATA_SIZE]; //串口接收到的原始数据缓存 u8 countTail; //串口接收计数 } RcvRawData; //接收到的原始数据 struct { u8 Cache[FRAME_CACHE_SIZE]; //接收有效指令缓存器,不包含帧头 u8 countTail; // } RcvFrameCache; //接收到的帧数据 //#define DEBUG #ifdef DEBUG struct { u16 correctNum; u8 errNum; u8 errbuf[256]; } FrameNum; #endif static void RowDataInput(u8 byte); //////////////////////////////////////////////////////////// //---------------------------------------------------------------- /******** IC层 ********/ /* @Function : UART初始化 8bit数据位,1位停止位,无校验位,允许接收和发送 @Input : 波特率 @Output : None **/ void Uart_Init(u32 baudrate) { UART2_Cmd(DISABLE); UART2_DeInit(); //恢复默认值 UART2_Init(baudrate, UART2_WORDLENGTH_8D, // 8bit数据位 UART2_STOPBITS_1, // 1bit停止位 UART2_PARITY_NO, // 无校验位 UART2_SYNCMODE_CLOCK_DISABLE, // 禁用同步模式 UART2_MODE_TXRX_ENABLE); // 发送、接收使能 UART2_ITConfig(UART2_IT_RXNE_OR, ENABLE); // 开接收中断 UART2_Cmd(ENABLE); // 使能UART2 } /* @Function : 发送数据 @Input : ptr 数据首地址 len 要发送的长度 @Output : None **/ void UartSendData(u8 *ptr, u8 len) { while(len--) { while(UART2_GetFlagStatus(UART2_FLAG_TXE) == RESET); UART2_SendData8(*ptr++); } } /* @Function : 发送数据 @Input : ptr 数据首地址 @Output : 发送的字节长度 **/ u8 UartSendStr(u8 *str) { u8 i; for(i=0; *str != 0x00; i++) { while(UART2_GetFlagStatus(UART2_FLAG_TXE) == RESET); UART2_SendData8(*str++); } return i; } /* @Function : UART2中断服务函数 @Input : None @Output : None **/ @far @interrupt void UART2_IRQHandler(void) { u8 byte; if(UART2_GetFlagStatus(UART2_FLAG_RXNE) != RESET) { UART2_ClearFlag(UART2_FLAG_RXNE); byte = UART2_ReceiveData8(); RowDataInput(byte); } } //---------------------------------------------------------------- /******** 传输层 ********/ /* @Function : CRC计算 @Input : ptr 数据帧首地址,不包含帧头(首地址内容为长度) @Output : CRC校验码 **/ u8 CRC_Calculation(u8* pbuf) { u8 len, check_code; len = pbuf[0]; check_code = (u8)(len ^ pbuf[1] ^ pbuf[len-3] ^ pbuf[len-2]); return check_code; } /* @Function : 数据帧CRC校验 @Input : ptr 数据帧首地址 @Output : 0 校验失败 1 校验成功 **/ static u8 CRC_Check(u8 *pbuf) { u8 len, check_code; len = pbuf[0]; check_code = CRC_Calculation(pbuf); if(check_code == pbuf[len-1]) { return 1; } return 0; } /* @Function : 数据复制 @Input : ptrdes ptrsrc len 复制的字节长度 @Output : 目的地址 **/ static void* mymemcpy(void* pdes, void* psrc, unsigned int len) { char* ptrdes = (char*)pdes; char* ptrsrc = (char*)psrc; if(pdes == 0 || psrc == 0) return pdes; if(ptrdes>ptrsrc?(ptrdes-ptrsrc= ROW_DATA_SIZE) { RcvRawData.countTail = 0; } RcvRawData.Reg[RcvRawData.countTail] = byte; } /* @Function : 接收数据帧(用于扫描接收数据) 接收到的数据存储于RcvFrameCache.Cache中 @Input : None @Output : 接收状态 **/ _frameRes_ DataFrame_Receive(void) { static u8 buffer[FRAME_LENGTH_MAX]; static RcvStatus_TypeDef RcvStatus; static u8 rec_countHead; static u8 cmd_offset; static u8 total_len; #ifdef TIMEOUT_MECHANISMS_ENABLE static u16 timeout; #endif u8 byte; _frameRes_ res = Cmd_NoCmd; if(rec_countHead != RcvRawData.countTail)//有接收到数据 { if(++rec_countHead >= ROW_DATA_SIZE) { rec_countHead = 0; } switch(RcvStatus) { case FINDING_HEAD1 : byte = RcvRawData.Reg[rec_countHead]; if(byte == (u8)(FRAME_HEAD1)) { RcvStatus = FINDING_HEAD2; #ifdef TIMEOUT_MECHANISMS_ENABLE timeout = 0x8000; #endif } break; case FINDING_HEAD2 : byte = RcvRawData.Reg[rec_countHead]; if(byte == (u8)(FRAME_HEAD2)) { RcvStatus = NEED_LENGTH; } else { RcvStatus = FINDING_HEAD1; } break; case NEED_LENGTH : byte = RcvRawData.Reg[rec_countHead]; if(byteFRAME_LENGTH_MAX) { RcvStatus = FINDING_HEAD1; res = Cmd_CRC_Wrong; break; } cmd_offset = 0; buffer[cmd_offset++] = byte; RcvStatus = GETTING_DATA; break; case GETTING_DATA : byte = RcvRawData.Reg[rec_countHead]; buffer[cmd_offset++] = byte; total_len = GET_TOTAL_LENGTH(buffer[0]); if(cmd_offset == total_len - 1) { RcvStatus = GETTING_CHECKSUM; } break; case GETTING_CHECKSUM : byte = RcvRawData.Reg[rec_countHead]; buffer[cmd_offset] = byte; RcvStatus = FINDING_HEAD1; timeout = 0; if(CRC_Check(buffer))//CRC校验 { if(RcvFrameCache.countTail + total_len - 1 >= FRAME_CACHE_SIZE) { mymemcpy(&RcvFrameCache.Cache[RcvFrameCache.countTail], buffer, (int)(FRAME_CACHE_SIZE - RcvFrameCache.countTail)); mymemcpy(&RcvFrameCache.Cache[0], buffer + (FRAME_CACHE_SIZE - RcvFrameCache.countTail), (int)(RcvFrameCache.countTail + total_len - FRAME_CACHE_SIZE)); RcvFrameCache.countTail = (u8)(RcvFrameCache.countTail + total_len - FRAME_CACHE_SIZE); } else { mymemcpy(&RcvFrameCache.Cache[RcvFrameCache.countTail], buffer, total_len); RcvFrameCache.countTail += total_len; } res = Cmd_OK; } else { res = Cmd_CRC_Wrong; } break; } } #if TIMEOUT_MECHANISMS_ENABLE != 0 else//没有接收到数据 { //超时计时 if(timeout & 0x8000) { if((++timeout & ~0x8000) >= TIME_OUT) { timeout = 0; RcvStatus = FINDING_HEAD1; res = Cmd_TimeOut; } } } #endif #ifdef DEBUG if(res == Cmd_OK) FrameNum.correctNum++; else if(res != Cmd_NoCmd) { static u8 Framecount = 0; FrameNum.errNum++; FrameNum.errbuf[Framecount++] = res; } #endif return res; } /* @Function : 获取数据帧(获取缓存中未处理的数据帧) 接收到的数据存储于RcvFrameCache.Cache中, @Input : buffer @Output : 接收状态 **/ _frameRes_ getDataFrame(u8 *buffer) { #ifdef DEBUG u8 i; u8 framebuf[FRAME_LENGTH_MAX]; #endif vu8 total_len; static u8 countHead; _frameRes_ fr = Cmd_NoCmd;; if(countHead != RcvFrameCache.countTail) { total_len = RcvFrameCache.Cache[countHead]; total_len = GET_TOTAL_LENGTH(total_len); if(countHead + total_len - 1 >= FRAME_CACHE_SIZE) { mymemcpy(buffer, &RcvFrameCache.Cache[countHead], (int)(FRAME_CACHE_SIZE - countHead)); mymemcpy(buffer + (FRAME_CACHE_SIZE - countHead), &RcvFrameCache.Cache[0], (int)(countHead + total_len - FRAME_CACHE_SIZE)); countHead = (u8)(countHead + total_len - FRAME_CACHE_SIZE); } else { mymemcpy(buffer, &RcvFrameCache.Cache[countHead], total_len); countHead += total_len; } fr = Cmd_OK; #ifdef DEBUG for(i=0; i