您的位置:首页 > 移动开发 > Android开发

CRC16 单片机版(C语言版) VC版 android版(java) 测试通过

2013-12-26 15:31 549 查看
CRC校验的基本思想是利用线性编码理论

C语言版 单片机版 VC版

/*********************************************************************

*文件名:crc16.c

*功能: 计算CRC16循环冗余校验程序,所用方法为计算法 。

**********************************************************************/

unsigned int crc16(unsigned char *str, unsigned char num) //CRC计算子程序

{

unsigned char i,j;

unsigned int crc;

crc=0xffff;
//初始化

for (i=0;i<num;i++)

{

crc^=str[i]&0x00ff; //异或 相异出1

for (j=0;j<8;j++)//

{

if (crc&0x0001)

{

crc>>=1;
//移位

crc^=0xa001; //异或 1010 0000 0000 0001

}

else

crc>>=1;

}

}

return(crc);

}

android版(java)

package crctest;

public class crctest {

public static void main(String[] arg) {
System.out.println("test");
byte power = 0x53;
byte num = 0;
byte type = 0x06;
byte pow_con = 0;
byte gncs = 0x01;
byte zkb = 0x02;
short sddl = 20;
short sddy = 42;
short sdgl = 500;
short mcpl = 10;
short mcdl = 5;
short ydl = 5;
byte sj[] = { power, num, type, pow_con, gncs, zkb,
(byte) (sddl * 1000 % 256), (byte) (sddl * 1000 / 256),
(byte) (sddy * 1000 % 256), (byte) (sddy * 1000 / 256),
(byte) (sdgl % 256), (byte) (sdgl / 256), (byte) (mcpl % 256),
(byte) (mcpl / 256), (byte) (mcdl * 1000 % 256),
(byte) (mcdl * 1000 / 256), (byte) (ydl * 1000 % 256),
(byte) (ydl * 1000 / 256) }; // 53 0C 06 00 C8 00 00 0F 39 00 64
// 78
// byte sj[]={0x53,0x07,0x06,0x00,0x07,0x6C };
short i, j;
sj[1] = (byte) (sj.length + 2);
i = crc16(sj, (byte) (sj.length));
//System.out.printf("%4X\n",i); //
for (j = 0; j < (byte) (sj.length); j++)
System.out.printf("%02X ", sj[j]); // 打印

System.out.printf("%02X %02X", i % 256, i / 256); // 低字节 高字节   93 25
}

public static short crc16(byte[] str, byte num) // CRC计算子程序
{
byte i, j;
int crc;
crc = (int) (0xffff);
for (i = 0; i < num; i++) {
crc ^= (int) (str[i] & 0x00ff);

for (j = 0; j < 8; j++) {
if ((crc & 0x0001) == 1) {
crc >>= 1;
crc ^= 0xa001;
} else
crc >>= 1;
}
}
return (short)(crc);
}
}


java版更新1 上面有错误

