terça-feira, 9 de abril de 2013

Discadora completa - Avr


          Como funciona?

               Olá, hoje vou trazer um projeto completo e funcional de uma discadora para alarmes
 usando a discagem por pulsos,o funcionamento é bem simples basta deixar o jumper (ou uma chave on/off) fechado para configurar os telefones a serem discados e com a chave aberta  ao energizar o circuito ele já inicia a discagem(após 5s). assim basta ligar a alimentação do circuito a saida da sirene(que geralmente é 12V).Para configurar os telefones basta deixar o jumper fechado e enviar pela serial do seu pc (lembre se de usar o ci max 232,para não queimar os pinos de comunicação do seu microcontrolador) um comando com a seguinte formatação "<" + "memoria" + "digitos do telefone" + ">",onde "memoria" é o numero do registro (no máximo 3 registros) e os digitos é o numero do telefone(maximo de 15 digitos ).Por exemplo vamos supor que vc queira liguar para três numeros '111','222' e '333'então basta enviar os comandos "<0111>","<1222>" e "<2333>", mas se vc quer apenas 2 telefones faça assim: "<0111>","<1222>" e "<2>",então o circuito só vai ligar para 111 e 222.
  
          O esquemático:

        

       O circuito de simulação:


        O código fonte:


/*
 *                                       Discadora simples configurada via porta serial
 *   Version    : 1.0
 *   microcontrolador : AVR ATMega328
 *   descrição  : discadora por pulso(apenas liga não toca som), liga para 3 numeros
 *   criado: 08/04/2013 
 *   autor: aguivone moretti fogia
 */


#define F_CPU 20000000  // 20 MHz
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdio.h>
#include <util/delay.h>
  #include <avr/eeprom.h>//usado para acessar memoria

//funçoes basicas dos pinos
#define alterna_pino(x,y) x ^= _BV(y)   
#define liga_pino(x,y) x |= _BV(y)
#define desliga_pino(x,y) x &= ~(_BV(y))
#define estado_pino(x,y) ((x & _BV(y)) == _BV(y)) //o pino deve estar como entrada ,testa se está em nivel logico 1

#define PULSO    PB0  //no rele de discagem deve ser colocado um resistor de 470R para não curto circuitar a linha telefonica 
#define LED     PB2  //led piscante

int tel_num[3][15];//matriz pra guardar os numeros dos telefones
int disparo = 0;
int tempo_led = 0;

//variaveis para RS-232
unsigned char caracter;            //usado para pegar o caracter que chega pela serial
int  tam_buffer;                   //usado para contar o tamanho do buffer de recepção
volatile char rec_buffer ='S';     //usado para notificar que chegou dados
char buffer_serial[17];            //buffer da serial,tamanho máximo de 17 caracter


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

void RS232_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);
}

void escreve_caracter(unsigned char carac)//adaptado para funcionar com RS485
{  
            _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 
}

//////////////////////////interrupções requerida para usar a recepção serial///////////////////////////////////
ISR(USART_RX_vect)//aqui pega os dados da serial
{
  caracter = (char)UDR0;
  if(caracter == '>')
   {
        if(tam_buffer<17)//max do buffer/maximo de digitos 17
          {
                          buffer_serial[tam_buffer]=caracter;
                          tam_buffer++;
                          rec_buffer ='F';
                          buffer_serial[tam_buffer]='\0';
           }
           else
           {
            rec_buffer ='E';//tamanhoa incompativel
           }
   }
   else
   {
      if(rec_buffer == 'I')
       {
        buffer_serial[tam_buffer]=caracter;
        tam_buffer++;
        }
    }
  if(caracter == '<')//inicia a captura dos numeros do telefone
   {
   rec_buffer ='I';
   buffer_serial[0]='<';
   tam_buffer=1;
   }
}

void numero(int valor)// função usada para fazer a discagem
{
    int xis=0;
     while(xis < valor)
     {
      desliga_pino(PORTB,PULSO);
      _delay_ms(35);
      liga_pino(PORTB,PULSO);
      _delay_ms(65); 
      xis++;
     }
     _delay_ms(400);//tempo necessario entre cada digito
}

