#include <stdio.h>
#include <string.h>
/**
*******************************************************************************
* @brief 获取 BCC校验(异或校验) 函数
* @param [in] *buf - 数据块指针
* @param [in] size - 数据块字节大小
* @return 校验码
* @note 将每个字节数据(一般是两个16进制的字符)进行异或后即得到校验码
* 适用于大多数要求不高的数据通讯,像很多单片机系统的串口通讯。
*******************************************************************************
*/
unsigned char GetBCC(unsigned char *buf, unsigned long size)
{
unsigned char check = 0; //校验字节 初始化
while(size--) check ^= *buf++; //异或计数
return check;
}
/**
*******************************************************************************
* @brief 获取 LRC校验(纵向冗余校验) 函数
* @param [in] *buf - 数据块指针
* @param [in] size - 数据块字节大小
* @return 校验码
* @note 将每个字节数据求和结果与256求余,再按位取反加 1(256 - 余数)后即得到校验码
* 在工业领域Modbus协议Ascii模式采用该算法
*******************************************************************************
*/
unsigned char GetLRC(unsigned char *buf, unsigned long size)
{
unsigned char check = 0; //校验字节 初始化
while(size--) check += *buf++ ; //累加求余(只保留余数字节就是数据求和结果与256求余)
return (unsigned char)((check ^ 0xFF) + 1);
}
/**
*******************************************************************************
* @brief 获取 累加和校验 函数
* @param [in] *buf - 数据块指针
* @param [in] size - 数据块字节大小
* @return 校验码
* @note 校验和的数值超过十六进制的FF,也就是255,就要求其补码作为校验和。
*******************************************************************************
*/
unsigned char GetCheckSum8(unsigned char *buf, unsigned long size)
{
unsigned long cksum = 0; //校验字节 初始化
while(size--) cksum += *buf++ ;
if(cksum > 0xFF)
{
cksum = ~cksum;
cksum += 1;
}
return (unsigned char)(cksum & 0xFF);
}
/**
*******************************************************************************
* @brief 获取 累加和校验 函数
* @param [in] *buf - 数据块指针
* @param [in] size - 数据块字节大小
* @return 校验码
* @note 16位数据进行累加,奇数字节则最后补0凑成16位,再把累加和的高16位与低16位进行累加,
* 发生进位则把进位累加上,最后取反。
*******************************************************************************
*/
unsigned short GetCheckSum16(unsigned short *buf, unsigned long size)
{
unsigned long cksum = 0;
while(size > 1) //16位为单位数字相加
{
cksum += *buf++;
size -= 2;
}
if(size) cksum += *((unsigned char *)buf); //长度是奇数
cksum = (cksum>>16) + (cksum&0xFFFF); //高16位 与 低16位相加
cksum += (cksum>>16); //加上进位
return (unsigned short)(~cksum); //最后取反
}
/**
*******************************************************************************
* @brief 主函数
* @param [in] None
* @return None
* @note 验证校验函数
*******************************************************************************
*/
void main()
{
char *str = "Hello World!";
printf("BCC (\"%s\") = 0x%02X\n", str, GetBCC((unsigned char *)str, strlen(str)));
printf("LRC (\"%s\") = 0x%02X\n", str, GetLRC((unsigned char *)str, strlen(str)));
printf("CheckSum8 (\"%s\") = 0x%02X\n", str, GetCheckSum8((unsigned char *)str, strlen(str)));
printf("CheckSum16 (\"%s\") = 0x%02X\n", str, GetCheckSum16((unsigned short *)str, strlen(str)));
while(1);
}
运行结果: