?? recv.c
字號:
/******************************************************************************
* 源程序文件名: recv.c *
* 功能: 串行通信接收模塊 *
* 說明: 本文件中包含的子模塊有:接收串行數據,檢查數據的正確性 *
******************************************************************************/
/* 加載頭文件 */
# include "crc.h"
# include "recv.h"
# include "machine.h"
# include "ctrlout.h"
# include "chksafety.h"
/* 從發射機接收的數據 */
SioPackRecvBuf SioRecvBuf;
unsigned char cSioRecvBufEnd;
unsigned char cRecvBufType;
unsigned int nflgCommDatRight;
unsigned char cflgCommDatOvertime;
/******************************************************************************
* 函數原型: void InitDataRecv(void); *
* 功能: 數據接收模塊相關變量的初始化 *
* 說明: 無 *
******************************************************************************/
void InitDataRecv (void)
{
cSioRecvBufEnd = 0;
cRecvBufType = 0x00;
nflgCommDatRight = CommDatRightTime0;
cflgCommDatOvertime = 0;
}
/******************************************************************************
* 函數原型: void RecvMOnTimeReadRxBuf(void); *
* 功能: 將接收緩沖區中的數據轉移到SioRecvBuf.buf中 *
* 說明: 無 *
******************************************************************************/
void RecvMOnTimeReadRxBuf (void)
{
int n, m;
if(cUART1RxEnd == cUART1RxHead) // 如果UART1接收緩沖區中無數據
return; // 返回
// 留2個字節的余量
n = CMSioRecvPackLenMax-cSioRecvBufEnd-2; // 最多接收的字節數
m = UART1GetRx(SioRecvBuf.buf+cSioRecvBufEnd,n); // 接收數據,m為實際接收到的字節數
cSioRecvBufEnd += m; // 重新設置SioRecvBuf.buf的尾
}
/******************************************************************************
* 函數原型: int RecvMOnTimeCheckLead(void); *
* 功能: 在SioRecvBuf.buf中尋找包頭 *
* 說明: 1.UniversalPackLead未被定義 *
* 2.返回值為接收包"類型+序列"的下標 *
* 3.注意:連續2個FF+1個非FF即認為收到了正確的包!!! *
******************************************************************************/
int RecvMOnTimeCheckLead (void)
{
# ifdef UniversalPackLead
int i, j, k;
for(k = 0; k < cSioRecvBufEnd; k++)
{
for(i = k; i < cSioRecvBufEnd; i++)
if(SioRecvBuf.buf[i] == 0x00FF)
break;
if(i+CMSioRecvPackLenMin > cSioRecvBufEnd)
break;
for(j = i; j < cSioRecvBufEnd; j++)
if(SioRecvBuf.buf[j] != 0x00FF)
break;
if(j-i >= CMSioLeadLenMin)
return j;
}
return 0;
# else // UniversalPackLead
# define p SioRecvBuf.buf
int k;
for(k = 2; k < cSioRecvBufEnd; k++)
if(p[k-2] == 0xFF && p[k-1] == 0xFF && p[k-0] != 0xFF)
return k;
return 0;
# undef p
# endif // UniversalPackLead
}
/******************************************************************************
* 函數原型: void RecvMOnTimeNormalBuf(int lead); *
* 功能: 將接收到的有效包移至SioRecvBuf.buf的起始位置 *
* 說明: 1.注意不同情況的處理方式 *
* 2.將SioRecvBuf.buf的前3個字節設置成引導字節 *
******************************************************************************/
void RecvMOnTimeNormalBuf (int lead)
{
int n, adj, len;
n = cSioRecvBufEnd-CMSioLeadLenMax; // n = cSioRecvBufEnd-4
if(n <= 0) // 如果SioRecvBuf.buf中的數據不超過4字節
return; // 不處理,返回
if(!lead) // 如果沒有找到"FF+FF+非FF"的包頭
{
// __memmovebufforlittle
__memmovebuf(SioRecvBuf.buf,n,CMSioLeadLenMax); // 移動最末尾的4個字節到包的頭部,以便不
// 影響下一次尋找包頭的操作(有效包最多有
// 4個字節的引導字)
cSioRecvBufEnd = CMSioLeadLenMax; // 設置包尾為4
return; // 處理完畢,返回
}
if(lead == CMSioLeadLen) // 如果包類型字節的下標是3
return; // 不必處理,返回
adj = lead-CMSioLeadLen; // 統一將有效包調整為有3個引導字
len = cSioRecvBufEnd-(adj>0?adj:0); // lead最小值為2,adj有小于0的情況
// __memmovebufforlittle(lead>3) or __memmovebufforlarge(lead==2)
__memmovebuf(SioRecvBuf.buf,adj,len); // 前3個字節均為引導字
cSioRecvBufEnd -= adj; // 重新設置包尾
}
/******************************************************************************
* 函數原型: int CRCChk(char *cp, char nn); *
* 功能: 對接收到的數據包進行CRC校驗 *
* 說明: 1.cp指向需校驗數據包的包頭,nn為有效數據的長度(不含CRC校驗碼) *
* 2.返回值為1說明傳輸無差錯 *
******************************************************************************/
int CRCChk (char *cp, char nn)
{
SioPackCRC *crcp, crc;
// crcp指向包的CRC1
crcp = (SioPackCRC *)(cp+nn);
// cp指向包的第1個有效字節,nn為有效字節的長度
crc = crc1608strrevCRC16(cp, nn, NULL);
return crc==*crcp?1:0;
}
/******************************************************************************
* 函數原型: int MachineAddrChk(unsigned int addr, int Rc); *
* 功能: 檢查并設定遙控器的機器地址 *
* 說明: 1.addr為要設定的地址值,Rc為設定機器地址的標志(1有效) *
* 2.注意本函數在不同情況下的返回值,返回0表示地址校驗失敗 *
* 3.遙控器的ID號一旦被設置,將永遠不能用常規的辦法更改該ID號,且不再接受 *
* 通用機器地址 *
******************************************************************************/
int MachineAddrChk (unsigned int addr, int Rc)
{
nMachineAddr = (unsigned int)GetMachineAddr(); // 從單片機內獲取機器的ID號
if(nMachineAddr == addr) // 如果對碼成功
return 1; // 返回1!
if(nMachineAddr == NoMachineAddr && addr == UniversalMachineAddr)
// 如果機器尚未設置ID號且接收的地址為通
// 用的機器地址
return 2; // 返回2!
if(nMachineAddr == NoMachineAddr && Rc == 1) // 如果機器尚未設置ID號且接收到的數據包
// 通過了CRC校驗
{
PutMachineAddr((unsigned long)addr); // 為機器設置ID號
return 3; // 返回3!
}
return 0; // 出現錯誤,返回0!
}
/******************************************************************************
* 函數原型: void RecvMOnTimeDebug(void); *
* 功能: 收到"調試"包的處理 *
* 說明: 不做任何事情 *
******************************************************************************/
void RecvMOnTimeDebug (void)
{
return;
}
/******************************************************************************
* 函數原型: int RecvMOnTimeCheckData(void); *
* 功能: 對收到的包進行整體校驗 *
* 說明: 1.本函數依次進行CRC校驗和機器地址校驗 *
* 2.注意本函數在不同情況下的返回值 *
******************************************************************************/
int RecvMOnTimeCheckData (void)
{
SioPackHead *pack;
char type, len;
unsigned char *cp;
int Rc, Ra, i = 0;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -