0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

TPS929120的CRC校验的三种实现方法

冬至子 来源:Auto FAE进阶之路 作者:Yingming 2023-05-30 10:39 次阅读

最近在帮客户编写基于S32K144编写TPS929120的软件驱动时,需要在发送数据的末端增加8bit的CRC校验码。因为之前使用E522.49时,其数据手册直接提供了自身CRC校验算法的代码,而TPS929120的手册只告知了算法的CRC多项式为 ,初始值为0xFF,所以代码部分需要自己实现。

我查阅了TLD7002,BD18331,MPQ7225等LED Driver的数据手册,都是采用的CRC校验算法,其中MPQ7225的CRC校验算法和TPS929120是一样的。因为之前接触CRC校验不多,特定将相关的学习过程记录下来,方便后面有需要时快速完成其他厂家的LED Driver软件驱动。

CRC基础知识

这一章节主要介绍CRC概念和参数模型(来源于网络

CRC概念

CRC(Cyclic Redundancy Checksum)是一种纠错技术,代表循环冗余校验和。

数据通信领域中最常用的一种差错校验码,其信息字段和校验字段长度可以任意指定,但要求通信双方定义的CRC标准一致。主要用来检测或校验数据传输或者保存后可能出现的错误。它的使用方式可以说明如下图所示:

在数据传输过程中,无论传输系统的设计再怎么完美,差错总会存在,这种差错可能会导致在链路上传输的一个或者多个帧被破坏(出现比特差错,0变为1,或者1变为0),从而接受方接收到错误的数据。

为尽量提高接受方收到数据的正确率,在接收方接收数据之前需要对数据进行差错检测,当且仅当检测的结果为正确时接收方才真正收下数据。检测的方式有多种,常见的有 奇偶校验因特网校验循环冗余校验等。

CRC参数模型

一个完整的CRC参数模型应该包含以下信息WIDTH,POLY,INIT,REFIN,REFOUT,XOROUT

  • NAME :参数模型名称。
  • WIDTH :宽度,即生成的CRC数据位宽,如CRC-8,生成的CRC为8位
  • POLY :十六进制多项式,省略最高位1,如 ,二进制为 1 0000 0111 ,省略最高位1,转换为十六进制为0x07。
  • INIT :CRC初始值,和WIDTH位宽一致。
  • REFIN :true或false,在进行计算之前,原始数据是否翻转,如原始数据:0x34 = 0011 0100 ,如果REFIN为true,进行翻转之后为0010 1100 = 0x2c
  • REFOUT :true或false,运算完成之后,得到的CRC值是否进行翻转,如计算得到的CRC值:0x97 = 1001 0111 ,如果REFOUT为true,进行翻转之后为11101001 = 0xE9。
  • XOROUT :计算结果与此参数进行异或运算后得到最终的CRC值,和WIDTH位宽一致。

通常如果只给了一个多项式,其他的没有说明则: **INIT=0x00,REFIN=false,REFOUT=false,XOROUT=0x00** 。

TPS929120的CRC值计算方式

CRC参数:

根据数据手册,TPS929120选择的是CRC多项式为 ,初始值为0xFF;所以POLY为0x31,INIT为FF。由于UART的数据传输是LSB(先传输低位),所以REFIN为True。综上所述,TPS929120的CRC参数表为:

NAME = CRC_TPS929120
WIDTH = 8
POLY = 0x31 = 0011 0001(最高位1已经省略)
INIT = 0xFF
XOROUT = 0x00
REFIN = TRUE
REFOUT = FALSE

算法图:

TPS929120数据手册提供了自身CRC校验的算法图,如下所示:图片

因为TPS929120要求第一个发送的数据0x55(用于同步)不参与计算,所以下面介绍的几种计算方式都不会将0x55纳入CRC计算范围。

计算方法一:

方法一按照TPS929120提供的算法图进行实现。

计算步骤:

结合TPS929120数据手册提供的算法图,方法一的计算步骤如下所示:

1. 将0xFF作为CRC初始值。

2. 当第一个输入字节的Bit0到来时,

   2.1 将初始值的Bit7和输入值的Bit0进行异或运算,得到的值保留,记作Temp_Bit;

   2.2 将初始值的Bit6代替原本的Bit72.3 将初始值的Bit5代替原本的Bit62.4 将初始值的Bit4和Temp_Bit进行异或运算,使用得到的值代替原本的Bit52.5 将初始值的Bit3和Temp_Bit进行异或运算,使用得到的值代替原本的Bit42.6 将初始值的Bit2代替原本的Bit32.7 将初始值的Bit1代替原本的Bit22.8 将初始值的Bit0代替原本的Bit12.9 使用Temp_Bit代替原本的Bit03. 第一个输入字节的剩余7bit也是同样的操作,然后得到第一个输入字节的CRC值。

4. 第二个输入字节到来,使用上一次计算得到的CRC值作为CRC初始值,重复23步骤。

5. 当最后一个输入字节计算完毕之后,就得到了最终的CRC校验值。

实现代码为:

  • 单个字节的CRC值计算
#define BIT0 (0x01)
#define BIT1 (0x02)
#define BIT2 (0x04)
#define BIT3 (0x08)
#define BIT4 (0x10)
#define BIT5 (0x20)
#define BIT6 (0x40)
#define BIT7 (0x80)

unsigned int CRC_Calculation(unsigned int CRC_Initial, unsigned int Input_Data)
{
 unsigned int Temp_Bit, Input_Bit;
    /* store every bit value of Input_Data */
 unsigned int bit0, bit1, bit2, bit3, bit4, bit5, bit6, bit7;   
 /* store the Input_Data (byte) 's CRC */
    unsigned int CRC=0; 
    /* get every bit of CRC initial value */
 unsigned int i=0; bit0 = CRC_Initial & BIT0; 
    
 bit1 = (CRC_Initial & BIT1)>>1;
 bit2 = (CRC_Initial & BIT2)>>2;
 bit3 = (CRC_Initial & BIT3)>>3;
 bit4 = (CRC_Initial & BIT4)>>4;
 bit5 = (CRC_Initial & BIT5)>>5;
 bit6 = (CRC_Initial & BIT6)>>6;
 bit7 = (CRC_Initial & BIT7)>>7;
    
 for(i=0; i<8; i++)
 {
        /* extract one bit of Input Data (from LSB to MSB) */
  Input_Bit = (Input_Data >> i) & 0x01;
        /* Do Input_Bit XOR bit7 */
  Temp_Bit = Input_Bit ^ bit7; 
  bit7 = bit6;
  bit6 = bit5;
        /* Do bit4 XOR Temp_Bit */
  bit4 = bit4 ^ Temp_Bit; 
  bit5 = bit4;
        /* Do bit3 XOR Tmep_Bit */
  bit3 = bit3 ^ Temp_Bit; 
  bit4 = bit3;
  bit3 = bit2;
  bit2 = bit1;
  bit1 = bit0;
  bit0 = Temp_Bit;
 }
 
 CRC = (bit7<<7)|(bit6<<6)|(bit5<<5)|(bit4<<4)|(bit3<<3)|(bit2<<2)|(bit1<<1)|bit0;
 return CRC;
}
  • 命令帧的CRC值计算
unsigned int CRC(unsigned int commandFrame_withoutCRC[], unsigned int byteLength)
{
 unsigned int j;
   unsigned int CRCtemp;
   for(j=0; j

计算方法二:

Github上面有一套成熟的开源CRC算法,如下,

GitHub - whik/crc-lib-c: 基于C语言的CRC校验库,包括常用的21个CRC参数模型实现^[1]^

参考其中的 CRC-8/MAXIM ,并根据TPS929120的CRC参数进行微调,得到的算法如下:

/* as UART transmit from LSB to MSB, 
 * invert the polynomial 0x31 (0011 0001) to 0x8C (1000 1100)
 */
#define polynomialINV 0x8C 
#define LSB 0x01

/* calculate CRC of command frame */
unsigned int CRC_LUT(unsigned int commandFrame_withoutCRC[], unsigned int byteLength) 
{
 unsigned int remainder, k, j;
    /* assign the initial value 0xFF */
 remainder = 0xFF; 
    /* the first SYNC byte not engage CRC calculation */
 for(k=1;k

计算方法三:

方法三在方法二的基础上进行优化,将CRC的计算部分(如下图)提前做成数组,涵盖0-255的CRC计算结果,然后用到的时候直接查表。

for(i=0; i<8; i++)
 {
  if(remainder & LSB)
  {
            /* right shift 1 bit and do the XOR operation with 0x8C */
   remainder = (remainder>>1) ^ polynomialINV; 
  }
  else
  {
   remainder = remainder>>1;
  }
 }

最终的实现形式如下:

/* as UART transmit from LSB to MSB, 
 * invert the polynomial 0x31 (0011 0001) to 0x8C (1000 1100)
 */
#define polynomialINV 0x8C 
#define LSB 0x01
unsigned int crcArray[256];

/* calculate and store the CRC of data from 0x00 to 0xFF */
void crcInitial() 
{
 unsigned int k, j, remainder;
 for(k=0;k<256;k++)
 {
  remainder=k;
  for(j=8;j>0;j--)
  {
   if(remainder & LSB)
   { 
                /* right shift 1 bit and do the XOR operation with 0x8C */
    remainder = (remainder>>1) ^ polynomialINV; 
   }
   else
   {
    remainder = remainder>>1;
   }
  }
  crcArray[k]=remainder;
 }
}

/* calculate CRC of command frame */
unsigned int CRC_LUT(unsigned int commandFrame_withoutCRC[], unsigned int byteLength) 
{
 unsigned int remainder, tempData, k;
    /* assign the initial value 0xFF */
 remainder = 0xFF; 
    /* the first SYNC byte not engage CRC calculation */
 for(k=1;k

验证:

使用一个数组{0x55,0x80,0x61,0x00}进行验证,其中0x55不参与CRC计算,以计算方法一为例,添加打印的mian函数如下:

#include 
int main()
{
 unsigned int data[4] = {0x55,0x80,0x61,0x00};
 unsigned int crc;

 for(int i = 0; i < 4; i++)
 {
  printf("%02x ", data[i]);
 }
 printf("\\n");
 crc = CRC(data,4);
 printf("Method 1:CRC result of TPS929120 is %02x\\n", crc);
 return 0;
}

使用在线C语言编译器(菜鸟教程在线编辑器 (runoob.com) ^[2]^ )进行验证,计算结果如下图,为0x74:

图片

使用在线CRC计算工具进行验证,结果也是0x74:

图片

使用TPS929120自带的Excel形式的CRC计算工具进行验证,结果也是0x74:

图片

其他两种方式经过验证也是一样的结果,有兴趣的读者可以使用在线C语言编辑器试一下。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • C语言
    +关注

    关注

    180

    文章

    7530

    浏览量

    128722
  • CRC校验
    +关注

    关注

    0

    文章

    81

    浏览量

    15030
  • UART接口
    +关注

    关注

    0

    文章

    123

    浏览量

    15068
  • S32k144
    +关注

    关注

    1

    文章

    6

    浏览量

    1797
收藏 人收藏

    评论

    相关推荐

    FPGA实现CRC校验

    最近在学习CRC校验,根据生成多项式,通过编码代码实现CRC校验,就是不知道怎么实现,求
    发表于 01-05 16:17

    请问FPGA怎么实现CRC校验

    最近在学习CRC校验,根据生成多项式,通过编码代码实现CRC校验,就是不知道怎么实现,求
    发表于 05-21 02:21

    CRC校验方法通过CAN总线通信来实现

    检测、格式错误检测、填充错误检测、应答错误检测和CRC错误检测。作为一重要的错误检测手段,CRC错误检测是接收节点判断CAN帧信息的完整性并向总线确认应答的依据。常见的校验方法1、最
    发表于 09-25 15:41

    CRC校验具体实现方式

    CRC校验具体实现方式CRC校验是一常见的校验方式
    发表于 12-03 08:30

    电话网远程通信中CRC校验码的设计及实现

    本文介绍了基于电话网远距离分布式测控系统的通信方法,重点介绍了传输协议中CRC 循环校验校验原理,CRC 码的生成、检测
    发表于 08-12 10:24 18次下载

    40位以内任意长度的CRC计算及校验实现

    论述了40位以内任意长度的CRC计算及校验在TMS320C5000系列DSP中的实现方法。运用该方法
    发表于 05-05 20:31 1837次阅读
    40位以内任意长度的<b class='flag-5'>CRC</b>计算及<b class='flag-5'>校验</b>的<b class='flag-5'>实现</b>

    CRC校验码算法的研究与实现

    为了提高实际通信中检查信号传输错误的能力,提高和推广CRC校验技术,本论文用逻辑代数知识、按模运算、代数知识和C语言编程工具设计了几种具体实用的CRC校验码的计算
    发表于 05-28 15:41 0次下载

    crc校验原理_怎样修复crc校验错误

    crc校验原理 利用CRC进行检错的过程可简单描述为:在发送端根据要传送的k位二进制码序列,以一定的规则产生一个校验用的r位监督码(CRC
    发表于 09-05 09:26 3.4w次阅读
    <b class='flag-5'>crc</b><b class='flag-5'>校验</b>原理_怎样修复<b class='flag-5'>crc</b><b class='flag-5'>校验</b>错误

    CRC校验 、STM32中CRC计算单元、 CRC应用

    CRC校验、STM32中CRC计算单元、CRC应用
    的头像 发表于 03-04 13:54 5370次阅读

    CRC校验码并行计算的FPGA实现

    用软件实现 CRC 校验码计算很难满足高速数据通信的要求 ,基于硬件的实现方法中 ,有串行经典算法 LFSR 电路 以及由软件算法推导出来的
    发表于 03-28 09:34 30次下载
    <b class='flag-5'>CRC</b><b class='flag-5'>校验</b>码并行计算的FPGA<b class='flag-5'>实现</b>

    CRC校验算法原理及c语言实现

    CRC校验算法原理及c语言实现
    发表于 11-30 10:04 9次下载

    CRC校验原理及实现

    作者:王超首发:电子电路开发学习目录前言CRC算法简介CRC计算CRC校验CRC计算的C语言实现
    发表于 01-26 17:37 28次下载
    <b class='flag-5'>CRC</b><b class='flag-5'>校验</b>原理及<b class='flag-5'>实现</b>

    基于S32K144实现TPS929120的基本控制功能

    TPS929120是TI公司在2019年4月份发布的具有FlexWire接口的12通道汽车级40V高边LED驱动芯片
    的头像 发表于 05-30 10:49 2912次阅读
    基于S32K144<b class='flag-5'>实现</b><b class='flag-5'>TPS929120</b>的基本控制功能

    奇偶校验crc校验的区别 CRC校验和奇偶校验之间有什么关系?

    奇偶校验crc校验的区别 CRC校验和奇偶校验之间有什么关系? 奇偶
    的头像 发表于 10-17 16:28 2464次阅读

    CRC校验原理及其软件实现

    电子发烧友网站提供《CRC校验原理及其软件实现.pdf》资料免费下载
    发表于 11-16 10:11 0次下载
    <b class='flag-5'>CRC</b><b class='flag-5'>校验</b>原理及其软件<b class='flag-5'>实现</b>