quarta-feira, 4 de dezembro de 2013

Gerando 13000V com o pic 12F675

       Um dia meu carro deu um problema na bobina(mas sabemos que dificilmente essas bobinas queimam de verdade o que acontece é defeitos no circuito de acionamento) então pensei em demostrar como gerar altas tensões utilizando um microcontrolador PIC de 8 pinos (12F675) , vale lembra que eu aproveitei o circuito já existente(pois o único defeito dessa bobina eram os fios de ligação aos terminais que estavam todos ressecados e dobradiços devido ao calor do motor do carro),na figura abaixo é demostrado a bobina do corsa:
        Para fazer o acionamento desta bobina é preciso saber quais os terminais desta placa será utilizado, então veja a descrição na figura a seguir:


       Os sinais que vem do modulo de gerenciamento central do carro são aplicados nas entrada in1 e in2, out1 e out2 vão para os terminais da bobina e o +12V vai ao outro terminal da bobina e a placa de controle e por fim o GND que também vai a esta placa.Depois de saber onde colocar o sinal que vira do microcontrolador montei um circuito para acionar e refiz algumas interligação da placa aos terminais da bobina ficando assim:

     O esquemático do circuito que fiz é este:
       O circuito é muito simples coloquei um led para indicar cada vez que pressiono um dos botões e caso eu fique com ele pressionado o valor da largura de pulso aumenta ou diminue enquanto manter este pressionado,no pino GP2 sai o sinal que será aplicado ao circuito de controle da bobina(que nada mais é do que um drive que aciona 2 IGBTs que mandam o pulso ao transformador da bobina).vou mostrar o vídeo que está disponível no you tube e logo em seguida o código fonte do circuito:

      O código fonte:

/*
 *                       Gerando altas tensões com uma bobina
 *
 * Compilador : MPlabXC8
 * Microcontrolador: 12F675
 * Autor: aguivone
 * Versão: 1
 * data: 04/12/2013
*/ #include <stdio.h> #include <stdlib.h> #include <xc.h> /////////////////////////////////////////////////////////configuraçôes////////////////////////////////////////////////// #pragma config FOSC = INTRCIO // Oscillator Selection bits (INTOSC oscillator: I/O function on GP4/OSC2/CLKOUT pin, I/O function on GP5/OSC1/CLKIN) #pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled) #pragma config PWRTE = ON // Power-Up Timer Enable bit (PWRT enabled) #pragma config MCLRE = OFF // GP3/MCLR pin function select (GP3/MCLR pin function is digital I/O, MCLR internally tied to VDD) #pragma config BOREN = OFF // Brown-out Detect Enable bit (BOD disabled) #pragma config CP = OFF // Code Protection bit (Program Memory code protection is disabled) #pragma config CPD = ON // Data Code Protection bit (Data memory code protection is enabled) //////////////////////////////////////////////////////Rotina principal/////////////////////////////////////////////////////////////// delay_ms(long t)//tempo aproximado {//aqui está usado o clock interno long temp=0; int conta=0; while(temp < t) { conta=0; while(conta<40) { conta++; } temp++; } } void main(void) { TRISIO = 0X03;//configura gp1 e gp2 como entrada CMCON = 7;//desabilita comparadores ANSEL = 0;//habilita as portas de I/O int tempo=1; for(;;) { if(GP0 == 0) { delay_ms(100);//debounce do botão(filtro) if(GP0 == 0) { while(GP0 == 0)//enquanto botão pressionado incrementa { tempo++; delay_ms(100);//debounce do botão(filtro) GP4 = !GP4;//alterna led a cada incremento if(tempo>50) { tempo = 1;//limita valor maximo para 50 } } GP4 = 0; } } if(GP1 == 0) { delay_ms(100);//debounce do botão(filtro) if(GP1 == 0) { while(GP1 == 0)//enquanto botão pressionado decrementa { tempo--; delay_ms(100);//debounce do botão(filtro) GP4 = !GP4;//alterna led a cada decremento if(tempo<1) { tempo = 10;//limita valor minimo para 1 } } GP4 =0; } } GP2 = 1; delay_ms(tempo); GP2 = 0; delay_ms(1000); }//loop infinito }

quinta-feira, 3 de outubro de 2013

usando a interface USB HID do PIC18F4550 no MplabXC8

              Para quem leu o post sobre a criação de uma porta com virtual ( http://microcontroladores-c.blogspot.com.br/2013/10/exemplo-de-rs-232-via-usb-com-pic.html ) este exemplo segue o mesmo raciocínio embora seja mais simples que o da porta COM virtual(usa pouca biblioteca ) .Me basei em outro exemplo da microchip onde o microcontrolador vai indicar através de leds o estado da porta usb e também controlar esses leds, além de monitorar o estado de uma chave conectada ao pino RB5.
              Aqui está os arquivos para baixar: https://drive.google.com/folderview?id=0Bx9JeN0dmzXxV0h6LWMzVWVvLVE&usp=sharing  .dentro desta paste tem um aplicativo exemplo da microchip e que será utilizado para testar sua aplicação("HID.exe" veja figura abaixo) , a diferença deste programa em relação ao da porta COM virtual é que aqui é usado o modo de transferência em massa (em que é possível enviar grandes pacotes) .

             o hardware necessário para este exemplo e bem simples veja na figura a seguir:

Ao descompactar a pasta "exemplo usb_HID" e rodar a IDE Mplab XC8 procure na pasta firmware o arquivo do programa , pronto é rodar e gravar no microcontrolador a partir dai faça as alterações que você julgar necessário, finalizo aqui os exemplos usb com pic.  

quarta-feira, 2 de outubro de 2013

exemplo de RS-232 via USB com pic 18F4550 no Mplab XC8

    Olá a todos que seguem este blog pelo face e aos visitantes,hoje vou ensinar como fazer uma aplicação usando a USB no modo CDC(emula uma porta virtual RS232).Este exemplo foi baseado nos exemplos da microchip,todos os includes necessário para funcionar com o PIC18F4550 foram agrupados em uma pasta, procurei manter a estrutura da pasta da microchip pois a pilha usb  só funciona com a mesma estrutura da pasta de exemplo da microchip,assim para criar uma nova aplicação basta copiar esta pasta e alterar o nome da copia, e fazer algumas modificações que será explicado logo mais.
    Para fazer uma aplicação USB você vai precisar de instalar em seu PC os seguintes softwares que podem ser baixados no site da michochip:

    -> compilador C18 vá a este link e faça o dowload(pode ser versão acadêmica)
http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1406&dDocName=en010014   
    -> framework USB da microchip (drive da usb).
 http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=2680&dDocName=en547784  
     Supondo que vc já tenha instalados os programas acima, verifique no XC8 se aparece o compilador C18(use como se fosse abrir um novo projeto),quando aparecer esta tela estará ok!



      Agora baixe a pasta "exemplo usb_cdc.rar" neste link : https://drive.google.com/folderview?id=0Bx9JeN0dmzXxV0h6LWMzVWVvLVE&usp=sharing,descompacte a pasta e renomeie(se quiser) e em seguida abrir com o XC8(abra pelo programa XC8),depois de aberto clique no arquivo "main.c" conforme a foto abaixo:

        

      veja que aparecerá algum "Warning" no compilador mas não se preocupe com isso pois isso é pelo fato de ter retirado algumas biblioteca que não são necessário para esta aplicação.
pronto! agora é só compilar e gravar o micro controlador.
      para criar seu programa basta alterar e verificar as seguinte bibliotecas:

"HardwareProfile.h", aqui está configurado o clock e os pinos do microcontrolador
"usb_descriptors"  , aqui é configurado o nome do dispositivo e a classe.
 
      Depois disto é só adicionar seu programa no local que está a rotina principal, para testar a microchip já deixou uma aplicativo de teste com o nome "Dynamic CDC Demo.exe" clique nele e digite algo para testar o programa(que apenas pega o que vem da serial virtual e retorna ao pc). o programa main deste exemplo tem a seguinte aparência:

 
O código fonte da rotina main():

//////////////////////includes necessários  /////////////////////////////////////////
// o resto das configurações então em hardware profile
#include "./USB/usb.h"//chama todas as lib necessarias
#include "/MPLAB.X/HardwareProfile.h" //aqui está configurado o clock e os pinos do microcontrolador
#include "GenericTypeDefs.h"//lib que define os tipos utilizados
#include "./USB/usb_function_cdc.h"//funçoes da serial
#include "Compiler.h"//aqui se define o compilador que está sendo utilizado
#include "usb_config.h"//configura a usb
#include "USB/usb_device.h"


//////////////config. dos fuses do microcontrolador///////////////////////////////
#pragma config PLLDIV   = 5         // (usei um cristal de 20 MHz )
#pragma config CPUDIV   = OSC1_PLL2
#pragma config USBDIV   = 2         // o clock do pll será 96MHz PLL/2 = 48Mhz
#pragma config FOSC     = HSPLL_HS
#pragma config FCMEN    = OFF
#pragma config IESO     = OFF
#pragma config PWRT     = OFF
#pragma config BOR      = ON
#pragma config BORV     = 3
#pragma config VREGEN   = ON      //ativa o regulador de voltagem da USB
#pragma config WDT      = OFF
#pragma config WDTPS    = 32768
#pragma config MCLRE    = ON
#pragma config LPT1OSC  = OFF
#pragma config PBADEN   = OFF
//      #pragma config CCP2MX   = ON
#pragma config STVREN   = ON
#pragma config LVP      = OFF
//      #pragma config ICPRT    = OFF       // Dedicated In-Circuit Debug/Programming
#pragma config XINST    = OFF       // Extended Instruction Set
#pragma config CP0      = OFF
#pragma config CP1      = OFF
//      #pragma config CP2      = OFF
//      #pragma config CP3      = OFF
#pragma config CPB      = OFF
//      #pragma config CPD      = OFF
#pragma config WRT0     = OFF
#pragma config WRT1     = OFF
//      #pragma config WRT2     = OFF
//      #pragma config WRT3     = OFF
#pragma config WRTB     = OFF       // proteção de escrita da inicialização (Boot)
#pragma config WRTC     = OFF
//      #pragma config WRTD     = OFF
#pragma config EBTR0    = OFF
#pragma config EBTR1    = OFF
//      #pragma config EBTR2    = OFF
//      #pragma config EBTR3    = OFF
#pragma config EBTRB    = OFF

/////////////////////variaveis requerida pela USB /////////////////////////////////////////////////////

#pragma udata
char USB_Out_Buffer[CDC_DATA_OUT_EP_SIZE];
char RS232_Out_Data[CDC_DATA_IN_EP_SIZE];

unsigned char NextUSBOut;
unsigned char NextUSBOut;
//char RS232_In_Data;
unsigned char LastRS232Out; // Number of characters in the buffer
unsigned char RS232cp; // current position within the buffer
unsigned char RS232_Out_Data_Rdy = 0;
BOOL espera = 0;
USB_HANDLE lastTransmission;

//BOOL stringPrinted;


/**********prototipo das funções ***************************************/
void USBDeviceTasks(void);
void YourHighPriorityISRCode();
void YourLowPriorityISRCode();
void USBCBSendResume(void);
//void BlinkUSBStatus(void);
void UserInit(void);
void InitializeUSART(void);
unsigned char getcUSART();

/********** remapeando vetores ****************************/
#define REMAPPED_RESET_VECTOR_ADDRESS        0x1000
#define REMAPPED_HIGH_INTERRUPT_VECTOR_ADDRESS    0x1008
#define REMAPPED_LOW_INTERRUPT_VECTOR_ADDRESS    0x1018
#define APP_VERSION_ADDRESS                     0x1016 //Fixed location, so the App FW image version can be read by the bootloader.
#define APP_SIGNATURE_ADDRESS                   0x1006 //Signature location that must be kept at blaknk value (0xFFFF) in this project (has special purpose for bootloader).

#define APP_FIRMWARE_VERSION_MAJOR  1   //valid values 0-255
#define APP_FIRMWARE_VERSION_MINOR  0   //valid values 0-99

/////////////////defines da porta serial /////////////////////////////

#define mDataRdyUSART() PIR1bits.RCIF
#define mTxRdyUSART()   TXSTAbits.TRMT
//--------------------------------------------------------------------------

#pragma romdata AppVersionAndSignatureSection = APP_VERSION_ADDRESS
ROM unsigned char AppVersion[2] = {APP_FIRMWARE_VERSION_MINOR, APP_FIRMWARE_VERSION_MAJOR};
#pragma romdata AppSignatureSection = APP_SIGNATURE_ADDRESS
ROM unsigned short int SignaturePlaceholder = 0xFFFF;

#pragma code HIGH_INTERRUPT_VECTOR = 0x08

void High_ISR(void) {
    _asm goto REMAPPED_HIGH_INTERRUPT_VECTOR_ADDRESS _endasm
}
#pragma code LOW_INTERRUPT_VECTOR = 0x18

void Low_ISR(void) {
    _asm goto REMAPPED_LOW_INTERRUPT_VECTOR_ADDRESS _endasm
}
extern void _startup(void); // See c018i.c in your C18 compiler dir
#pragma code REMAPPED_RESET_VECTOR = REMAPPED_RESET_VECTOR_ADDRESS

void _reset(void) {
    _asm goto _startup _endasm
}
#pragma code REMAPPED_HIGH_INTERRUPT_VECTOR = REMAPPED_HIGH_INTERRUPT_VECTOR_ADDRESS

void Remapped_High_ISR(void) {
    _asm goto YourHighPriorityISRCode _endasm
}
#pragma code REMAPPED_LOW_INTERRUPT_VECTOR = REMAPPED_LOW_INTERRUPT_VECTOR_ADDRESS

void Remapped_Low_ISR(void) {
    _asm goto YourLowPriorityISRCode _endasm
}
#pragma code
#pragma interrupt YourHighPriorityISRCode

void YourHighPriorityISRCode() {

#if defined(USB_INTERRUPT)
    USBDeviceTasks();
#endif

} //This return will be a "retfie fast", since this is in a #pragma interrupt section
#pragma interruptlow YourLowPriorityISRCode

void YourLowPriorityISRCode() {

} //This return will be a "retfie", since this is in a #pragma interruptlow section

#pragma code
static void inicializa_cpu(void)
{
    ADCON1 |= 0x0F; // coloca todos os pinos como saida
    #if defined(USE_USB_BUS_SENSE_IO)
    tris_usb_bus_sense = INPUT_PIN; // veja HardwareProfile.h
    #endif
    #if defined(USE_SELF_POWER_SENSE_IO)
    tris_self_power = INPUT_PIN; // veja HardwareProfile.h
    #endif

    UserInit();
    USBDeviceInit(); //usb_device.c.  inicializa o modulo USB e os SFRs
    //variaveis para saber o status.
}//fim de inicializa_cpu

void UserInit(void) {
    unsigned char i;
    InitializeUSART();
    //     inicializa vetor
    for (i = 0; i<sizeof (USB_Out_Buffer); i++) {
        USB_Out_Buffer[i] = 0;
    }
    NextUSBOut = 0;
    LastRS232Out = 0;
    lastTransmission = 0;
}//end UserInit

void InitializeUSART(void) {
    unsigned char c;
    UART_TRISRx = 1; // RX
    UART_TRISTx = 0; // TX
    TXSTA = 0x24; // TX enable BRGH=1
    RCSTA = 0x90; // Single Character RX
    SPBRG = 0x71;
    SPBRGH = 0x02; // 0x0271 for 48MHz -> 19200 baud
    BAUDCON = 0x08; // BRG16 = 1
    c = RCREG; // read

}//end InitializeUSART

void putcUSART(char c) {//escreve na serial
    TXREG = c;
}

#if defined(USB_CDC_SET_LINE_CODING_HANDLER)
void mySetLineCodingHandler(void)
{    
    if (cdc_notice.GetLineCoding.dwDTERate.Val <= 115200)//velocidade maxima
     {
        //atualiza o baudrate no drive CDC
        CDCSetBaudRate(cdc_notice.GetLineCoding.dwDTERate.Val);
        //atualiza o baudrate da porta serial
#if defined(__18CXX) || defined(__XC8) // sem este "if" o programa não funciona(bug do compilador)
        {
            DWORD_VAL dwBaud;
            dwBaud.Val = (DWORD) (GetSystemClock() / 4) / line_coding.dwDTERate.Val - 1;
            SPBRG = dwBaud.v[0];
            SPBRGH = dwBaud.v[1];
        }
    }
}
#endif

unsigned char getcUSART() { //pega caracteres vindo da serial
    char c;
    if (RCSTAbits.OERR) // no caso de ocorrer um overrun
    {
        RCSTAbits.CREN = 0; // reseta porta
        c = RCREG;
        RCSTAbits.CREN = 1; // volta a funciona.
    } else {
        c = RCREG;
    }
    return c;
}



///funçoes prontas para os eventos da usb, caso queira usar alguma é só inserir os codigo-fonte nas chaves
//////////////////////////
void USBCBSuspend(void) {}
void USBCBWakeFromSuspend(void) {}
void USBCB_SOF_Handler(void) {}
void USBCBErrorHandler(void) {}
void USBCBCheckOtherReq(void)
{ 
    USBCheckCDCRequest();
}
void USBCBStdSetDscHandler(void) {}
void USBCBInitEP(void)
{    //habilita os enpoits do modo CDC
    CDCInitEP();
}

void USBCBSendResume(void) {
    static WORD delay_count;

    if (USBGetRemoteWakeupStatus() == TRUE) {
        //Verify that the USB bus is in fact suspended, before we send
        //remote wakeup signalling.
        if (USBIsBusSuspended() == TRUE) {
            USBMaskInterrupts();

            //Clock switch to settings consistent with normal USB operation.
            USBCBWakeFromSuspend();
            USBSuspendControl = 0;
            USBBusIsSuspended = FALSE;
            delay_count = 3600U;
            do {
                delay_count--;
            } while (delay_count);

            //Now drive the resume K-state signalling onto the USB bus.
            USBResumeControl = 1; // Start RESUME signaling
            delay_count = 1800U; // Set RESUME line for 1-13 ms
            do {
                delay_count--;
            } while (delay_count);
            USBResumeControl = 0; //Finished driving resume signalling

            USBUnmaskInterrupts();
        }
    }
}
////////////////////////////////////////////////////////////////////
#if defined(ENABLE_EP0_DATA_RECEIVED_CALLBACK)

void USBCBEP0DataReceived(void) {
}
#endif

BOOL USER_USB_CALLBACK_EVENT_HANDLER(int event, void *pdata, WORD size) {
    switch (event) {
        case EVENT_TRANSFER:
            //funçoes de retorno da porta usb
            break;
        case EVENT_SOF:
            USBCB_SOF_Handler();
            break;
        case EVENT_SUSPEND:
            USBCBSuspend();
            break;
        case EVENT_RESUME:
            USBCBWakeFromSuspend();
            break;
        case EVENT_CONFIGURED:
            USBCBInitEP();
            break;
        case EVENT_SET_DESCRIPTOR:
            USBCBStdSetDscHandler();
            break;
        case EVENT_EP0_REQUEST:
            USBCBCheckOtherReq();
            break;
        case EVENT_BUS_ERROR:
            USBCBErrorHandler();
            break;
        case EVENT_TRANSFER_TERMINATED:
            break;
        default:
            break;
    }
    return TRUE;
}

void rotina_principal(void)
{
   if((USBDeviceState < CONFIGURED_STATE)||(USBSuspendControl==1))
         {
             //se a usb estiver em modo suspensonão faz nada
             return;
         }else{
            if(mUSBUSARTIsTxTrfReady())//não tem dados pendentes?
            {
                    if(espera == 0)
                    {
                     putrsUSBUSART(" \r\n escreva algo!");
                     espera = 1;//indica pra esperar uma resposta
                    }
                    else
                    {
                       char buffer[20];
                       char escrever[50] = "\r\n foi digitado:   ";
                      if((getsUSBUSART(buffer , sizeof(buffer))) != 0)//tem dados
                        {
                          int tamanho = 0;
                          while(tamanho <= sizeof(buffer))
                          {
                             escrever[tamanho+17] = buffer[tamanho];
                             //adiciona o que foi digitado ao que está escrito na variavel
                             tamanho++;
                          }
                          putUSBUSART(escrever ,sizeof(escrever));
                         // putUSBUSART(&escrever ,sizeof(escrever));
                          espera = 0;
                        }
                    }
            }
         CDCTxService();
         }

}//fim do programa principal

void main(void)
{
    inicializa_cpu();
  //  #if defined(USB_INTERRUPT)//se definido a usb vai usar as interrupções
    USBDeviceAttach();//para verifica o status e os eventos gerados
 //   #endif
    while (1)
    {
       #if defined(USB_POLLING)//se definido para verificar de tempo em tempo
        USBDeviceTasks();//executa as tarefas da usb(verifica o status e os eventos gerados)
        #endif
        //////////////coloque aqui seu programa///////////////////////////
        rotina_principal();
    ////////////////////////fim do programa /////////////////////////////////////////////
    }//fim do laço infinito
}//fim do main

aparência do programa "Dynamic CDC Demo" :




logo abaixo o hardware necessário:




quarta-feira, 25 de setembro de 2013

Como usar a USB do PIC18F4550 no MPlab XC8 (passo - a - passo)

                 Diante da dificuldade em usar a USB e da sua complexidade, simplesmente desistimos de usa-lá optando por usar a RS-232 , mesmo sabendo que existe exemplos pré compilados da microchip (motivo pelo qual nem vou implementar um exemplo para o blog neste momento) existe a dificuldade em fazer tudo funcionar por falta de tempo ou mesmo experiência.Nesta matéria vou apenas descrever os passos para usar a USB:

-> entenda como é o protocolo USB, procure na internet materiais que o faça entender o processo de comunicação(ex. http://www.apostilando.com/download.php?cod=2899&categoria=Hardware ou por exemplo http://homepages.dcc.ufmg.br/~adrianoc/usb/ , enfim existe muito material sobre a usb na web).

-> leia o datasheet no item "UNIVERSAL SERIAL BUS(USB)" (aqui eu usei o PIC18F4550), assim você terá um entendimento de como o hardware controla a usb e o modulo SIE(Serial Interface Engine).

->após entender e compreender a usb você precisa instalar o compilador C18(pode ser a versão trial ou acadêmica(não expira, a diferença da versão para é algumas otimizações)).

-> depois de instalado o C18 é hora de instalar o drive usb para dispositivos microchip, procure no site da microchip por "USB framework" ,baixe a versão feita para seu sistema operacional veja neste link : http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=2896 , instale o drive.

->baixe agora o pacote de exemplos da microchip "microchip-libraries-for-applications-v2013-06-15-windows-installer.exe", essa versão depende de quando saiu a atualização dos exemplos da microchip.Quando esse arquivo é executado é criado em seu pc uma pasta que fica geralmente em :
"C:\microchip_solutions_v2013-06-15" dentro desta pasta existe vários exemplos.

->supondo que vc tenha o MPlab XC8 instalado, está tudo pronto pra rodar os exemplos usb,abra o XC8 vá em "Open project " procure a pasta que acabou de ser criada (microchip solution) e dentro dela busque pela pasta USB,entro desta pasta existe muitos exemplos, aqui vou pegar o exemplo "Device-CDC – Basic Demo"(neste exemplo é emulado uma porta RS-232/USB ) , quando esse exemplo for selecionado o compilador irá buscar todo os arquivos(includes) que compõem o exemplo,agora escolha uma das placas de exemplo pra selecionar o microcontrolador(para o 18F4550 é PCDEM_FSUSB, veja a figura),compile o código e pronto !




-> agora vá a pasta "Device - DC – Basic Demo" e procure por "PC Dynamic Software Example" nesta pasta contem um software pra vc testar se o programa funcionou,basta rodar o software e plugar a sua placa na usb (veja neste site um exemplo : http://www.waitingforfriday.com/index.php/PIC_USB_Development_Board ) irá aparecer uma notificação do windows sobre o hardware conectado e então após o windows instalar os drives no programa aparece a mensagem de que está conectado e qual a porta criada("COM3 ou COM4 ou qualquer outra porta COM"). A partir de agora é só mexer no código para adapta-ló a sua necessidade(em breve pretendo colocar um exemplo usb).

sexta-feira, 13 de setembro de 2013

usando o comando "goto" para resetar o PIC - XC8

        As vezes desejamos pular de um ponto a outro no programa dai usa-se um comando(herança do assembly) "goto" para isso, aqui vou demonstrar como resetar o chip com esse pequeno programa:

/*
 *                                               Exemplo de reset do microcontrolador usando o comando "goto"
 *
 * Compilador : MPlabXC8
 * Microcontrolador: 16F648A
 * Autor: aguivone
 * Versão: 1
 * Data :  13 de setembro de 2013
 */
#include <stdio.h>
#include <stdlib.h>
#define _XTAL_FREQ 4000000    //vou usar o oscilador interno
#include <xc.h>


/////////////////////////////////////////////////////////configuraçôes//////////////////////////////////////////////////
#pragma config FOSC = INTOSCIO  // Oscillator Selection bits (INTOSC oscillator: I/O function on RA6/OSC2/CLKOUT pin, I/O function on RA7/OSC1/CLKIN)
//#pragma config FOSC = HS        // Oscillator Selection bits (HS oscillator: High-speed crystal/resonator on RA6/OSC2/CLKOUT and RA7/OSC1/CLKIN)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = ON       // Power-up Timer Enable bit (PWRT enabled)
#pragma config MCLRE = OFF      // RA5/MCLR/VPP Pin Function Select bit (RA5/MCLR/VPP pin function is digital input, MCLR internally tied to VDD)
#pragma config BOREN = OFF      // Brown-out Detect Enable bit (BOD disabled)
#pragma config LVP = OFF        // Low-Voltage Programming Enable bit (RB4/PGM pin has digital I/O function, HV on MCLR must be used for programming)
#pragma config CPD = OFF        // Data EE Memory Code Protection bit (Data memory code protection off)
#pragma config CP = OFF         // Flash Program Memory Code Protection bit (Code protection off)

#define reseta_chip                    PORTBbits.RB0
#define led                            PORTBbits.RB2

void delay_ms(long valor)
{
    while(valor>0)
    {//aproximadamente 1ms
        long useg=0;
      while(useg>999)
        {
          useg++;//como esta usando o oscilado interno então cada ciclo leva 1uS
        }
        valor--;
    }
}
void main(void)
{
    INICIO:
    TRISB = 0X01;//configura portB  como saida(exceto pino B0)
    TRISA = 0X00;//configura portA como saida
    PORTB = 0;  // limpar as portas que estão configuradas como saidas
    CMCON = 7;//desliga modulo comparador
    led =1;//liga led
    delay_ms(1000);//espera 1 segundo
    led =0;//desliga led
    delay_ms(1000);//espera 1 segundo
    for(;;)
    {
       if(reseta_chip == 0)
       {
          goto INICIO;
       }
    }//laço infinito
}

    veja que se o botão estiver pressionado o comando não é executado, mas se o botão estiver liberado ele fica reiniciando o programa o tempo todo fazendo o LED piscar. 


segunda-feira, 19 de agosto de 2013

Trena ultrassônica com PIC - MBLAB XC8



/*
 *                              detector ultrasonico MPlab XC8
 *
 * Compilador : MPlabXC8
 * Microcontrolador: 16F648A
 * Autor: aguivone
 * Versão: 1
 * descrição:trena ultrassônica
 * Data :  19 de agosto de 2013
 */
#include <stdio.h>
#include <string.h> //para usar funçoes de string deve se adicionar este header
#include <stdlib.h>
#define _XTAL_FREQ 16000000    // use este cristal pois a variavel de centimetros é do tipo inteiro 16 bits
#include <xc.h>
#include <delays.h>


/////////////////////////////////////////////////////////configuraçôes//////////////////////////////////////////////////
#pragma config FOSC = HS        // Oscillator Selection bits (HS oscillator: High-speed crystal/resonator on RA6/OSC2/CLKOUT and RA7/OSC1/CLKIN)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF       // Power-up Timer Enable bit (PWRT enabled)
#pragma config MCLRE = OFF      // RA5/MCLR/VPP Pin Function Select bit (RA5/MCLR/VPP pin function is digital input, MCLR internally tied to VDD)
#pragma config BOREN = OFF      // Brown-out Detect Enable bit (BOD disabled)
#pragma config LVP = OFF        // Low-Voltage Programming Enable bit (RB4/PGM pin has digital I/O function, HV on MCLR must be used for programming)
#pragma config CPD = OFF        // Data EE Memory Code Protection bit (Data memory code protection off)
#pragma config CP = OFF         // Flash Program Memory Code Protection bit (Code protection off)

#define LED     PORTBbits.RB4  //pisca a cada aquisição
#define TRIGGER PORTBbits.RB5  //pino de saida de pulso
#define ECO     PORTBbits.RB6  //pino de retorno(eco do som) 

//variaveis usadas/////////////////////////////////////////////////////
 unsigned long distancia_cm= 0;
 unsigned char caracter;
 bit flag_interrupcao = 0;

///////////////////////////////////////////////////interrupção//////////////////////////////////////////////////////////////
void interrupt RS232(void)//vetor de interrupção
 {
     caracter = RCREG;
     flag_interrupcao = 1;
     RCIF = 0;//  limpa flag de interrupção de recepção
 }

/////////////////////////////////funçoes usadas pela uart //////////////////////////////////////////////////////
void inicializa_RS232(long velocidade,int modo)
{////por padrão é usado o modo 8 bits e sem paridade, mas se necessario ajuste aqui a configuração desejada.
    //verifique datasheet para ver a porcentagem de erro e se a velocidade é possivel para o cristal utilizado.
    RCSTA = 0X90;//habilita porta serial,recepção de 8 bit em modo continuo,assincrono.
    int valor;
        if(modo == 1)
        {//modo = 1 ,modo alta velocidade
         TXSTA = 0X24;//modo assincrono,trasmissao 8 bits.
         valor =(int)(((_XTAL_FREQ/velocidade)-16)/16);//calculo do valor do gerador de baud rate
        }
        else
        {//modo = 0 ,modo baixa velocidade
         TXSTA = 0X20;//modo assincrono,trasmissao 8 bits.
         valor =(int)(((_XTAL_FREQ/velocidade)-64)/64);//calculo do valor do gerador de baud rate
        }
    SPBRG = valor;
    RCIE = 1;//habilita interrupção de recepção
    TXIE = 0;//deixa interrupção de transmissão desligado(pois corre se o risco de ter uma interrupção escrita e leitura ao mesmo tempo)
}
void escreve(char valor)
{
    TXIF = 0;//limpa flag que sinaliza envio completo.
    TXREG = valor;
    while(TXIF ==0);//espera enviar caracter
}
void imprime(const char frase[])
{
     char indice = 0;
     char tamanho = strlen(frase);
      while(indice < tamanho ) ///veja que o programa pode travar se aqui não tiver as duas aspas
       {
           escreve(frase[indice]);
           indice++;
       }
}
void int_to_char(unsigned long  quant)
{
    char convert_char1='0';
    char convert_char2='0';
        char convert_char3='0';
        char convert_char4='0';
        if(quant > 400)//maior que o range maximo
        {
          //  imprime("fora do range! \n\r");
            //faz nada!
        }
        else
        {
       while(quant>=1000)
        {
         quant=quant-1000;
         convert_char1++;
         }
       while(quant>=100)
        {
         quant=quant-100;
         convert_char2++;
         }
       while(quant>=10)
        {
         quant=quant-10;
        convert_char3++;
         }
       while(quant>=1)
        {
           quant=quant-1;
         convert_char4++;
         }
          escreve(convert_char1);
          escreve(convert_char2);
          escreve(convert_char3);
          escreve(convert_char4);
          imprime("- \n\r");
        }

}

void main(void)
{
    TRISB = 0X42;   //configura pino b1 e b6 como entrada(RX) e o resto como saida
    PORTB = 0;  // limpar as portas que estão configuradas como saidas
    CMCON = 0x07;        // Comparadores desligados.
    OPTION_REG = 0X80;//desabilita pull ups
    inicializa_RS232(9600,1);//modo de alta velocidade
    PEIE = 1;//habilita interrupção de perifericos do pic
    GIE = 0; //GIE: Global Interrupt Enable bit - neste caso não vou precisar das interrupções
    imprime("Trena ultrassônica! \n\r");
    for(;;)
    {

                          LED = 1;
              TRIGGER = 1;
                          __delay_us(20);
              TRIGGER = 0;
              while(!ECO);//espera o pino ir para nivel alto
                          distancia_cm=0;
              while(ECO)//espera o pino ir para nivel baixo
              {
                              distancia_cm++;
                          }
              //de forma empirica verifiquei que 1cm = 30unidades de contagem(aproximadamente)
                          distancia_cm = distancia_cm/ 11;//valor empirico aproximado!
                  int_to_char(distancia_cm);///envia valor para porta serial
              LED = 0;
                          __delay_ms(500);//espera 1s para ler novo valor
              //(no datasheet eles alertam que este tempo não pode ser menor que 60ms para não pegar ecos falsos)
    }//fim do for


}

terça-feira, 13 de agosto de 2013

Trena ultrassônica com HC - SR04 (ATMEGA328):


/*
 *                         usando o sensor ultrassônico HC-SR04
 *   Version    : 1
 *   microcontrolador : AVR ATMega328
 *   descrição  : medir distancia com o modulo HC-SRO4
 *   criado: 13/08/2013
 *   autor: aguivone moretti fogia
 */
/////////////////////////////////////////////////////////////////////////
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdio.h>
#define F_CPU 16000000UL  // 16MHz deve vir antes da funcão de delay
#include <util/delay.h>
#include <string.h>
#include <avr/eeprom.h>//usado para acessar memoria
////////////////////////////parametros///////////////////////////////////
//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

//configurando os pinos/////////////////////////////////////////////////

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

 //variaveis usadas/////////////////////////////////////////////////////
 long distancia_cm= 0;

 ///////////////////////////funçoes auxiliares//////////////////////////
void delay_ms(long conta)
{
  long valor=0;
  while(valor<conta)
  {
    _delay_us(999);// 1ms
    valor++;
  }
}

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;
    UBRR0H = (unsigned char)(velocidade>>8);
    UBRR0L = (unsigned char)velocidade;
    UCSR0B = 0X18;//não vou habilitar nenhuma interrupção da porta serial
    /* 8 bits , 1 stop bit, assincrono , sem paridade,modo nornal */
    UCSR0C = (1<<USBS0)|(3<<UCSZ00);
}

void escreve_caracter(unsigned char carac)
{  
            _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
}

void impri_serial(const char frase[20])
{
      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++;
       }
}

void int_to_char(long quant)
{


       char convert_char1='0';
       char convert_char2='0';
       char convert_char3='0';
       char convert_char4='0';


       while(quant>=1000)
        {
         quant=quant-1000;
         convert_char1++;
         }
       while(quant>=100)
        {
         quant=quant-100;
         convert_char2++;
         }
       while(quant>=10)
        {
         quant=quant-10;
        convert_char3++;
         }
       while(quant>=1)
        {
           quant=quant-1;
         convert_char4++;
         }
          escreve_caracter(convert_char1);
          escreve_caracter(convert_char2);
          escreve_caracter(convert_char3);
          escreve_caracter(convert_char4);
          impri_serial("- \n\r");

} 


int main(void)
{
           DDRB = 0XFE;  //inicializa portC,como saida exceto B0  - usado para icp1
           DDRC = 0X00;  //inicializa portC,como entrada
           DDRD = 0XF6;  //inicializa portD como Saida exceto pd0 e d3;      
           liga_pino(PORTB,TRIGGER);
           RS232_inicializa(9600);
           impri_serial("Sensor de distancia ultrassonica! \n\r");
           sei();
           long tempo;
      for(;;)
            { 
              desliga_pino(PORTB,LED);
              tempo = 0;
              desliga_pino(PORTB,TRIGGER);
              _delay_us(20);//20us necessario para gerar os pulsos
              liga_pino(PORTB,TRIGGER);
              while(estado_pino(PINB,PB0)==0);//espera o pino ir para nivel alto
              while(estado_pino(PINB,PB0)==1)//espera o pino ir para nivel baixo
              {distancia_cm++;}    
              //de forma empirica verifiquei que 1cm = 30unidades de contagem(aproximadamente)
              distancia_cm = distancia_cm/30;
              int_to_char(distancia_cm);///envia valor para porta serial
              desliga_pino(PORTB,LED);
              delay_ms(1000);//espera 1s para ler novo valor
              //(no datasheet eles alertam que este tempo não pode ser menor que 60ms para não pegar ecos falsos)
             }//fim do for
}//fim do main

quarta-feira, 5 de junho de 2013

Montando um conversor RS232 para Ethernet com o ATmega328.

Eu estava aqui brincando com uma plaquinha na qual eu fiz um conversor ethernet para serial /serial para ethernet e resolvi postar o código fonte pra vcs. Se alguém quiser um aplicativo que funciona como terminal ethernet é só me enviar um e-mail, para o serial existe no mercado um monte de opção. neste projeto o único porem que vi foi quando envio dados da serial para o pc pois se for maior que 40 caracteres ele acaba perdendo o restante ,para minha aplicação do jeito que está basta ,veja a figura abaixo que demonstra como configurar os pinos do AVR como o modulo wiznet (o qual apresentei em posts anteriores.) 







O código fonte :

//***********************************************************************************************************
//                               conversor ethernet - serial RS232
//
//  versão                        : 1.0
//  descrição                   : conversor ethernet-serial/serial-ethernet
//  Autor                      : Aguivone
//  microcontrolador           : ATmega328 P
//  compilador                   : AVR-GCC / Atmel AVR Studio 4.17
//  Data do projeto            : 05 / 06 / 2013.

//*************************************************************************************************************
#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
#include <avr/eeprom.h> ///para usar a eeprom
////////////////////////funçoes auxiliares/////////////////////////////
#define liga_pino(x,y) x |= _BV(y)
#define desliga_pino(x,y) x &= ~(_BV(y))
#define alterna_pino(x,y) x ^= _BV(y)
#define pino_alto(x,y) ((x & _BV(y)) == _BV(y)) //o pino deve estar como entrada ,testa se está em nivel logico 1
/////////////////////////////////////////////////////////////////////////////////////////////
//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 a 0x0405
#define S0_DPORT   0x0410      // Socket 0: aqui é colocado o valor da porta TCP de destino->  endereço = 0x0410 a 0x0411
#define S0_DHAR    0x0406      // Socket 0: endereçamento de registro de hardware(tipo MAC)->  endereço = 0x0406 a 0x040B
#define S0_DIPR    0x040C      // Socket 0: IP de acesso remoto ->  endereço = 0x040C a 0x040F
#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 a 0x0423
#define S0_TX_WR   0x0424      // Socket 0: ponteiro de escrita do buffer de transmissão: 0x0424 a 0x0425
#define S0_RX_RSR  0x0426      // Socket 0: tamanho do registrador de recepção: 0x0426 a 0x0427
#define S0_RX_RD   0x0428      // Socket 0: ponteiro de leitura do tamanho dos dados: 0x0428 a 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 8K de Tx/Rx Buffer(pode se usar até 8K)
#define TCP_PORT         0X1388       // porta TCP/IP usada pelo pc porta 5000
#define MAX_BUF          100      // tamanho maximo do buffer de recepção reduzi de 100 pra 10
/////////
//////// variaveis globais ////////////////////////////////////////
////////
char buf[MAX_BUF];//o maior dado será #C-255-255-255-255-255-255-255-255-255-255-255-1023-1022*
char buffer_serial[MAX_BUF];//buffer da serial

//////////////valores padrao

uint8_t sockstat=0;
char comando;
int ip_placa=5;
int rsize;
int tempo_250ms=0;

//para serial

 unsigned char caracter;//
 //int  tam_buffer;//usado para contar o tamanho do buffer de recepção
 volatile char rec_buffer ='S';
 int dados_serial_conta=0;


int timeout_serial =0;

///////////////////////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))); 
   // escreve bytes mais significativo no buffer spi
  SPDR = (endereco & 0xFF00) >> 8;
   // espera finalizar a transmissão
  while(!(SPSR & (1<<SPIF))); 
   //escreve os bytes menos significativo no buffer spi
  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)
{
  unsigned char porta[] = {0x13,0X88};// ex 5000 = 0X1388 -> 0X13 +0X88 //porta 5000
  //unsigned char porta[] = {0x00,0X50};// ex 80 = 0X0050 -> 0X00 +0X50 //porta tcp
  unsigned char mac_addr[] = {0x00,0x16,0x36,0xDE,0x58,0xF6};//MAC usado pelo microcontrolador(para teste)
  unsigned char ip_addr[] = {192,168,0,ip_placa};//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 gateway cliente (valor para teste,do pc)
  //este ip não é necessariamente o do pc mas deve estar nesta faixa

  spi_escreve(MR,0x80);            // MR = 0b10000000; isso inicicializa os registradores internos automaticamente
  _delay_ms(1);
  //configura porta de comunicação para acesso remoto
  spi_escreve(S0_PORT , porta[0]);
  spi_escreve(S0_PORT + 1,porta[1]);//porta de envio e de destino são iguais 
  spi_escreve(S0_DPORT , porta[0]);
  spi_escreve(S0_DPORT + 1,porta[1]);
  spi_escreve(S0_MR,MR_TCP);    // configura o registrador de modo (MR)
  _delay_ms(1);
  // configura o MAC de acesso remoto
  spi_escreve(S0_DHAR , mac_addr[0]);
  spi_escreve(S0_DHAR + 1,mac_addr[1]);
  spi_escreve(S0_DHAR + 2,mac_addr[2]);
  spi_escreve(S0_DHAR + 3,mac_addr[3]);
  spi_escreve(S0_DHAR + 4,mac_addr[4]);
  spi_escreve(S0_DHAR + 5,mac_addr[5]);
  _delay_ms(1);
  // endereço de IP de acesso remoto será sempre 1 a mais
  spi_escreve(S0_DIPR,ip_addr[0]);
  spi_escreve(S0_DIPR + 1,ip_addr[1]);
  spi_escreve(S0_DIPR + 2,ip_addr[2]);
  spi_escreve(S0_DIPR + 3,ip_placa + 1);
  _delay_ms(1);
  //configura gateway
  spi_escreve(GAR + 0,gtw_addr[0]);///o gateway deve ter mesma faixa de ip senão não funciona,mas nunca usar ip 1 pois é do gateway.
  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 ,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 ,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,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));
}
////////////////////////////////conecta pelo modo servidor////////////////////
uint8_t conex_servidor(uint8_t socket)
{
    uint8_t retval=0;   
     if (socket != 0)//teste socket0
      return retval;
     if (spi_ler(S0_SR) == SOCK_CLOSED) // verificando se o socket 0 está fechado.
      {
      fechar_socket(socket);
      }     
    // abrindo o  Socket 0
    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;
}
void put_serial(unsigned char *carac)
{
           while ( !( UCSR0A & (1<<UDRE0)) ); //espera transmitir para enviar um novo
           UDR0 = *carac;
           /* Wait for empty transmit buffer */

}
void escreve_caracter(unsigned char carac)
{
           while ( !( UCSR0A & (1<<UDRE0)) ); //espera transmitir para enviar um novo
           UDR0 = carac;
}
////////////////////////////envia pacote////////////////////////////////////
uint16_t envia_pacote(unsigned char pacote[],uint16_t buffer_tamanho)
{
    unsigned int ponteiro,ende_temp,ende_real,tx_tamanho,timeout;   

    if (buffer_tamanho <= 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 10ms
         if (timeout++ > 10) 
           {
            // desconecta socket 0 pois não há espaço livre após 10ms
           desconectar(0);
           return 0;
           }
    }
    tx_tamanho=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[tx_tamanho]);
      ende_temp++;
      tx_tamanho++;
    }
    // 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//////////////////////////////////////////
