quarta-feira, 4 de abril de 2012

Usando RS485 no AVR STUDIO - ATmega328:

 /*

 *                                                 usando a rs485
 *   Version    : 1.0
 *   microcontrolador : AVR ATMega328
 *   descrição  : exemplo usando a comunicação rs 485 em modo mestre-escravo
 *   criado: 3/4/2012 10:10:07
 *   autor: aguivone moretti fogia
 */


#define F_CPU 16000000  // 16 MHz
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdio.h>
#include <util/delay.h>
#include <string.h>

  #define alterna_pino(x,y) x ^= _BV(y)   
  #define liga_pino(x,y) x |= _BV(y)
  #define desliga_pino(x,y) x &= ~(_BV(y))
  char caracter;

///////////////////////////////////////////////funçoes usadas pela usart////////////////////////////////////////////////

void RS485_inicializa(unsigned int BAUD)
{

   unsigned int velocidade = F_CPU/16/BAUD-1;
   //veja que na simulação do proteus dá erros nas velocidade diferentes de 9600 mas na pratica funciona.
   UCSR0A = 0X20;
/* habilita receiver and transmitter buffers */
  UBRR0H = (unsigned char)(velocidade>>8);
  UBRR0L = (unsigned char)velocidade;
  UCSR0B = 0X98;//deve se habilitar somente a interrupção de recepção para não travar o microcontrolador
  /* 8 bits , 1 stop bit, assincrono , sem paridade,modo nornal */
  UCSR0C = (1<<USBS0)|(3<<UCSZ00);
  desliga_pino(PORTD,PD2);
}

void escreve_caracter(unsigned char carac)
{  

            liga_pino(PORTD,PD2);//pino de controle da RS-485 
            _delay_loop_1(1);//tempo para estabilizar tensão            
            while ( !( UCSR0A & (1<<UDRE0)) ); //espera transmitir para enviar um novo
            UDR0 = carac;    
            while ( !( UCSR0A & (1<<UDRE0)) ); //espera transmitir desabilita a transmissão
            _delay_loop_1(1);//tempo para garantir o envio
            desliga_pino(PORTD,PD2);//pino de controle da RS-485   
}
void impri_serial(const char frase[80])
{
      unsigned int indice=0;
      unsigned int tamanho = strlen(frase);    
       while(indice<=tamanho)///veja que o programa pode travar se aqui não tiver as duas aspas
       {
            escreve_caracter(frase[indice]);
            indice++;
       }

}

//////////////////////////interrupções requerida para usar a recepção serial///////////////////////////////////
ISR(USART_RX_vect)
{
 caracter = (char)UDR0;
 escreve_caracter(caracter);
}
 

  
//////////////////////////////////////////////função principal///////////////////////////////////////////
int main(void)
{
           DDRD = 0XFE;  //inicializa portD,4 a 7 entrada
           RS485_inicializa(9600);
           sei();
           impri_serial("Inicializado ... \n\r");
           impri_serial("pronto !\n\r");    

          //////////////////////////
          int long teste;
          for(;;)
            { 
                if(teste > 100000)
                {
                    alterna_pino(PORTB,PB1);
                    teste=0;                                        
                }                                    
              teste++;
            }
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////

É preciso estar atento na hora de simular pois em testes feito no proteus gerou alguns erros :se colocar um baud rate diferente de 9600 ,os caracteres saem as vezes errados mas em teste práticos isso não acontece(vale lembrar que quando é usado só a serial 232 isso não acontece) acredito que seria uma limitação do software de simulação, veja abaixo imagem da simulação e o esquemático:



       veja que na simulação aparece alguns avisos.Neste exemplo tudo que você digitar no terminal rs485 é repetido no 232,pois no programa é solicitado que repita o que chegar no microcontrolador,assim termino aqui mais um exemplo de uso dos microcontroladores AVR.


configuração do proteus (o clock é de 16MHZ - se usar o cristal interno deve se reconfigurar todos os fuses do microcontrolador):