|
七 数据帧
在很多时候,通信时都是一帧一帧的数据,但数据帧的格式确不尽相同,特别是使用串口通信时,每个人使用的协议也不尽相同。为此,想写一个标准的数据帧处理基本是不现实的。但,很多时候,我们会使用带1、2字节帧头或1、2字节帧尾的通信格式,例如GPRS基本为0x0D、0x0A两字节结束,而GPS则使用$为头,以0x0D、0x0A为尾的格式,对于类似的数据帧我们则可以编写出一个标准的处理代码,下面就针对这种格式编写。
1. 结构体
- #if ((OS_CMM_MAX > 0) && (OS_CMM_FRM_EN > 0))
- typedef struct
- {
- // 帧数据格式 [1-数据长度,2-第一字节数据,2-第二字节数据]
- U8 Head[3]; // 头数据
- U8 Tail[3]; // 尾数据
-
- //--------------------------------------------------------------------------
- U8 HMrk; // 头标志
- U8 *RBuf; // 帧接收缓冲
- U16 RSiz; // 帧接收缓冲大小
- U16 RLen; // 帧接收长度
- } OS_CMM_FRM; // 帧
- #endif
复制代码
2. 初始化帧格式
数据帧格式众多,需要处理那种格式,得先定义好
- /**************************************************************************************
- * frame data
- **************************************************************************************/
- /**************************************************************************************
- * FunctionName : OSCmmInitFrm()
- * Description : 初始化帧
- * EntryParameter : pFrm - 帧缓冲
- * ReturnValue : None
- **************************************************************************************/
- #if ((OS_CMM_MAX > 0) && (OS_CMM_FRM_EN > 0))
- void OSCmmInitFrm(OS_CMM_FRM *pFrm, U8 *pHead, U8 *pTail)
- {
- memcpy(pFrm->Head, pHead, 3);
- memcpy(pFrm->Tail, pTail, 3);
- }
- #endif
复制代码
3. 创建帧缓冲
- /**************************************************************************************
- * FunctionName : OSCmmCreateFrm()
- * Description : 帧接收创建
- * EntryParameter : pFrm - 帧缓冲
- * ReturnValue : None
- **************************************************************************************/
- #if ((OS_CMM_MAX > 0) && (OS_CMM_FRM_EN > 0))
- void OSCmmCreateFrm(OS_CMM_FRM *pFrm, U8 *pBuf, U16 bufSize)
- {
- pFrm->RLen = 0x0000; // 初始化计数器
- pFrm->RSiz = bufSize; //
- pFrm->RBuf = pBuf;
-
- memset(pFrm->RBuf, 0, pFrm->RSiz); // 清缓冲
- }
- #endif
复制代码
4. 清空数据帧
- /**************************************************************************************
- * FunctionName : OS_CmmClrFrm()
- * Description : 清除接收缓冲
- * EntryParameter : pFrm - 帧缓冲
- * ReturnValue : None
- **************************************************************************************/
- #if ((OS_CMM_MAX > 0) && (OS_CMM_FRM_EN > 0))
- void OSCmmClrFrm(OS_CMM_FRM *pFrm)
- {
- pFrm->HMrk = 0x00;
- pFrm->RLen = 0x0000; // 初始化计数器
- memset(pFrm->RBuf, 0, pFrm->RSiz); // 清缓冲
- }
- #endif
复制代码
5. 头尾判断
用于判断接收缓冲区中的,数据头和数据尾
- /**************************************************************************************
- * FunctionName : OS_CmmHeadFrm()
- * Description : 数据头处理
- * EntryParameter : pFrm - 帧缓冲,dat - 数据
- * ReturnValue : None
- **************************************************************************************/
- #if ((OS_CMM_MAX > 0) && (OS_CMM_FRM_EN > 0))
- void OS_CmmHeadFrm(OS_CMM_FRM *pFrm, U8 dat)
- {
- if (dat == pFrm->Head[pFrm->HMrk+1])
- {
- pFrm->RBuf[pFrm->RLen++] = dat;
- pFrm->HMrk++;
- }
- else
- {
- OSCmmClrFrm(pFrm);
- }
- }
- #endif
- /**************************************************************************************
- * FunctionName : OS_CmmTailFrm()
- * Description : 数据尾处理
- * EntryParameter : pFrm - 帧缓冲
- * ReturnValue : None
- **************************************************************************************/
- #if ((OS_CMM_MAX > 0) && (OS_CMM_FRM_EN > 0))
- OS_BOOL OS_CmmTailFrm(OS_CMM_FRM *pFrm)
- {
- if (pFrm->Tail[0] == 1)
- {
- if (pFrm->RBuf[pFrm->RLen-1] == pFrm->Tail[1]) // 获取一帧数据
- {
- return OS_TRUE;
- }
- }
- else if (pFrm->Tail[0] == 2) // 两字节帧头
- {
- if ((pFrm->RBuf[pFrm->RLen-2] == pFrm->Tail[1]) && // 获取一帧数据
- (pFrm->RBuf[pFrm->RLen-1] == pFrm->Tail[2]))
- {
- return OS_TRUE;
- }
- }
-
- return OS_FALS;
- }
- #endif
复制代码
6. 获取一帧数据
- /**************************************************************************************
- * FunctionName : OS_CmmGetFrm()
- * Description : 获取数据帧
- * EntryParameter : None
- * ReturnValue : 获取一帧返回OS_TRUE,否则返回OS_FALS
- **************************************************************************************/
- #if ((OS_CMM_MAX > 0) && (OS_CMM_FRM_EN > 0))
- OS_BOOL OS_CmmGetFrm(U8 num, OS_CMM_FRM *pFrm)
- {
- U8 tmpDat;
- for (U16 i=0; i<OSCmmGetLen(num); i++) // 循环处理数据
- {
- if (OSCmmReadByte(num, &tmpDat) == OS_TRUE) // 读取一字节数据
- {
- if (pFrm->HMrk < pFrm->Head[0]) // 未读到头
- {
- OS_CmmHeadFrm(pFrm, tmpDat); // 头处理
- }
- else
- {
- pFrm->RBuf[pFrm->RLen++] = tmpDat; // 数据存储
- if (OS_CmmTailFrm(pFrm) == OS_TRUE) // 尾处理
- {
- return OS_TRUE;
- }
-
- if (pFrm->RLen > pFrm->RSiz) // 越界判断
- {
- OSCmmClrFrm(pFrm);
- }
- }
- }
- }
- return OS_FALS;
- }
- #endif
复制代码
7. 接收数据的处理
- /**************************************************************************************
- * FunctionName : OSCmmRcvPro()
- * Description : 接收数据处理
- * EntryParameter : pCmm - 接收,pFrm - 帧缓冲
- * ReturnValue : None
- **************************************************************************************/
- #if ((OS_CMM_MAX > 0) && (OS_CMM_FRM_EN > 0))
- OS_BOOL OSCmmRcvPro(U8 num, OS_CMM_FRM *pFrm)
- {
- while (OSCmm[num].RCnt != OSCmm[num].WCnt) // 缓冲中有数据
- {
- if (OS_CmmGetFrm(num, pFrm) == OS_TRUE)
- {
- return OS_TRUE;
- }
- }
-
- return OS_FALS;
- }
- #endif
- /**************************************************************************************
- * end of file
- **************************************************************************************/
复制代码
|
|