public class crctest {

public static void main(String[] arg) {
System.out.println("test");
/*	byte power = 0x53;
byte num = 0;
byte type = 0x06;
byte pow_con = 0;
byte gncs = 0x01;
byte zkb = 0x02;
short sddl = 20;
short sddy = 42;
short sdgl = 500;
short mcpl = 10;
short mcdl = 5;
short ydl = 5;
byte sj[] = { power, num, type, pow_con, gncs, zkb,
(byte) (sddl * 1000 % 256), (byte) (sddl * 1000 / 256),
(byte) (sddy * 1000 % 256), (byte) (sddy * 1000 / 256),
(byte) (sdgl % 256), (byte) (sdgl / 256), (byte) (mcpl % 256),
(byte) (mcpl / 256), (byte) (mcdl * 1000 % 256),
(byte) (mcdl * 1000 / 256), (byte) (ydl * 1000 % 256),
(byte) (ydl * 1000 / 256) }; // 53 0C 06 00 C8 00 00 0F 39 00 64
*/										// 78
byte sj[]={0x01,0x10,0x00,(byte) 0xC9,0x00,0x10,0x10,(byte) 0xE6,(byte) 0x88,(byte) 0x91,(byte) 0xE6,(byte) 0x98,(byte) 0xAF,(byte) 0xE8,(byte) 0xB0,(byte) 0x81,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };
int i, j;
//sj[1] = (byte) (sj.length + 2);
i = (int) crc16(sj, (byte) (sj.length));
//System.out.printf("%4X\n",i); //
for (j = 0; j < (byte) (sj.length); j++)
System.out.printf("%02X ", sj[j]); // 打印

System.out.printf("%02X %02X", (byte)(i % 256), (byte)(i / 256)); // 低字节 高字节   93 25
}

public static int crc16(byte[] str, byte num) // CRC计算子程序
{
byte i, j;
int crc;
crc = (int) (0xffff);
for (i = 0; i < num; i++) {
crc ^= (int) (str[i] & 0x00ff);

for (j = 0; j < 8; j++) {
if ((crc & 0x0001) == 1) {
crc >>= 1;
crc ^= 0xa001;
} else
crc >>= 1;
}
}
return (int)(crc);
}
}


附:测试

#include <stdio.h>

/*********************************************************************

*文件名:crc16.c

*功能: 计算CRC16循环冗余校验程序,所用方法为计算法 。

**********************************************************************/

unsigned int crc16(unsigned char *str, unsigned char num) //CRC计算子程序

{

unsigned char i,j;

unsigned int crc;

crc=0xffff;
//初始化

for (i=0;i<num;i++)

{

crc^=str[i]&0x00ff; //异或 相异出1

for (j=0;j<8;j++)//

{

if (crc&0x0001)

{

crc>>=1;
//移位

crc^=0xa001; //异或 1010 0001

}

else

crc>>=1;

}

}

return(crc);

}

void main()

{

unsigned char power=0x53;

unsigned char num=0;

unsigned char type=0x06;

unsigned char pow_con=0;

unsigned char gncs=0x01;

unsigned char zkb=0x02;

unsigned int sddl=20;

unsigned int sddy=42
;

unsigned int sdgl=500;

unsigned int mcpl=10
;

unsigned int mcdl=5
;

unsigned int ydl=5 ;

unsigned char sj[]={power,num,type,pow_con,gncs,zkb,sddl*1000%256,sddl*1000/256,sddy*1000%256,sddy*1000/256,sdgl%256,sdgl/256,mcpl%256,mcpl/256,mcdl*1000%256,mcdl*1000/256,ydl*1000%256,ydl*1000/256}; //53 0C 06 00 C8 00
00 0F 39 00 64 78

// unsigned char sj[]={0x53,0x07,0x06,0x00,0x07,0x6C };

unsigned int i,j;

sj[1]=sizeof(sj)+2;

i=crc16(sj,sizeof(sj));

// printf("%4X\n",i); //

for(j=0;j<sizeof(sj);j++)

printf("%02X ",sj[j]); //打印

printf("%02X %02X",i%256,i/256); //低字节 高字节 93 25

while(1);

}

// PSerialPort.h: interface for the CPSerialPort class.
//
//////////////////////////////////////////////////////////////////////

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

//typedef void (*LPDataArriveProc)(char *data,int length,DWORD userdata);    //函数指针

class CPSerialPort
{
//扩展

public:

BOOL hexSend;  //
BOOL hexReceive;
BOOL SendStr(CString str);
CString ReceiveStr(void);

public:
CPSerialPort();
virtual ~CPSerialPort();

BOOL OpenPort(LPCTSTR Port,int Baudrate,int DataBits,int StopBits,int Parity,DWORD userdata=0); //打开串口
BOOL ClosePort(); //关闭串口

DWORD ReadDataWaiting( void );
DWORD ReadData( void *buffer, DWORD limit );

DWORD WritePort(void *data,int length); //发送数据
DWORD WriteFileToPort(LPCTSTR FileName); //发送文件

unsigned int CPSerialPort::crc16(unsigned char *str, unsigned char num);               //CRC计算子程序

private:

HANDLE m_hComm; //串口设备handle
HANDLE m_hReadThread; //读串口线程handle
BOOL m_bReceiving; //是否持续接收
int m_nBufferSize; //缓冲大小

char *Buffer; //缓冲区

//	LPDataArriveProc m_lpDataArriveProc;
DWORD m_dwUserData;

//串口设置以及超时参数
DCB dcb;
COMMTIMEOUTS CommTimeOuts;
protected:
OVERLAPPED m_OverlappedRead;
};


