sábado, 7 de julho de 2012

ATMEGA328 gerando DTMF !

            A forma mais simples de gerar tom DTMF é por meio de CIS que fazem isso(exemplo: MV5089, EF71189, LC7365, MT8880, TP5088) aqui vou demonstrar como usar o chip da holtek HT9200A este chip é de fácil montagem visto que necessita de poucos componentes externos(dois capacitores e um crital),observado a figura abaixo que foi retirada do datasheet do fabricante é fácil perceber como é simples  sua utilização:


            Para comunicar é preciso envia um pacote de pulsos(clock) e então colocar os dados de forma serial , lembrando que o pino de habilitação do chip "CE" deve ser colocado em nível baixo para comuinicar   veja a figura:

            Bom então vamos ao código fonte:
/*
 *                                                 usando gerador de DTMF HT9200
 *   Version    : 1.0
 *   microcontrolador : AVR ATMega328
 *   descrição  : exemplo usando o HT9200, neste exemplo gera tom de 0 a 9 ao iniciar e depois o programa para.
 *   criado: 07/07/2012 
 *   autor: aguivone moretti fogia
 */
//sempre deixar as otimizações em 01 pra não ter surpresas em teu codigo

#define F_CPU 16000000  // 16 MHz
#include <avr/io.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))


 //SERIAL DTMF

 #define DTMF_DADOS PD2 //gera sinal de dados
 #define DTMF_CLOCK PD3 // gera sinal de clock
 #define DTMF_HABILITA PD4//habilita chip HT9200



//////////////////////////////////////////////////////////////////////////////////////////////////////////
//DTMF

void DTMF_envia(int DT)
{
      int X=1;
      desliga_pino(PORTD,DTMF_HABILITA);//habilita chip
      _delay_ms(10);//espera oscilador do chip estabilizar
      while(X > 0)
      {
          if((DT & X) > 0)
            {// igual a 1
             liga_pino(PORTD,DTMF_DADOS);//nivel um            
            }
            else
            {///igual a zero
            desliga_pino(PORTD,DTMF_DADOS);//nivel zero
            }
            X=X*2;//o mesmo que rotacionar
            _delay_ms(5);//espera estabilizar pinos
            desliga_pino(PORTD,DTMF_CLOCK);//habilita leitura de dados 
            _delay_ms(10);//espera ler
            liga_pino(PORTD,DTMF_CLOCK);//mantem clock en nivel alto

      }
      desliga_pino(PORTD,DTMF_DADOS);//sem dados
      

}
  
//////////////////////////////////////////////função principal///////////////////////////////////////////
int main(void)
{
           DDRD = 0XFE;  //inicializa portD,somente D0 é entrada
           DDRC = 0XFF;  //inicializa portD,somente D0 é entrada
          //////////////////////////

          liga_pino(PORTD,DTMF_HABILITA);//desabilita chip
          liga_pino(PORTD,DTMF_CLOCK);//mantem clock en nivel alto
          desliga_pino(PORTD,DTMF_DADOS);//sem dados

          for(;;)
            { 
                  DTMF_envia(10);//o zero é 10 em DTMF
                  _delay_ms(500);//tempo para reconhecer o dtmf(simula aperta da tecla do telefone)

                  DTMF_envia(1);
                  _delay_ms(500);//tempo para reconhecer o dtmf(simula aperta da tecla do telefone)

                  DTMF_envia(2);
                  _delay_ms(500);//tempo para reconhecer o dtmf(simula aperta da tecla do telefone)

                  DTMF_envia(3);
                  _delay_ms(500);//tempo para reconhecer o dtmf(simula aperta da tecla do telefone)

                  DTMF_envia(4);
                  _delay_ms(500);//tempo para reconhecer o dtmf(simula aperta da tecla do telefone)

                  DTMF_envia(5);
                  _delay_ms(500);//tempo para reconhecer o dtmf(simula aperta da tecla do telefone)

                  DTMF_envia(6);
                  _delay_ms(500);//tempo para reconhecer o dtmf(simula aperta da tecla do telefone)

                  DTMF_envia(7);
                  _delay_ms(500);//tempo para reconhecer o dtmf(simula aperta da tecla do telefone)

                  DTMF_envia(8);
                  _delay_ms(500);//tempo para reconhecer o dtmf(simula aperta da tecla do telefone)

                  DTMF_envia(9);
                  _delay_ms(2000);//tempo para reconhecer o dtmf(simula aperta da tecla do telefone)
                    DTMF_envia(31);//Stop bit//manda para o som dtmf
                  liga_pino(PORTD,DTMF_HABILITA);//desabilita chip    
          
                  _delay_ms(2000);                        
            }
                 
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////
até a próxima pessoal!


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):

quinta-feira, 29 de março de 2012

Fonte chaveada com LM555:

Este é um dos meus experimentos sobre a possibilidade de fazer uma fonte chaveada simples e barata , mas é apenas para efeito didático , com essa fonte consegui gerar 5V na saída, usando um diodo zener é possível alimentar o chip(lm555) e ligar o transformador na fonte de tensão(até 30V) diretamente funcionando assim como um regulador de tensão pois de 12 a 30V ele consegue manter 5V na saída do circuito: 

    
Até a próxima postagem pessoal!


ERRATA: entre o resistor de 1K e 82K existe um nó que deve ser ligado ao pino 7 do lm555 e não no pino 5,o pino 5 pode ficar em aberto,lembrando que a alimentação do chip é no pino8(VCC) e 1(GND). Conforme figura abaixo:


quarta-feira, 7 de março de 2012

