以前都是使用软件CRC,浪费计算时间,有硬件CRC不用,真是可惜。本次使用硬件CRC对ModBus的CRC进行计算,测试时,遇到点问题,自带的库文件里面,把方法写死了,结果和Modubs的对不上。
文档上说的公式和modbus是一样的,那么就有可能是初值与异或值不同造成的,先相信硬件不会出错嘛。
自带的crc库也不要用了,一共没有用到3个寄存器,直接搞。
uint16_t rt_hw_get_crc16_modbus(uint8_t *pdat, uint16_t len)
{
CRC->CRC16D = 0xffff; //init dat
CRC->CRC16CTRL = 0x0002; //LSB
while (len--)
{
CRC->CRC16DAT = *pdat++;
}
return (CRC->CRC16D);
}
当然初始化时钟是要加上的啦
RCC_EnableAHBPeriphClk(RCC_AHB_PERIPH_CRC, ENABLE);
就是这么简单,再不用担心写错CRC代码了,肯定是算错了,硬件不会错
给它上个锁,避免被抢占打断后,计算出错。
#include
#include
#include
#include
/* 指向互斥量的指针 /
static rt_mutex_t crc_mutex = RT_NULL;
void hw_crc_init(void)
{
RCC_EnableAHBPeriphClk(RCC_AHB_PERIPH_CRC, ENABLE);
/ 创建一个动态互斥量 */
crc_mutex = rt_mutex_create("crc_mutex", RT_IPC_FLAG_PRIO);
if (crc_mutex == RT_NULL)
{
rt_kprintf("create crc mutex failed.n");
return;
}
}
uint16_t rt_hw_get_crc16(uint8_t *pdat, uint16_t len)
{
uint16_t crc_16 = 0;
rt_mutex_take(crc_mutex, RT_WAITING_FOREVER);
/ init dat /
CRC->CRC16D = 0xffff;
/ LSB /
CRC->CRC16CTRL = 0x0002;
while (len--)
{
CRC->CRC16DAT = *pdat++;
}
crc_16 = CRC->CRC16D;
rt_mutex_release(crc_mutex);
return crc_16;
}
发现问题,这个数据太迷惑了,以上代码有问题,请不要使用
终于可以正确的使用CRC硬件进行modbus的CRC16计算了.
uint16_t rt_reverse_16(uint16_t dat)
{
uint16_t x = dat;
x = (((x & 0xaaaa) >> 1) | ((x & 0x5555) << 1));
x = (((x & 0xcccc) >> 2) | ((x & 0x3333) << 2));
x = (((x & 0xf0f0) >> 4) | ((x & 0x0f0f) << 4));
return ((x >> 8) | (x << 8));
}
uint16_t rt_hw_get_crc16(const uint8_t *pdat, uint16_t len)
{
uint16_t crc_16 = 0;
rt_mutex_take(crc_mutex, RT_WAITING_FOREVER);
CRC->CRC16CTRL = CRC16_LSB | CRC16_CLR;
CRC->CRC16D = 0xFFFF;
CRC->LRC = 0;
while (len--)
{
CRC->CRC16DAT = *pdat++;
}
crc_16 = CRC->CRC16D;
rt_mutex_release(crc_mutex);
crc_16 = rt_reverse_16(crc_16);
return crc_16;
}
这么搞之后就是modbus的CRC16啦。
-
寄存器
+关注
关注
31文章
5328浏览量
120116 -
MODBUS
+关注
关注
28文章
1778浏览量
76867 -
CRC校验
+关注
关注
0文章
84浏览量
15194
发布评论请先 登录
相关推荐
评论