// PSerialPort.cpp: implementation of the CPSerialPort class.

//
//接收可以用线程或定时  每次最大接收LIMIT  陈
//默认为十六进制接收与发送  发送时去空格
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
//#include "SerialPort.h"
#include "PSerialPort.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

#define MAX_READ_BUFFER 16384
#define MAX_WRITE_BUFFER 16384

#define LIMIT 100  //接收的最大字节数
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CPSerialPort::CPSerialPort()  //
{
memset( &m_OverlappedRead, 0, sizeof( OVERLAPPED ) );
m_hComm=INVALID_HANDLE_VALUE;//无准句柄值
m_hReadThread=NULL;
m_bReceiving=FALSE;
m_nBufferSize=1024; //缓冲大小

hexSend=TRUE;
hexReceive=TRUE;
}
CPSerialPort::~CPSerialPort()
{
ClosePort();
}

BOOL CPSerialPort::OpenPort(LPCTSTR Port,int BaudRate,int DataBits,int StopBits,int Parity,DWORD userdata)
{

m_dwUserData=userdata;

if(m_hComm==INVALID_HANDLE_VALUE)
{
m_hComm=CreateFile(Port,GENERIC_READ|GENERIC_WRITE,0,0,OPEN_EXISTING,0,0);   // OPEN_EXISTING, //打开现有的还不是创建 // 同步I/O操作
if(m_hComm==INVALID_HANDLE_VALUE )
{
AfxMessageBox(_T("无法打开端口!请检查是否已被占用。"));
return FALSE;
}
GetCommState(m_hComm,&dcb);  //获取串口的初始配置
dcb.BaudRate=BaudRate;	//波特率,指定通信设备的传输速率。
dcb.ByteSize=DataBits;  // 通信字节位数,4—8
dcb.Parity=Parity;		//奇偶校验方法
dcb.StopBits=StopBits;  //指定停止位的位数。
dcb.fParity=FALSE;
dcb.fBinary=TRUE;
dcb.fDtrControl=0;
dcb.fRtsControl=0;
dcb.fOutX=dcb.fInX=dcb.fTXContinueOnXoff=0;

//设置状态参数
SetCommMask(m_hComm,EV_RXCHAR);		//指定一组监视通信设备的事件  EV_RXCHAR:输入缓冲区中已收到数据,即接收到一个字节并放入输入缓冲区。
SetupComm(m_hComm,MAX_READ_BUFFER,MAX_WRITE_BUFFER);	//设置I/O缓冲区的大小

if(!SetCommState(m_hComm,&dcb))	//设置COM口的设备控制块
{
AfxMessageBox(_T("无法按当前参数配置端口,请检查参数!"));
PurgeComm(m_hComm,PURGE_TXCLEAR|PURGE_RXCLEAR);		//	清空缓冲区
ClosePort();    //关闭串口
return FALSE;
}
//设置超时参数  这个一直在读,重新设
//RI:-1 RM:-1 RC:-2 WM:0 WC:0
GetCommTimeouts(m_hComm,&CommTimeOuts);		//获取串口的初始超时配置
CommTimeOuts.ReadIntervalTimeout=-1;		//最大值0xffff ffff
CommTimeOuts.ReadTotalTimeoutMultiplier=-1;
CommTimeOuts.ReadTotalTimeoutConstant=-2;
CommTimeOuts.WriteTotalTimeoutMultiplier=0;
CommTimeOuts.WriteTotalTimeoutConstant=0;

/*

//设置超时参数  这个一直在读,重新设
GetCommTimeouts(m_hComm,&CommTimeOuts);
CommTimeOuts.ReadIntervalTimeout=100;
CommTimeOuts.ReadTotalTimeoutMultiplier=1;
CommTimeOuts.ReadTotalTimeoutConstant=100;
CommTimeOuts.WriteTotalTimeoutMultiplier=0;
CommTimeOuts.WriteTotalTimeoutConstant=0;
*/

if(!SetCommTimeouts(m_hComm,&CommTimeOuts)) 	//设置串口的超时配置
{
AfxMessageBox(_T("无法设置超时参数!"));
PurgeComm(m_hComm,PURGE_TXCLEAR|PURGE_RXCLEAR);
ClosePort();
return FALSE;
}

PurgeComm(m_hComm,PURGE_TXCLEAR|PURGE_RXCLEAR);

return TRUE;
}

return FALSE;
}