controle remoto pela internet


            Coloquei este vídeo para  demonstrar como funciona um modulo que pode ser usado para pequenas automações e sem precisar saber nada de programação . Com ele vc pode controlar o que quiser ,apenas configurando no software o que deve ser feito, tem a opção de agendar hora de ligar e desligar equipamentos, possui 5 entradas de sinal digital(que são acionados por meio de um sinal de 5V),  uma entrada analógica que pode ser usada para ler sensores ( temperatura , pressão ou qualquer outro que varie de 0 a 5V) e 8 saídas a rele com disponibilidade de usar os contatos normalmente aberto e normalmente fechado.
            é alimentado por uma fonte atx de pc(é mais em conta que uma chaveada especifica ), basta conectar a placa à porta de ethernet do computador ou com auxilio de um switch(dai você pode usar a porta para se conectar com a internet e com a placa ao mesmo tempo), sugiro usar esta placa sempre com o pc pois assim vc pode acessar sua maquina de outro computar remoto via algum software tipo vnc ou logmein , para ver o manual ou mais informações entre em contato pelo e-mail : aguivone@ibest.com.br. na aquisição do produto vai a placa e o software de controle remoto local.



aparência do modulo de automação:



sexta-feira, 9 de dezembro de 2011

Frequencímetro via RS232 com ATmega8:

Neste exemplo de código vou demonstrar como ler frequência usando o ATmega8(pode ser adaptado para outros modelos como o ATmega328), como tem caráter apenas didático o range de frequência está de 500Hz a 32kHz(pois o simulador não vai conseguir passar disto) ,mas você pode melhorar o código e adequar a cada necessidade, o intuito aqui é só exemplificar como fazer um frequencímetro usando o AVR STUDIO (ele é grátis ).
O código fonte:


///************************************************************************/
//                             contador de pulsos - (frequencimetro)
//  Version    : 1.0
//  microcontrolador : AVR ATMega8
//  Autor        : Aguivone
//  descrição  : captura de sinais
//  data : 09/12/2011.
//
//************************************************************************/
#define F_CPU 16000000UL  // 16 MHz deve vir antes das interrupçoes
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdio.h>
#include <util/delay.h>
#include <string.h>

int amostra1, amostra2 ;
int dig1='0';
int dig2='0';
int dig3='0';
int dig4='0';
int dig5='0';
int valor_lido=0;
int  frequencia;
int tem_interrupcao=0;
int estouro = 0;

/////////////////////////////////////////////////Funções usadas/////////////////////////////////////////////
void inicializa_timer1(void)
{
    //TIMSK = 0x21; //Habilita interrupção de captura do timer1 , e habilita interrupção de estouro do contador1
    TIMSK = 0x20; //Habilita interrupção de captura do timer1 , e habilita interrupção de estouro do contador1
    TCCR1A=0X00;//desabilita geração de pulsos 
    TCNT1=0x00;//zera contagem; 
    OCR1A =0x00;//desabilita comparadores 
    OCR1B =0x00;//desabilita comparadores
    TCCR1B=0x41;//filtro de ruido desabilitado(atrasa 4 ciclos),habilita interrupção na borda de subida,preescaler div por 1 
    /*
    pra outros valores basta mudar o ultimo digito para:
    1-dividido por 1
    2-dividido por 8
    3-dividido por 64
    4-dividido por 256
    5-dividido por 1024

    obs: o registrador ICR1 só pode ser zerado no modo de geração de pulso.
    ou seja é melhor zerar o TCNT1, pois quando o conteudo deste for copiado ele será zerado tambem.
    */


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

void serial_inicializa(unsigned int BAUD)
{
unsigned int valor = F_CPU/16/BAUD-1; //é recomendavel ver o data sheet para ter certeza se está formula irá funcionar na sua mcu
/* baud rate */
UBRRH = (unsigned char)(valor>>8);
UBRRL = (unsigned char)valor;
UCSRA = 0X20;
/* habilita receiver and transmitter buffers */
UCSRB = 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 */
UCSRC = 0X86;
}
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
       {
           while ( !( UCSRA & (1<<UDRE)) ); //espera transmitir para enviar um novo
           UDR =frase[indice];
           indice++;
       }
}
void put_serial(int carac)
{
           while ( !( UCSRA & (1<<UDRE)) ); //espera transmitir para enviar um novo
           UDR = carac;
}


void converte(int quant)//converte int para 3 caracter numerico
{
   dig1='0';
   dig2='0';
   dig3='0';
   dig4='0';
   dig5='0';
   if(quant > 0)
       {
       while(quant>=10000)
        {
         quant=quant-10000;
         dig1++;
         }
       while(quant>=1000)
        {
         quant=quant-1000;
         dig2++;
         }
       while(quant>=100)
        {
         quant=quant-100;
         dig3++;
         }
       while(quant>=10)
        {
         quant=quant-10;
        dig4++;
         }
       while(quant>=1)
        {
           quant=quant-1;
         dig5++;
         }
      }
      }

