[资料工具] 单片机模块化程序--CRC校验

[复制链接]
 楼主| jerow 发表于 2019-12-30 10:27 | 显示全部楼层 |阅读模式
计算CRC
  1. /**
  2. * [url=home.php?mod=space&uid=247401]@brief[/url] calculate CRC
  3. * @param *modbusdata: Source data address
  4. * @param length: data length
  5. * @param
  6. * @retval CRC16 Value
  7. * [url=home.php?mod=space&uid=389923]@example[/url]
  8. **/
  9. int crc16_modbus(u8 *modbusdata, int length)
  10. {
  11.   int i, j;
  12.   int crc = 0xffff;//0xffff or 0
  13.   for (i = 0; i < length; i++)
  14.   {
  15.     crc ^= modbusdata[i];
  16.     for (j = 0; j < 8; j++)
  17.     {
  18.       if ((crc & 0x01) == 1)
  19.       {
  20.         crc = (crc >> 1) ^ 0xa001;
  21.       }
  22.       else
  23.       {
  24.         crc >>= 1;
  25.       }
  26.     }
  27.   }

  28.   return crc;
  29. }


 楼主| jerow 发表于 2019-12-30 10:28 | 显示全部楼层
判断接收的数据CRC是否正确
  1. /**
  2. * @brief check CRC for data
  3. * @param *modbusdata: Read data address
  4. * @param length: Read data length
  5. * @param
  6. * @retval 1:CRC16 OK
  7. * @example
  8. **/
  9. int crc16_flage(u8 *modbusdata, int length)
  10. {
  11.   int Receive_CRC=0,calculation=0;

  12.   if(length<=2)
  13.   {
  14.     return 0;
  15.   }

  16.   Receive_CRC = crc16_modbus(modbusdata, length-2);
  17.   calculation = modbusdata[length-2];
  18.   calculation <<= 8;
  19.   calculation += modbusdata[length-1];
  20.   if(calculation != Receive_CRC)
  21.   {
  22.     return 0;
  23.   }
  24.   return 1;
  25. }
 楼主| jerow 发表于 2019-12-30 10:29 | 显示全部楼层
发送的数据加上CRC
我想发送 01 00 55 aa 数据
359415e0961022b387.png
最终发送的数据
975225e096119807dd.png
说明:

  1.最后两位 F7 和 BE就是经过CRC16计算之后的数据;高位在前,低位在后

  2.整个数据发给另一个设备以后,另一个设备用同样的方式计算 01 00 55 aa 的CRC16值

  然后判断下自己计算的值是不是 F7,BE
 楼主| jerow 发表于 2019-12-30 10:30 | 显示全部楼层
判断接收的数据CRC是否正确
500075e09614104fa3.png
472525e0961489649c.png
 楼主| jerow 发表于 2019-12-30 10:31 | 显示全部楼层
上位机(C# / JAVA)CRC16校验程序
  1. /// <summary>
  2.   /// calculate CRC
  3.   /// </summary>
  4.   /// <param name="modbusdata">Source data address</param>
  5.   /// <param name="length">data length</param>
  6.   /// <returns></returns>
  7.   private int crc16_modbus(byte[] modbusdata, int length)
  8.   {
  9.     int i, j;
  10.     int crc = 0xffff; //0xffff or 0
  11.     try
  12.     {
  13.       for (i = 0; i < length; i++)
  14.       {
  15.         crc ^= modbusdata[i]&0xff;
  16.         for (j = 0; j < 8; j++)
  17.         {
  18.           if ((crc & 0x01) == 1)
  19.           {
  20.             crc = (crc >> 1) ^ 0xa001;
  21.           }
  22.           else
  23.           {
  24.             crc >>= 1;
  25.           }
  26.         }
  27.       }
  28.     }
  29.     catch (Exception)
  30.     {
  31.       throw;
  32.     }
  33.     return crc;
  34.   }





  35.   /// <summary>
  36.   ///
  37.   /// </summary>
  38.   /// <param name="modbusdata"></param>
  39.   /// <param name="length"></param>
  40.   /// <returns></returns>
  41.   private int crc16_flage(byte[] modbusdata, int length)
  42.   {
  43.     int Receive_CRC = 0, calculation = 0;//接收到的CRC,计算的CRC
  44.     if(length<=2) return 0;
  45.     Receive_CRC = crc16_modbus(modbusdata, length-2);
  46.     calculation = modbusdata[length -2];
  47.     calculation <<= 8;
  48.     calculation += modbusdata[length-1];
  49.     if (calculation != Receive_CRC)
  50.     {
  51.       return 0;
  52.     }
  53.     return 1;
  54.   }



  55.   注:对于上位机byte类型需要&0xff

185095e096184cae51.png
 楼主| jerow 发表于 2019-12-30 10:32 | 显示全部楼层
扩展
大部分设备的CRC16计算方式,这个地方是 0xffff, 但是也有0的情况
61635e0961a743a4b.png
您需要登录后才可以回帖 登录 | 注册

本版积分规则

72

主题

520

帖子

3

粉丝
快速回复 在线客服 返回列表 返回顶部

72

主题

520

帖子

3

粉丝
快速回复 在线客服 返回列表 返回顶部