terça-feira, 5 de março de 2013

Acessando a eeprom - Mplab XC8

 
Neste exemplo é demonstardo como escrever e ler na eeprom do pic16F877A,depois de lido os dados e então enviado a porta serial do pic: 
        

O código fonte:
 
 
/*
 *                                              voltimetro usando RS-232 no MPlab XC8
 *
 * Compilador : MPlabXC8
 * Microcontrolador: 16F877A
 * Autor: aguivone
 * Versão: 1
 * Data :  04 de março 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 20000000    // cristal de 20 Mhz
#include <xc.h>

/////////////////////////////////////////////////////////configuraçôes//////////////////////////////////////////////////

#pragma config FOSC = HS        // Oscillator Selection bits (HS oscillator)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF      // Power-up Timer Enable bit (PWRT disabled)
#pragma config BOREN = OFF      // Brown-out Reset Enable bit (BOR disabled)
#pragma config LVP = OFF        // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3 is digital I/O, HV on MCLR must be used for programming)
#pragma config CPD = OFF        // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off)
#pragma config WRT = OFF        // Flash Program Memory Write Enable bits (Write protection off; all program memory may be written to by EECON control)
#pragma config CP = OFF         // Flash Program Memory Code Protection bit (Code protection off)


////////////////////////////////////////////////variaveis globais///////////////////////////////////////////////////////////
char caracter,dados;
bit flag_interrupcao = 0;
///////////////////////////////////////////////////interrupção//////////////////////////////////////////////////////////////
void interrupt interrupcoes(void)//vetor de interrupção
 {
    if(RCIF)
    {//se interrupção de recepção da serial
        //aqui não será usado essa funcã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_RS232(char valor)
{
    TXIF = 0;//limpa flag que sinaliza envio completo.
    TXREG = valor;
    while(TXIF ==0);//espera enviar caracter
}
void imprime_RS232(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_RS232(frase[indice]);
           indice++;
       }
}

char ler_memoria(char ende)
{
    RP0 = 1; RP1 = 0;//acessa banco de memoria 2,para acessar o registrador EEADR
    EEADR = ende;//endereço 1 , verifique qual o endereço maximo de seu microcontrolador
    RP0 = 1; RP1 = 1;//acessa banco de memoria 3,para acessar o registrador EECON1
    EEPGD = 0;//ponteiro da memoria de dados
    RD = 1;//inicia leitura
    RP0 = 1; RP1 = 0;//retorna ao banco para ler os dados
   return(EEDATA);
}
void escreve_memoria(char endereco,char dados)
{
     char interrupcao;
     if(GIE == 1)//pega o estado da interrupção
     { interrupcao = 1; }
     RP0 = 1; RP1 = 1;//acessa banco de memoria 3,para acessar o registrador EECON1
     while(WR == 1);//checa se está havendo escrita ,espera terminar algum processo de escrita se existir
     RP0 = 1; RP1 = 0;//acessa banco de memoria 2,para acessar o registrador EEADR
     EEDATA = dados; //escreve dados(é um bug do compilador mas os dados devem ser escritos antes do endereço)
     EEADR = endereco;//endereço 1 , verifique qual o endereço maximo de seu microcontrolador
     RP0 = 1; RP1 = 1;//acessa banco de memoria 3,para acessar o registrador EECON1
     EEPGD = 0;
     WREN = 1;//habilita escrita
     GIE = 0;//desabilita as interrupções
     EECON2 = 0X55;//ação requerida conforme datasheet
     EECON2 = 0XAA;//é um codigo de segurança
     WR = 1;//inicia escrita na memoria
     if(interrupcao == 1)
     { GIE = 1;}
     WREN = 0;//disabilita escrita
}
//////////////////////////////////////////////////////Rotina principal///////////////////////////////////////////////////////////////

void main(void)
{
    TRISB = 0X02;//configura portB  B1 (pino RX) como entrada
    PORTB = 0;  // limpar as portas que estão configuradas como saidas
    inicializa_RS232(9600,1);//modo de alta velocidade
    PEIE = 1;//habilita interrupção de perifericos do pic
    GIE = 1; //GIE: Global Interrupt Enable bit
    imprime_RS232("acessando a eeprom \n\r");
    escreve_memoria(0X01,'T');//escreve dados
    escreve_memoria(0X02,'E');
    escreve_memoria(0X03,'S');
    escreve_memoria(0X04,'T');
    escreve_memoria(0X05,'E');
     imprime_RS232("Dados da memoria : \n\r");
     escreve_RS232(ler_memoria(0X01)) ;//ler os dados do endereço
     escreve_RS232( ler_memoria(0X02)) ;//da eeprom
     escreve_RS232( ler_memoria(0X03)) ;
     escreve_RS232( ler_memoria(0X04)) ;
     escreve_RS232(ler_memoria(0X05)) ;
    for(;;)
    {
   
    }//loop infinito

}
 

4 comentários :

  1. Olá
    Me ajudou muito em um projeto, era só isto que me faltava.
    Parabéns pelo blog muito bom mesmo.

    ResponderExcluir
  2. Ola
    Primeiramente parabéns pelo blog, comecei a trabalhar com o xC8 e estou usando seus exemplos como base.
    Quanto ao exemplo acima, acredito que as linhas que seta o BANK2 estão invertidas. Não seria RP0 = 0 e RP1 = 1.
    Estou com um projeto montado e usando o 16F873 e fui obrigado a inverter agora esta 100%.
    Novamente parabéns pelo blog e obrigado por compartilhar.
    Abraço.

    ResponderExcluir
  3. onde esta o rp0 e rp1 no data sheet?

    Obrigado

    ResponderExcluir
  4. como fazer para escrever valor int por exemplo? Já Q cada local da memoria só comporta 8 bits

    ResponderExcluir

olá,digite aqui seu comentário!