terça-feira, 30 de novembro de 2010

Calculo do CRC no protocolo modbus


// protocolo modbus
//
//microcontrolador : microchip
//compilador : CCS
//autor : aguivone
//data : 23/11/2010
//descrição : calculando o crc no modbus;
//..................................................................................................
#include <16F877A.h>
#fuses XT,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20M)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7)//,enable=PIN_D4)
//////////////////////////////////////////declaração das variaveis///////////////////////////////////
unsigned char buf_485[30];
unsigned char CRC_bytes[2];//cria um vetor para armazenar o valor do crc


///////////////////////////////////////////////funçoes usadas/////////////////////////////////////////
void Calculo_CRC(unsigned int num_of_char,unsigned char *ptr_num)//,register unsigned int checksum) checksum = 0XFFFF
{
char i,j;//variaveis local
long checksum = 0XFFFF;//resultado do crc
for (i=0; i < num_of_char; i++) { checksum ^= *ptr_num; // executa uma operação ex or (XOR) ptr_num++; // pega proximo caracter da sequencia(rotaciona uma unidade a direita no vetor) for (j=0; j < 8; j++) // checa os 8 bits do caracter { if ((checksum & 0x01) == 0) // se LSB bit = 0 { checksum >>= 1;//apenas rotaciona o bit sem nenhum tratamento
}
else
{
checksum = (checksum >> 1) ^ 0XA001;//rotaciona o bit e faz um ou logico(OR) com 0XA001
}
}
}
CRC_bytes[0]=checksum;
CRC_bytes[1]=checksum>>8;

}

/////////////////////////////////////////////////////////////////////////////////////////////////////
void main()
{
buf_485[0] = 0x01; // Endereço do Slave
buf_485[1] = 0x06; // Função MODBUS: Read Input Register
buf_485[2] = 0x01; // Registro inicial para ler (MSB)
buf_485[3] = 0x2C; // Registro inicial para ler (LSB)
buf_485[4] = 0x32; // Total de registros para ler (MSB)
buf_485[5] = 0x10; // Total de registros para ler (LSB)
Calculo_CRC(6, buf_485); //coloque a quantidade-1,pois a contagem
buf_485[6] = CRC_bytes[0]; // CRC (LSB)
buf_485[7] = CRC_bytes[1]; // CRC (MSB)
printf("MODBUS = %X - %X - %X - %X - %X - %X \r\n",buf_485[0],buf_485[1],buf_485[2],buf_485[3],buf_485[4],buf_485[5]);
printf("CRC = %X - %X ", buf_485[6],buf_485[7]);
}

Esta é a simulação:


7 comentários :

  1. obrigado pelo codigo ,testei e funcionou

    ResponderExcluir
  2. I need modbus protocol in AVR ATmega32
    How to do this modbus protocol communication RS485

    ResponderExcluir
  3. substituir essa linha:
    checksum ^= *ptr_num
    por essa:
    checksum ^= ptr_num[i]
    Daí funciona direitinho, obrigado pelo post \o

    ResponderExcluir
  4. Parabéns, muito bom esse seu código! Muito brigado.

    ResponderExcluir
  5. Estou tentando escrever em multiplas saidas digitais função 15 ou 0x0F, este é o protocolo que está sendo enviado (0x1 - 0xf - 0x0 - 0x0 - 0x0 - 0x8 - 0x1 - 0x0 - 0x2 - 0x95 - 0x41), neste caso o CRC é 0x95- 0x41, mas não estou conseguindo chegar neste resultado, queria saber qual valor alocar em cada posição do vetor neste caso, obrigado.

    ResponderExcluir
  6. Muito bom o seu código! Funcionou perfeitamente! Obrigado!

    ResponderExcluir

olá,digite aqui seu comentário!