巡回冗長検査 CRC(Cyclic Redundancy Check)
データの受け渡し時、データが正しく届いたか確認するために送出データの最後にCRCで計算したデータを追加して送出します。受取側で受け取ったデータもCRC計算し、送られてきたCRCと比較して等しかったら正しくデータを受け取れたと判断します。
CRCの仕組み及び詳細は他のサイトを見ていただくとして、ここでは実際に使用しているコードにつて説明します。
本件では実験基板(ファームウェア)とコンピュータ(アプリケーション)間で通信を行うので各々にCRC計算処理が必要です。
どちらも以下のC言語で実装しても良いのですが
// CRC計算
#define CRC16POLY 0x1021 // 生成多項式:x16+x12+x5+1
unsigned short crc16(unsigned short crc, unsigned char const* ptr, int len)
{
int i, j;
for (i = 0; i < len; i++) {
crc ^= (((unsigned short)ptr[i]) << 8);
for (j = 0; j < 8; j++) {
if (crc & 0x8000) {
crc = (crc << 1) ^ CRC16POLY;
}
else {
crc <<= 1;
}
}
}
return crc;
}
// 使用方法
unsigned short crc = crc16(0x5abe, &data, size); // data:データ size:データサイズ
実験基板に使用しているCPUにはCRC計算モジュールが内蔵されているので、それを使用してファームウェアの負荷を減らします。
このモジュールの初期設定はCubeMXで生成してもらいます。
1.CubeMXの設定
2.CubeMXによる初期化コードの生成
3.モジュールを使ったCRC計算
1.CubeMXの設定
生成多項式:x16+x12+x5+1
初期値:0x5abe
ビットシフト方向:左送り
出力XOR:0x0000(非反転)
この設定は送り側と受け側のCRC計算で同じにする必要があります。
2.CubeMXによる初期化コードの生成
/**
* @brief CRC Initialization Function
* @param None
* @retval None
*/
static void MX_CRC_Init(void)
{
/* USER CODE BEGIN CRC_Init 0 */
/* USER CODE END CRC_Init 0 */
/* USER CODE BEGIN CRC_Init 1 */
/* USER CODE END CRC_Init 1 */
hcrc.Instance = CRC;
hcrc.Init.DefaultPolynomialUse = DEFAULT_POLYNOMIAL_DISABLE;
hcrc.Init.DefaultInitValueUse = DEFAULT_INIT_VALUE_DISABLE;
hcrc.Init.GeneratingPolynomial = 4129; // 0x1021
hcrc.Init.CRCLength = CRC_POLYLENGTH_16B;
hcrc.Init.InitValue = 0x5abe;
hcrc.Init.InputDataInversionMode = CRC_INPUTDATA_INVERSION_NONE;
hcrc.Init.OutputDataInversionMode = CRC_OUTPUTDATA_INVERSION_DISABLE;
hcrc.InputDataFormat = CRC_INPUTDATA_FORMAT_BYTES;
if (HAL_CRC_Init(&hcrc) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN CRC_Init 2 */
/* USER CODE END CRC_Init 2 */
}
3.モジュールを使ったCRC計算
// 前記プログラムによるCRC計算
unsigned short crc = crc16(0x5abe, &data, size); // data:データ size:データサイズ
// CPU CRCモジュールによるCRC計算
CRC_HandleTypeDef hcrc;
hcrc.Init.InitValue = 0x5abe;
HAL_CRC_Init(&hcrc);
uint32_t uwCRCValue1 = HAL_CRC_Accumulate(&hcrc, (uint32_t *)&data, size);
crc = (uint16_t)(uwCRCValue1 & 0x0000ffff);
コンピュータ側のアプリケーションプログラムはC#で作成しているのでC#用に書き換えます。