void  recebe_pacote(char pacote[],int taman)
{
        unsigned int ponteiro,ende_temp,ende_real; 
        char recebido;
        ponteiro = spi_ler(S0_RX_RD);//pega localização do dado recebido(tamanho)
        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(taman>0) 
        {
          taman--;
          ende_real=RXBUFADDR + (ende_temp & RX_BUF_MASK);//endereço inicial de leitura + endereço dos dados recebidos 
          recebido = spi_ler(ende_real);
          escreve_caracter(recebido);
          ende_temp++;          
        }
    // 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(5);    // espera terminar leitura.
}
///////////////////////////////////////////////////////////////////////
int Buffer_recepcao(void)
{
  return (((spi_ler(S0_RX_RSR) & 0x00FF) << 8 ) + spi_ler(S0_RX_RSR + 1)); //
}

////////////////////////funçoes auxiliares///////////////////////////////

void inicializa_spi(void)
{
// Seta MOSI (PORTB3),SCK (PORTB5) and PORTB2 (SS) , e os outros pinos como saida 
  SPI_DDR = (1<<PORTB3)|(1<<PORTB5)|(1<<PORTB2)|(1<<PORTB1);//coloca b1 como saida
  // 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);  
}
///////////////////////////////////////////////funçoes usadas pela usart////////////////////////////////////////////////