//////////////////////////interrupções do timer1 ///////////////////////////////////
ISR(TIMER1_CAPT_vect)
{///quando a interrupção é ativada e o vetor de interrupção é zerado 
       unsigned char sreg;
       cli();//disabilita as interrupçoes
       TCNT1 = 0;//zera contador 
       sreg = SREG;//salva o valor dos flags de interrupçoes.
       valor_lido = ICR1;
       tem_interrupcao = 1;
       SREG = sreg;//restaura o valor das interrupçoes globais (consequentemente habilita as interrupçoes novamente)
}
//////////////////////////////////////////////função principal///////////////////////////////////////////
int main(void)
{
           DDRC = 0xFF;  //inicializa portd
           PORTC = 0;
           inicializa_timer1();
           serial_inicializa(9600);
           sei();
           for(;;)
            {//obs : no laço for não pode ficar sem nenhuma acão,deve ser coisa do compilador

                  if(tem_interrupcao == 1)
                  {
                     frequencia=16000000/valor_lido;//veja que vai ser arredondado para dar o resultado em inteiros.
                     converte(frequencia);
                     put_serial(dig1);
                     put_serial(dig2);
                     put_serial(dig3);
                     put_serial(dig4);
                     put_serial(dig5);             
                     put_serial(*"\n"); //pula linha 
                     put_serial(*"\r"); //retorna ao inicio da linha
                     estouro =0;
                  }
                  tem_interrupcao=0;

                 
            }            
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////
A simulação:



sexta-feira, 21 de outubro de 2011

display 20X4 com atmega8 no avr studio:





///************************************************************************/
//                             usando LCD 20X4
//  Version    : 1.0
//  microcontrolador : AVR ATMega8
//  Autor        : Aguivone
//  descrição  : usando lcd interface de 4 bits
//  data : 20/10/2011.
//
//************************************************************************/
#define F_CPU 4000000UL  // 4 MHz 
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdio.h>
#include <util/delay.h>
#include <string.h>

/////////////////////////////////////variaveis usada no lcd ///////////////////////////////////////////
#define LCD PORTC //define qual porta vai usar
//o pino r/w é conectado ao terra pois não é feita nenhuma leitura no display
//configuração:
//
// pino display  / pino da porta selecionada
//
// D4 = bit 0 da porta
// D5 = bit 1 da porta
// D6 = bit 2 da porta
// D7 = bit 3 da porta
//
// RS = bit 4 da porta
// EN = bit 5 da porta
//
/////////////////////////////////////////////////Funções usadas no LCD/////////////////////////////////////////////

void inicializa_LCD(void)
{
    _delay_ms(15);//tempo para estabilizar a tensão e preparar o display
    // o primeiro digito é de controle e o segundo configuração

    LCD = 0X22;//nesse momento o display ainda está em modo 8bits solicita modo de 4 bits
    _delay_ms(1);//tempo estabilizar o pino
    LCD = 0X02;//ao passar do nivel alto para o nivel baixo ele faz leitura
    _delay_ms(15);
                // é preciso colocar este comando pelo menos 2 vezes para que funcione o display
    LCD = 0X22;//nesse momento o display  está em modo 4bits 
    _delay_ms(1);//tempo estabilizar o pino
    LCD = 0X02;//ao passar do nivel alto para o nivel baixo ele faz leitura
    _delay_ms(15);

    ////////entrou no modo 4bits/////////////////////////////////////

    LCD = 0X28;//nesse momento o display  está em modo 4bits,manda usar 2 linhas 
    _delay_ms(1);//tempo estabilizar o pino
    LCD =0X08;//ao passar do nivel alto para o nivel baixo ele faz leitura
    _delay_ms(15);

    /////////////////////envia 0X01 - limpar display ////////////////////////////////////
    LCD = 0X20;//manda limpar o display
    _delay_ms(1);//tempo estabilizar o pino
    LCD = 0X00;//ao passar do nivel alto para o nivel baixo ele faz leitura
    _delay_ms(15);//substitui a leitura do busy flag 

    LCD = 0X21;//segundo nibble (limpa display)
    _delay_ms(1);//tempo estabilizar o pino
    LCD = 0X01;//ao passar do nivel alto para o nivel baixo ele faz leitura
    _delay_ms(15);//substitui a leitura do busy flag 

        /////////////////////envia 0X06  - movimento e pisca do display////////////////////////////////////
    
     LCD = 0X20;//manda deslocar a direita (0x06)
    _delay_ms(1);//tempo estabilizar o pino
    LCD = 0X00;//ao passar do nivel alto para o nivel baixo ele faz leitura
    _delay_ms(15);

     LCD = 0X26;//segundo nibble (desloca a direita)
    _delay_ms(1);//tempo estabilizar o pino
    LCD = 0X06;//ao passar do nivel alto para o nivel baixo ele faz leitura
    _delay_ms(15);//substitui a leitura do busy flag 

    /////////////////////envia 0X0C - desliga display ////////////////////////////////////

    LCD = 0X20;//cursor desligado (0X0C)
    _delay_ms(1);//tempo estabilizar o pino
    LCD = 0X00;//ao passar do nivel alto para o nivel baixo ele faz leitura
    _delay_ms(15);//substitui a leitura do busy flag 

    LCD = 0X2C;//segundo nibble (cursor deligado)
    _delay_ms(1);//tempo estabilizar o pino
    LCD = 0X0C;//ao passar do nivel alto para o nivel baixo ele faz leitura
    _delay_ms(15);//substitui a leitura do busy flag 

        /////////////////////envia 0X2F - modo 4bits modo 4 linhas tipo de fonte ////////////////////////////////////

    LCD = 0X22;//cursor desligado (0X2F)
    _delay_ms(1);//tempo estabilizar o pino
    LCD = 0X02;//ao passar do nivel alto para o nivel baixo ele faz leitura
    _delay_ms(15);//substitui a leitura do busy flag 

    LCD = 0X2F;//segundo nibble (cursor deligado)
    _delay_ms(1);//tempo estabilizar o pino
    LCD = 0X0F;//ao passar do nivel alto para o nivel baixo ele faz leitura
    _delay_ms(15);//substitui a leitura do busy flag 
    
}
// escreve nibble
void escr(unsigned char crt,int vlr)
{
    if(vlr == 1)
    {
    LCD = crt | 0X30 ;//escreve dados
    _delay_us(30);//tempo estabilizar o pino
    LCD = crt | 0X10;//ao passar do nivel alto para o nivel baixo ele faz leitura
    _delay_us(30);
    }
    else
    {
    LCD = crt | 0X20 ;//escreve comando
    _delay_us(30);//tempo estabilizar o pino
    LCD = crt | 0X00;//ao passar do nivel alto para o nivel baixo ele faz leitura
    _delay_us(30);
    }
}
// escreve caracter ou comando
void escreve(unsigned char carac,int val)
{
    unsigned char temp=carac;
    carac = ((carac >> 4) & 0X0F);
    temp  = temp & 0X0F;
    escr(carac,val);  //escreve primeiro nibble
    escr(temp,val);  //escreve segundo nibble
}

void impri_lcd(char frase[17])
{
      unsigned int indice=0;
      unsigned int tamanho = strlen(frase);
      while(indice<tamanho)
       {         
            if(frase[indice]=='\n')//linha 1 
            {
                 escreve(0X80,0);
            }
            if(frase[indice]=='\r')//linha2
            {
                 escreve(0XBF,0);//
            }
            if(frase[indice]=='@')//linha 3 
            {
                 escreve((0X94),0);
            }
            if(frase[indice]=='$')//linha4
            {
                escreve((0XD4),0);
            }
            if((frase[indice]!='\r') && (frase[indice]!='\n') && (frase[indice]!='@') && (frase[indice]!='$'))//dados
            {
               if(indice<18)
               {
                escreve(frase[indice],1);
               }
            }   
       indice++;
       }
} 

 
//////////////////////////////////////////////função principal///////////////////////////////////////////
int main(void)
{
           DDRC = 0XFF;  //inicializa portC
         //  DDRD = 0XFE;  //inicializa portD
           inicializa_LCD();
           impri_lcd("\nTESTE DE LCD 20X4 ");
           impri_lcd("\r    AGUIVONE      ");
           impri_lcd("@escrevendo nas    ");
           impri_lcd("$4 linhas!         ");
          for(;;)
            {
                 //faz nada!
            }
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////

quarta-feira, 19 de outubro de 2011

Bootloader para pic wireless:

Passeando pela web vi este projeto do Sandro Juca que achei muito interessante se trata de um bootloader do pic via zigbee (wireless com alcance de até 1KM).

sexta-feira, 15 de julho de 2011

Protocolo wiegand com micrococontrolador ATMEGA 8 (usando o avr studio) :


//************************************************************************
//                             leitor de cartão akiyama (PE310)
//  Version    : 1.0
//  microcontrolador : AVR ATMega8
//  Autor        : Aguivone
//  descrição  : usando protocolo wigand
//  data : 15/07/2011.
//
//************************************************************************
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdio.h>
#include <util/delay.h>
#include <string.h>

#define F_CPU 4000000UL  // 4 MHz deve vir antes das interrupçoes
////////////////////////////definicões auxiliares//////////////////////////////////////////
#define alterna_pino(x,y) x ^= _BV(y)
////////////////////////////parametrização//////////////////////////////////////////

#define LEITOR1_B     PD2
#define LEITOR1_A     PD3
#define PROCESSA      PD5
#define LEITOR_SAIDA     PORTD


////////////////////////////variaveis usadas ////////////////////////////////////////
  int conta=0,ID,fac_code;
  int num=0;
  char teste[27];
///////////////////////////////////////////////funçoes usadas pela usart////////////////////////////////////////////////

void serial_inicializa(unsigned int BAUD)
{
unsigned int valor = F_CPU/16/BAUD-1; //é recomendavel ver o data sheet para ter certeza se está formula irá funcionar na sua mcu
/* baud rate */
UBRRH = (unsigned char)(valor>>8);
UBRRL = (unsigned char)valor;
UCSRA = 0X20;
/* habilita receiver and transmitter buffers */
UCSRB = 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 */
UCSRC = 0X86;
}

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
       {
           while ( !( UCSRA & (1<<UDRE)) ); //espera transmitir para enviar um novo
           UDR =frase[indice];
           indice++;
       }
}

void put_serial( char carac)
{
           while ( !( UCSRA & (1<<UDRE)) ); //espera transmitir para enviar um novo
           UDR = carac;
}

void inicializa_interrupt(void)
{
   MCUCR = 0X0A;//configura  a interrupção 1 e 0 para borda de descida
   GICR = 0xC0;//habilita int1 e int0
   sei(); //habilita interrupções
}

//////////////////////////interrupções externas ///////////////////////////////////
ISR(INT0_vect )   //int0
  {
   teste[num]='0';
   num++;
  }
ISR(INT1_vect ) //int1
  {
   teste[num] = '1';
   num++;
  }


//////////////////////////////////////////////função principal///////////////////////////////////////////
int main(void)
{
            inicializa_interrupt();
            serial_inicializa(4800);//configura serial para 4800 
            DDRD = 0xF0;  //inicializa portd
            LEITOR_SAIDA = 0X0F;
            impri_serial("leitor de cartão inicializado! \n\r");
            sei();
            num=0;
           while(1)
            {
                  if(num > 25)
                  {
                   num=0;
                     impri_serial("codigo :");
                     while(num<27)
                      {
                       put_serial(teste[num]);
                       num++;
                       }
                      impri_serial(" \n\r");
                     num=0;
                  }  
              alterna_pino(LEITOR_SAIDA,PROCESSA); //só para simular
              _delay_ms(100);
             //faz nada!
            }
            return(0);
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////

sexta-feira, 8 de julho de 2011

Comunicação Ethernet com avr Studio (atmega8) :

             Fazendo um teste com os diferentes chips de ethernet chequei a conclusão que o melhor chip seria o W5100 do fabricante wiznet ,pois não precisa de se preocupar com a camada física nem com o protocolo TCP/IP ou UDP pois isto já é implementado no chip, para o usuário  basta enviar alguns comandos via comunicação SPI e pronto vc está na rede.Vale lembra que o desenvolvedor deverá ler atentamente o datasheet do fabricante e saber sobre o protocolo SPI,e um pouco de HTML.
             Outro detalhe interessante é que ele tem velocidade de 100Mbs. Enquanto que os outros chips (como o ENC28j60 e os pics que vem com ethernet embutido mas a velocidade é de 10Mbs),o ponto negativo deste chip é que aqui no brasil é muito difícil de encontrar, quando encontra é o modulo(chip + rj45com trafo(http://www.wiznet.co.kr/)) WIZ810MJ, cujo o revendedor dele aqui no brasil é a HITECH (http://www.hitech.com.br/) .
             O esquemático de ligação do microcontrolador com o WZ810MJ é simples conforme figura abaixo,veja que a alimentação deste chip e de 3 a 3,5 V (eu usei uma fonte atx para isso),o resistor no pino 1 do jumper 1 com o pino 9 do jumper 2 habilita o chip para comunicação SPI, pois , ele pode comunicar com interface para lela também, dai o motivo de ter tantos pinos na placa do WIZ810MJ, para este exemplo utilizei apenas o jumper 1(exceto pelo pino 9 do jumper 2).
  
             Apesar de todos esses fatores acho que vale a pena ao desenvolvedor experimentar este chip pois ele livra o microcontrolador  de implementar uma pilha TCP/IP , para demonstrar a simplicidade de uso vou postar aqui um exemplo(em breve irei postar um exemplo dele pra PIC assim que eu fizer o algoritmo) no qual eu aciono um led via Ethernet :

//***********************************************************************************************************
//                              acendendo um led com o chip W5100
//  versão                        : 1.0
//  descrição                   : exemplo de uso do Wiznet W5100
//  Autor                      : Aguivone
//  micropcontrolador          : ATmega8(funciona também pro 168/328) 
//  compilador                   : AVR-GCC / Atmel AVR Studio 4.17
//  Data do projeto : 04/ 07 / 2011
//*************************************************************************************************************
#include <avr/io.h>
#include <string.h>
#include <stdio.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>// AVRJazz Mega328 SPI I/O

#define F_CPU 16000000L
/*frequencia em hz , valor do cristal*/

//configuração dos pinos SPI
#define SPI_PORT PORTB //porta que será usado para SPI
#define SPI_DDR  DDRB  
#define SPI_SS   PORTB2//seleção de chip(habilita comunicação SPI)
// Wiznet W5100 Op Code usados
#define WIZNET_ESCREVE_OPCODE 0xF0  
#define WIZNET_LER_OPCODE     0x0F
// Wiznet W5100 endereço dos registradores
#define MR         0x0000   // Registrador de modo
#define GAR           0x0001   // endereço(inicial) de Gateway : 0x0001 a 0x0004
#define SUBR       0x0005   // mascara de subrede           : 0x0005 a 0x0008
#define SAR           0x0009   // Source Address Register , endereço de hardware (MAC)   : 0x0009 a 0x000E
#define SIPR       0x000F   // IP do hardware(escolhido pelo programador): 0x000F to 0x0012 //Socket 0
#define RMSR       0x001A   // RX tamanho do buffer(memória) de recepção
#define TMSR       0x001B   // TX tamanho do buffer(memória) de envio

#define S0_MR       0x0400      // Socket 0: registrador do socket0 
#define S0_CR       0x0401      // Socket 0: registrador de comandos do socket0
#define S0_IR       0x0402      // Socket 0: registrador de interrupçoes do socket0
#define S0_SR       0x0403      // Socket 0: registrador de status do socket0
#define S0_PORT    0x0404      // Socket 0: aqui é colocado o valor da porta TCP ->  endereço = 0x0404 to 0x0405
#define SO_TX_FSR  0x0420      // Socket 0: tamanho do registrador de transmissão: 0x0420 to 0x0421
#define S0_TX_RD   0x0422      // Socket 0: ponteiro de leitura do buffer de transmissão : 0x0422 to 0x0423
#define S0_TX_WR   0x0424      // Socket 0: ponteiro de escrita do buffer de transmissão: 0x0424 to 0x0425
#define S0_RX_RSR  0x0426      // Socket 0: tamanho do registrador de recepção: 0x0425 to 0x0427
#define S0_RX_RD   0x0428      // Socket 0: ponteiro de leitura: 0x0428 to 0x0429

#define TXBUFADDR  0x4000      // W5100 posição inicial do buffer de escrita
#define RXBUFADDR  0x6000      // W5100 posição inicial do buffer de recepção
//S0_MR (possiveis configuração)
#define MR_CLOSE      0x00    // socket não usado
#define MR_TCP          0x01    // TCP
#define MR_UDP          0x02    // UDP
#define MR_IPRAW      0x03      // IP LAYER RAW SOCKET
#define MR_MACRAW      0x04      // MAC LAYER RAW SOCKET
#define MR_PPPOE      0x05      // PPPoE
#define MR_ND          0x20      // sem delay de Ack(somente TCP) 
#define MR_MULTI      0x80      // suporte ao multicast(valido somente para UDP)
// S0_CR values
#define CR_OPEN          0x01      // Initializa ou abre socket
#define CR_LISTEN        0x02      // espera resposta de um ponto na rede (no modo tcp(modo servidor))
#define CR_CONNECT       0x04      // envia resposta a um ponto da rede(modo cliente)
#define CR_DISCON        0x08      // finaliza conexão e gera interrupção se falhar(desconexão)
#define CR_CLOSE         0x10      // desconecta socket
#define CR_SEND          0x20      // atualiza memoria de transmissão e envia dados
#define CR_SEND_MAC      0x21      // envia dados com o endereço do MAC, sem o processo ARP(modo UDP)
#define CR_SEND_KEEP     0x22      // ckeca estado da conexão - envia um byte pra testar a conexão (modo tcp)
#define CR_RECV          0x40      // indica uma recepção no socket
// S0_SR values
#define SOCK_CLOSED      0x00     // socket fechado
#define SOCK_INIT        0x13      // inicializa conexão
#define SOCK_LISTEN      0x14      // verifica estado(listen)
#define SOCK_SYNSENT     0x15      // comando de conexão foi iniciado
#define SOCK_SYNRECV     0x16      // houve sincronismo de recepção
#define SOCK_ESTABLISHED 0x17      // sucesso na conexão
#define SOCK_FIN_WAIT    0x18      // esperando finalizar
#define SOCK_CLOSING     0x1A      // finalizando conexão
#define SOCK_TIME_WAIT     0x1B      // espera tempo para finaliza
#define SOCK_CLOSE_WAIT  0x1C      // recebeu comando de fechar pelo host
#define SOCK_LAST_ACK    0x1D      // durante a finalização é o ultimo ack
#define SOCK_UDP         0x22      // UDP     socket
#define SOCK_IPRAW       0x32      // IP raw  socket
#define SOCK_MACRAW      0x42      // MAC raw socket
#define SOCK_PPPOE       0x5F      // PPPOE   socket
#define TX_BUF_MASK      0x07FF   // Mascara do buffer de transmissão 2K :
#define RX_BUF_MASK      0x07FF   // Mascara do buffer de recepção 2K :
#define NET_MEMORIA      0x05     // Use 2K de Tx/Rx Buffer(pode se usar até 8K)
#define TCP_PORT         80       // porta TCP/IP usada pelo pc
#define MAX_BUF          512      // tamanho maximo do buffer
/////////
//////// variaveis globais ////////////////////////////////////////
////////
uint8_t buf[MAX_BUF];
uint8_t led,sockreg;
  int get_pos, post_pos;

/////////variaveis da serial///////////////////////
unsigned char caracter;//
unsigned int  tam_buffer;//usado para contar o tamanho do buffer de recepção
///////////////////////função de escrita SPI////////////////////////

void spi_escreve(unsigned int endereco,unsigned char dados)
{
  // ativa pino de habilitação do SPI
  SPI_PORT &= ~(1<<SPI_SS);  
  SPDR = WIZNET_ESCREVE_OPCODE;//inicializa escrita pelo W5100  
  // espera terminar a comunicação
  while(!(SPSR & (1<<SPIF))); 
   // inicialização do Wiznet W5100 envia os bytes mais significativo
  SPDR = (endereco & 0xFF00) >> 8;
   // espera finalizar a transmissão
  while(!(SPSR & (1<<SPIF))); 
   //inicialização do Wiznet W5100 envia os bytes menos significativo
  SPDR = endereco & 0x00FF;  
  // espera finalizar a transmissão
  while(!(SPSR & (1<<SPIF)));   

  SPDR = dados;  // inicializa transmissão de dados
  while(!(SPSR & (1<<SPIF))); // espera finalizar a transmissão
  // finaliza comunicação.
  SPI_PORT |= (1<<SPI_SS);
}
/////////////////////////de leitura////////////////////////////////
unsigned char spi_ler(unsigned int endereco)
{
  // ativa pino de habilitação do SPI
  SPI_PORT &= ~(1<<SPI_SS);
  //inicializa leitura pelo W5100 
  SPDR = WIZNET_LER_OPCODE;
   // espera finalizar a transmissão
  while(!(SPSR & (1<<SPIF)));
   // inicialização do Wiznet W5100 envia os bytes mais significativo
  SPDR = (endereco & 0xFF00) >> 8;
   // espera finalizar a transmissão
  while(!(SPSR & (1<<SPIF)));
  //inicialização do Wiznet W5100 envia os bytes menos significativo
  SPDR = endereco & 0x00FF;
   // espera finalizar a transmissão
  while(!(SPSR & (1<<SPIF)));   

  // envia um valor qualquer para ler os dados(pois isto liga o sinal de clock do registrado SPI)
  SPDR = 0x00;
  // espera finalizar a transmissão
  while(!(SPSR & (1<<SPIF))); 
  // finaliza comunicação.
  SPI_PORT |= (1<<SPI_SS);
  return(SPDR);//retorna o valor lido do W5100
}
////////////////////////inicializa ethernet //////////////////////////////////
void W5100_Inicializa(void)
{
  // configura variaveis locais da ethernet


  // informação sobre o MAC de alguns fabricantes
  /*
00-04-25   (hex)      Atmel Corporation
000425     (base 16)  Atmel Corporation
                      Multimedia & Communications Group
                      2200 Gateway Centre, Suite 201
                      Morrisville NC 27560
                      UNITED STATES00-04-A3   (hex)      Microchip Technology, Inc.
0004A3     (base 16)  Microchip Technology, Inc.
                      2355 W. Chandler Blvd.
                      Chandler AZ 85224
                      UNITED STATES00-08-DC   (hex)      Wiznet
0008DC     (base 16)  Wiznet
                      5F Simmtech bldg., 228-3,
                      Nonyhun, Kangnam
                      Seoul  135-830
                      KOREA, REPUBLIC OF
 */
  unsigned char mac_addr[] = {0x00,0x16,0x36,0xDE,0x58,0xF6};//MAC usado pelo microcontrolador(para teste)
  unsigned char ip_addr[] = {192,168,0,5};//enderreço de ip do servidor(valor para teste,do microcontrolador)
  unsigned char sub_mask[] = {255,255,255,0};//mascara de sub_rede
  unsigned char gtw_addr[] = {192,168,0,1};//enderreço de ip do cliete (valor para teste,do pc)

  spi_escreve(MR,0x80);            // MR = 0b10000000; isso inicicializa os registradores internos automaticamente
  _delay_ms(1);
  //configura gateway
  spi_escreve(GAR + 0,gtw_addr[0]);
  spi_escreve(GAR + 1,gtw_addr[1]);
  spi_escreve(GAR + 2,gtw_addr[2]);
  spi_escreve(GAR + 3,gtw_addr[3]);
  _delay_ms(1);
  // configura o MAC (SAR): 0x0009 à 0x000E
  spi_escreve(SAR + 0,mac_addr[0]);
  spi_escreve(SAR + 1,mac_addr[1]);
  spi_escreve(SAR + 2,mac_addr[2]);
  spi_escreve(SAR + 3,mac_addr[3]);
  spi_escreve(SAR + 4,mac_addr[4]);
  spi_escreve(SAR + 5,mac_addr[5]);
  _delay_ms(1);
  // mascara de sub rede (SUBR): 0x0005 à 0x0008
  spi_escreve(SUBR + 0,sub_mask[0]);
  spi_escreve(SUBR + 1,sub_mask[1]);
  spi_escreve(SUBR + 2,sub_mask[2]);
  spi_escreve(SUBR + 3,sub_mask[3]);
  _delay_ms(1);
  // endereço de IP (SIPR): 0x000F à 0x0012
  spi_escreve(SIPR + 0,ip_addr[0]);
  spi_escreve(SIPR + 1,ip_addr[1]);
  spi_escreve(SIPR + 2,ip_addr[2]);
  spi_escreve(SIPR + 3,ip_addr[3]);
  _delay_ms(1);
  // configura o tamanho do buffer  de memoria de escrita e leitura 
  spi_escreve(RMSR,NET_MEMORIA);//configura para cada socket 2K de memoria de leitura(no W5100 tem 4 socket mas vamos usar somente o socket 0)
  spi_escreve(TMSR,NET_MEMORIA);//configura para cada socket 2K de memoria de transmissao(no W5100 tem 4 socket mas vamos usar somente o socket 0)
}
//////////////////////////////////fecha socket 0  ///////////////////////
void fechar_socket(uint8_t socket)
{
   if (socket != 0)return;
   // manda fechar
   spi_escreve(S0_CR,CR_CLOSE);   // espera que S0_CR seja zerado(finalizado)
   while(spi_ler(S0_CR));
}
//////////////////////////////////fecha conexão//////////////////////////
void desconectar(uint8_t sock)
{
   if (sock != 0) return;   // envia comando para desconectar
   spi_escreve(S0_CR,CR_DISCON);   // espera desconexão.
   while(spi_ler(S0_CR));
}
////////////////////////////////inicializa socket0////////////////////
uint8_t inicia_socket(uint8_t socket,uint8_t eth_protocol,uint16_t tcp_port)
{
    uint8_t retval=0;   
     if (socket != 0) return retval;
     if (spi_ler(S0_SR) == SOCK_CLOSED) // verificando se o socket 0 está fechado.
      {
      fechar_socket(socket);
      } 
    spi_escreve(S0_MR,eth_protocol);    // configura o registrador de modo (MR)
    // abrindo o  Socket 0
    spi_escreve(S0_PORT,((tcp_port & 0xFF00) >> 8 ));
    spi_escreve(S0_PORT + 1,(tcp_port & 0x00FF));
    spi_escreve(S0_CR,CR_OPEN);                   // abre socket 
    while(spi_ler(S0_CR)); //espera abrir  
    if (spi_ler(S0_SR) == SOCK_INIT)//checa estado inicial
      retval=1;
    else
      fechar_socket(socket);
    return retval;
}
/////////////////////////////"escuta" a rede/////////////////////////////////
uint8_t escutar_rede(uint8_t socket)
{
     uint8_t retval = 0;
     if (socket != 0)
     return retval;
     if (spi_ler(S0_SR) == SOCK_INIT) 
     { 
         spi_escreve(S0_CR,CR_LISTEN);//envia comando para escutar a rede
         while(spi_ler(S0_CR));     // espera terninar processo de escuta
         if (spi_ler(S0_SR) == SOCK_LISTEN) //verifica status de escuta
           retval=1;
         else
           fechar_socket(socket);
     }
    return retval;
}
////////////////////////////envia pacote////////////////////////////////////
uint16_t envia_pacote(uint8_t sock,const uint8_t *pacote,uint16_t buffer_tamanho)
{
    uint16_t ponteiro,ende_temp,ende_real,tx_tamanho,timeout;   

    if (buffer_tamanho <= 0 || sock != 0)return 0;//verifica se tem espaço livre para transmitir
    tx_tamanho=spi_ler(SO_TX_FSR);
    tx_tamanho=(((tx_tamanho & 0x00FF) << 8 ) + spi_ler(SO_TX_FSR + 1));//calcula tamanho do buffer de transmissão.
    timeout=0;
    while (tx_tamanho < buffer_tamanho) 
    {
          _delay_ms(1);
         tx_tamanho= spi_ler(SO_TX_FSR);
         tx_tamanho=(((tx_tamanho & 0x00FF) << 8 ) + spi_ler(SO_TX_FSR + 1));     // Timeout para aproximadamente 1s
         if (timeout++ > 1000) 
           {
            // desconecta pois não há espaço livre após 1S
           desconectar(sock);
           return 0;
           }
    }    
   ponteiro = spi_ler(S0_TX_WR);//lê o ponteiro de escrita.
   ende_temp = (((ponteiro & 0x00FF) << 8 ) + spi_ler(S0_TX_WR + 1));
    while(buffer_tamanho) 
    {
      buffer_tamanho--;
      // calcula o endereço real do buffer de transmissão. 
      ende_real = TXBUFADDR + (ende_temp & TX_BUF_MASK);      // copia pacote para W5100(TX_buffer)
      spi_escreve(ende_real,*pacote);
      ende_temp++;
      pacote++;
    }
    // incrementa valor de  S0_TX_WR , então este será o ponto da proxima transmissão
    spi_escreve(S0_TX_WR,( ende_temp & 0xFF00) >> 8 );
    spi_escreve(S0_TX_WR + 1,( ende_temp & 0x00FF));
    // agora envia o comando de enviar dados para rede.
    spi_escreve(S0_CR,CR_SEND);
    // espera terminar o envio
    while(spi_ler(S0_CR));
    return 1;
}

/////////////////////////////////recebe pacote//////////////////////////////////////////
uint16_t recebe_pacote(uint8_t socket,uint8_t *pacote,uint16_t buffer_tamanho)
{
    uint16_t ponteiro,ende_temp,ende_real;       

    if ((buffer_tamanho <= 0) || (socket != 0))
    return 1;   
    // se o tamanho retornado for maior que o tamanho do vetor ou o socket for diferente do socket 0 retorna 1

    if (buffer_tamanho > MAX_BUF)//se exceder o tamanho maximo
      buffer_tamanho = MAX_BUF - 2;    //define tamanho como o tamanho maximo - 2.
    ponteiro = spi_ler(S0_RX_RD);//pega localização do dado recebido
    ende_temp = (((ponteiro & 0x00FF) << 8 ) + spi_ler(S0_RX_RD + 1));////pega localização do dado recebido por ser 16 bits "ponteiro" deve ser descolado 

        while(buffer_tamanho) 
        {
          buffer_tamanho--;
          ende_real=RXBUFADDR + (ende_temp & RX_BUF_MASK);//endereço inicial de leitura + endereço dos dados recebidos 
          *pacote = spi_ler(ende_real);
          ende_temp++;
          pacote++;
        }
    *pacote='\0';        // String de fim de pacote
    // incrementa S0_RX_RD ,este será o ponto da proxima recepção
    spi_escreve(S0_RX_RD,(ende_temp & 0xFF00) >> 8 );
    spi_escreve(S0_RX_RD + 1,(ende_temp & 0x00FF));///////////////////////////////////////////////////vou ver isso//////////
    //envia comando para leitura 
    spi_escreve(S0_CR,CR_RECV);
    _delay_us(10);    // espera terminar leitura.                    
    return 1;
}
///////////////////////////////////////////////////////////////////////
uint16_t tamanho_recepcao(void)
{
  return ((spi_ler(S0_RX_RSR) & 0x00FF) << 8 ) + spi_ler(S0_RX_RSR + 1);
}
////////////////////////////////////////////////////////////////////////
int string_index(char *str_de_teste,char *str_compara)//procura posição de uma string
{
  uint16_t i,str_tamanho;

  str_tamanho=strlen(str_compara);// pega tamanho da string
  for(i=0;*(str_de_teste+i); i++)//percorre o ponteiro 
  {
    if (strncmp(str_de_teste+i,str_compara,str_tamanho) == 0)//compara com str_compara  
      return i;
  }
  return -1;
}

////////////////////função principal/////////////////////////////////////
int main(void)
 {
  uint8_t sockstat;
  uint16_t rsize;
  char botao_0[10],botao_1[10];
  //////////////////inicializa port D /////////////////////////////////////////////////////////////////////
  DDRD = 0xFE;       // Seta PORTD como saida exceto a entrada serial
  PORTD = 0xFF;
  _delay_ms(100);
  PORTD = 0X0F;    
  //////////////////////////////////////inicializa SPI ////////////////////////////////////////////////////
  // Seta MOSI (PORTB3),SCK (PORTB5) and PORTB2 (SS) como saida, e os outros pinos como saida 
  SPI_DDR = (1<<PORTB3)|(1<<PORTB5)|(1<<PORTB2);
  // SS não ativado
  SPI_PORT |= (1<<SPI_SS); 
  // habilita SPI, modo mestre 0, seta clock para fck/2
  SPCR = (1<<SPE)|(1<<MSTR);
  SPSR |= (1<<SPI2X);  
  ///////////////////// inicializa ethernet (W5100) ///////////////////////////////////////////////////////
  W5100_Inicializa();  // 
  sockreg=0;//socket usado
  //////////////////////////////////////////////////
  for(;;)
    {       sockstat=spi_ler(S0_SR);
            switch(sockstat) 
            {
             case SOCK_CLOSED: ///socket fechado.
                 if (inicia_socket(sockreg,MR_TCP,TCP_PORT) > 0) 
                 {// Listen(escuta)  Socket 0
                    if (escutar_rede(sockreg) <= 0)
                         _delay_ms(1);
                 }break;    
             case SOCK_ESTABLISHED://conectado
                 {
                 // pega o tamanho do pacote recebido do cliente
                 rsize=tamanho_recepcao();
                 if (rsize > 0) 
                     {
                      // lê o pacote recebido
                       if (recebe_pacote(sockreg,buf,rsize) <= 0)
                          // Check the Request Header
                          get_pos=string_index((char *)buf,"GET /");//procura pela posição da string "GET /"
                        //  post_pos=string_index((char *)buf,"POST /");//procura pela posição da string "POST /"
                              if (get_pos >= 0 || post_pos >= 0) 
                                 {
                                  // ckeca botão do codigo html
                                  //if (post_pos >= 0) //se modo post
                                      if (get_pos >= 0)    //se modo get
                                        {
                                            if (string_index((char *)buf,"Bot=0") > 0)//procura pela posição da string "Bot=0"
                                                 { 
                                                 led=0;
                                                 PORTD=0X0F;//desliga port D
                                                 strcpy_P(botao_0,PSTR("checked"));//marca opção de desligar habilitado
                                                 strcpy(botao_1,"");

                                                 }
                                            if (string_index((char *)buf,"Bot=1") > 0)//procura pela posição da string "Bot=1"
                                                 {
                                                  led=1;
                                                  PORTD=0XFF;//liga port D
                                                  strcpy(botao_0,"");
                                                  strcpy_P(botao_1,PSTR("checked"));//marca opção de ligar habilitado
                                                 }
        
                                        }                       
                                     // criando pagina HTTP de resposta 
                                    strcpy_P((char *)buf,PSTR("HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n"));
                                    strcat_P((char *)buf,PSTR("<html><body><span style=\"color:#0000A0\">\r\n"));
                                    strcat_P((char *)buf,PSTR("<h1>Microcontrolador AVR - MODO SERVIDOR</h1>\r\n"));
                                    strcat_P((char *)buf,PSTR("<h3>http://microcontroladores-c.blogspot.com/ </h3>\r\n"));
                                    strcat_P((char *)buf,PSTR("<h3> Por Aguivone  </h3>\r\n"));
                                    strcat_P((char *)buf,PSTR("<p><form method=\"GET\">\r\n"));
                                    // cria resposta do botao HTTP
                                    strcat_P((char *)buf,PSTR("<p><input type=\"radio\" name=\"Bot\" value=\"0\" "));
                                    strcat((char *)buf,botao_0);//valor do botao "" ou checked
                                    strcat_P((char *)buf,PSTR(">Desligar LED\r\n"));
                                    strcat_P((char *)buf,PSTR("<br><input type=\"radio\" name=\"Bot\" value=\"1\" "));
                                    strcat((char *)buf,botao_1);//valor do botao "" ou checked
                                    strcat_P((char *)buf,PSTR(">Ligar LED\r\n"));
                                    strcat_P((char *)buf,PSTR("</strong><p>\r\n"));
                                    strcat_P((char *)buf,PSTR("<input type=\"submit\" value=\"Enviar\" >\r\n"));
                                    strcat_P((char *)buf,PSTR("</form></span></body></html>\r\n"));//finaliza pagina 
                                    // // enviando pagina HTTP de resposta do botao
                                    if (envia_pacote(sockreg,buf,strlen((char *)buf)) <= 0)//socket 0 ,envia o vetor buf,coloca o tamanho do vetor
                                    break;
                                 }
                             desconectar(sockreg);// desconecta socket
                    }
                  else
                    {
                      _delay_us(10);    // espera resposta
                    }
              }break;      
              case SOCK_FIN_WAIT:
              case SOCK_CLOSING:
              case SOCK_TIME_WAIT:
              case SOCK_CLOSE_WAIT:
              case SOCK_LAST_ACK:
              fechar_socket(sockreg);// força o fechamento do socket
      }//chave do switch
   }//chave do laço infinito (for)
}//chave de main



Aqui você vê como ficará quando rodar o programa no seu navegado padrão,não precisa instalar programa nenhum:

Para montar este exemplo tirei como base este site :
vale a pena ver esse material!