int char_to_int(char valor,int seleciona)//seleciona entre numero e pulsos
 {//converte caracter para numero
      int retorno = 100;//se retornar 100 é porque deu erro
      switch(valor)
         {
           case '0':
               {
                 if(seleciona == 1)
                 {
                  retorno = 10;//nos pulsos 10 = 0    
                  }
                  else
                  {
                  retorno = 0;
                  }              
               }break;
           case '1':
               {
                 retorno = 1;
               }break;
           case '2':
               {
                 retorno = 2;
               }break;
           case '3':
               {
                 retorno = 3;
               }break;
           case '4':
               {
                 retorno = 4;
               }break;
           case '5':
               {
                 retorno = 5;
               }break;
           case '6':
               {
                 retorno = 6;
               }break;
           case '7':
               {
                 retorno = 7;
               }break;
           case '8':
               {
                 retorno = 8;
               }break;
           case '9':
               {
                 retorno = 9;
               }break;
           case '*':
               {
                 retorno = 11;
               }break;
           case '#':
               {
                 retorno = 12;
               }break;

         }

         return(retorno);
 }  

//////////////////////////////////////////////função principal///////////////////////////////////////////
int main(void)
{
           DDRB = 0XFF;  //inicializa portB como saida;
           DDRD = 0X02;  //inicializa portD como entrada e D1 como saida;
           desliga_pino(PORTB,PULSO);//rele de discagem
           RS232_inicializa(9600);//inicializa serial com a velocidae de 9600bps
           sei();//habilita interrupções
           char gravado = 'n';
           _delay_ms(500);//espera estabilizar a tensão
           _EEGET(gravado,50);//pega valor da posição de memoria 50

           if(gravado == 'G')//memoria já foi gravado alguma vez
           {     
                  int x = 0;  
                  while(x<3)
                   {
                    int posi = x*15;//pega posição inicial   
                    int y=0;      
                    while(y < 15 )
                        {
                         _EEGET(tel_num[x][y],posi); //pega valores da memoria eeprom
                         y++;
                           posi++;
                         }
                     x++;
                    }
            }
        
           for(;;)
           {
              if(estado_pino(PIND,2))//checa pra ver se modo discadora habilitado
                      {//se estiver no modo discadora nem chega a serial para evitar que ruidos apague os dados
                        if(disparo < 2)//aqui define quantas vezes o circuito vai repetir as chamadas
                         {
                          int nume=0;
                                 while(nume<3)
                             {
                               _delay_ms(5000);//espera 5s antes de discar pois pode ter sido só um bip do alarme ; comentar na simulação pois leva muito tempo
                               alterna_pino(PORTB,LED);
                               int digito = 0;
                               liga_pino(PORTB,PULSO);
                               _delay_ms(200); //espera para dar linha para discar
                               while((digito<15)&&(tel_num[nume][digito]!= 100)&&(tel_num[nume][digito] != 0))//se maior que 15 e se valor null ou '>' manda parar
                               {
                                 numero(tel_num[nume][digito]);//disca numero
                                 escreve_caracter(tel_num[nume][digito] + '0'); //escreve o digito na serial
                                 digito++;
                               }
                               alterna_pino(PORTB,LED);     
                               _delay_ms(20000);//tempo de chamada  //comentar na simulação pois leva muito tempo
                               desliga_pino(PORTB,PULSO);
                               escreve_caracter('\n'); //pula linha
                               escreve_caracter('\r'); //retorna a linha inicial
                               nume++;                         
                             }
                          disparo++;  
                         }
                      }
                      else
                      {
                        if(rec_buffer == 'F')//tem dados pra ler na serial.
                                  {
                                      int xis=255; 
                                      xis = char_to_int(buffer_serial[1],0);
                                      if(xis < 3)//vetor valido
                                              {   
                                                  xis = 2; 
                                                  while(xis<tam_buffer)
                                                    {//tem que converte para char
                                                     tel_num[char_to_int(buffer_serial[1],0)][xis-2] = char_to_int(buffer_serial[xis],1);//copia e já converte em numero e pulsos
                                                      _EEPUT(((xis-2) +(char_to_int(buffer_serial[1],0)*15) ),tel_num[char_to_int(buffer_serial[1],0)][xis-2] );//endereço/dado para memoria
                                                     xis++;            
                                                    }
                                                     _EEPUT(((xis-2) +(char_to_int(buffer_serial[1],0)*15) ),100);
                                                    escreve_caracter('O');//ok dados gravados
                                                    _EEPUT(50,'G');
                                              }
                                              else
                                              {
                                                escreve_caracter('F');//dados invalidos
                                              }
                                      rec_buffer ='S';//indica que foi lido 
                                  }
                      } 
            tempo_led++;
            if(tempo_led > 20000)//tempo do led piscar
                {                             
                alterna_pino(PORTB,LED);
                tempo_led = 0;    
                }  
           }//for infinito
}//main

até a próxima veja também a  pagina no face : busque pelo perfil "Microcontroladores-C"

Nenhum comentário :

Postar um comentário

olá,digite aqui seu comentário!