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)
java版更新1 上面有错误
附:测试
#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);
}
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); }
相关文章推荐
- java之crc16测试代码
- crc16 ccitt 单片机与java匹配算法
- AndroidStudio下通过JNI实现java和c互调
- Android系统原理与源码分析(1):利用Java反射技术阻止通过按钮关闭对话框
- 如何通过Android CTS测试—testPackageSignatures
- android java 与C 通过 JNI双向通信
- 在Android中通过Java修改文件权限
- JAVA 注册tomcat成系统服务和自启动(测试通过使用)
- android环境下写了一个测试Java类,带有main方法,可是无法运行
- AndroidJNI 通过C++调用JAVA
- Android webView与java代码互调API 16+
- 为Android系统内置Java应用程序测试Application Frameworks层的硬件服务
- Android 通过Java代码动态获取控件位置的终极解决之道
- javaWeb服务详解(含源代码,测试通过,注释)
- 关于Android开发中Java对象序列化的一次测试
- android java 在同时支持ipv4 与 ipv6 状况下,仅支持ipv4 或 ipv6的方法(测试中)
- 在Ubuntu上为Android系统内置Java应用程序测试Application Frameworks层的硬件服务
- AndroidJNI 通过C++调用JAVA
- JUnit测试通过,但控制台Console中有报错:java.lang.ClassNotFoundException: com.mysql.jdbc.Driver