本帖最后由 Harvard 于 2016-11-30 00:08 编辑
首先,什么是CRC?
循环冗余校验(Cyclic Redundancy Check, CRC)是一种根据网络数据包或电脑文件等数据产生简短固定位数校验码的一种散列函数,主要用来检测或校验数据传输或者保存后可能
出现的错误。它是利用除法及余数的原理来作错误侦测的。
CRC在串口通信中很常见,如常见的ModbusRtu 采用的就是CRC16, 不同的CRC有不同的多项式;如果用纯软件代码来实现CRC,流程都非常类似; 可以看一个例子:
生成 CRC 的过程为:
1. 将一个 16 位寄存器(称作 CRC 寄存器)初始赋值为十六进制 FFFF (全 1);
2. 将报文的第一个字节( 8位)与 16 位 CRC 寄存器的低字节异或,结果置于 CRC 寄存器;
3. 将 CRC 寄存器右移 1位 (向 LSB 方向), MSB 充零,并检测 LSB:
4. (如果 LSB 为 0): 重复步骤 3 (另一次移位).
(如果 LSB 为 1): 对 CRC 寄存器异或多项式值 0xA001 (1010 0000 0000 0001).
5. 重复步骤 3 和 4,直到完成 8 次移位操作后,一个字节的处理完毕。
6. 对报文中的下一个字节重复步骤 2 到 5继续此操作,直至所有报文被处理完毕。
7. CRC 寄存器中的最终值为 CRC 值.
8. 当放置 CRC 值于报文时,注意高低字节必须交换。
看了以上过程是不是 感觉繁琐, 大概理解,但是毕竟还是需要代码去完成, 随着技术发展,如今的很多单片机,把crc模块变成了标准内部资源,Navota100系列也是如此.
循环冗余校验(CRC)模块生成16/32 位CRC 码以便进行误差检测,CRC 模块提供实施16 位或32 位CRC标准所需的可编程多项式、WAS 和其他参数。对于32 位数据,每次都计算该16/32 位代码。
注:MCU 进去低功耗模式后,该模块时钟禁用,任何进行中的CRC 计算都会停止。
具体crc的性能,可以看数据手册. 我本次实验的目地就是看crc模块,是否可以工作.因此,编译并运行了厂家开发包中的nv32f100_pdk\build\keil\NV32\CRC_demo例程,虽为crc体验,其实同时也学习了UART,实验是从串口1输出了一些信息.利用的是printf函数功能,同时,系统配置的是115200bps的波特率,大家注意.开发板自带的ft232驱动也记得装好. 串口调试软件打开时,选择正确的波特率和串口号.
<span style="font: 14px/24px arial, 宋体, sans-serif; color: rgb(51, 51, 51); text-transform: none; text-indent: 28px; letter-spacing: normal; word-spacing: 0px; float: none; display: inline !important; white-space: normal; widows: 1; font-size-adjust: none; font-stretch: normal; background-color: rgb(255, 255, 255); -webkit-text-stroke-width: 0px;"></span>
<p><span style="font: 14px/24px arial, 宋体, sans-serif; color: rgb(51, 51, 51); text-transform: none; text-indent: 28px; letter-spacing: normal; word-spacing: 0px; float: none; display: inline !important; white-space: normal; widows: 1; font-size-adjust: none; font-stretch: normal; background-color: rgb(255, 255, 255); -webkit-text-stroke-width: 0px;">/********************************************************************/
int main (void)
{
uint8_t u8Ch;
uint32_t u32Crc_ConverterResult;
uint32_t u32SeedValue;
CRC_ConfigType sCRC_ConfigType = {0};
CRC_ConfigType *pCRC_Config=&sCRC_ConfigType;</span></p><p><span style="font: 14px/24px arial, 宋体, sans-serif; color: rgb(51, 51, 51); text-transform: none; text-indent: 28px; letter-spacing: normal; word-spacing: 0px; float: none; display: inline !important; white-space: normal; widows: 1; font-size-adjust: none; font-stretch: normal; background-color: rgb(255, 255, 255); -webkit-text-stroke-width: 0px;"> uint8_t MessageSource[] = {"123456789"} ; /*!< initialize mesasge */ </span></p><p><span style="font: 14px/24px arial, 宋体, sans-serif; color: rgb(51, 51, 51); text-transform: none; text-indent: 28px; letter-spacing: normal; word-spacing: 0px; float: none; display: inline !important; white-space: normal; widows: 1; font-size-adjust: none; font-stretch: normal; background-color: rgb(255, 255, 255); -webkit-text-stroke-width: 0px;"> /* Perform processor initialization */
sysinit();</span></p><p><span style="font: 14px/24px arial, 宋体, sans-serif; color: rgb(51, 51, 51); text-transform: none; text-indent: 28px; letter-spacing: normal; word-spacing: 0px; float: none; display: inline !important; white-space: normal; widows: 1; font-size-adjust: none; font-stretch: normal; background-color: rgb(255, 255, 255); -webkit-text-stroke-width: 0px;"> printf("\nRunning the CRC_demo project.\n");
/* inital CRC register works under 16-bit mode */
pCRC_Config->u32PolyData = 0x1021; /*!< initialize CRC-CCITT poly value */
u32SeedValue = 0xFFFF; /*!< set CRC-CCITT seed value */
pCRC_Config->bWidth = CRC_WIDTH_16BIT;
pCRC_Config->bTransposeReadType = CRC_READ_TRANSPOSE_NONE; /*!< do not transpose in read */
pCRC_Config->bTransposeWriteType = CRC_WRITE_TRANSPOSE_NONE; /*!< do not transpose in write */
/* begin to CRC-CCITT convertion */
CRC_Init(pCRC_Config); /*!< crc module inital as 16-bit mode */
printf("CRC0->GPOLY=0x%x, CRC0->CTRL=0x%x\n",CRC0->GPOLY,CRC0->CTRL);
u32Crc_ConverterResult = CRC_Cal16(u32SeedValue, &MessageSource[0], (sizeof(MessageSource)-1));
printf("CRC-CCITT function calculation result = 0x%x [url=home.php?mod=space&uid=14343]@seed[/url] = 0x%x .\n", u32Crc_ConverterResult, u32SeedValue );
/* reset CRC register for 32-bit mode calculation*/
CRC_DeInit();
/* inital CRC register works under 32-bit mode */
pCRC_Config->u32PolyData = 0x04C11DB7; /*!< set CRC32 poly value */
u32SeedValue = 0xFFFFFFFF; /*!< set CRC32 seed value */
pCRC_Config->bWidth = CRC_WIDTH_32BIT;
pCRC_Config->bTransposeReadType = CRC_READ_TRANSPOSE_ALL; /*!< do not transpose in read */
pCRC_Config->bTransposeWriteType = CRC_WRITE_TRANSPOSE_BIT; /*!< do not transpose in write */
pCRC_Config->bFinalXOR = TRUE; /*!< reverse CRC result */
/* begin to CRC-CCITT convertion */
CRC_Init(pCRC_Config); /*!< crc module inital as 32-bit mode */
u32Crc_ConverterResult = CRC_Cal32(u32SeedValue, &MessageSource[0], (sizeof(MessageSource)-1));
printf("CRC32 function calculation result = 0x%x [url=home.php?mod=space&uid=14343]@seed[/url] = 0x%x .\n", u32Crc_ConverterResult, u32SeedValue );</span></p><p><span style="font: 14px/24px arial, 宋体, sans-serif; color: rgb(51, 51, 51); text-transform: none; text-indent: 28px; letter-spacing: normal; word-spacing: 0px; float: none; display: inline !important; white-space: normal; widows: 1; font-size-adjust: none; font-stretch: normal; background-color: rgb(255, 255, 255); -webkit-text-stroke-width: 0px;">
while(1)
{
u8Ch = UART_GetChar(TERM_PORT);
UART_PutChar(TERM_PORT, u8Ch);
}
}</span></p>
|