// 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:
obrigado pelo codigo ,testei e funcionou
ResponderExcluirI need modbus protocol in AVR ATmega32
ResponderExcluirHow to do this modbus protocol communication RS485
substituir essa linha:
ResponderExcluirchecksum ^= *ptr_num
por essa:
checksum ^= ptr_num[i]
Daí funciona direitinho, obrigado pelo post \o
Parabéns, muito bom esse seu código! Muito brigado.
ResponderExcluirEstou 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.
ResponderExcluirMuito brigado!
ResponderExcluirMuito bom o seu código! Funcionou perfeitamente! Obrigado!
ResponderExcluir