/******************************************/
/***********计算法求CRC-8校验码************/
/******************************************/
//本程序包含3种CRC8校验码计算的方法:
//1、多项式为X^8+X^2+X^1+X^0=263,16进制为0x107;
//2、多项式为X^8+X^2+X^1+X^0=263,16进制为0x107,计算方法与第一种不同;
//3、多项式为X^8 + X^5 + X^4 + 1=0x8c(字节向右移位,0X31的反转);
/******************************************/
/******************************************/
#include "reg669.h"
#include"string.h"
#include"stdio.h"
/******************************************/
#define INBUF 10
typedef unsigned char uchar;
typedef unsigned int uint;
uchar xdata Long0;
uint crc_8(uchar *ptr,uchar len);
uchar xdata UART0_count=0;
uchar xdata UART0_inbuf[INBUF];
uchar xdata crc_8_buff[]={0x00,0x01,0x02,0x03};
bit UART0_read_flag=0;
uint crc;
/******************************************/
void Uart0_Init()
{
S0STAT=0x20;//区分接收和发送中断;
S0CON=0x50; //串行口工作方式1,允许串行接收;
TMOD=0x20; //定时器T1工作方式2;
TCON=0x40; //TR1=1,T1运行控制位打开;
PCON=0x00; //SMOD=0;
TH1=0xD0; //串行口0波特率2400;
TL1=0xD0;
EA=1; //使能所有中断;
ES0=1; //打开串行中断0;
ET1=0; //定时器T1中断允许;
}
/******************************************/
/********向串口0发送一个ASCII字符*********/
/******************************************/
void UART0_Send_char(unsigned char u0_a)
{
S0BUF=u0_a; //将ASCII字符放入串口0发送缓冲区;
while(TI_0==0); //等待TI_0==1;
TI_0=0; //发送中断标志位清零;
}
/*****************************************/
/*********通讯中断接收程序(串口0)*******/
/*****************************************/
void UART0_Inpt()interrupt 4 //中断号10;
{
if(RI_0)
{
unsigned char ch;
RI_0=0;
ch=S0BUF;
if(ch==0x2E)
{
UART0_inbuf[UART0_count]=ch;
Long0=UART0_count;
UART0_count=0;
UART0_read_flag=1;
}
else
{
UART0_inbuf[UART0_count]=ch;
UART0_count++;
}
}
}
void main(void)
{
uchar *ptr;
Uart0_Init();
RI_0=0;
ES0=0;
ptr=crc_8_buff;//缓冲区首地址;
crc=crc_8(ptr,4);
UART0_Send_char(crc);
ES0=1;
while(1)
{
if(UART0_read_flag)
{
UART0_read_flag=0;
ES0=0;
crc=0;
ptr=UART0_inbuf;
crc=crc_8(ptr,Long0);
UART0_Send_char(crc);
ES0=1;
}
}
}
/*******************************/
/**8位CRC校验码计算函数方法1****/
/*******************************/
/*******************************
第一个字节向左移位(高位先行),如果进位了则和多项式异或,
得到的结果继续移位;重复以上过程,把8 位移完,
计算成功。1Byte移8次;得到了CRC。再算下一个,其它都相同,
前次的结果这次来抑或。遇1就运算,遇0 就前进。
********************************/
/*
uint crc_8(uchar *ptr,uchar len)
{
uchar i;
crc=0;
while(len--)
{
for(i=0x80;i!=0;i>>=1)//8次循环右移,每一位相应计算;
{
if((crc&0x80)!=0) //检查余式最高位是否为0;
{
crc<<=1; //如果最高位不为0,则余式左移一位;
crc^=0x07; //余式异或多项式,多项式为X^8+X^2+X^1+X^0=263,16进制为0x107,因数据位为8位,故取0x07;
}
else
{
crc<<=1; //如果余式最高位是0,则余式只左移一位,不异或多项式;
}
if((*ptr&i)!=0) crc^=0x07;//检查8次循环是否结束,如果结束,则ptr++,否则余式异或多项式;
}
ptr++;
}
return(crc);
}
*/
/*******************************/
/**8位CRC校验码计算函数方法2****/
/*******************************/
/*******************************
第一个字节向左移位(高位先行)
1、预置8位crc寄存器初值0;
2、把第一个8位数据与crc寄存器相异或,并检查最高位是否为1;
3、把寄存器的内容向左移一位;
4、数据内容同时左移一位;
5、检查最高位是否为1,如果为1,crc寄存器与多项式码进行异或;
6、如果高位为0,再次移位;
7、重复2、3、4、5、6步,直到左移8次,这样整个8位数据全部进行了处理;
8、数据指针加1;
9、重复步骤2到8,进行下一个8位数据的处理;
10、最后得到的crc寄存器即为crc码。
/********************************/
/*
uint crc_8(uchar *ptr,uchar len)
{
unsigned int i, f;
crc=0; //预置8位crc寄存器初值0;
while(len--)
{
for (i = 0; i < 8; ++i) //8次循环左移,每一位相应计算;
{
f=(*ptr^crc)&0x80; //把第一个8位数据与crc寄存器相异或,并检查最高位是否为1;
crc <<= 1; //寄存器的内容向左移一位;
*ptr <<= 1; //数据内容同时左移一位;
if(f) crc^=0x07; //检查最高位是否为1,如果为1,crc寄存器与多项式码进行异或;
}
ptr++ ; //指针加1;
}
return (crc); //返回crc码。
}
*/
/*******************************/
/**8位CRC校验码计算函数方法3****/
/*******************************/
/*******************************
第一个字节向右移位(低位先行)
1、预置8位crc寄存器初值0;
2、把第一个8位数据与crc寄存器相异或,并检查最低位是否为1;
3、把寄存器的内容向右移一位;
4、数据内容同时右移一位;
5、检查最低位是否为1,如果为1,crc寄存器与多项式码进行异或;
6、如果低位为0,再次移位;
7、重复2、3、4、5、6步,直到右移8次,这样整个8位数据全部进行了处理;
8、数据指针加1;
9、重复步骤2到8,进行下一个8位数据的处理;
10、最后得到的crc寄存器即为crc码。
/********************************/
uint crc_8(uchar *ptr,uchar len)
{
uchar i,f;
crc=0; //预置8位crc寄存器初值0;
while(len--)
{
for (i = 0; i < 8; ++i)
{
f = (*ptr^crc) & 1; //把第一个8位数据与crc寄存器相异或,并检查最低位是否为1;
crc >>= 1; //把寄存器的内容向右移一位;
*ptr >>= 1; //数据内容同时右移一位;
if (f) crc ^= 0x8c; //检查最低位是否为1,如果为1,crc寄存器与多项式码进行异或;
}
ptr++; //数据指针加1;
}
return(crc); //返回crc码。
}