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

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
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版 crc16 

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
/*********************************************************************
*文件名: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
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;jprintf("%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='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='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>=1;
				crc^=0xa001;
			}
			else
				crc>>=1;
		}
	}
	return(crc);
}



Java 校验和

public class test {
	public static byte[] str2Byte(String hexStr) {
		hexStr = hexStr.replaceAll(" ", ""); // 去空格
		if ((hexStr == null) || (hexStr.equals(""))) {
			return null;
		}
		
		int b = hexStr.length() % 2;
		if (b != 0) {
			hexStr = "0" + hexStr;
		}
		String[] a = new String[hexStr.length() / 2];
		byte[] bytes = new byte[hexStr.length() / 2];
		for (int i = 0; i < bytes.length; i++) {
			a[i] = hexStr.substring(2 * i, 2 * i + 2);
		}
		for (int i = 0; i < bytes.length; i++) {
			bytes[i] = (byte) Integer.parseInt(a[i], 16);
		}
		return bytes;
	}
	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);
	}
	public static int crcNum(byte[] str, byte num) // CRC计算子程序  
    {  
        
        int crc=0;  
        for(int i=0;i


你可能感兴趣的:(c语言,java,Android复习,c++复习,单片机)