void serial_inicializa(int BAUD)
{
   int valor = ((F_CPU/16)/BAUD)-1; //verifique se na simulação não está habilitado pra divir por oito o clock do microcontrolador
/* baud rate */
   UCSR0A = 0X20;
/* habilita receiver and transmitter buffers */
  UBRR0H = (unsigned char)(valor>>8);
  UBRR0L = (unsigned char)valor;
/* habilita receiver and transmitter buffers */
  UCSR0B = 0X98;//deve se habilitar somente a interrupção de recepção para não travar o microcontrolador
/* modo assicrono,8 bits , 1 stop bit, assincrono , sem paridade */
   UCSR0C = 0X06;
  //UCSR0C = (1<<USBS0)|(3<<UCSZ00);
}




//////////////////////////interrupções requerida para usar a serial///////////////////////////////////
ISR(USART_RX_vect)
{
 caracter = (char)UDR0;
 buffer_serial[dados_serial_conta] = caracter;
 dados_serial_conta++ ;
 timeout_serial=0;
 rec_buffer ='D';
}

//////////////////////////////////////////////função principal/////////////////////////////////////
int main(void)
 {
  
  //////////////////inicializa port D e port C /////////////////////////////////////////////////////////////////////
  DDRD = 0xFF;//configura port D como saida       
  PORTD = 0x00;//limpa o port D
  DDRC = 0x00;//configura port C como entradas
  //i = PINB; //ler pinos
  inicializa_spi();    //comunicação spi
  ip_placa=5;
  W5100_Inicializa();  //ethernet
  serial_inicializa(9600);//não importa frequencia e 9600
  sei();
  //impri_serial("Use < ou >  \n ");
  //impri_serial("para enviar comando ! \n "); 
  desliga_pino(PORTB,PB0);///// //reseta o chip de ethernet
  _delay_ms(1);
  liga_pino(PORTB,PB0);
  ///////////////////////////////////
  sei();
  ///////////////////////////////////////////////////////
 //OBS : devo desabilitar o bit RSTDISBL para qu e o pino C6 possa ser usado como I/O
 ///////////////////////////////////////////////////////
  for(;;)
    {
       if(tempo_250ms > 30000)//tempo qualquer
          {
            alterna_pino(PORTB,PB1);
            tempo_250ms =0;            
         }
          tempo_250ms++;
          timeout_serial++;
                  
     ////////////////////////rotina ethernet////////////////////////
            sockstat=spi_ler(S0_SR);
            switch(sockstat) 
            {
            case SOCK_CLOSED: ///socket fechado. fica escutando a rede
                 if ( conex_servidor(0) > 0) 
                     {// Listen(escuta)  Socket 0
                        if (escutar_rede(0) <= 0)//socket 0
                             _delay_ms(1);
                     }
                     break;    
             case SOCK_ESTABLISHED://conectado
                 {
                   // lê o pacote recebido e verifica se é valido
                   if(timeout_serial > 3000)//se maior que alguns milisegundos verifica se houve novos dados
                   {
                      if(rec_buffer == 'D')
                      {///tem dados
                       envia_pacote(buffer_serial,MAX_BUF);//envia dados
                       while(dados_serial_conta>0)
                       {
                         buffer_serial[dados_serial_conta] = 0; 
                         dados_serial_conta--;
                       }
                       rec_buffer = 'S';
                      }
                    timeout_serial=0;
                   }
                    if (Buffer_recepcao() > 0)//checa buffer de recepção
                         {
                          // lê o pacote recebido e verifica se é valido

                              rsize=((spi_ler(S0_RX_RSR) & 0x00FF) << 8 ) + spi_ler(S0_RX_RSR + 1);//pega tamanho dos dados recebido
                              recebe_pacote(buf,rsize);
                          }
                              tempo_250ms++;//se conectado pisca 2X mais
                              tempo_250ms++;//se conectado pisca 3X mais rapido
              
                 }break;//fim socket estabilizado      
              case SOCK_FIN_WAIT:
              case SOCK_CLOSING:
              case SOCK_TIME_WAIT:
              case SOCK_CLOSE_WAIT:
              case SOCK_LAST_ACK:
              fechar_socket(0);// força o fechamento do socket 0
              break;
              }//chave do switch

      ////////////////////////fim da rotina ethernet////////////////////////

   }//chave do laço infinito (for)
}//chave de main