📄 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 + -