BOOL CPSerialPort::ClosePort()
{
if(m_hComm!=INVALID_HANDLE_VALUE)
{
SetCommMask(m_hComm,0);
PurgeComm(m_hComm,PURGE_TXCLEAR|PURGE_RXCLEAR);
CloseHandle(m_hComm);
m_hComm=INVALID_HANDLE_VALUE;
return TRUE;
}

return TRUE;
}
DWORD CPSerialPort::ReadDataWaiting( void )				//在使用ReadFile 函数进行读操作前,应先使用ClearCommError函数清除错误。
{
if(m_hComm==INVALID_HANDLE_VALUE || m_hComm == NULL)
return( 0 );

DWORD dwErrorFlags;
COMSTAT ComStat;

ClearCommError( m_hComm, &dwErrorFlags, &ComStat );		//获得通信错误并报告串口的当前状态,同时,该函数清除串口的错误标志以便继续输入、输出操作。

return ( ComStat.cbInQue );   //输入缓冲区的字节数
}
DWORD CPSerialPort::WritePort(void *data,int length)
{
if(m_hComm==INVALID_HANDLE_VALUE)
{
return 0;
}

BOOL fWriteState;
DWORD dwBytesWritten=0;

fWriteState=WriteFile(m_hComm,data,length*sizeof(char),&dwBytesWritten,NULL);

return dwBytesWritten;
}

DWORD CPSerialPort::ReadData( void *buffer, DWORD limit )
{
BOOL bReadStatus;
DWORD dwBytesRead;

dwBytesRead=ReadDataWaiting();
if(dwBytesRead==0) return( 0 );
if(dwBytesRead>limit)
dwBytesRead=limit;			//取最小值

bReadStatus = ReadFile( m_hComm, buffer, dwBytesRead, &dwBytesRead, &m_OverlappedRead );
if( !bReadStatus ){
if( GetLastError() == ERROR_IO_PENDING ){	 //GetLastError()函数返回ERROR_IO_PENDING,表明串口正在进行读操作
WaitForSingleObject( m_OverlappedRead.hEvent, 2000 );   //使用WaitForSingleObject函数等待,直到读操作完成或延时已达到2秒钟
//当串口读操作进行完毕后,m_osRead的hEvent事件会变为有信号
return( dwBytesRead );  //返回读到的字节数
}
return( 0 );
}
return( dwBytesRead ); //返回读到的字节数

}

DWORD CPSerialPort::WriteFileToPort(LPCTSTR FileName)
{
if(m_hComm==INVALID_HANDLE_VALUE)
{
return 0;
}

CFile cf;

BOOL fWriteState;
DWORD dwBytesWritten;
DWORD dwCharToWrite;

dwCharToWrite=0;

if(!cf.Open(FileName,CFile::modeRead))
{
//AfxMessageBox(_T("无法打开Hex文件!"));
return 0;
}
dwCharToWrite=(DWORD)cf.GetLength();
cf.Seek(0,CFile::begin);
dwBytesWritten=0;

if(m_hComm!=INVALID_HANDLE_VALUE&&dwCharToWrite!=0)
{
char* buf=new char[dwCharToWrite];
cf.Read(buf,dwCharToWrite);

fWriteState=WriteFile(m_hComm,buf,dwCharToWrite*sizeof(char),&dwBytesWritten,NULL);
if(!fWriteState)
{
//AfxMessageBox(_T("无法向端口写入数据!"));
}
delete[] buf;
}
cf.Close();
return dwBytesWritten;
}

