以前都是使用軟件CRC,浪費計算時間,有硬件CRC不用,真是可惜。本次使用硬件CRC對ModBus的CRC進行計算,測試時,遇到點問題,自帶的庫文件里面,把方法寫死了,結(jié)果和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);
}
當(dāng)然初始化時鐘是要加上的啦
RCC_EnableAHBPeriphClk(RCC_AHB_PERIPH_CRC, ENABLE);
就是這么簡單,再不用擔(dān)心寫錯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);
/ 創(chuàng)建一個動態(tài)互斥量 */
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;
}
發(fā)現(xiàn)問題,這個數(shù)據(jù)太迷惑了,以上代碼有問題,請不要使用
終于可以正確的使用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啦。
-
寄存器
+關(guān)注
關(guān)注
31文章
5336瀏覽量
120228 -
MODBUS
+關(guān)注
關(guān)注
28文章
1799瀏覽量
76947 -
CRC校驗
+關(guān)注
關(guān)注
0文章
84瀏覽量
15207
發(fā)布評論請先 登錄
相關(guān)推薦
評論