TUTORIAL: RS-485 com PIC
"É um padrão de comunicação serial, também denominado EIA-485."
"O padrão RS-485 é baseado na transmissão diferencial de dados, através de um par de fios, que é ideal para transmissão em altas velocidades, longas distâncias e em ambientes propícios a interferência eletromagnética. Ele permite a comunicação entre vários elementos( escravos ) em uma mesma rede de dados. A transmissão diferencial de dados funciona da seguinte forma: qualquer transmissor RS-485 possui dois canais independentes conhecidos como A e B, que transmitem níveis de tensão iguais, porém com polaridades opostas."
O compilador MikroC PRO oferece suporte para a comunicação RS-485. Possui 6 funções:
RS485Master_Init() - Inicializa o MCU como Master( Mestre ).
RS485Master_Receive( char *dat ) - Recebe os dados do escravo.
dat - 7 bytes recebidos e que contem várias informações:
dat[0..2] - Conteúdo da mensagem;
dat[3] - Número de bytes da mensagem.
dat[4] - Flag. Recebeu uma mensagem( dat[4] = 255 ). Deve ser limpa via software.
dat[5] - Flag. Erro ( dat[5] == 255 ). Deve ser limpa via software.
dat[6] - Endereço do escravo que enviou a mensagem.
RS485Master_Send( char *dat, char length, char address ) - Envia uma mensagem a um determinado escravo.
dat - 3 bytes a serem enviados ao escravo.
length - O tamanho da mensagem. 1 a 3 bytes.
address - O endereço do escravo.
RS485Slave_Init( char address ) - Inicializa o MCU como Slave( Escravo ).
address - Define um endereço para o escravo.
RS485Slave_Receive( char *dat ) - Recebe os dados do mestre.
dat - 6 bytes recebidos e que contém várias informações:
dat[0..2] - Conteúdo da mensagem;
dat[3] - Número de bytes da mensagem.
dat[4] - Flag. Recebeu uma mensagem( dat[4] = 255 ). Deve ser limpa via software.
dat[5] - Flag. Erro ( dat[5] == 255 ). Deve ser limpa via software.
RS485Slave_Send( char *dat, char length ) - Envia uma mensagem ao mestre.
dat - 3 bytes a serem enviados ao escravo.
length - O tamanho da mensagem. 1 a 3 bytes.
Obs.:
- Mensagem contendo o endereço 50 será recebido por todos os escravos, exceto os escravos com endereços 150 e 169.
- A biblioteca UARTx deve ser inicializada.
EXEMPLO: Master
sbit rs485_rxtx_pin at RD0_bit; sbit rs485_rxtx_pin_direction at TRISD0_bit; char dat[8]; void interrupt() { RS485Master_Receive( dat ); } void main() { Uart1_Init( 9600 ); //Inicializa o modulo UART RS485Master_Init(); //inicializa o MCU como master Soft_Uart_Init( &PORTD, 6, 7, 9600, 0 ); RCIE_bit = 1; //Habilita interrupção por recepcao TXIE_bit = 0; //Desabilita interrupção por transmissao PEIE_bit = 1; //Habilita interrupção dos periféricos GIE_bit = 1; //Habilita a interrupção global dat[4] = 0; //limpa flag dat[5] = 0; //limpa flag while(1) { dat[0] = 0x22; dat[1] = 0x67; dat[2] = 0x40; //Mensagem a ser enviada //Envia a mensagem para o escravo com o endereço 'C' RS485Master_Send( dat, 3, 'C' ); //Aguarda o recebimento da mensagem do escravo while( dat[4] != 255 ); dat[4] = 0; //limpa a flag //Envia a mensagem recebida para o PC Soft_Uart_Write( dat[0] ); Soft_Uart_Write( dat[1] ); Soft_Uart_Write( dat[2] ); Delay_ms( 1000 ); //Recepe o processo novamente só que para outro escravo dat[0] = 0x01; dat[1] = 0x22; dat[0] = 0x22; RS485Master_Send( dat, 3, 'T' ); while( dat[4] != 255 ); dat[4] = 0; Soft_Uart_Write( dat[0] ); Soft_Uart_Write( dat[1] ); Soft_Uart_Write( dat[2] ); Delay_ms( 1000 ); } }
EXEMPLO: Slave
sbit rs485_rxtx_pin at RB0_bit; sbit rs485_rxtx_pin_direction at TRISB0_bit; char dat[8]; unsigned ADC_Rd; void interrupt() { RS485Slave_Receive( dat ); } void main() { Uart1_Init( 9600 ); //inicializa como escravo e endereço = 'T' RS485Slave_Init( 'T' ); RCIE_bit = 1; //Habilita interrupção por recepcao TXIE_bit = 0; //Desabilita interrupção por transmissao PEIE_bit = 1; //Habilita interrupção dos periféricos GIE_bit = 1; //Habilita a interrupção global dat[4] = 0; //limpa flag dat[5] = 0; //limpa flag while(1) { if( dat[4] ) //Recebeu alguma mensagem { dat[4] = 0; //limpa a flag //Supondo q o MCU possui canal analógico ADC_Rd = ADC_Read(0); //Faz a leitura do canal analógico dat[0] = 0; //Informa a leitura do canal 0 dat[1] = ((char*)&ADC_Rd)[0]; dat[2] = ((char*)&ADC_Rd)[1]; RS485Slave_Send( dat, 3 ); //Envia 3 bytes ao master } } }
Boa tarde Tiago você teria algum exemplo de comunicação rs485 entre dois pic's mestre e escravo tipo eu preciono um botão no mestre ele envia para o escravo o escravo executa e informa ao mestre qual o seu estado.
ResponderExcluirVocê teria algo desse tipo agradeço a ajuda.
O codigo seria semelhante ao de cima, so adicione os tratamentos do botoes.
ExcluirBoa noite você teria como me falar onde devo colocar os botões.
ResponderExcluirESTOU TRABALHANDO NUM PROJETO PARA LIGAR O PIC EM UMA HMI TOUCH, MAS COMO ELA TEM O PADRAO RS485 PARA ACIONAR AS PORTAS DIGITAIS B10001 A B19999 COMO EU PODERIA DECLARAR ESTAS VARIAVEIS NO PIC ?
ResponderExcluirBoa tarde, tenho uma aplicação onde tenho 4 circuitos comunicando em 485 e preciso adquirir a mesma informação nesses 4 circuitos e exibir a soma delas. Fiquei com um pouco de dúvida no código, se utilizar um pic, ele deve enviar um byte para "ligar" cada escravo? Eu endereço o byte por exemplo para o escravo 3, quando receber uma resposta eu verifico na variavel correspondente ao endereço do escravo se foi o 3 que respondeu e a partir disso faço o tratamento das outras informações também recebidas? Obrigado, parabéns pelo blog.
ResponderExcluirOlá! uma dúvida.... pq no whille tem o de (dat[4] != 255) para aguardar a resposta do slave? sendo que assim que o master recebe pela interrupção, a flag dat[4] é setada 255, da forma que está o código não fica preso no whille, ele segue rodando pq a flag ainda é 0... não seria, whille(dat[4] == 255); ? para o código ficar preso e esperar a interrupção jogar o dat[4] para 255? Abraços e parabéns pelo blog! muito bom!
ResponderExcluirSeu código funciona perfeitamente, fiz um esquema no proteus e deu tudo certo... acho que estou confuso ainda na lógica da biblioteca RS485 do MIKROC. Abrços
ExcluirEle só vai sair do while quando dat[4] == 255, ou seja, enquanto não for 255, ele fica no loop.
ExcluirOlá, boa tarde!
ResponderExcluirTenho dificuldades em encontrar o MAX 485 no Proteus. Devo baixar alguma biblioteca para inseri-lo?
Obrigado
USE O MAX 487 É O MESMO PADRÃO MAXIM 485
ExcluirBoa tarde Galera, onde devo colocar os botões saídas de sinal?
ResponderExcluirQual configuração de fuses e cristal você recomenda? Estou usando um de 20Mhz e na prática o master reseta sozinho depois de alguns dados enviados. Ele tem outras funções além dessa do 485, eu apenas me baseei no seu código. O engraçado é com outras configurações de cristal que coloco o slave não recebe, mas também o master não reseta sozinho. Tem alguma idéia do que possa ser?
ResponderExcluirOlá! Com essa biblioteca eu só consigo enviar dados para os Slaves? Eu estou precisando coletar os dados que estão sendo executados nas entradas analógicas dos escravos... Até que eu consegui, porem depois de alguns instantes os Master trava no while.... é como se tivesse acontecido alguma falha de comunicação... Alguém pode me ajudar? Eu estou precisando muito de uma luz...
ResponderExcluirOlá dê uma olhada aqui: http://www.rogercom.com/CursoOnlineUSB/ModuloUnicoAula018.htm
Excluirgalera eu sou novo com mikroc como faço pra iniciar a biblioteca UARTx?
ResponderExcluirOlá, Estou precisando de um projeto para que eu possa controlar/enviar comandos IR via RS485. Alguém sabe onde posso encontrar ou alguém que possa vender essa solução?
ResponderExcluir