原创 CRC校验C语言实现

2011-9-3 16:35 5851 7 8 分类: MCU/ 嵌入式

一般标准的通讯协议中都需要有校验方法来校验通讯过程中的数据的正确性,如我们工程中用的标准MODBUS串行通讯网络采用两种错误校验方法,奇偶校验可以用于检验每一个字符,信息帧校验(LRC或CRC)使用于整个信息的校验,字符校验和信息帧校验均由主机设备产生,并在传送前加到信息中去。从机设备在接收信息过程中校验每个字符和整个信息。

CRC校验(循环冗余校验)是现代通信领域的重要技术之一。掌握CRC的算法与实现方法,在通信系统的设计、通信协议的分析以及软件保护等诸多方面,能发挥很大的作用。

CRC的代数的一般性算法网上的内容很多,在这里不在赘述。一般CRC的C语言有两种实现算法:比特型算法和字节型算法,由于比特型算法需要逐位进行计算,效率比较低,不适合高速通讯的场合,所以我们一般采用字符型算法,下面重点介绍字符型算法的CRC校验。

1、  实现原理:

循环冗余校验CRC区为2个字节,含一个16位二进制数据。由发送设备计算CRC值,并计算CRC值,并把计算值附在信息中,接收设备在接收信息时,重新计算CRC的值,并把计算值与接收的在CRC区中的实际值进行比较,若两者不相同,则产生一个错误。

2、CRC的产生

(1)把16位CRC寄存器置成全1,即0xffff。

(2)第一个8位数据与CRC寄存器低8位进行异或运算,把结果存入CRC寄存器。

    char         rs485Arg[32];       /* RS-485参数缓存*/

    /*

     *  初始化UART0

     */

    UartInit(UART0, uartInitArg, NULL);      /* 初始化UART0   */

    sprintf(rs485Arg, "RS485Dir=%u", P0_04);   /* 获取RS-485方向控制引脚*/

    UartSetMode(UART0, SET_RS485, rs485Arg);  /* 使能RS-485设置其方向控制引脚 */

    SetVICIRQ(UART0_IRQ_CHN, 8, (uint32)UART0_ISR);    

    while (1) {

         crc=crc16byte(cStrTmp,6);                                   (1)

          crch=(crc&0xff00)>>8;                                       (2)

          crcl=(crc&0x00ff);                                              (3)

         cStrTmp[6]=crch;                                                (4)

         cStrTmp[7]=crcl;                                           

UartWrite(UART0, (uint8 *)cStrTmp,8, NULL);                (5)

        OSTimeDly(OS_TICKS_PER_SEC);

    }

}

做几点说明:

我们在工程中通常会碰到这样的问题,比如驱动电机,你需要在用主机对从机发送转动指令包括是正转还是反转,转动多少,这就需要我们发送一帧经CRC校验好的指令信息。上面的任务程序就简单的实现了这一点。

(1)对除校验位以外的6为数据计算校验码

(2)计算出来的16位校验值取其高字节并右移8位放入crch

(3)计算出来的16位校验值取其低字节放入crcl

(4)将计算出来的高低位分别放入待发送信息的最后2位,这样cStrTmp内8位数据信息的校验值就为0了。

(5)校验好的信息通过UART0发送至从机。

在此,做一点补充,包括前面的日志所用的数据类型都是根据μcos系统的定义来的具体如下:

typedef unsigned char  BOOLEAN;   /*  布尔变量           */

typedef unsigned char  INT8U;      /*  无符号8位整型变量 */

typedef signed   char  INT8S;     /*  有符号8位整型变量 */

typedef unsigned short INT16U;    /*  无符号16位整型变量*/

typedef signed   short INT16S;   /*  有符号16位整型变量 */

typedef unsigned long  INT32U;  /*  无符号32位整型变量 */

typedef signed   long  INT32S; /*  有符号32位整型变量          */

typedef float        FP32;    /*  单精度浮点数(32位长度)    */

typedef double      FP64    /*  双精度浮点数(64位长度)    */

计算机内存中的数据都是以二进制的形式存在的,各种类型的数据譬如无符号整型数具体是多少位二进制跟cpu的位数有关。

二进制、16进制与10进制的关系:以一个十六进制的数为例

1111 1111 1111 1111        二进制

0xffff                    16进制

0xff*256+0xff             十进制

PARTNER CONTENT

文章评论1条评论)

登录后参与讨论

xucun915_925777961 2011-9-6 16:12

来学习一下^_^
相关推荐阅读
用户967659 2011-10-06 13:50
FAT16格式SD卡磁盘存储结构分析
本文根据“file allocation table - 16bit”(16位文件分配表)一文,使用WinHex工具分析FAT16格式的SD卡存储结构。 一.格式化后,放入文件和文件夹SD卡抓图: ...
用户967659 2011-10-06 11:16
FAT16文件系统磁盘存储结构
file allocation table - 16bit clark@hushmail.com | updates closed forewordsthis article is about f...
用户967659 2011-10-06 10:43
电容滤波要注意的两个要点
电容在EMC设计中非常重要,也是我们常用的滤波元件!但在实际过程中,大家对电容的使用并不是很明确,存在像:滤波电容值越大越好等理解误区!这里我把电容滤波的两个要点介绍一下: 1、电容滤波是有频段的,...
用户967659 2011-08-25 10:23
预处理命令基础和常用预处理命令实例
  引子: 最近在学习Protothreads--PT是一中轻量级、无堆栈轮询任务简单的实时操作系统。PT采用纯C(就是很多宏(MACRO))代码,可以在任何平台上使用,和硬件结构无关。在调试跟踪代...
用户967659 2011-08-25 10:22
Protothreads简介
2008-10-18 20:44 951人阅读 评论(0) 收藏 举报     原来在用RTOS时感觉特别方便的就是任务函数中可以调用系统提供的延时,等待等函数,切换到其它任务上执行,这样写程序又...
EE直播间
更多
我要评论
1
7
关闭 站长推荐上一条 /3 下一条