/*==========================================
串口接收CRC校验(程翔宇 chanceller@163.com)
==========================================*/
#include <stdio.h>
#include <string.h>
//对串口接收的数据进行自后向前的移位存储
void shiftMemory(unsigned char *PBuf,unsigned char BufSize,unsigned char bufRec)
{
memmove(PBuf,PBuf+1,BufSize-1);//前面的字符左移一位
memset(PBuf+BufSize-1,bufRec,1);//末端填充新字符
//memcpy(PBuf+BufSize-1,&bufRec,1);//末端填充新字符
}
//CRC校验程序
unsigned short CrcCheck(unsigned char*bufOut,unsigned char *buf,unsigned char length)
{
unsigned short tmp,CRC;
unsigned char i,j,CRCHi,CRCLo;
memcpy(bufOut,buf,length); //前端存储原字符
bufOut[length+2]='\0'; //后端存储结束符
//CRC校验核心代码
CRC=0xFFFF;
for(i=0; i<length; i++)
{
CRC=buf[i]^CRC;
for(j=0;j<8;j++)
{
tmp=CRC&0x0001;
CRC=CRC>>1;
if(tmp)
CRC=CRC^0xA001;
}
}
CRCLo = CRC & 0x00FF;
CRCHi = CRC >> 8;
bufOut[length]=CRCLo; //CRC校验码存在原字符后面(低前高后)
bufOut[length+1]=CRCHi; //CRC校验码存在原字符后面(低前高后)
return CRC; //返回CRC校验码(高前低后)
}
/*========================================================
对移位寄存器中的字符串,进行CRC校验后,输出有效数据
PseRec有效数据输出
RecSt有效数据起始地址
RecLe有效数据字节长度
CrcSt校验位起始地址
CrcLe校验位字节长度
PserBuf移位寄存器首地址
========================================================*/
unsigned char seRecCrc(unsigned char *PseRec,unsigned char RecSt,unsigned char RecLe,unsigned char *PserBuf,unsigned char CrcSt,unsigned char CrcLe)
{
unsigned char i;
unsigned char buf2[CrcSt+CrcLe+3]; //定义二次校验字节数组
unsigned short crc2; //定义二次校验码存储变量
crc2=CrcCheck(buf2,PserBuf,CrcSt+2); //二次校验
if(crc2==0) //二次校验码为零,校验有效
{
memcpy(PseRec,PserBuf+RecSt,RecLe);//拷贝有效数据
return 1;//校验成功
}
else
{
return 0;//校验失败
}
}
int main()
{
unsigned char i,j;
//模拟串口收到的数据
unsigned char serChar[36] = {
'x','y','1',0x41,0x42,0x61,0x62,0x89,0x3B,'\r','\n','\0',
'x','z','1',0x43,0x44,0x63,0x64,0xE9,0xD3,'\r','\n','\0',
'x','a','1',0x45,0x46,0x65,0x66,0xC9,0x11,'\r','\n','\0',
};
unsigned char bufRec;//串口收到的字节
unsigned char BufSize=12;//串口移位缓存大小(9(=7+2)个有效字节)
unsigned char serBuf[BufSize];//串口移位缓存
unsigned char ch[3][2]={{0x78,0x79},{'x','z'},"xa"};//识别分割字符串(命令头)
//共用体。通过存储的有效字节DP[4],获得实际数据neData
union dataInt{
unsigned char DP[4];
int neData;
}DataRec;
for(i=0;i<36;i++)//模拟串口中断程序接收单字节程序
{
unsigned char CrcS=0;//校验是否成功标志
bufRec=serChar[i];//相当于:bufRec=SBUF,接收串口字符
shiftMemory(serBuf,BufSize,bufRec);//自后向前,移位存储
if(strncmp(serBuf,ch[0],2)==0)//判断是否收到命令头ch[0]
{
//CRC校验,并获得有效数据,存放在共用体中
CrcS=seRecCrc(DataRec.DP,3,4,serBuf,7,2);
//显示有效数据
if (CrcS) //CRC校验成功
{
printf("\n收到CH[0]命令\n提取的有效数据:");
for(j=0;j<4;j++)
{
printf("%02x ",DataRec.DP[j]);//低前高后
}
printf("\n");
printf("转化为整形数据:0x%08x\n",DataRec.neData);//高前低后
}
}
else if(strncmp(serBuf,ch[1],2)==0)//判断是否收到命令头ch[1]
{
//CRC校验,并获得有效数据,存放在共用体中
CrcS=seRecCrc(DataRec.DP,3,4,serBuf,7,2);
//显示有效数据
if (CrcS) //CRC校验成功
{
printf("\n收到CH[1]命令\n提取的有效数据:");
for(j=0;j<4;j++)
{
printf("%02x ",DataRec.DP[j]);//低前高后
}
printf("\n");
printf("转化为整形数据:0x%08x\n",DataRec.neData);//高前低后
}
}
else if(strncmp(serBuf,ch[2],2)==0)//判断是否收到命令头ch[2]
{
//CRC校验,并获得有效数据,存放在共用体中
CrcS=seRecCrc(DataRec.DP,3,4,serBuf,7,2);
//显示有效数据
if (CrcS) //CRC校验成功
{
printf("\n收到CH[2]命令\n提取的有效数据:");
for(j=0;j<4;j++)
{
printf("%02x ",DataRec.DP[j]);//低前高后
}
printf("\n");
printf("转化为整形数据:0x%08x\n",DataRec.neData);//高前低后
}
}
}
return 0;
}