Mostrando postagens com marcador microcontroladores PIC. Mostrar todas as postagens
Mostrando postagens com marcador microcontroladores PIC. Mostrar todas as postagens

terça-feira, 6 de dezembro de 2016

Conversor de 12V para 24V com microcontrolador pic18F13K22

         Olá, hoje o exemplo será de um conversor DC/DC (STEP UP) elevador de tensão, o projeto é dividido em 2 etapas;montagem do circuito de elevação DC e a implementação do firmware de controle.
          O "coração do circuito" é basicamente oc componentes L1,C1 e D1 além do componente de chaveamento que pode ser transistor(aquece mais) ou mosfet. Veja a figura a seguir para melhor compreensão:

         O circuito é bem simples de se implementar, provavelmente o mais trabalhoso será encontrar o indutor, dai se tem 3 escolhas : arrancar um indutor de uma fonte chaveada usada(sucata), este indutor pode ser feito com fios de cobre esmaltado, a bitola do fio vai depender da corrente a ser manuseada pelo circuito , e por ultimo ainda encontrar um indutor comercial que se aproxime do indutor desejado.Não vou entrar em muitos detalhes de dimensionamento do circuito pois isso foge da proposta do blog que é apenas montar o código-fonte.
          No microcontrolador PIC18F13K22 o pinos usado foram pino 5 (usado para pwm), pino 8(ref_tensão), pino 15 (para led que indica falha) e pino16 (indica o status, fica piscando).Este código pode ser transferido para qualquer outro modelo de microcontrolador  que tenha PWM.
          Vamos então agora para o código fonte :

Código-fonte principal :


/*
 *                 Conversor DC/DC
 *
 * Compilador :      MPlabXC8
 * Microcontrolador: 18F13K22
 * Autor:            Aguivone
 * Versão:           1
 * Data de criação:  19/05/2015.
 * Retomada do projeto:  30/11/2016
 * Primeira versão estavel:  06/11/2016
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h> //para usar funçoes de string deve se adicionar este header
#include <xc.h>
#include "config_cpu.h"
#include "conv_adc.h"

// configuração de frequencia de PWM  
#define PWM_20KHZ_CLK16        inicializa_PWM1(1, 200, 1)  
#define _XTAL_FREQ 16000000//usado para rotinas de  delays

#define VAL_MAX_PWM   70 //  valor max de pwm  pra não sobreaquecer demais a bobina
#define VAL_MIN_PWM   5  // valor minimo de pwm  

#define MAX_CORRENTE   1024//só pra ignorar por enquanto // em unidades do conversor
//para calcular a tensão faça : (tensão desejada)/0,05371 ;
// o valor deve ser inteiro(sem virgula) por exemplo;
//para 12V temos : 12/0,05371 = 223,4 então será 223 ou 224.
#define DDP_TRAB       450// para 24V (depende do divisor resistivo)

#define LED_STATUS                      LATCbits.LATC0
#define LED_FALHA                       LATCbits.LATC1

//************************************************************************************/
//VARIAVEIS GLOBAIS
//************************************************************************************/
//parametros de tensão/corrente
long   glTensao = 0;// em V
long   glCorrente = 0;// em A
int    uiStatus = 0; //indica o modo como está o estado das tensões


//pwm
long   uiMax_passos = 0;//frequencia em khz
int    uiDuty_cycle = 1;

//variaveis de uso geral
long glTempo_led=0;
int  uiAlterna_leds=0;


//===================================================================================
//Função:    _interrupcoes
//Parâmetro: não tem.
//Retorno:   não tem.
//Descrição: usada para tratar as interrupções geradas pelo microcontrolador.
//===================================================================================
void interrupt interrupcoes(void)//vetor de interrupção
 {
    if(ADIF)
    {//se interrupção do modulo analogico!
        ADIF = 0;//limpa flag
    }    
    if(TMR2IF)
    {//interrupção do timer2
      TMR2IF = 0;//não será usado
    }
    if(CCP1IF)
    {//interrupção do ccp1
      CCP1IF = 0;//não será usado
    }     
 }

//===================================================================================
//Função:    _delay_ms
//Parâmetros: long delay, essa função cobre uma falha nas rotinas de tempo para o pic da serie 18F
//Retorno:   não tem retorno.
//Descrição: faz microcontrolador perder tempo.
//===================================================================================
void delay_ms(long delay)
{
    while(delay > 0)
    {
     __delay_ms(1);
     delay--;
    }
}
//===================================================================================
//Função:    _liga_leitura_0
//Parâmetro: não tem.
//Retorno:   não tem.
//Descrição: liga entrada de sinal analogico na porta 0.
//===================================================================================
void  liga_leitura_0(void)
 {
      ADCON0 = 0X21;
 }
//===================================================================================
//Função:    _liga_leitura_1
//Parâmetro: não tem.
//Retorno:   não tem.
//Descrição: liga entrada de sinal analogico na porta 1.
//===================================================================================
void  liga_leitura_1(void)
 {
      ADCON0 = 0X25;
 }

void ler_ADC(int giMedia)//numero de amostras
{
      int iMedia=0;
      glTensao = 0;
      glCorrente = 0;
      while(iMedia < giMedia)
      {
        glTensao = glTensao +  ler_adc_un();
        __delay_us(2);//tempo minino para aquisições
        iMedia++;
      }
      liga_leitura_1();//agora lê a corrente
      __delay_us(2);//tempo minino para aquisições
      iMedia=0;
      while(iMedia < giMedia)
      {
        glCorrente = glCorrente + ler_adc_un();
        __delay_us(2);//tempo minino para aquisições
        iMedia++;
      }
      liga_leitura_0();//volta a ler tensão 
      glTensao = glTensao/giMedia;
      glCorrente = glCorrente/giMedia;
}
void inicializa_PWM1(char prescaler,char pr2,char postcaler)//prescaler / PR2 / postcaler
{
    uiMax_passos =(int) pr2;
    switch(prescaler)
    {
        case 1:
        {
           prescaler = 0;
        }break;
        case 4:
        {
           prescaler = 1;
        }break;
        case 16:
        {
           prescaler = 3;
        }break;
    }
    T2CON = (postcaler - 1)<<3;
    T2CON = T2CON + 4 + prescaler;//o 4 é para habilitar o timer 
    PR2 = pr2;
    CCP1CON = 0X0F;//habilita pwm
    CCP1IE = 1;//desabilita interrupção pois não vamos precisar dela, modulo ccp1
    TMR2IE = 0; //desabilita interrupção pois pode até travar processamento(não vamos usar tambem); timer 2
}

void duty_cicle(long valor)
{
    CCPR1 = valor;    
}

//===================================================================================
//Função:    _inicializa_cpu
//Parâmetros: não tem
//Retorno:   não tem retorno.
//Descrição: inicializa os registradores do microcontrolador.
//===================================================================================
void inicializa_cpu(void)
{
    TRISC = 0xC0;//habilita 6 e 7 com entrada analogica
    TRISA = 0XFF;//configura portA como entrada
    TRISB = 0X20;//configura portB  B5 (pino RX) como entrada
    PORTB = 0;  // limpar as portas que estão configuradas como saidas
    ADCON0 = 0X21;//liga modulo analogico digital e configura   entrada de sinal para o pino RC6(AN8)
    ADCON1 = 0X00;// Vref- seta ao Vss e  Vref+ ao Vdd
    ADCON2 = 0b10111110;// justificado a direita// tempo de aquisição 20TAD // clk Fosc/64
    PEIE = 1;//habilita interrupção de perifericos do pic
    GIE = 1; //GIE: Global Interrupt Enable bit
    ANSEL = 0x00;//desabilita portas analogicas(para não atrapalhar recepção no pino)
    ANSELH = 0x03;//em alguns casos não funciona nem a interrupção de recepção. habilita somente os pinos que vão funcionar como AD
    PWM_20KHZ_CLK16;//100khz veja no comentario abaixo "SUGESTÃO DE DEFINES :"    
    duty_cicle(1);//inicia com valor minimo
    uiDuty_cycle = 1;
}
//


//*******************************Rotina principal*********************************************/
void main(void)
{
  inicializa_cpu();
  for(;;)
    {
        glTempo_led++; 
        if(glTempo_led > 100)
        {
            
            if(uiAlterna_leds == 0)
            {
               LED_STATUS = 1;
               uiAlterna_leds=1; ;//pisca led 
            }
            else
            {
                LED_STATUS = 0;
               uiAlterna_leds = 0; ;//pisca led 
            }
            if(uiStatus > 0)
            {
                LED_FALHA = 1;
            }
            else
            {
                LED_FALHA = 0;  
            }
            glTempo_led=0;
        }   
        ///processamento das tensões
        ler_ADC(4);//pega pelo menos 5 amostras para tirar media
         /// /verifica tensão
          if(glTensao > DDP_TRAB )//flutuação máxima 
          {//tensão superior a permitida
              if(uiDuty_cycle < VAL_MIN_PWM)
              {   //não consegue mais compensar chegou ao limite
                 uiStatus = 2;//sobretensão                
              }
              else
              { 
                  //tenta compensar valor
                  uiDuty_cycle--;//a
                  duty_cicle(uiDuty_cycle);
                  uiStatus = 0;//tudo ok
             }
          }
          else              
          {
                if(glTensao < DDP_TRAB )//flutuação máxima 
                {
                  //tensão inferior a permitida
                        if(uiDuty_cycle > VAL_MAX_PWM)
                        {
                             //não consegue mais compensar chegou ao limite
                             uiStatus = 3;//subtensão  
                        }
                        else
                        {
                            //tenta compensar valor
                            uiDuty_cycle++;//lembre que a saida é invertida
                            duty_cicle(uiDuty_cycle);
                            uiStatus = 0;//tudo ok
                        }

              }//fim de tensão fora do range
          }
      ////////////////       
           
    }//loop infinito
}



        

/*calculos para pwm
    *
    * periodo do pwm
    *
    *  Tpwm = [PR2+1]*4*Tosc*prescaler(do timer2)
    *
    * duty cycle
    *             <bits 5e4>
    * D = (CCPR1L + CCP1CON) * Tosc * prescaler (do timer2)
    *
    * numero de passos do pwm
    *
    * N = (Fosc/(Fpwm * 4 * prescaler)) 
    */


