Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
0
Help us understand the problem. What are the problem?

CRC-15-CANを計算するプログラムを書いた

はじめに

仕事でCAN通信のプログラムを書いているんだけど、CRCエラーの表示が出る。
デバッグのために、CRCの変換プログラムが必要になっった。
CANのCRCはCRC-15という特殊なフォーマットでネット上に資料が少ない。
ソースや調べたことをまとめておくことにした。

実装例

言語はcを使用。
(追記)コメントでint_to_binstr()の終端処理等の記述が抜けていたという指摘があり、修正した。


#include <stdio.h>
#include <stdint.h>

//  int to bin
char* int_to_binstr(char buff[], int bin, int len)
{
    int i;

    for (i = 0; i < len; i++) {
        if (bin & (1UL << (len - i - 1))) {
            buff[i] = '1';
        }
        else {
            buff[i] = '0';
        }
    }
    buff[len] = '\0';
    return buff;
}

uint16_t can_crc_next(uint16_t crc, uint8_t data)
{
    uint8_t i;
    crc ^= (uint16_t)data << 7;

    for (i = 0; i < 8; i++) {
        crc <<= 1;
        if (crc & 0x8000) {
            crc ^= 0xc599;
        }
    }
    return crc & 0x7fff;
}

void cal_crc15(unsigned char* buff, int len) {
    uint16_t crc;
    crc = 0;

    printf("crc15 0x");
    for (int i = 0; i < len; i++) {
        printf("%02X ", buff[i]);
    }

    printf("\n-> "); 

    for (int i = 0; i < len; i++) {
        crc = can_crc_next(crc, buff[i]);
    }
    char binstr[16];
    printf("0x%04X(%s)\n", crc, int_to_binstr(binstr, (int)crc, 15));
}

int main()
{
    uint8_t data[] = { 0x00, 0x80, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
    cal_crc15(data, 11);
}

CRC元データについて

CRCの元データはSOFからデータまで。スタッフビットは除く。
バイナリはHEXにする。
SOF側が半端なビットになるようにする。

CRC元データ.png

uint8_t data[] = { 0x00, 0x80, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }

プログラムの動作

CRCの初期値は0。


crc = 0;

データをHEXごとに取り出して7ビット左シフトしてCRCと排他的論理和をとる。


crc ^= (uint16_t)data << 7;

CRCを1ビット左シフト


crc <<= 1;

CRCの最上位ビットが1なら、CRC15の生成多項式x^15 + x^14 + x^10 + x^8 + x^7 + x^4 + x^3 + 1(=0xc599)との排他的論理和を取る。


        if (crc & 0x8000) {
            crc ^= 0xc599;
        }

15ビットなので16ビットの最上位ビットを省く。


return crc & 0x7fff;

注意

CANコントローラ(MCP2515)の吐き出した値と一致することは確認できているが、CAN15の仕様と完全に一致しているかは確認できていない。
おそらく大丈夫だとは思うが。

参考URL

http://forum.easyelectronics.ru/viewtopic.php?f=49&t=34508
https://qiita.com/niQSun/items/5bf1d8d9ceea16d83951
https://qiita.com/dearblue/items/669e2ce2fae57baf1e90
https://ja.wikipedia.org/wiki/%E5%B7%A1%E5%9B%9E%E5%86%97%E9%95%B7%E6%A4%9C%E6%9F%BB
https://reveng.sourceforge.io/crc-catalogue/1-15.htm#crc.cat-bits.15

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
0
Help us understand the problem. What are the problem?