CRC 16 Modbus RTU

Como podéis comprobar en el siguiente enlace:

http://www.lammertbies.nl/comm/info/crc-calculation.html

Existen diferentes CRC que pueden calcularse de un mismo array de datos, ya no distinguiendo en el número de bytes sino en el polinomio para calcularlo. En el link anterior veréis que se distingue incluso entre 3 CRC de 16bits, uno de ello el utilizado par Modbus RTU. Para la comprobación a modo de debug manual la web anterior es buena, pero he pensado interesante colgar a continuación un pequeño código en C de toda la vida para incluirlo en vuestro firmware o software de test.

Tened en cuenta que el polinomio a utilizar es 2^15+2^13+1 (0xA001)y que a modo de recordatorio las variables definidas como unsigned int y int son de 16bits (2bytes) y las unsigned char y char de 8bits (1byte)

#define POLINOMIO_MODBUS 0xA001

unsigned int ModbusRTU_CRC16(unsigned char* ptucBuffer, unsigned int uiLen)
{
   unsigned char ucCounter;
   unsigned int uiCRCResult;
   for(uiCRCResult=0xFFFF; uiLen!=0; uiLen --)
   {
      uiCRCResult ^=*ptucBuffer ++;
      for(ucCounter =0; ucCounter <8; ucCounter ++)
      {
         if(uiCRCResult & 0x0001)
            uiCRCResult =( uiCRCResult >>1)^POLINOMIO_MODBUS;
         else
            uiCRCResult >>=1;
      }
   }
   return uiCRCResult;
}

 

Tagged with: , , , , , , ,
Posted in Blog Técnico, Hardware Firmware, ModBUS
5 Comments » for CRC 16 Modbus RTU
  1. Juan Hauara dice:

    Excelente info, una pregunta, he estado leyendo el estándar MODBUS RTU y según el documento “Modbus_over_serial_line_V1_02” al final de la página 40 especifica que el polinomio generador debe ser “(Generating polynomial = 1 + x2 + x 15 + x 16)”.
    El documento lo baje de la página oficial http://www.modbus.org/specs.php.
    Es posible usar este código con el polinomio que especifica el estándar?
    Que diferencia tiene con el código sugerido en las páginas 42 y 43 del mismo documento?
    Saludos y gracias.

  2. Mauricio Alvarez dice:

    Hola Xavier.

    Buen aporte.

    Para que funcione correctamente debes sustituir la linea

    if(uiCRCResult && 0x0001) por la siguiente:

    if(uiCRCResult & 0x0001)

    Saludos desde Venezuela
    Mauricio Alvarez

  3. Juan dice:

    hola Xavier,

    gran aporte pero, creo que tienes un error en “if(uiCRCResult && 0x0001)”, este deberia ser “if(uiCRCResult & 0x0001)” y el retorno deberia devolver el resultado swapped, es decir “return (uiCRCResult>>8)+(uiCRCResult<<8);".

    Saludos.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos necesarios están marcados *

*


*

enlaces patrocinados