/*
SUGESTÃO DE DEFINES :
 * use estes valores como referencia
 * Note que os valores do meio são o numero de passos do pwm(quanto mais passos mais preciso será)
 *
//clock de 4mhz
#define PWM_250HZ_CLK4         inicializa_PWM1(16, 250, 1) //
#define PWM_500HZ_CLK4         inicializa_PWM1(16, 125, 1) //
#define PWM_1KHZ_CLK4          inicializa_PWM1(4, 250, 1)  //
#define PWM_1K25HZ_CLK4        inicializa_PWM1(16, 50, 1)  //
#define PWM_2KHZ_CLK4          inicializa_PWM1(4, 125, 1)  //
#define PWM_2K5HZ_CLK4         inicializa_PWM1(4, 100, 1)  //
#define PWM_4KHZ_CLK4          inicializa_PWM1(1, 250, 1)  //
#define PWM_5KHZ_CLK4          inicializa_PWM1(1, 200, 1)  //
#define PWM_8KHZ_CLK4          inicializa_PWM1(1, 125, 1)  //
#define PWM_10KHZ_CLK4         inicializa_PWM1(1, 100, 1)  //
#define PWM_20KHZ_CLK4         inicializa_PWM1(1,  50, 1)  //
#define PWM_25KHZ_CLK4         inicializa_PWM1(1,  40, 1)  //
#define PWM_100KHZ_CLK4        inicializa_PWM1(1, 10, 1)   //
//clock de 8mhz
#define PWM_500HZ_CLK8         inicializa_PWM1(16, 250, 1) //
#define PWM_1KHZ_CLK8          inicializa_PWM1(16, 125, 1) //
#define PWM_2KHZ_CLK8          inicializa_PWM1(4, 250, 1)  //
#define PWM_2K5HZ_CLK8         inicializa_PWM1(16, 50, 1)  //
#define PWM_4KHZ_CLK8          inicializa_PWM1(4, 125, 1)  //
#define PWM_5KHZ_CLK8          inicializa_PWM1(4, 100, 1)  //
#define PWM_8KHZ_CLK8          inicializa_PWM1(1, 250, 1)  //
#define PWM_10KHZ_CLK8         inicializa_PWM1(1, 200, 1)  //
#define PWM_16KHZ_CLK8         inicializa_PWM1(1, 125, 1)  //
#define PWM_20KHZ_CLK8         inicializa_PWM1(1, 100, 1)  //
#define PWM_40KHZ_CLK8         inicializa_PWM1(1,  50, 1)  //
#define PWM_50KHZ_CLK8         inicializa_PWM1(1,  40, 1)  //
#define PWM_200KHZ_CLK8        inicializa_PWM1(1, 10, 1)   //
//clock de 16mhz
#define PWM_1KHZ_CLK16         inicializa_PWM1(16, 250, 1) //
#define PWM_2KHZ_CLK16         inicializa_PWM1(16, 125, 1) //
#define PWM_4KHZ_CLK16         inicializa_PWM1(4, 250, 1)  //
#define PWM_5KHZ_CLK16         inicializa_PWM1(16, 50, 1)  //
#define PWM_8KHZ_CLK16         inicializa_PWM1(4, 125, 1)  //
#define PWM_10KHZ_CLK16        inicializa_PWM1(4, 100, 1)  //
#define PWM_16KHZ_CLK16        inicializa_PWM1(1, 250, 1)  //
#define PWM_20KHZ_CLK16        inicializa_PWM1(1, 200, 1)  //
#define PWM_32KHZ_CLK16        inicializa_PWM1(1, 125, 1)  //
#define PWM_40KHZ_CLK16        inicializa_PWM1(1, 100, 1)  //
#define PWM_80KHZ_CLK16        inicializa_PWM1(1,  50, 1)  //
#define PWM_100KHZ_CLK16       inicializa_PWM1(1,  40, 1)  //
#define PWM_400KHZ_CLK16       inicializa_PWM1(1, 10, 1)   //

/////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////

*/
Código-fonte "config_cpu.h" :
/* 
 * File:   config_cpu.h
 * Author: aguivone
 *
 * Created on 25 de Agosto de 2014, 16:24
 */

#ifndef CONFIG_CPU_H
#define    CONFIG_CPU_H

/*******************************configuraçôes do pic ****************************************************/

// CONFIG1H
#pragma config FOSC = HS        // Oscillator Selection bits (HS oscillator)
#pragma config PLLEN = OFF      // 4 X PLL Enable bit (PLL is under software control)
#pragma config PCLKEN = ON      // Primary Clock Enable bit (Primary clock enabled)
#pragma config FCMEN = OFF      // Fail-Safe Clock Monitor Enable (Fail-Safe Clock Monitor disabled)
#pragma config IESO = OFF       // Internal/External Oscillator Switchover bit (Oscillator Switchover mode disabled)

// CONFIG2L
#pragma config PWRTEN = OFF     // Power-up Timer Enable bit (PWRT disabled)
#pragma config BOREN = OFF      // Brown-out Reset Enable bits (Brown-out Reset disabled in hardware and software)
#pragma config BORV = 19        // Brown Out Reset Voltage bits (VBOR set to 1.9 V nominal)

// CONFIG2H
#pragma config WDTEN = OFF      // Watchdog Timer Enable bit (WDT is controlled by SWDTEN bit of the WDTCON register)
#pragma config WDTPS = 32768    // Watchdog Timer Postscale Select bits (1:32768)

// CONFIG3H
#pragma config HFOFST = ON      // HFINTOSC Fast Start-up bit (HFINTOSC starts clocking the CPU without waiting for the oscillator to stablize.)
#pragma config MCLRE = OFF      // MCLR Pin Enable bit (RA3 input pin enabled; MCLR disabled)

// CONFIG4L
#pragma config STVREN = ON      // Stack Full/Underflow Reset Enable bit (Stack full/underflow will cause Reset)
#pragma config LVP = OFF         // Single-Supply ICSP Enable bit (Single-Supply ICSP enabled) desliga programação em baixa voltage
#pragma config BBSIZ = OFF      // Boot Block Size Select bit (512W boot block size)
#pragma config XINST = OFF      // Extended Instruction Set Enable bit (Instruction set extension and Indexed Addressing mode disabled (Legacy mode))

// CONFIG5L
#pragma config CP0 = OFF        // Code Protection bit (Block 0 not code-protected)
#pragma config CP1 = OFF        // Code Protection bit (Block 1 not code-protected)

// CONFIG5H
#pragma config CPB = OFF        // Boot Block Code Protection bit (Boot block not code-protected)
#pragma config CPD = OFF        // Data EEPROM Code Protection bit (Data EEPROM not code-protected)

// CONFIG6L
#pragma config WRT0 = OFF       // Write Protection bit (Block 0 not write-protected)
#pragma config WRT1 = OFF       // Write Protection bit (Block 1 not write-protected)

// CONFIG6H
#pragma config WRTC = OFF       // Configuration Register Write Protection bit (Configuration registers not write-protected)
#pragma config WRTB = OFF       // Boot Block Write Protection bit (Boot block not write-protected)
#pragma config WRTD = OFF       // Data EEPROM Write Protection bit (Data EEPROM not write-protected)

// CONFIG7L
#pragma config EBTR0 = OFF      // Table Read Protection bit (Block 0 not protected from table reads executed in other blocks)
#pragma config EBTR1 = OFF      // Table Read Protection bit (Block 1 not protected from table reads executed in other blocks)

// CONFIG7H
#pragma config EBTRB = OFF      // Boot Block Table Read Protection bit (Boot block not protected from table reads executed in other blocks)

#endif    /* CONFIG_CPU_H */
//////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////
Código-fonte "conv_adc.h" :

/*
 *                          FUNÇOES USADAS NA CONVERSAO ANALOGICO/DIGITAL
 *
 * Compilador :      MPlabXC8
 * Microcontrolador: 18F13K22
 * Autor:            Aguivone
 * Versão:           1
 * Data de criação:  21 de agosto de 2014.
 */

#include <xc.h>


// ===================================================================================
// Função:    _ler_adc_un
// Parâmetros: não tem.
// Retorno   : unsigned long ultensao.
// Descrição : retorna o valor lido em unidades de medidas.
// ===================================================================================

unsigned long ler_adc_un(void)
{
    unsigned long ultensao;
    ADCON0bits.GO = 1; //inicia conversão
    while (ADCON0bits.GO_DONE == 1); //espera finalizar leitura
    ultensao = (ADRESH << 8) | ADRESL;
    return(ultensao);
}

// ===================================================================================
// Função:    _ler_adc_mv
// Parâmetros: não tem.
// Retorno   : unsigned long ultensao.
// Descrição : retorna o valor lido em milivolts.
// ===================================================================================
unsigned long ler_adc_mv(void)
{
    unsigned long ultensao;
    ultensao =((ler_adc_un() * 5000)/1023); //Vref está em milliVolts
    return(ultensao);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Exemplo do protótipo funcionando :


Conclusões do projeto: 

               O circuito funcionou de forma satisfatória, conseguiu compensar a queda de tensão para uma carga de 300mA(com uma queda de tensão de saída de 0,3V), além de regular a tensão na saída mesmo que a entrada de tensão do circuito variasse. Como todos os outros exemplos postados aqui no blog este projeto é apenas didático podendo ser melhorado para uso comercial.
              A tensão minima de trabalho ficou em 11V e a máxima é até 23V (geralmente até 1 ou 2 volta da tensão de saída), para mudar o valor da tensão de saída basta mudar o valor da variável "DDP_TRAB", não recomendo colocar um valor menor do que a entrada pois o circuito apenas eleva(conversor boost) a tensão.
             Uma ultima dica é usar um dissipador de calor no mosfet de chaveamento.
               Lembrando que para acompanhar as postagens basta entrar na página do facebook e curtir.
https://www.facebook.com/Microcontroladores-C-576463872371829  ou procurando por microcontroladores-c no face.

terça-feira, 9 de agosto de 2016

Gerando sinais analógicos com o PIC(onda triangular e dente de serra).

Olá,
      As vezes precisamos converter dados digitais em sinais analógicos apesar de alguns microcontroladores terem esta opção já inclusa podemos também recorrer a chips dedicado para esta função como os chips da "analog devices" os AD5601/AD5611/AD5621 que são de 8,10 e 12 bits respectivamente.
      O circuito montado no proteus foi este a seguir:
     Observe que coloquei uma porta serial para saber o qual valor eu estava sendo enviado, o voltímetro 'lê'  a tensão que estava saindo a cada incremento no chip.O código fonte ficou dividido em duas partes; uma gera onda dente de serra e o outro gera uma onda triangular, veja na imagem abaixo os prints da tela:

As formas de ondas em azul são os pacotes SPI que foram enviados ,em verde o clock gerado a cada transmissão de pacotes e em vermelho o momento em que o pino de "slave select " é ativado. Na figura a seguir é visto como é feito o cálculo para o chip AD5601, para calcular para os outros chips segue o mesmo raciocínio ou seja pega o valor de 5V e divide pelo números de resolução(incrementos) do chip ou seja 255 incrementos para o AD5601,1024 para o AD5611 e 4096 incrementos para o AD5621.
O código fonte fica :


/*
 *                                Usando comunicação SPI  com ADS601/ADS611/ADS621     
 *
 * Compilador : MPlabXC8
 * Microcontrolador: 16F1947
 * Autor: aguivone
 * Versão: 1
 * Data :  09/08/2016
 */
#include <xc.h>
#include <stdio.h>
#include "serial16F1947.c"
#include "SPI.c"
#define _XTAL_FREQ 16000000  //usado para rotinas de  delays
#define LED               LATAbits.LATA0
#define LER_LED           PORTAbits.RA0


//
///////////configuração dos fuses bits/////////////////////////////////////////////
// CONFIG1
#pragma config FOSC = HS        // Oscillator Selection (HS Oscillator, High-speed crystal/resonator connected between OSC1 and OSC2 pins)
#pragma config WDTE = OFF       // Watchdog Timer Enable (WDT disabled)
#pragma config PWRTE = OFF      // Power-up Timer Enable (PWRT disabled)
#pragma config MCLRE = ON       // MCLR Pin Function Select (MCLR/VPP pin function is MCLR)
#pragma config CP = OFF         // Flash Program Memory Code Protection (Program memory code protection is disabled)
#pragma config CPD = OFF        // Data Memory Code Protection (Data memory code protection is disabled)
#pragma config BOREN = OFF      // Brown-out Reset Enable (Brown-out Reset disabled)
#pragma config CLKOUTEN = OFF   // Clock Out Enable (CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin)
#pragma config IESO = ON        // Internal/External Switchover (Internal/External Switchover mode is enabled)
#pragma config FCMEN = ON       // Fail-Safe Clock Monitor Enable (Fail-Safe Clock Monitor is enabled)

// CONFIG2
#pragma config WRT = OFF        // Flash Memory Self-Write Protection (Write protection off)
#pragma config VCAPEN = OFF     // Voltage Regulator Capacitor Enable (VCAP pin functionality is disabled)
#pragma config PLLEN = OFF      // PLL Enable (4x PLL disabled)
#pragma config STVREN = OFF     // Stack Overflow/Underflow Reset Enable (Stack Overflow or Underflow will not cause a Reset)
#pragma config BORV = LO        // Brown-out Reset Voltage Selection (Brown-out Reset Voltage (Vbor), low trip point selected.)
#pragma config LVP = OFF        // Low-Voltage Programming Enable (High-voltage on MCLR/VPP must be used for programming)
//////////////////////////////////////////////////////////////////////////////////

//************************************************************************************/
//VARIAVEIS GLOBAIS
//************************************************************************************/
bit flag_led=0;
////variaveis da porta serial
char   gcCaracter;
//*******************************************************************************/
//===================================================================================
//Função:    _interrupcoes
//Descrição: usada para tratar as interrupções geradas pelo microcontrolador.
//===================================================================================
void interrupt interrupcoes(void)//vetor de interrupção
 {
      if(RC1IF)//verifica interrupção da serial na COM1
    {//interrupção da serial
        gcCaracter = RC1REG;   
        escreve_RS232(gcCaracter,0);//finaliza string
        RC1IF = 0;//  limpa flag de interrupção de recepção
    }
    /*if(RC2IF)//verifica interrupção da serial na COM2
    {//interrupção da serial
        gcCaracter = RC2REG;
        escreve_RS232(gcCaracter,1);//finaliza string
        RC2IF = 0;//  limpa flag de interrupção de recepção
    }*/
}

//===================================================================================
//Função:    _config_CPU
//Parâmetros: não tem
//Retorno:   não tem retorno.
//Descrição: inicializa os registradores do microcontrolador.
//===================================================================================
void config_CPU()
{
    //configura portas logicas
    TRISA = 0X00;
    TRISB = 0X00;
    TRISC = 0x80;
    TRISD = 0x00;
    TRISE = 0x00;
    TRISF = 0x00;//todos entrada e ainda são as entrasas analogicas
    TRISG = 0x04;
    // inicializa portas logicas configuradas como saida para 0
    LATA = 0;
    LATB = 0;
    LATC = 0;
    LATD = 0;
    LATE = 0;
    LATF = 0;
    LATG = 0;
    inicializa_RS232(9600,1,0);//modo de alta velocidade inicializa COM1
    //inicializa_RS232(9600,1,1);//modo de alta velocidade inicializa COM2
    PEIE = 1;//habilita interrupção de perifericos do pic
    GIE = 1; //GIE: Global Interrupt Enable bit  
    __delay_ms(100);
    
}

void Envia_pacote(unsigned long valor,int modo,int tipo)//valor,modo de operação,tipo do sensor
{
    switch(tipo)
    {
        case 0:
        {
           valor = valor << 6; //8 bits - ADS601
        }break;
        case 1:
        {
            valor = valor << 4;//10 bits - ADS611
        }break;
        case 2:
        {
            valor = valor << 2;//12 bits - ADS621
        }break;
    }
     valor =  valor & 0B0011111111111111;//zera os 2 primeiros bits
     switch(modo)
    {//modos do power down
        case 1:
        {
           valor  = valor + 0X4000;//1K ligado ao gnd 
        }break;
        case 2:
        {
           valor  = valor + 0X8000;//100K ligado ao gnd 
        }break;
        case 3:
        {
           valor  = valor + 0XC000; //three state
        }break;
    }
    escreve_SPI(((unsigned char)(valor>>8)),(unsigned char)valor ,1,0);//byte1 , byte2,numero de bytes a ser enviado(0 = 1 e 1 = 2),tipo de ligação ao terra 
    
}

void main(void) 
{
    config_CPU(); 
    imprime_RS232("Imprimindo: COM 1!\r\n",0); 
    imprime_RS232("Digite um caracter:\r\n",0);
    inicializa_spi_mestre(0);
    long tensao,tempo=0;
    for(;;)
    { 
         ///////////////simulação do trecho 1(onda dente de serra)//////////////
            imprime_RS232("Valor enviado = ",0);
            long_to_char_RS232(tempo,5,0,0);
            Envia_pacote(tempo,0,0); //8 bits - ADS601  o valor a ser colocado deve ser de 0 a 255.
           // Envia_pacote(tensao,0,1); //10 bits - ADS611  o valor a ser colocado deve ser de 0 a 1024.
           // Envia_pacote(tensao,0,2); //12 bits - ADS601  o valor a ser colocado deve ser de 0 a 4096.
            __delay_ms(200);//tempo de cada degrau
            imprime_RS232("\r\n",0);
            if(tempo > 245)
            {
                tempo = 0;
            }
             tempo = tempo + 10;
            ////////////////fim do trecho 1//////////////////////
///////////////simulação do trecho 2(onda triangular)////////////// /* //descomente esta linha para gerar a onda senoidal mas o trecho 1 deve ser comentado if(tempo > 254) { tensao--; if(tensao == 0) { tempo =0; } } else { tensao++; } Envia_pacote(tensao,0,0); __delay_ms(1);//tempo de cada degrau *///descomente esta linha para gerar a onda senoidal mas o trecho 1 deve ser comentado ////////////////fim do trecho 2////////////////////// tempo++; } }

código dos includes externos
--------------------------------------------
"serial16F1947.c"
/*
 *                          FUNÇOES USADAS NA SERIAL
 *
 * Compilador :      MPlabXC8
 * Microcontrolador: 16F1947
 * Autor:            Aguivone
 * Versão:           1
 * Data de criação:  21 de agosto de 2014.
 */

#include <xc.h>
#include <stdio.h>
#include <string.h> //para usar funçoes de string deve se adicionar este header
#define _XTAL_FREQ 16000000//usado para rotinas de  delays

//===================================================================================
//Função:    _inicializa_RS232
//Parâmetros: unsigned long ulVelocidade
//          : unsigned int uiModo
//          : porta serial(1 ou 0) 
//Retorno:   não tem retorno.
//Descrição: usada para iniciar a porta serial.
//===================================================================================
void inicializa_RS232(unsigned long ulVelocidade,unsigned int uiModo,int porta)
{//// 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.
    unsigned long valor;
    if(porta == 0)
    {
        RC1STA = 0X90;//habilita porta serial,recepção de 8 bit em modo continuo,assincrono.        
            if(uiModo == 1)
            {//modo = 1 ,modo alta velocidade
             TX1STA = 0X24;//modo assincrono,trasmissao 8 bits.
             valor =(((_XTAL_FREQ/ulVelocidade)-16)/16);//calculo do valor do gerador de baud rate
            }
            else
            {//modo = 0 ,modo baixa velocidade
             TX1STA = 0X20;//modo assincrono,trasmissao 8 bits.
             valor =(((_XTAL_FREQ/ulVelocidade)-64)/64);//calculo do valor do gerador de baud rate
            }
        SP1BRG = valor;
        RC1IE = 1;//habilita interrupção de recepção
        TX1IE = 0;//deixa interrupção de transmissão desligado(pois corre se o risco de ter uma interrupção escrita e leitura ao mesmo tempo)

    }
    else
    {
       RC2STA = 0X90;//habilita porta serial,recepção de 8 bit em modo continuo,assincrono.
        if(uiModo == 1)
        {//modo = 1 ,modo alta velocidade
         TX2STA = 0X24;//modo assincrono,trasmissao 8 bits.
         valor =(((_XTAL_FREQ/ulVelocidade)-16)/16);//calculo do valor do gerador de baud rate
        }
        else
        {//modo = 0 ,modo baixa velocidade
         TX2STA = 0X20;//modo assincrono,trasmissao 8 bits.
         valor =(((_XTAL_FREQ/ulVelocidade)-64)/64);//calculo do valor do gerador de baud rate
        }
    SP2BRGL = valor;
    SP2BRGH = valor<<8;
    RC2IE = 1;//habilita interrupção de recepção
    TX2IE = 0;//deixa interrupção de transmissão desligado(pois corre se o risco de ter uma interrupção escrita e leitura ao mesmo tempo)
    }
    
}
//===================================================================================
//Função:    _escreve1_RS232
//Parâmetros: char cValor, int porta
//Retorno:   não tem retorno.
//Descrição: usada para escrever 1 caracter.
//===================================================================================
 void escreve_RS232(char cValor,int porta)
{
     if(porta == 0)
    {
        TX1IF = 0;//limpa flag que sinaliza envio completo.
        TX1REG = cValor;
        while(TX1IF ==0);//espera enviar caracter
    }
    else
    {
        TX2IF = 0;//limpa flag que sinaliza envio completo.
        TX2REG = cValor;
        while(TX2IF ==0);//espera enviar caracter
    }
     __delay_us(50);
}
 
//===================================================================================
//Função:    _imprime_RS232
//Parâmetros: const char ccFrase[], int porta
//Retorno:   não tem retorno.
//Descrição: usada para escrever uma string(vetor de caracteres).
//===================================================================================
 void imprime_RS232(const char ccFrase[],int porta)
{
     unsigned char indice = 0;
     unsigned char tamanho = strlen(ccFrase);     
      while(indice < tamanho ) ///veja que o programa pode travar se aqui não tiver as duas aspas
       {
           escreve_RS232(ccFrase[indice],porta);
           indice++;
       }
}
//===================================================================================
//Função:    _long_to_char_RS232
//Parâmetros: unsigned long  ulQuant, -> valor a ser impresso na serial
//            int iTam,-> numero de caracter que deve ser impresso
//Retorno:   não tem retorno.
//Descrição: converte um long ou int em uma sequencia de caracteres.
//===================================================================================
void long_to_char_RS232(unsigned long  ulQuant,int iTam,int virgula,int porta)
{
        char cTexto[7];
        int  iValor = 0;
        if(virgula == 0)
        { virgula = 20;//dessa forma nunca será usado a virgula
        }
        while(iValor < 6 )
        {
             cTexto[iValor]='0';
             iValor++;
        }        
         while(ulQuant>=10000)
            {
             ulQuant=ulQuant-10000;
             cTexto[5]++;
             }
         while(ulQuant>=1000)
            {
             ulQuant=ulQuant-1000;
             cTexto[4]++;
             }
          while(ulQuant>=100)
            {
             ulQuant=ulQuant-100;
             cTexto[3]++;
             }
           while(ulQuant>=10)
            {
             ulQuant=ulQuant-10;
             cTexto[2]++;
             }
           while(ulQuant>=1)
            {
             ulQuant=ulQuant-1;
             cTexto[1]++;
             }
        iValor = iTam ;
          while(iValor != 0 )
           {
              escreve_RS232(cTexto[iValor],porta);
              iValor--;
              if(virgula == iValor){ escreve_RS232(',',porta);}
           }
}
------------------------------------------------------------------------------------
"SPI.c"

/*
 * File:   SPI.c
 * Author: aguivone
 *
 * Created on 14 de Julho de 2016, 14:54
 */
#include <xc.h>
#define _XTAL_FREQ 16000000  //usado para rotinas de  delays

#define SPI1_SS            LATCbits.LATC2 //configura pino de Slave selected
#define SPI2_SS            LATCbits.LATC0 //configura pino de Slave selected


unsigned char ler_SPI( unsigned char dado,int porta_spi)
{//le um byte
  unsigned char TempVar;
  unsigned char Retorno;
  if(porta_spi == 0)
  {
    SPI1_SS    = 1;
    __delay_us(5);
    TempVar = SSP1BUF;        // limpa BF
    SSP1BUF = dado;           // escreve no buffer o codigo da solicitação
    while (!SSP1STATbits.BF);//espera terminar o envio
    TempVar = SSP1BUF;        // limpa BF
    SSP1BUF = 0X00;           // envia um dado qualquer somente para fazer a leitura
    while (!SSP1STATbits.BF);
     SPI1_SS    = 0;
     Retorno = SSP1BUF;
  }
  else
  {
     SPI2_SS    = 1;
    __delay_us(5);
    TempVar = SSP2BUF;        // limpa BF
    SSP2BUF = dado;           //escreve no buffer o codigo da solicitação
    while (!SSP2STATbits.BF);//espera terminar o envio
    TempVar = SSP1BUF;        // limpa BF
    SSP2BUF = 0X00;           // envia um dado qualquer somente para fazer a leitura
    while (!SSP2STATbits.BF);
     SPI2_SS    = 0;
     Retorno = SSP2BUF;
  }
  return (Retorno);       // byte lido
}


void escreve_SPI( unsigned char byte0,unsigned char byte1 ,int num_byte,int porta_spi)
{//geralmente o primeiro byte tambem é chamado de opcode
   unsigned char TempVar;
   if(porta_spi == 0)
   {//usa a SPI 1
        SPI1_SS = 0;//verifique se o hardware funciona deste modo ou é invertido
        __delay_us(5);
        TempVar = SSP1BUF;        // limpa BF
        SSP1BUF = byte0;           // escreve no buffer
        while ( !SSP1STATbits.BF ); //espera terminar o envio
        if(num_byte == 1)
        {
            TempVar = SSP1BUF;        // limpa BF
            SSP1BUF = byte1;           // escreve no buffer o byte 2
            while (!SSP1STATbits.BF );//espera terminar o envio
        }
        SPI1_SS = 1;
   }
   else
   {//usa a SPI 2
       SPI2_SS    = 0;//verifique se o hardware funciona deste modo ou é invertido
        __delay_us(5);
        TempVar = SSP2BUF;        // limpa BF
        SSP2BUF = byte0;           // escreve no buffer
        while (!SSP2STATbits.BF); //espera terminar o envio
        if(num_byte == 1)
        {
            TempVar = SSP2BUF;        // limpa BF
            SSP2BUF = byte1;           // escreve no buffer
            while (!SSP2STATbits.BF);
        }
        __delay_us(5);
        SPI2_SS = 1;
   }
}
 void inicializa_spi_mestre(int tipo)//inicialica modo mestre - 0-habilita somente spi1 , 1- habilita spi2 e 2- habilita os 2 spi  
{  
     if((tipo == 0)||(tipo == 2))
     {
       // SSP1CON1 = 0X20; //habilita pinos de spi // FOSC/4 //clock em nivel 0
       // SSP1CON1 = 0X21; //habilita pinos de spi // FOSC/16 //clock em nivel 0
        SSP1CON1 = 0X22; //habilita pinos de spi // FOSC/64 //clock em nivel 0
       // SSP1STAT = 0X40; //pega amostras no meio do byte e a trasmissão será na borda de subida
        SSP1STAT = 0X40; //pega amostras no meio do byte e a trasmissão será na borda de descida
        SPI1_SS = 1;//inicia em nivel alto para AD5601/AD5611/AD5621
     }
     if((tipo == 1)||(tipo == 2))
     {
        SSP2CON1 = 0X21; //habilita pinos de spi // FOSC/16 //clock em nivel 0
        SSP2STAT = 0XC0; //pega amostras no fim do byte e a trasmissão será na borda de subida
        SPI2_SS = 0;
     }
}

segunda-feira, 8 de agosto de 2016

Balança óptica com o PIC 12F675.

          Olá, hoje vou apenas lançar uma ideia para que vocês usem em seus projetos ou mesmo para aprender mais sobre como usar sensores ópticos.Este projeto pode ser montado usando receptores como fotodiodo,fototransistor  e LDR(fotoresistor) como sensores de proximidades.O principio de funcionamento é bem simples, se baseia na variação de distancia entre um diodo emissor de luz(pode ser de qualquer espectro de luz que o sensor aceite) e o elemento sensor.
        Um detalhe que influencia no resultado final são as sapatas usadas como elemento sensor(pode ser de borracha, espuma ou qualquer outro elemento que apresente a propriedade mecânica de ser elástico).Neste projeto como eu queria algo mais sensível usei espumas(tipo de colchoes), veja que a variação de unidades lidas vão depender da curva característica das sapatas de apoio e também da capacidade de flambar(sofrer flexão) do material usado como base.
       A opção de usar um fotodiodo é devido a seu maior tempo de resposta embora que o uso de LDR seja uma boa opção devido a sua característica de varia a resistência numa faixa maior do que os fotodiodos, o capacitor de 100nF é para filtrar pequenos ruídos que possam afetar a leitura.O esquemático elétrico é visto a seguir:

         Observe que este projeto é uma aplicação do exemplo apresentado anteriormente aqui no blog("emulando uma porta serial" ), para comunicar com o PC é necessário usar um CI para fazer o "casamento" das tensões(popular MAX232).O software para usar  a porta serial pode ser qualquer aplicativo que "leia" a porta serial de seu pc. As configurações da seria são 9600b/s, 8 bits de dados, sem paridade, 1 bit de stop.Todo o circuito funciona com 5V, veja o vídeo de demonstração:
         
O código fonte:            
            Agora vamos para a parte lógica desta balança veja as linhas de código fonte a seguir:
/*
 *                                    balança óptica          
 *
 * Compilador : MPlabXC8
 * Microcontrolador: 12F675
 * Autor: aguivone
 * Versão: 1
 * Data :  05/08/2016
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>//para trabalhar com string
#include <xc.h>
#define _XTAL_FREQ 20000000  

/////////////////////////////////////////////////////////configuraçôes//////////////////////////////////////////////////
// CONFIG
#pragma config FOSC = HS        ////High speed para o cristal
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF      // Power-Up Timer Enable bit (PWRT disabled)
#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 = OFF        // Data Code Protection bit (Data memory code protection is disabled)

///parametros da porta serial emulada////////////////////////////////////////////////////////////////
#define  TIME_BAUD  97//9600 bps - 20MHZ
#define  BAUD_RX    95//9600 bps - 20MHZ 
/////para simulação do proteus descomentar esta linha e comentar as 2 anteriores
//#define  TIME_BAUD  202//4800 bps - 20MHZ
//#define  BAUD_RX    200//4800 bps - 20MHZ 

#define  TX  GP2//configura o pino que será TX
#define  RX  GP1//configura o pino que será RX
#define  BOTAO  GP3//configura o pino como entrada, botão setar nova referencia 

///variaveis globais usada neste projeto
long tensao=0;
char flag_libera=0;
long tensao_anterior=0;
long variacao=0;
long referencia=0;
bit  flag_sinal=0;

///usado para converter tensão.
int ler_adc_un()
{
        int ultensao;
        PIR1bits.ADIF = 0;//limpa flag
        ADCON0bits.GO = 1; //inicia conversão
        while (PIR1bits.ADIF == 0); //espera finalizar leitura
        ultensao = (ADRESH << 8) | ADRESL;
        return(ultensao);
}

/////////////////////Funçoes utilizadas pela porta serial emulada ///////
void escreve_char(char dados) {
    int contagem = 0;
    TX = 0;
    while (contagem < 8) //envia dados + stop bit
    {
        __delay_us(TIME_BAUD);
        if ((dados & 0X01) == 0X01) //testa bit menos significativo (LSB)
        {
            TX = 1;
        } else {
            TX = 0;
        }
        dados = dados >> 1; //rotaciona bit
        contagem++;
    }
    __delay_us(TIME_BAUD); //tempo do ultimo bit
    TX = 1; //volta pra nivel alto (fim de transmissão de caracter)
    __delay_us(TIME_BAUD); //stop bit
}
//imprime uma cadeia de caracteres
void escreve_frase(char *frase) {
    int tam_frase = strlen(frase);
    int contagem = 0;
    while (contagem < tam_frase)           
    {
        escreve_char(frase[contagem]);
        contagem++;
    }

}

//usado para converter um numero em string 
void long_to_char(int ulQuant)
{
        char cTexto[4]={'0','0','0','0'};
         while(ulQuant>=1000)
            {
             ulQuant=ulQuant-1000;
             cTexto[3]++;
             }
          escreve_char(cTexto[3]);
          while(ulQuant>=100)
            {
             ulQuant=ulQuant-100;
             cTexto[2]++;
             }
          escreve_char(cTexto[2]);
           while(ulQuant>=10)
            {
             ulQuant=ulQuant-10;
             cTexto[1]++;
             }
          escreve_char(cTexto[1]);
           while(ulQuant>=1)
            {
             ulQuant=ulQuant-1;
             cTexto[0]++;
             }
          escreve_char(cTexto[0]);
          escreve_frase(" \r\n");
}
// pega referência para calcular a variação somente na descida do sinal
void pega_ref(void)
{
    referencia = 0;
    for(int val=0;val<5;val++)
    {
      referencia = referencia + ler_adc_un();
      __delay_ms(100);
    }
    referencia = referencia/5;//tira media
    escreve_frase("Referencia:");
    long_to_char(referencia);
    escreve_frase("\r\n");
}
///////////////////////////////////////Rotina principal////////////////////////////////////////////////
void main(void) {
    CMCON = 7;//desabilita comparadores
    ANSEL = 0X31;//usa AN0 como entrada analogica e usa o clock interno do chip(2 a 6 us)
    WPU = 0X00;//desabilita pull ups
    TMR0 = 0;
    ADCON0 = 0X80;//justificado a esquerda , ref ligado ao vdd,usando AN0
    OSCCAL = 0XFF;//configura o oscilador interno para frequencia maxima(4mhz)
    OPTION_REG = 0X81;//pull up desabilitado/preescaler ligado ao timer0(dividido por 4)
    PIR1 = 0X00; //desabilita interrupções não necessaria
    TRISIO = 0X03;//configura gp0 e gp1 como entrada
    INTCON = 0XC0;//desabilita interrupção do timer 0 e habilitainterrupção global e de perifericos
    ADCON0bits.ADON = 1;//liga modulo de conversão
    __delay_ms(100);//debounce e tempo para preparar hardware
    //logo a frequencia de interrupção é 250khz
    escreve_frase("inicializando... \r\n");//a primeira escrita é sempre perdida(ainda não sei o porque)
    escreve_frase("Pesagem optica \r\n");
    //inicializa pegando um valor de referencia
    pega_ref();//pega referencia
    for(;;)
    {  //
        __delay_ms(100);//como tem um intevalo grande tira ruidos pontuais 
            if(BOTAO == 0)
            {
               pega_ref();//pega nova referencia
               __delay_ms(500);//debounce 
            }
            tensao = ler_adc_un();
            if(tensao_anterior >tensao)
            {
                variacao = tensao_anterior - tensao;
                flag_sinal=1;//indica que o sinal está descendo
            }
            else
            {
                variacao = tensao - tensao_anterior; 
                flag_sinal=0;//indica que o sinal está subindo
            }
            if(variacao > 3)//verifica variação se é maior que 3 (filtro)
            {
                if((referencia > tensao)&&(flag_sinal==1))//o valor sempre terá que ser menor que o de referencia(pois o led aproxima mais do sensor))
                {///se for maior pode ser ruidos(no momento de desdetecção) 
                    escreve_frase("Valor lido =");
                    long_to_char(tensao); 
                    escreve_frase("Variacao = ");
                    long_to_char(referencia - tensao);
                }
                 tensao_anterior = tensao;  
            }
    }//loop infinito
}//main


//NOTAS DE PARAMETRIZAÇÃO(sugestão):

//***********************************************************************************************************
//oscilador interno do pic 12F675(testado fisicamente )//////////////////////////////////////////////////////
// configure assim o fuse do oscilador interno => #pragma config FOSC = INTRCIO
// configure assim o fuse do cristal de 4MHZ => #pragma config FOSC = XT
//
//#define  TIME_BAUD  14//19200 bps - 4MHZ - usando cristal 
//#define  TIME_BAUD  16//19200 bps - 4MHZ - usando oscilador interno
//#define  BAUD_RX    12//19200 bps - 4MHZ - osc. interno - recepção não fica confiavel 

//#define  TIME_BAUD  68//9600 bps - 4MHZ - usando oscilador interno
//#define  BAUD_RX    58//9600 bps - 4MHZ - cristal 4MHZ - recepção funcionou bem(houve pouquissimo erros) - no proteus esse valor não funciona
//#define  BAUD_RX    60//9600 bps - 4MHZ - recepção funcionou bem(houve pouquissimo erros)

//#define  TIME_BAUD  175//4800 bps - 4MHZ 
//#define  BAUD_RX    165//4800 bps - 4MHZ - recepção funcionou muito bem(100% confiavel fisicamente, mas no proteus apresenta falhas)


//*************************************************************************************************
// oscilador com cristal de 20MHZ (testado fisicamente funcionou ok)
// configure assim o fuse do cristal => #pragma config FOSC = HS
//#define  TIME_BAUD  45//19200 bps - 20MHZ
//#define  BAUD_RX    42//19200 bps - 20MHZ 

//#define  TIME_BAUD  97//9600 bps - 20MHZ
//#define  BAUD_RX    95//9600 bps - 20MHZ 

//#define  TIME_BAUD  202//4800 bps - 20MHZ
//#define  BAUD_RX    198//4800 bps - 20MHZ 
         
Obrigado a todos que acompanham minhas postagens, e até a próxima pessoal!

segunda-feira, 29 de fevereiro de 2016

PIC 16F648A comunicando via WIFI com ESP8266.

            Olá, a melhor forma de se comunicar hoje com qualquer PC ou smartphone é via wifi ou bluetooth,como já foi abordado aqui no blog o uso do bluetooth vamos hoje "brincar" com a wifi.Antes porém é preciso saber de alguns detalhes, que vou comentar logo a seguir.
           Para comunicar pelo padrão TCP/IP é preciso abrir um "socket'(canal de comunicação) , uma vez aberto o socket é possível comunicar via pagina http ou enviando os dados diretamente a um dispositivo, por este motivo neste exemplo demonstro como fazer as 2 interfaces.Para a comunicação via socket tudo que for enviado ao microcontrolador é devolvido(funcionando exatamente igual a um terminal serial rs-232).Para a comunicação http criei uma pequena página(pois este microcontrolador tem pouca memoria) que permite ligar ou desligar um led, essa pagina é acessada via navegador do google chrome(não funcionou muito bem no firefox e internet(pode ter sido alguma configuração do navegador)),para isso basta digitar o IP+Porta se for usada a porta 80(padrão) não será necessário digitar no buscador a porta.
           Uma configuração de rede que deve ser respeitado é quanto ao DHCP(que pegar um ip automaticamente), no modulo deixei ele desligado para conseguir trabalhar com IP fixo, mas no PC pode até ficar habilitado embora eu recomendo que para a conexão entre pc e placa já deixe o DHCP desligado e coloque um IP diferente do modulo wifi, por exemplo aqui estou usando como gateway do modulo e IP o valor = 192.168.5.1 na porta 5000, então meu pc deve estar no ip 192.168.5.10 por exemplo e configure como gateway o IP 192.168.5.1 deixando a mascara com o valor 255.255.255.0.Se deixar o DHCP de ambos ligado toda vez que você se conectar será gerado um novo ip que talvez vc nem saiba qual será.
           O modulo ESP8266 tem a possibilidade de trabalhar como "Acess point"(AP) ou "station"(estação de trabalho) e ainda como ambos, para este exemplo deixei ele como AP.Um ponto um pouco chato de se configurar este modulo é que as respostas dos comandos devem ser sempre checadas e não se tem a possibilidade de configurar ele todo de uma vez só, ou seja deve ser configurado parâmetro por parâmetro, para isso criei uma maquina de estados (Inicializa_ESP8266), que controla a inicialização do modulo.Dependendo de como for a configuração desejada alguns comandos retornam erros o que complica mais um pouco a situação nossa como programadores de firmware(como eu sofri com esse modulo pois não encontrei material sobre ele para pic somente para arduino).
             Este modulo apesar de ser simples para configurar exige um certo conhecimento de comunicação TCP e arquitetura de redes sem fio, pois isso é fundamental para que se alcance o resultado desejado,pois parâmetros específicos como DHCP,canal de frequência da wifi, protocolo TCP/IP,etc... , com o exemplo aqui é possível ter um caminho de exemplo para que vocês possam prosseguir com seu projetos.Link pra baixar o programa para testar o modulo na ethernet(terminal): https://drive.google.com/file/d/0Bx9JeN0dmzXxaXh5MHI4aF9fT1U/view?usp=sharing ,com este programa você pode acessar dispositivos por meio de protocolo TCP/IP, roda no windows.
             Vamos conhecer a aparência e pinagem do modulo ESP8266 na figura abaixo, juntamente com a pinagem do microcontrolador.


            Fisicamente um  limitante é o hardware que trabalha com tensões diferentes(3,3V e 5V) dai a solução que adotei foi a do esquemático a seguir,o ponto critico é que em altas velocidades da porta serial o microcontrolador deve trabalhar em 5V para não prejudicar a comunicação.A solução consiste de divisor resistivo para casar os valores de tensão.

             Para alimentar o circuito usei os tradicionais LM7805, sendo um ligado ao microcontrolador e outro ligado a um segundo regulador LD1086V33(3,3V) e só então ligado ao modulo wifi.Coloquei 3 leds para indicações de status, conexão(abertura de socket) e falha(usado também para ser acionado pela web).Quando o circuito é alimentado o microcontrolador irá tentar configurar o modulo caso não dê certo pisca os leds verde e amarelo,caso contrário apenas o led verde pisca.
             No firmware o único arquivo adicional é o da comunicação serial "serial_rs232.c", não uso o famoso "print" do código C por consumir mais memoria do que esta funções(pois as que implementei são mais enxuta, o que as vezes gera um pouquinho de trabalho mas o código se torna mais leve).
           
O código fonte:


/*
*
 *                               Comunicando via WIFI com modulo ESP8566
 *
 * Compilador : MPlabXC8
 * Microcontrolador: 16F648A
 * Autor: aguivone
 * Versão: 1
 * Data :  19 de janeiro de 2016
 * Atualizações :  19/02/2016 - melhorando a inicialização
 * Atualizações :  23/02/2016 - melhorando a inicialização
 * Atualizações :  29/02/2016 - finalizado.
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h> //para usar funçoes de string deve se adicionar este header
#define _XTAL_FREQ 20000000    // oscilador interno de 4 Mhz
#include <xc.h>
#include "serial_rs232.c"
/////////////////////////////////////////////////////////configuraçôes//////////////////////////////////////////////////
#define LED_CONEX RB3
#define LED_WEB RB5
#define LED_STATUS RB0
#define TAM_MAX 40 //tamanho maximo do buffer da serial
#define NUM_MAX_TENTATIVA 3 //numero maximo de tentativa em cada comando
#define TEMPO_RX 100 //tempo max entre caracteres recebidos(timeout)
#define FIM_CONF 'x'
#define TIMEOUT_CONF 40//40S//tempo maximo sem resposta de envio


#pragma config FOSC = HS 
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = ON      // Power-up Timer Enable bit (PWRT ligado) para que o microcontrolador inicialize corretamente
#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 enabled)
#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)

  //variaveis de tempo
int  giTempo_us=0;
long glTempo_ms=0;
long glTempo_led=0;
long glTempo_rx=0;
  //variaveis da serial
char gcCaracter=0;
unsigned char gucStatus_serial='N';//N = sem dados,R= recebendo dados , F=fim de recepção
unsigned char gucEstado_de_envio='0';//0 = sem dados,V=dados validados , N=dados não validado
unsigned long gulTam_recebido=0;
unsigned char gucBuffer_serial[TAM_MAX];//só pra testar
  //variaveis da maquina de estado
unsigned char gucStado_do_modulo='A';//inicia em A
unsigned long  gulTempo_de_espera=0;
unsigned long  gulTimeout_de_envio=0;
unsigned int  guiTentativa_envio=0;



//*******************************************************************************/
//===================================================================================
//Função:    _limpa_buffer
//Parâmetro: não tem.
//Retorno:   não tem.
//Descrição: usada para limpar o buffer de recpção.
//===================================================================================
void limpa_buffer()
{
    long tamanho = 0;
    while(tamanho<TAM_MAX)
    {
        gucBuffer_serial[tamanho]=0X00; 
        tamanho++;
    }    
}
//*******************************************************************************/
//===================================================================================
//Função:    _trata_int_conf
//Parâmetro: não tem.
//Retorno:   não tem.
//Descrição: usada para pegar as respostas das configurações.
//===================================================================================

void trata_int_conf()
{
            if(gucStatus_serial == 'R')
            {//primeiro dado
              gucBuffer_serial[gulTam_recebido] = gcCaracter; 
              gulTam_recebido++;
              if(gulTam_recebido>(TAM_MAX-1))
              { 
                  gucStatus_serial = 'N';//sobrescreve o vetor
              }
            }
            if(gucStatus_serial == 'N')
            {//primeiro dado
              gucBuffer_serial[0] = gcCaracter; 
              gulTam_recebido =1;
              gucStatus_serial = 'R';
            } 
}
//*******************************************************************************/
//===================================================================================
//Função:    trata_int_dados
//Parâmetro: não tem.
//Retorno:   não tem.
//Descrição: usada para pegar os dados(após a configuração).
//===================================================================================
void trata_int_dados()
{
     if(gcCaracter == '\n')//caracter de retorno de carro "LR" (depois vejo, talvez verificar se tem o \n))
            {//final da frase
             if((gucBuffer_serial[gulTam_recebido-2]=='D')||(gucBuffer_serial[gulTam_recebido-2]=='T'))
                {//verifica se está abrindo ou fechando o socket(comunicação)                 
                 if((gucBuffer_serial[gulTam_recebido-5]=='N')&&(gucBuffer_serial[gulTam_recebido-4]=='E')&&(gucBuffer_serial[gulTam_recebido-3]=='C'))
                    {//abrindo conexão recebe "CONNECT"
                       LED_CONEX = 1;
                       gulTam_recebido=0;//zera variavel de tamanho
                       gucStatus_serial = 'N';//prepara para pegar novos dados
                    }
                  if((gucBuffer_serial[gulTam_recebido-5]=='O')&&(gucBuffer_serial[gulTam_recebido-4]=='S')&&(gucBuffer_serial[gulTam_recebido-3]=='E'))
                    {//fechando conexão recebe "CLOSED"
                       LED_CONEX = 0;
                       gulTam_recebido=0;//zera variavel de tamanho
                       gucStatus_serial = 'N';//prepara para pegar novos dados
                    }                   
                }
             
            }
            if(gucStatus_serial == 'R')
            {//está recebendo dados
              gucBuffer_serial[gulTam_recebido] = gcCaracter; 
              gulTam_recebido++;
              if(gulTam_recebido>TAM_MAX-2)
              {//gera aviso de estouro pois o buffer de recpção não consegue armazenar o pacote todo.
                  gucStatus_serial = 'E';
              }
            }
            if(gucStatus_serial == 'N')
            {//primeiro caracter capturado 
              gucBuffer_serial[0] = gcCaracter; 
              gulTam_recebido =1;
              gucStatus_serial = 'R';
            } 
}
//*******************************************************************************/
//===================================================================================
//Função:    _interrupcoes
//Parâmetro: não tem.
//Retorno:   não tem.
//Descrição: usada para tratar as interrupções geradas pelo microcontrolador.
//===================================================================================
void interrupt interrupcoes(void)//vetor de interrupção
 {
   if(T0IF)
    {//rotinas de tempo(15us))
        giTempo_us++;
        TMR0 = 254;//reinicia timer com o valor calculado
        T0IF = 0;
        if(giTempo_us>66)//1ms
        {//executa a cada 1ms
            giTempo_us = 0;
            glTempo_ms++;
            if(glTempo_rx > 0)
            {
              glTempo_rx--;
            }
            if(gulTempo_de_espera > 0)
            {
              gulTempo_de_espera--;
            }
            if(glTempo_led>0)
            {
              glTempo_led--;  
            }
            if(glTempo_ms>1000)
            {//executa a cada 1s
               glTempo_ms=0;
               gulTimeout_de_envio++;
            }
        }
        //62.5us + os delay da rotinas  = 75us
    }
   if(RCIF)//verifica interrupção da serial
    {//interrupção da serial
        gcCaracter = RCREG;
        if(gucStado_do_modulo == FIM_CONF+1)
            {//Modulo já foi configurado
               trata_int_dados();
            }
        else
        {
           trata_int_conf();
        }
      glTempo_rx = TEMPO_RX;  
      RCIF =0;//limpa flag de interrupçao
    }
   
}
//===================================================================================
//Função:    _inicializa_CPU
//Parâmetro: não tem.
//Retorno:   não tem.
//Descrição: configura o microcontrolador.
//===================================================================================
void inicializa_CPU()
{
    TRISA = 0XFF;//todas são entradas
    TRISB = 0X02;//configura portB  como saida exceto rb2(pino RX))
    PORTB = 0;  // limpar as portas que estão configuradas como saidas
    CMCON = 0X07;
    ///////////inicializa o timer0 
    OPTION_REG = 0X03;//timer0 com prescaler dividido por 16
    T0IE = 1;//habilita interrupção do timer0
    TMR0 = 254;//zera registrador de contagem
    /////////////////////////////////////////////
    inicializa_RS232_HS(115200,20);//modo de alta velocidade de clock
    //  inicializa_RS232(9600,1,20);//na simulação(pra não sobrecarregar o simulador se necessario))
    PEIE = 1;//habilita interrupção de perifericos do pic
    GIE = 1; //GIE: Global Interrupt Enable bit
    LED_CONEX=0;
    LED_WEB=0;
}
//===================================================================================
//Função:    _Verifica_resposta
//Parâmetro: char prox,char anterior,unsigned char procurar[].
//Retorno:   não tem.
//Descrição: verifica se o comando foi aceito.
//===================================================================================
void Verifica_resposta(char prox,char anterior,unsigned char procurar[])
{    
    if(glTempo_rx == 0)//espera receber o comando
            {
                if(BuscaPalavra(gucBuffer_serial,procurar) != 0XFFFF)
                {  
                  gucStado_do_modulo = prox;//vai para proximo passo
                  guiTentativa_envio = 0;
                }
               else
                {
                  if(guiTentativa_envio >= NUM_MAX_TENTATIVA)
                   {///registra falha na inicialização
                    gulTimeout_de_envio = 250;//Deu erro na configuração
                   } 
                  else
                  {
                   gucStado_do_modulo = anterior;//passo anterior
                  }
                }
            }
}
//*******************************************************************************/
//===================================================================================
//Função:    Envia_comando
//Parâmetro: unsigned char dados[],char mod,int multi_tempo.
//Retorno:   não tem.
//Descrição: usada para enviar comandos.
//===================================================================================
void Envia_comando(unsigned char dados[],char mod)
   {
        PEIE = 0;//desabilita interrupção de perifericos do pic        
        gulTimeout_de_envio=0;
        gucStado_do_modulo = mod;
        limpa_buffer();
        gucStatus_serial = 'N';//põe pra ir pro inicio do vetor
        gulTam_recebido =0;//zera o tamanho
        imprime_RS232(dados);        
        glTempo_rx = TEMPO_RX*3;//seta tempo de recepção de dados um pouco maior para primeira amostra  
        guiTentativa_envio++; 
        PEIE = 1;//habilita interrupção de perifericos do pic   
    }
//===================================================================================
//Função:    _Inicializa_ESP8266
//Parâmetros: não tem.
//Retorno:   não tem.
//Descrição: é uma maquina de estado que configura o modulo ESP8266.
//===================================================================================
//maquina de estado de inicialização do  modulo
void Inicializa_ESP8266(void)
{
    switch(gucStado_do_modulo)
   {
       case 'A'://teste inicial pra saber se o modulo está ativo
       { 
           Envia_comando("AT\r\n",'B');//comando , proximo passo
       }break;
       case 'B'://verifica resposta
       { 
            if(glTempo_rx == 0)//espera receber o comando
            {
                if(BuscaPalavra(gucBuffer_serial,"OK") != 0XFFFF)
                {  
                  gucStado_do_modulo = 'C';//vai para proximo passo
                  guiTentativa_envio = 0;
                }
               else
                {                    
                  gucStado_do_modulo = 'A';//passo anterior
                }
            }
       }break;       
       case 'C':
       { //configura o modo que o modulo vai funcionar, aqui deixei para funcionar como AP
        //   Envia_comando("AT+CWMODE=3\r\n",'D');//comando , proximo passo  - AP ou servidor
          Envia_comando("AT+CWMODE=2\r\n",'D');//comando , proximo passo - AP
        //   Envia_comando("AT+CWMODE=1\r\n",'D');//comando , proximo passo - servidor
       }break;
       case 'D'://verifica resposta
       { 
           Verifica_resposta('E','C',"OK");//colopra onde vai e qual é a palavra procurado
       }break;
       case 'E'://manda resetar o modulo 
       {    
           Envia_comando("AT+RST\r\n",'F');//comando , proximo passo  
       }break;
       case 'F'://verifica resposta
       {
           gulTimeout_de_envio=0;//zera variavel de contagem
           while(gulTimeout_de_envio < 15);//espera pelo menos 10segundos para resetar com segurança
           gulTimeout_de_envio=0;//zera variavel novamente
           Verifica_resposta('G','E',"ready");
       }break;
       case 'G':
       { //configura o modo que o modulo vai funcionar, aqui deixei para funcionar como AP
           Envia_comando("ATE0\r\n",'H');//pede pra não repetir o comando
       }break;
       case 'H'://verifica resposta
       { 
           Verifica_resposta('I','G',"OK");//colopra onde vai e qual é a palavra procurado
       }break;       
       case 'I':
       { 
           Envia_comando("AT+CIPMUX=1\r\n",'J');//comando , proximo passo//cofigura para conexões multiplas
         //  Envia_comando("AT+CIPMUX=0\r\n",'J');//comando , proximo passo//cofigura para conexao simples
       }break;
       case 'J'://verifica resposta
       { 
           Verifica_resposta('L','I',"OK");
       }break;       
       case 'L'://configura DHCP e modo de operação
       { //quando DHCP é ligado ele busca ip automaticamente
       //   Envia_comando("AT+CWDHCP=2,1\r\n",'M');//só aceitou o modo AP+STATION/dhcp ligado.(pega ip automatico))
       //  Envia_comando("AT+CWDHCP=2,0\r\n",'M');//AP+STATION/dhcp desligado.(para usar ip fixo))
             Envia_comando("AT+CWDHCP=0,0\r\n",'M');//modo AP(o sinal fica mais estavel)/DHCP desligado(para usar ip fixo) 
       }break;       
       case 'M'://verifica resposta
       { 
           Verifica_resposta('N','L',"OK");
       }break;       
       case 'N'://Nome do ponto de wifi,senha,canal(deixei o canal de freq.7)),tipo de segurança(0 = aberta))
       { //
          Envia_comando("AT+CWSAP=\"MICROCONTROLARES-C\",\"senha\",7,0\r\n",'O');
       }break;  
       case 'O'://verifica resposta
       { 
           Verifica_resposta('P','N',"OK");
       }break;
       case 'P':
       { //configura para criar servidor na porta 5000
           Envia_comando("AT+CIPSERVER=1,5000\r\n ",'Q'); 
        }break;
       case 'Q'://verifica resposta
       {             
           Verifica_resposta('R','P',"OK");
       }break;              
       case 'R':
       { //configura para criar servidor na porta 5000
           Envia_comando("AT+CIPAP=\"192.168.5.1\" \r\n",'S');//usa este IP para gateway e para o servidor 
        }break;
       case 'S'://verifica resposta
       {             
           Verifica_resposta('T','R',"OK");
       }break;       
       case 'T':
       { //seta time out
           Envia_comando("AT+CIPSTO=100\r\n",'U');//comando , proximo passo  
        }break;
       case 'U'://verifica resposta
       {             
                gucStado_do_modulo = FIM_CONF;//não precisa de confimação
       }break;
     
           
       
    } 
}
//===================================================================================
//Função:    _envia_pacote
//Parâmetros: long *tamanho,char *pacote[].
//Retorno:   não tem.
//Descrição: usado para o modo socket(sem usar uma pagina web, envia um pacote TCP).
//===================================================================================
void envia_pacote(long *tamanho,char *pacote[])
{
   char valor[]="0000";
   int pos = LongToChar(tamanho,valor);
   imprime_RS232("AT+CIPSEND=0,");//para conexão multipla informa o canal 
  // imprime_RS232("AT+CIPSEND=");//na conexoes simples não precisa informar o canal
        while(pos<4)
        {
            escreve_RS232(valor[pos]);  
            pos++;  
        }
   escreve_RS232(0X0D);
   escreve_RS232(0X0A);
    glTempo_rx = TEMPO_RX/2;
    while(glTempo_rx > 0);//espera receber a resposta do comando 
    pos=0;// 
        while(pacote[pos] != 0X00 )//envia os dados recebidos novamente
            { //imprime na porta TCP os dados recebidos(o tamanho max aqui será uns 30 caracteres))
               escreve_RS232(pacote[pos]);
               pos++;
            } 
    escreve_RS232(0X0D);
    escreve_RS232(0X0A);
}
//===================================================================================
//Função:    _envia_pagina
//Parâmetros: não tem.
//Retorno:   não tem.
//Descrição: Monta e envia a pagina HTML.
//===================================================================================
void envia_pagina()
{//lembre que \" = " logo conta como 1 caracter e não 2
   limpa_buffer();//solicita pra limpar o buffer serial 
   ///como vou conectar apenas 1 então o canal é 0 
   imprime_RS232("AT+CIPSEND=0,285");//para conexão multipla informa o canal (prepara envio e tamanho))
  // imprime_RS232("AT+CIPSEND=");//na conexoes simples não precisa informar o canal
    escreve_RS232(0X0D);
    escreve_RS232(0X0A);
    glTempo_rx = TEMPO_RX;
    while(glTempo_rx > 0);//espera receber a resposta do comando 
    imprime_RS232("<html><head><title>Teste</title></head><h1>PROGRAMA DE TESTE</h1>");
    imprime_RS232("<body><p><form method=\"GET\"></p>");
    imprime_RS232("<p><input type=\"radio\" name=\"Bot\" value=\"1\" CHECKED> Ligar led.</p>");
    imprime_RS232("<p><input type=\"radio\" name=\"Bot\" value=\"0\" > Desligar led.</p>");
    imprime_RS232("<p><input type=\"submit\"  value=\"Enviar\"></p></body></html>");
    escreve_RS232(0X0D);
    escreve_RS232(0X0A);
}
//////////////////////////////////////////////////////Rotina principal///////////////////////////////////////////////////////////////
//===================================================================================
//Função:    _main
//Parâmetros: não tem.
//Retorno:   não tem.
//Descrição: função principal.
//===================================================================================
///////////////http://microcontroladores-c.blogspot.com.br//////////////////////////////////////////
void main(void) 
{
    inicializa_CPU();
     for(;;)
    {        
        if(glTempo_led == 0)
        {//led de status            
            LED_STATUS = ~LED_STATUS;
            if(gucStado_do_modulo == FIM_CONF+1)
            {//Modulo pronto pra funcionar
              glTempo_led = 100;//tempo mais rapido  
            }
            else
            {
               glTempo_led = 500;//tempo normal 
               if(gulTimeout_de_envio>TIMEOUT_CONF)//se for maior que 30S o tempo de espera então indica falha
                {
                   LED_WEB = ~LED_WEB; //modulo não responde - falha
                }
            }
        }
        if(gucStado_do_modulo == FIM_CONF+1)
            {//Modulo pronto pra funcionar
                if((glTempo_rx == 0)&&(gulTam_recebido<8))//tamanho minimo em cada recpção de dados
                 {//descarta
                     gulTam_recebido=0;//zera variavel de tamanho
                       gucStatus_serial = 'N';//prepara para pegar novos dados
                 }
                if(gucStatus_serial == 'E')//espera terminar tempo de time out
                {//houve estouro do buffer logo a comunicação é via pagina HTTP 
                    if(BuscaPalavra(gucBuffer_serial,"GET") != 0XFFFF)//conexão por modo get
                        {//pagina web solicitada ou resposta recebida
                             if(BuscaPalavra(gucBuffer_serial,"GET / HTTP") != 0XFFFF)//solicitou pagina web
                                 envia_pagina();
                            if(BuscaPalavra(gucBuffer_serial,"GET /?Bot") != 0XFFFF)//resposta da pagina web 
                               {
                                  if(BuscaPalavra(gucBuffer_serial,"Bot=0") != 0XFFFF)//vê se é pra desligar led
                                    LED_WEB=0;
                                  if(BuscaPalavra(gucBuffer_serial,"Bot=1") != 0XFFFF)//vê se é pra desligar led
                                    LED_WEB=1;
                               }                                                                                      
                        }                    
                       gulTam_recebido=0;//zera variavel de tamanho
                       gucStatus_serial = 'N';//prepara para pegar novos dados 
                   
                }
                else
                {//é comunicação via socket
                    if((glTempo_rx == 0)&&(gulTam_recebido>8))//tamanho minimo
                    {//verifica se tem dados pra ler pois o tempo limite pra finalizar recpção já passou
                          if(BuscaPalavra(gucBuffer_serial,"+IPD") != 0XFFFF)
                           {//chegou dados validado
                               long auxiliar = BuscaPalavra(gucBuffer_serial,":");
                               long tamanho ;//tamanho dos dados
                               long pos_buffer=0;//tamanho dos dados
                               unsigned char gucBuffer_tratamento[TAM_MAX];
                               if(auxiliar != 0XFFFF)
                               {//pega o tamanho dos dados
                                   if(CharToInt(gucBuffer_serial[auxiliar-2])<10)
                                        {// o tamanho dos dados é maior que 10
                                             tamanho = (10*CharToInt(gucBuffer_serial[auxiliar-2]))+CharToInt(gucBuffer_serial[auxiliar-1]);
                                            if(CharToInt(gucBuffer_serial[auxiliar-3])<10)
                                             {
                                              tamanho = (100*CharToInt(gucBuffer_serial[auxiliar-3]))+tamanho; 
                                             }                                             
                                        }
                                        else
                                        {//o tamanho é menor que 10
                                          tamanho = CharToInt(gucBuffer_serial[auxiliar-1]);
                                        } 
                                       auxiliar++;//pra não pegar o ":"
                                       while( pos_buffer < tamanho )
                                       { //copia os dados para o vetor de tratamento
                                           gucBuffer_tratamento[pos_buffer] = gucBuffer_serial[auxiliar+pos_buffer];
                                           pos_buffer++;
                                       } 
                                       gucBuffer_tratamento[pos_buffer]=0X00;//caracter null 
                               }
                               //limpa_buffer();//solicita pra limpar o buffer serial   
                               envia_pacote(tamanho,gucBuffer_tratamento);
                           }                           
                          gulTam_recebido=0;//zera variavel de tamanho
                          gucStatus_serial = 'N';//prepara para pegar novos dados
                    }                 
                }        
            }
        else
        {//durante inicialização
            if(gucStado_do_modulo < FIM_CONF)
            {//inicializa o modulo
               if(gulTimeout_de_envio<TIMEOUT_CONF)//se for menor que 30S o tempo de espera terminar configuração           
                {
                    Inicializa_ESP8266();
                }
            }
            if(gucStado_do_modulo == FIM_CONF)
            {
             ///neste momento a WIFI já esta configurada e pronta pra receber dados   
              gucStado_do_modulo = FIM_CONF+1;
            }    
        }        
    }//loop infinito

}

O código do arquivo serial:

/*
 *                          FUNÇOES USADAS NA SERIAL 
 *
 * Compilador :      MPlabXC8
 * Microcontrolador: 16F877A
 * Autor:            Aguivone
 * Versão:           1.0.1
 * Descrição:   ->Assim como o printf tem a função de comunicar via rs232, mas com o diferencial de ter um menor processamento e gasto de memoria
 *              ->Mas exige um pouco mais de trabalho para imprimir caracteres numericos 
 * Data de criação:  08/09/2014.
 * Data de atualização : 29/01/2016 - melhorando o baud rate para altas velocidades
 */

#include <xc.h>
#include <string.h> //para usar funçoes de string deve se adicionar este header

//===================================================================================
//Função:    _inicializa_RS232
//Parâmetros: unsigned long ulVelocidade
//          : unsigned int uiModo
//Retorno:   não tem retorno.
//Descrição: usada para iniciar a porta serial com velocidades até 38400.
//===================================================================================
void inicializa_RS232(float fVelocidade,unsigned int uiModo,float fClock)
{//// 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.
    float valor;
        if(uiModo == 1)
        {//modo = 1 ,modo alta velocidade
         TXSTA = 0X24;//modo assincrono,trasmissao 8 bits.
        // valor =(((_XTAL_FREQ/ulVelocidade)-16)/16);//calculo do valor do gerador de baud rate
         valor =(((fClock/fVelocidade)-16)/16);//calculo do valor do gerador de baud rate
        }
        else
        {//modo = 0 ,modo baixa velocidade
         TXSTA = 0X20;//modo assincrono,trasmissao 8 bits.
         //valor =(((_XTAL_FREQ/ulVelocidade)-64)/64);//calculo do valor do gerador de baud rate
         valor =(((fClock/fVelocidade)-64)/64);//calculo do valor do gerador de baud rate
        }
    SPBRG =(int)valor;
   // PIE1 = 0X20;
    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)
}
//===================================================================================
//Função:    _inicializa_RS232_HS
//Parâmetros: unsigned long ulVelocidade
//          : unsigned int uiModo
//Retorno:   não tem retorno.
//Descrição: usada para iniciar a porta serial com velocidades acima 38400.
//===================================================================================
void inicializa_RS232_HS(float fVelocidade,int iClock)//o clock em mhz
{//// 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.
    TXSTA = 0X24;//modo assincrono,trasmissao 8 bits.modo = 1 ,modo alta velocidade
    switch(iClock)//cadastrei somente os cristais mais usados
   {
       case 4:
       { 
           if(fVelocidade > 57600)
           {//é 115200
             SPBRG =1;  
           }
           else
           {//é 57600
            SPBRG =3;   
           }
       }break;
       case 10:
       { 
           if(fVelocidade > 57600)
           {//é 115200
             SPBRG =4;  
           }
           else
           {//é 57600
            SPBRG =10;   
           }
       }break;
       case 16:
       { 
           if(fVelocidade > 57600)
           {//é 115200 ou 250000
               if(fVelocidade == 115200)
               {//é 115200
                 SPBRG =8; 
               }
               else
               {//é 250000
                 SPBRG =3;  
               }
           }
           else
           {//é 57600
            SPBRG =16;   
           }
       }break;
       case 20:
       { 
           if(fVelocidade > 57600)
           {//é 115200,250000,625000 ou 1250000(1,25Mbs))
               if(fVelocidade == 115200)
               {//é 115200
                 SPBRG =10; 
               }
               if(fVelocidade == 250000)
               {
                 SPBRG =4; 
               }
               if(fVelocidade == 625000)
               {
                 SPBRG =1; 
               }
               if(fVelocidade == 1250000)
               {
                 SPBRG =0; 
               }  
           }
           else
           {//é 57600
            SPBRG =21;   
           }
       }break;
    }
   // PIE1 = 0X20;
    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)
}
//===================================================================================
//Função:    _escreve_RS232
//Parâmetros: char cValor
//Retorno:   não tem retorno.
//Descrição: usada para escrever 1 caracter.
//===================================================================================
 void escreve_RS232(char cValor)
{
    TXIF = 0;//limpa flag que sinaliza envio completo.
    TXREG = cValor;
    while(TXIF ==0);//espera enviar caracter
}
//===================================================================================
//Função:    _imprime_RS232
//Parâmetros: const char ccFrase[]
//Retorno:   não tem retorno.
//Descrição: usada para escrever uma string.(maximo 255 caracteres)
//===================================================================================
 void imprime_RS232(const char *ccFrase[])
{
     unsigned char indice = 0;
     unsigned char tamanho = strlen(ccFrase);
      while(indice < tamanho ) ///veja que o programa pode travar se aqui não tiver as duas aspas
       {
          escreve_RS232(ccFrase[indice]);
           indice++;
       }
}
//===================================================================================
//Função:    _imprime_vetor_RS232
//Parâmetros: const char ccFrase[]
//Retorno:   não tem retorno.
//Descrição: usada para escrever uma vetor de caracteres.(maximo 255 caracteres))
//===================================================================================
 void imprime_vetor_RS232(unsigned char *ccFrase[])
{
     unsigned char indice = 0;
     unsigned char tamanho = strlen(ccFrase);
      while(indice < tamanho ) 
       {
           escreve_RS232(ccFrase[indice]);
           indice++;
       }
}
 //===================================================================================
//Função:    _BuscaPalavra
//Parâmetros: long ulQuant
//Retorno:   se = 0 não tem palavra igual, senão retorna a posição+1.
//Descrição: buscar uma palavra em um vetor de caracteres(máximo 65535 caracteres) e retorna primeira posição)
//===================================================================================
// As funçoes "strstr()" e "strspn()" não funcionaram bem por isto resolvi montar esta função
 //fica mais rapida
int BuscaPalavra(unsigned char *ccFrase[],unsigned char *palavra[])
{
     unsigned int indice = 0;
     unsigned int tamanho_palavra = strlen(palavra);
     unsigned int tamanho_vetor = strlen(ccFrase) - tamanho_palavra;//tamanho do vetor subtraido do tamanho da palavra
      while(indice <= tamanho_vetor) //tamanho do vetor subtraido do tamanho da palavra
       {
          if(palavra[0]==ccFrase[indice])
          {//se for parecido com a primeira letra da palavra então testa se é a palavra certa
              unsigned int tamanho_comparado=1;//inicia comparando próxima letra
              while(tamanho_comparado < tamanho_palavra) 
                 {
                      if(palavra[tamanho_comparado]!=ccFrase[indice+tamanho_comparado])
                       {
                         tamanho_comparado=tamanho_palavra+1;
                         indice = indice + tamanho_comparado;//já pula pra frente pois foi testado)
                       }
                    tamanho_comparado++;                      
                 }
              if(tamanho_comparado<tamanho_palavra+1)
              {
                return(indice); //retorna a posição da primeira ocorrencia da palavra 
              }
                 
          }
           indice++;
       }
     return(0XFFFF);//indica que não achou palavra igual
} 
 //===================================================================================
//Função:    _LongToChar
//Parâmetros: long ulQuant
//Retorno:   não tem retorno.
//Descrição: usada para escrever um numero(int ou long) pela serial
//===================================================================================
int LongToChar(long ulQuant,char *valor[])
{ 
    int ret=3;//indica apartir de quando pegar os dados para não imprimir 0 antes do numero
    if(ulQuant>=1000)//mas se quiser imprimir o zero basta usar o vetor inteiro
    {ret=0;}
    else
    {if(ulQuant>=100)
            {ret=1;}
            else
            {if(ulQuant>=10)
                {ret=2;}
            }
    }
            while(ulQuant>=1000)
            {
             ulQuant=ulQuant-1000;
             valor[0]++;
             }
            while(ulQuant>=100)
            {
             ulQuant=ulQuant-100;
             valor[1]++;
             }
             while(ulQuant>=10)
            {
             ulQuant=ulQuant-10;
             valor[2]++;
             }
            while(ulQuant>=1)
            {
             ulQuant=ulQuant-1;
             valor[3]++;
             }
    return(ret);
}
//===================================================================================
//Função:    _CharToInt
//Parâmetros: unsigned char convert_char
//Retorno:   retorna um numero.
//Descrição: usada para conveter um caracter em um numero
//===================================================================================
int CharToInt(unsigned char convert_char)
{
     switch(convert_char)
     {
         case '0':
         return(0);
         case '1':
         return(1);
         case '2':
         return(2);
         case '3':
         return(3);
         case '4':
         return(4);
         case '5':
         return(5);
         case '6':
         return(6);
         case '7':
         return(7);
         case '8':
         return(8);
         case '9':
         return(9);
         default:
             return(10);
     }
}

Depois de tanto trabalho o resultado pode ser visto no vídeo abaixo, a página http pode ser acessado por um smartphone também(testei com um samsung com android).

O vídeo de demonstração:



Até a próxima!