MAX14915为高性能、8通道、工业高边开关,具有丰富、先进的功能集。SPI接口允许微控制器监视和控制MAX14915的大部分方面。为了增强鲁棒性,MAX14915中的硬件循环冗余校验(CRC)电路可以选择保护其与微控制器之间的所有数据通信,防止误码。然而,在MAX14915中启用CRC功能是不够的。微控制器还必须在软件中实现相同的CRC算法,既要为发送到MAX14915的数据附加校验位,又要验证从MAX14915接收的数据。实现此目的的一种方法是检查数据手册并使用它来创建自定义固件以实现必要的CRC功能。为了提供更快且经过验证的解决方案,本应用笔记中提供了一系列功能。它们是用C语言编写的,应该很容易移植到任何常见的微控制器上。
串行接口上的CRC错误检测
MAX14915串行数据的CRC错误检测可以启用,以尽量减少由于SDI和SDO信号的数据损坏而导致的错误操作或错误信息。如果使能错误检测,通过设置CRCEN引脚= 1,MAX14915执行以下操作:
对从微控制器接收的SDI数据执行错误检测,以及
计算发送到微控制器的SDO数据的CRC,并将校验字节附加到发送到微控制器的SDO诊断/状态数据
这可确保从微控制器接收的数据(设置/配置)和发送到微控制器的数据(诊断/状态)出现未检测到错误的可能性较低。
CRC 错误检测支持SPI寻址和菊花链操作模式,以及标准和突发读/写周期。
SDI(读取周期)上的输入数据
将 CRCEN 输入设置为高电平可启用 CRC 错误检测。CRC 帧校验序列 (FCS) 随每个串行事务一起发送。5 位 FCS 基于生成器多项式 X5+ X4+ X2+ 1,CRC 起始值 = 11111。当CRC使能时,MAX14915期望在接收的SDI程序/配置数据后附加一个校验字节。图 1 显示了校验字节格式。
图1.微控制器的SDI检查字节。
5位FCS位CRC[4:0]是根据一个SPI命令中发送的所有数据计算的,包括校验字节MSB中的三个“0”。因此,在突发命令的情况下,CRC 的计算范围为 8+3 位到 24+3 位。CRC0是FCS的LSB。
MAX14915验证接收到的FCS位,如果未检测到错误,MAX14915设置OUT_输出开关和/或根据SDI数据更改器件配置。如果检测到CRC错误,MAX14915不会改变OUT_输出和/或器件配置。相反,MAX14915将COMERR逻辑输出设置为低电平,即COMERR输出晶体管漏极开路导通。
如果掩模寄存器设置为使能全局故障寄存器中的CRCfault位,MAX14915还将FAULT引脚设置为低电平,为微控制器提供中断,以进一步指示SPI接口上的通信错误。
SDO(写入周期)上的输出数据
当DAISY引脚为低电平时,MAX14915附加到SDO数据的检查字节的格式如图2所示:
图2.MAX14915在寻址SPI模式下发送SDO检查字节。
A1 和 A0 是 A1 和 A0 引脚的电平,而 THERR 位是在发生芯片热关断事件时设置的。CRC[4:0]是MAX14915根据SDO数据计算的1个CRC位,包括A0、A14915和THERR值。这允许微控制器检查从MAX<>接收的SDO数据是否存在错误。
源代码
本应用笔记提供了实现CRC生成器和CRC检查器的C源代码。MAX14915使用单字节或双字节包与微控制器通信。源代码为每种情况提供了一个编码器和解码器:
CRC5encode_2byte(用于传输 2 个字节)
CRC5encode_1byte(用于传输 1 字节)
CRC5check_2byte(用于检查MAX2的14915字节响应)
CRC5check_1byte(用于检查MAX1的14915字节响应)
除了选择单字节或双字节数据包与MAX14915通信外,请注意,在这些代码示例中,“byte”是8位无符号值的别名,有时以不同的方式标记,例如UINT8。
Send1为第一个字节,send2为第二个字节,发送至MAX14915。代码应先发送1,后发送2,再crc_code至MAX14915。
crc_code = crc5encode (send1, send2);
用户应通过SPI接口发送3个字节,先发送1,后跟send2,然后发送crc_code。当微控制器通过SPI接口将配置设置发送到MAX14915时,MAX14915同时将状态信息返回给微控制器。这是检查从MAX14915接收的crc_code是否正确的方法:
crc_ret = crc5decode (ret1, ret2);
字节结果“crc_ret”应与MAX14915接收的第三个字节相同。
图 3 和图 4 显示了 C 函数注释中提到的数据位置。下载电子表格
图3.CRC5数据发送到SDI上的MAX14915。
图4.MAX5在SDO上发送的CRC14915数据。
public byte crc5encode(byte BYTE1, byte BYTE2)
{
byte crc5_start = 0x1f;
byte crc5_poly = 0x15;
byte crc_result = crc5_start;
// BYTE1
for (int i=0; i<8; i++)
{
if( ((( BYTE1>>(7-i) ) &0x01) ^ ((crc_result & 0x10)>>4)) > 0 ) // IF(XOR(C6;BITAND(D5;2^4)/2^4)
{ crc_result = (byte) (crc5_poly ^ ((crc_result<<1) & 0x1f)); } // BITXOR($D$1;BITAND((D5*2);31))
else
{ crc_result = (byte)((crc_result<<1) & 0x1f); } // shift left, keep only lower 6 bits
}
// BYTE2
for (int i=0; i<8; i++)
{
if( ((( BYTE2>>(7-i) ) &0x01) ^ ((crc_result & 0x10)>>4)) > 0 ) // IF(XOR(C6;BITAND(D5;2^4)/2^4)
{ crc_result = (byte) (crc5_poly ^ ((crc_result<<1) & 0x1f)); } // BITXOR($D$1;BITAND((D5*2);31))
else
{ crc_result = (byte)((crc_result<<1) & 0x1f); } // shift left, keep only lower 6 bits
}
// 3 extra bits set to zero
byte BYTE3=0x00;
for (int i=0; i<3; i++)
{
if( ((( BYTE3>>(7-i) ) &0x01) ^ ((crc_result & 0x10)>>4)) > 0 ) // IF(XOR(C6;BITAND(D5;2^4)/2^4)
{ crc_result = (byte) (crc5_poly ^ ((crc_result<<1) & 0x1f)); } // BITXOR($D$1;BITAND((D5*2);31))
else
{ crc_result = (byte)((crc_result<<1) & 0x1f)); } // shift left, keep only lower 6 bits
}
return crc_result;
}
byte crc5_decode(byte BYTE1, byte BYTE2)
{
byte crc5_start = 0x1f;
byte crc5_poly = 0x15;
byte crc_result = crc5_start;
// BYTE1
for (int i=2; i<8; i++)
{
if( ((( BYTE1>>(7-i) ) &0x01) ^ ((crc_result & 0x10)>>4)) > 0 ) // IF(XOR(C6;BITAND(D5;2^4)/2^4)
{ crc_result = (byte) (crc5_poly ^ ((crc_result<<1) & 0x1f)); } // BITXOR($D$1;BITAND((D5*2);31))
else
{ crc_result = (byte)((crc_result<<1) & 0x1f); } // shift left, keep only lower 6 bits
}
// BYTE2
for (int i=0; i<8; i++)
{
if( ((( BYTE2>>(7-i) ) &0x01) ^ ((crc_result & 0x10)>>4)) > 0 ) // IF(XOR(C6;BITAND(D5;2^4)/2^4)
{ crc_result = (byte) (crc5_poly ^ ((crc_result<<1) & 0x1f)); } // BITXOR($D$1;BITAND((D5*2);31))
else
{ crc_result = (byte)((crc_result<<1) & 0x1f); } // shift left, keep only lower 6 bits
}
// 3 extra bits set to zero
byte BYTE3=0x00;
for (int i=0; i<3; i++)
{
if( ((( BYTE3>>(7-i) ) &0x01) ^ ((crc_result & 0x10)>>4)) > 0 ) // IF(XOR(C6;BITAND(D5;2^4)/2^4)
{ crc_result = (byte) (crc5_poly ^ ((crc_result<<1) & 0x1f)); } // BITXOR($D$1;BITAND((D5*2);31))
else
{ crc_result = (byte)((crc_result<<1) & 0x1f); } // shift left, keep only lower 6 bits
}
return crc_result;
}
结论
本应用笔记介绍了如何在与MAX14915八通道工业高边开关通信的微控制器上对CRC算法进行编码。该代码使用MAX14915EVKIT和相应的GUI进行测试。通过利用本应用笔记中的C代码示例,工程师获得了一个经过验证的解决方案来实现这种额外的数据通信保护。在某些情况下,应在目标微控制器上执行一些基准测试,尤其是在优先考虑快速执行速度的情况下。
审核编辑:郭婷
全部0条评论
快来发表一下你的评论吧 !