CString CPSerialPort::ReceiveStr(void)
{

//处理收到的数据
unsigned char *data = new unsigned char[LIMIT];
DWORD length= ReadData(data, LIMIT);
if(length)
{
CString THex(_T(""));
CString strDataReceived(_T(""));

if(hexReceive)
{
for(DWORD i=0;i<length;i++)
{
THex.Format(_T("%02X "),data[i]);
strDataReceived+=THex;
}
}
else  //不以十六进制显示
{
strDataReceived=CString(data).Left(length);  //很怪
}
delete []data;
return strDataReceived;
}
return "";

}

BOOL CPSerialPort::SendStr(CString str)
{

DWORD dwCharToWrite=0;
DWORD dwBytesWritten=0;
int i,j;
//得到发送区里的数据
//

if(!hexSend)//如果不是以十六进制发送
{

dwCharToWrite=(DWORD)str.GetLength();//如果是以字符发送,得到字符的长度
}
else   //以十六进制发送
{
str.MakeUpper();  //转换成大写
str.Remove(' ');  //在这里去掉所有的空格
for(i=0;i<str.GetLength()/2;i++)
{
if(((str.GetAt(i*2)>='0'&&str.GetAt(i*2)<='9')||(str.GetAt(i*2)>='A'&&str.GetAt(i*2)<='F'))&&((str.GetAt(i*2+1)>='0'&&str.GetAt(i*2+1)<='9')||(str.GetAt(i*2+1)>='A'&&str.GetAt(i*2+1)<='F')))
{
dwCharToWrite++;  //得到字节长度
}
}
}
dwBytesWritten=0;

if(dwCharToWrite)
{
char* buf=new  char[dwCharToWrite];
if(!hexSend)
{
for(i=0;i<(int)dwCharToWrite;i++)
{
buf[i]=( char)str.GetAt(i);
}
}
else  //以十六进制发送
{
j=0;
for(i=0;i<str.GetLength()/2;i++)
{
if(((str.GetAt(i*2)>='0'&&str.GetAt(i*2)<='9')||(str.GetAt(i*2)>='A'&&str.GetAt(i*2)<='F'))&&((str.GetAt(i*2+1)>='0'&&str.GetAt(i*2+1)<='9')||(str.GetAt(i*2+1)>='A'&&str.GetAt(i*2+1)<='F')))
{
if(str.GetAt(i*2+1)>='0'&&str.GetAt(i*2+1)<='9')
{
buf[j]=str.GetAt(i*2+1)-48;
}
else
{
buf[j]=str.GetAt(i*2+1)-55;
}
if(str.GetAt(i*2)>='0'&&str.GetAt(i*2)<='9')
{
buf[j]+=(str.GetAt(i*2)-48)*16;
}
else
{
buf[j]+=(str.GetAt(i*2)-55)*16;
}
j++;
}
}
}
dwBytesWritten= WritePort(buf, dwCharToWrite); //写入数据
if(dwBytesWritten==0)
{
AfxMessageBox(_T("无法向端口写入数据!"));
return FALSE;
}
delete[] buf;
}
//	Sleep(100);
return TRUE;
}
unsigned int CPSerialPort::crc16(unsigned char *str, unsigned char num)               //CRC计算子程序
{
unsigned char i,j;
unsigned int crc;
crc=0xffff;
for (i=0;i<num;i++)
{
crc^=str[i]&0x00ff;
for (j=0;j<8;j++)
{
if (crc&0x0001)
{
crc>>=1;
crc^=0xa001;
}
else
crc>>=1;
}
}
return(crc);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: