Autor Tema: Ejemplito 16F876A: La EEPROM interna puesta a nuestro servicio.  (Leído 4688 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado RedPic

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 5544
    • Picmania by Redraven
Ejemplito 16F876A: La EEPROM interna puesta a nuestro servicio.
« en: 04 de Marzo de 2006, 14:11:00 »
Continuando en mi línea de manejar el PIC desde el PC, vía RS232, he desarrollado
todo un sistema monitor, al estilo de los anteriores Ejemplitos 16F876 y sobre todo
usando lo que hemos estudiado en Ejemplitos C: Mis Funciones favoritas en CCS C

Igual que en los citados ejemplos anteriores hago uso del receptor RS232 sobre
un buffer y su tratamiento posterior ( Ver Ejemplito Nº 6: Recibiendo ... ) pero
en este caso vamos a implementar los comandos:

eedump, eeread, eewrite y eefill

que nos van a permitir volcar todo el contenido de la EEPROM en el hiperterminal,
leer una posición determinada, escribir sobre ella o rellenar con un valor dado
toda la EEPROM disponible.

En el fondo, con respecto a la EEPROM, solo vamos a utilizar realmente dos
funciones CCS específicas: read_eeprom(dir) y write_eeprom(dir, byte). Todo
lo demas lo compone nuestro programa receptor de comandos y ejecutor de
los mismos.

El programa entonces habla con nosotros así:



Codigo:


#include <16f876a.h>
#fuses   XT,NOWDT,NOPROTECT,NOLVP,PUT,BROWNOUT
#use     delay(clock=4000000)
#use     standard_io(b)
#use     rs232(baud=19200, xmit=PIN_C6, rcv=PIN_C7)

#include <stdlib.h>

// Constantes y definiciones ////////////////////////////////////////////////////////////

int const MAXLENBUFF=24;                         // Maxima longitud de los bufferes
int const MAXLENCOMMAND=12;                      // Maxima longitud de un comando (sin argumentos)
int const NUMPAGSEEPROM=7;                       // Numero de paginas (de 16 bytes) de la EEPROM interna

// Variables Globales ///////////////////////////////////////////////////////////////////

char buffrec[MAXLENBUFF];                        // Buffer de Recepcion
int  xbuffrec=0x00;                              // índice del Buffer de Recepcion
int1 new_command=0;                              // Flag para indicar comando disponible
int1 pdte_send_prompt=0;                         // Flags para enviar echo fuera de la int_rda
int1 pdte_send_tmp_prompt=0;
char xcommand[MAXLENCOMMAND];                    // Comprobador de comando recibido

// Declaracion de Funciones /////////////////////////////////////////////////////////////

void On_reset(void);                             // Tras RESET del Micro
void Send_listen(void);                          // Monitoriza RS232 : Comienzo
void Send_opts(void);                            // Monitoriza RS232 : Presenta opciones
void Send_prompt(void);                          // Monitoriza RS232 : Presenta el Cursor
void Send_tmp_prompt(void);                      // Monitoriza RS232 : Presenta el Cursor y el comando actual
void Ini_buffrec(void);                          // Borra el buffer de recepción
void Add_buffrec(char c);                        // Añade un caracter al buffer de recepción
int  Extrae_arg_hex(char tipo, int lenarg);      // Extrae del comando el valor hex tras -tipo
int  aschex2int(char d);                         // Convierte un caracter ascii a hex
void Procesa_comando(void);                      // Procesado de comandos
void Vuelca_EEPROM(void);                        // Vuelca el contenido de la EEPROM
void Rellena_EEPROM(int x);                      // Rellena toda la EEPROM con x
void Write_port(int port, int valor);            // Pone a valor el estado del puerto port


// INTERRUPCIONES ///////////////////////////////////////////////////////////////////////

// INTERRUPCION RDA - Recepción USART -

#int_rda
void serial_isr() {
   if(kbhit()){                                  // Si hay algo pendiente de recibir ...
      Add_buffrec(getc());                       // lo recibo y lo añado al Buffer de Recepcion
   }
}

// Control del Buffer de recepcion ---------------------------------------

void Ini_buff_rec(void){                         // Inicia a "" el Buffer de Recepcion

   int i;
   for(i=0;i<MAXLENBUFF;i++){                    // Bucle que pone a 0 todos los
      buffrec[ i ]=0x00;                         // caracteres en el Buffer de Recepcion
   }
   xbuffrec=0x00;                                // Inicializo el indice de siguiente caracter recibido
}

void Add_buffrec(char c){                        // Añade caracter al Buffer de Recepcion

      switch(c){
         case 0x0D:                              // [Enter] -> Habilita Flag para procesar comando en Main
            new_command=1;
            break;
         case 0x08:                              // [Del]   -> Borra último caracter del Buffer
            if(xbuffrec>0){                      //            Si hay algo en el buffer
               buffrec[--xbuffrec]=0x00;         //            decremento el índice, escribo un cero y ...
               pdte_send_tmp_prompt=1;           //            habilito flag para refrescar el prompt
            }
            break;
         case 0x01B:                             // [Esc]   -> Borra el Buffer completamente y ...
            Ini_buff_rec();                      //            habilito flag para refrescar el prompt
            pdte_send_prompt=1;
            break;
         case 0x009:                             // [Tab]   -> Refresca el prompt y el comando tal como esté
            pdte_send_tmp_prompt=1;
            break;
         default:
            buffrec[xbuffrec++]=c;               // Añade caracter recibido al Buffer
            putc(c);                             // y lo monitorizo
      }
}

// Rutinas y Funciones de RROS ///////////////////////////////////////////

void On_reset(void){                             // Inicializacion del Micro tras RESET

   disable_interrupts(GLOBAL);                   // todas las interrupciones desactivadas

   delay_ms(100);

   Ini_buff_rec();                               // Inicializo Buffer de recepcion
   new_command=0;                                // Desactivo flag de comando pendiente.
   pdte_send_prompt=0;                           // Desactivo Flags para enviar echo fuera de la int_rda
   pdte_send_tmp_prompt=0;

   enable_interrupts(int_rda);                   // interrupcion RDA habilitada
   enable_interrupts(global);                      // todas las interrupciones activadas

   Send_listen();                                // Presenta Comienzo
   Send_prompt();                                // Presenta el Cursor

}

void Send_listen(void){                          // Presenta Comienzo

   printf("EEPROM.PIC.OS v2.0

" );
   printf("? for valid commands
" );
}

void Send_opts(void){                            // Relación de comandos válidos

   printf("

" );
   Send_listen();
   printf("
" );
   printf("[?] comandos válidos
" );
   printf("[eedump] contenido de eeprom
" );
   printf("[eeread -dDD] lee byte en dir DDh
" );
   printf("[eewrite -dDD -bBB] escribe byte BBh en dir DDh
" );
   printf("[eefill -bBB] eeprom a BBh
" );
}

void Send_prompt(void){                          // Presenta el cursor

   printf("
>" );
}

void Send_tmp_prompt(void){                      // Presenta el cursor con el comando actual

   printf(">%s",buffrec);
}

int Extrae_arg_hex(char tipo, int lenarg){       // Extrae del comando el valor hex tras -tipo

   char cc[3], *ptr, Hex[3]="";                // Variables necesarias para extraer direccion de buffrec
   int  r=0;


   strcpy(cc,"-X" );                              // Compongo identificador de argumento para extraerlo
   cc[ 1 ]=tipo;

   ptr=strstr(buffrec,cc);                       // Obtengo puntero de donde comienza "-X" dentro de buffrec
   if(!ptr==0){                                  // Si realmente existe "-X" dentro de buffrec ...
      ptr+=2;                                    // avanzo el puntero 2 posiciones para saltarme "-X" y ...
      strncpy(Hex,ptr,lenarg);                   // copio el trozo siguiente a Hex ...
      Hex[lenarg]="";                          // y lo finalizo con "" para obterner Hex="DD".
      if(lenarg>1){
         r =(16*aschex2int(Hex[0]));             // Convierto de Hex Ascii 1 ó 2 digitos
         r+=(aschex2int(Hex[1]));
      }
      else{
         r=(aschex2int(Hex[0]));
      }
   }
   return(r);
}

int aschex2int(char d){                          // Convierte un caracter ascii a hex

   int r=0;

   if(isxdigit(d)){                              // Si es un digito hexadecimal ...
      if(isdigit(d)){                            // si es un digito decimal ...
         r=d-"0";                                // devuelvo su diferencia con el valor ascii del caracter "0"
      }
      if(isalpha(d)){                            // si es alfanumerico ...
         d=toupper(d);                           // lo paso a mayusculas y ...
         r=10+(d-"A");                           // devuelvo 10 mas su diferencia con el valor ascii de la letra "A"
      }
   }
   return(r);
}

// MAIN Programa Principal ///////////////////////////////////////////////

void main(void)
{
   On_reset();

   do {

      // Deteccion de la necesidad de procesar comandos pendientes ///////
      if(new_command==1){                        // Si hay un nuevo comando ...
         new_command=0;                          // deshabilito el aviso y ...
         Procesa_comando();                      // Procesado de comandos
         Ini_buff_rec();                         // inicializo todo para nuevo comando y ...
         pdte_send_prompt=1;                     // mando prompt.
      }

      // Deteccion de la necesidad de enviar echos ///////////////////////
      if(pdte_send_prompt==1){
         pdte_send_prompt=0;
         Send_prompt();
      }
      if(pdte_send_tmp_prompt==1){
         pdte_send_tmp_prompt=0;
         Send_tmp_prompt();
      }

   } while(TRUE);
}

// Funciones de Comando //////////////////////////////////////////////////

void Vuelca_EEPROM(void){                        // Vuelca el contenido de la EEPROM

   int i,j;

   printf("

** " );                          // Pongo cabecera de direcciones
   for(i=0;i<16;i++) printf("%X ",i );
   printf("
" );
   for(i=0; i<=NUMPAGSEEPROM; ++i) {             // Vuelco contenido paginado
      printf("%2x ",i*16 );
      for(j=0; j<=15; ++j) {
         printf( "%2x ", read_eeprom( i*16+j )  );
      }
      printf("
" );
   }
}

void Rellena_EEPROM(int x){                      // Rellena toda la EEPROM con x

   int i,j;

   for(i=0; i<=NUMPAGSEEPROM; ++i) {             // Escribo toda la eeprom
      for(j=0; j<=15; ++j) {
         write_eeprom(i*16+j,x);
      }
   }
}

// Procesa_comando: Hace cosas o manda hacerlas ... //////////////////////

void Procesa_comando(void){

   int1 procesado_ok=0;
   int waddress, wbyte;

   // COMANDO = "" intro en blanco ---------------------------------------
   strcpy(xcommand,"" );
   if(!strcmp(buffrec,xcommand)){
      procesado_ok=1;
      goto fin_procesa;
   }
   // COMANDO = "?" ------------------------------------------------------
   strcpy(xcommand,"?" );
   if(!strncmp(buffrec,xcommand,strlen(xcommand))){
      Send_opts();
      procesado_ok=1;
      goto fin_procesa;
   }

   // COMANDOS EEPROM ////////////////////////////////////////////////////

   // COMANDO = "eedump" - vuelca contenido de eeprom -----------------------
   strcpy(xcommand,"eedump" );
   if(!strncmp(buffrec,xcommand,strlen(xcommand))){
      Vuelca_EEPROM();
      procesado_ok=1;
      goto fin_procesa;
   }
   // COMANDO = "eeread" - lee una posicion de la eeprom --------------------
   strcpy(xcommand,"eeread" );
   if(!strncmp(buffrec,xcommand,strlen(xcommand))){
      waddress=Extrae_arg_hex("d",2);
      wbyte=read_eeprom(waddress);
      printf("
d%2x==b%2x",waddress,wbyte);
      procesado_ok=1;
      goto fin_procesa;
   }
   // COMANDO = "eewrite" - escribe una posicion de la eeprom ----------------
   strcpy(xcommand,"eewrite" );
   if(!strncmp(buffrec,xcommand,strlen(xcommand))){
      waddress=Extrae_arg_hex("d",2);
      wbyte=Extrae_arg_hex("b",2);
      write_eeprom(waddress,wbyte);
      printf("
%2x->%2x Ok",wbyte,waddress);
      procesado_ok=1;
      goto fin_procesa;
   }
   // COMANDO = "eefill" - rellena la eeprom a un valor ---------------------
   strcpy(xcommand,"eefill" );
   if(!strncmp(buffrec,xcommand,strlen(xcommand))){
      wbyte=Extrae_arg_hex("b",2);
      Rellena_EEPROM(wbyte);
      procesado_ok=1;
      goto fin_procesa;
   }

fin_procesa:

   // COMANDO ERRÓNEO - ¿ezo qué é lo que é ?-----------------------------
   if(procesado_ok==0){
      printf("
?%s",buffrec);
   }

}





Contra la estupidez los propios dioses luchan en vano. Schiller
Mi Güeb : Picmania

Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 18286
    • MicroPIC
RE: Ejemplito 16F876A: La EEPROM interna puesta a nuestro servicio.
« Respuesta #1 en: 06 de Marzo de 2006, 02:58:00 »
Ya nos estamos acostumbrando a tus acabados, Diego, pero eso no va a impedir que te envíe un aplauso.

Desconectado RedPic

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 5544
    • Picmania by Redraven
RE: Ejemplito 16F876A: La EEPROM interna puesta a nuestro servicio.
« Respuesta #2 en: 06 de Marzo de 2006, 07:13:00 »
Gracias Manolo por tu indulgencia con este "probe pogramadó" ...

Con este ejemplo en concreto me he ido al 90% de la FLASH del escaso 16F628, el de mi RRBOARD1, así que ya va siendo hora de pensar seriamente en terminar la RRBOARD2 para usar los 18FXXXX plétoricos de patillas, de ROM"es, de RAM"es y de EEPROM"es  ( tengo un 18F4455 que me mira con ojos de ternerillo de leche)



Contra la estupidez los propios dioses luchan en vano. Schiller
Mi Güeb : Picmania