Autor Tema: Programacion dinamica de datos sobre la memoria de programa de PIC18F  (Leído 4272 veces)

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

Desconectado pakotron

  • PIC10
  • *
  • Mensajes: 3
Hola amigos, soy nuevo en este foro y mi primera consulta es si alguien ha programado de forma dinamica datos en la Flash de memoria de programa. Mas concretamente, necesito mas espacio ROM que el que me proporciona la EEPROM interna del PIC, y habia pensado utilizar la memoria de programa para, en ejecucion, salvar datos en ella. Hay alguien que lo haya hecho alguna vez?

Muchas gracias por vuestra ayuda,

pakotron

Desconectado kikelc

  • PIC10
  • *
  • Mensajes: 22
RE: Programacion dinamica de datos sobre la memoria de programa de PIC18F
« Respuesta #1 en: 06 de Julio de 2004, 13:14:00 »
Hola pakotron

Lo que tu mencionas es totalmente realizable, yo lo he implementado en Pics de la serie 18F  como el 18F452 y el 18F252 ya que en estos pics sus localidades de memoria de programa son de 16 bits (0xFFFF) en cambio en los de la serie 16F87X como el 16F877 y el 16F876 También se puede hacer pero  tienes que tomar en cuenta que sus localidades de memoria de programa son de 14bits (0x3FFF). es por eso que prefiero los de la serie 18Fx para guardar dos Bytes o un Word sin problemas.

Para hacer esto yo utilizo programación en C del compilador CCS, si lo tienes puedes consultar la ayuda allí vienen instrucciones como:
write_program_eeprom (address, data)

read_program_eeprom (address)

ERASE_PROGRAM_EEPROM (address)

Con esas pues hacer lo que mencionas, solo unos comentarios: Para hacer una escritura correcta tendrá que estar la localidad de memoria previamente limpia o  borrada con la ultima instrucción que mencione, lo malo de esta instrucción hasta donde alcance a entender es que borra por bloques de localidades de memoria, es por eso que debes de tener cuidado al usar esa función, tampoco podrás usar la Protección de Código (CP) a la hora de programar el dispositivo, ten cuidado de no escribir algo en las localidades donde este alojado el programa del PIC, si lo haces en localidades posteriores no hay bronca, te recomiendo que hagas pruebas y que leas la memoria de programa del PIC con tu programador para ver los resultados.

Saludos
kikelc

Desconectado pacalaconcurso

  • PIC24F
  • *****
  • Mensajes: 718
RE: Programacion dinamica de datos sobre la memoria de programa de PIC18F
« Respuesta #2 en: 07 de Julio de 2004, 06:35:00 »
para usar la memoria ROM de esa forma recuerda reservarla previamente para que el compilador no aloje codigo en ella, de esa forma evitas los problemas que te anota Kike.

un saludo

Desconectado Modulay

  • Moderadores
  • DsPIC30
  • *****
  • Mensajes: 2651
RE: Programacion dinamica de datos sobre la memoria de programa de PIC18F
« Respuesta #3 en: 08 de Julio de 2004, 08:08:00 »
Entonces en un pic de la gama 16 como por ej. el 16F876 ¿cómo se haría para usar durante la ejecución la memoria de programa para guardar datos?
Necesito crear un buffer de al menos 300 bytes para almacenar una trama PDU enviada por un telefono móvil conectado al puerto serie del pic.Una de estas tramas puede tener 200 ó 300 caracteres que entran de forma ininterrumpida por usart.
¿Cómo se podría implementar este buffer en la memoria de programa del 16F876? He probado con esto:

#ORG 0x1E00 , 0xff8
byte buffer[70];

Pero me lo crea en memoria ram,por lo que sigo con el mismo problema de espacio

Desconectado pakotron

  • PIC10
  • *
  • Mensajes: 3
RE: Programacion dinamica de datos sobre la memoria de programa de PIC18F
« Respuesta #4 en: 08 de Julio de 2004, 12:01:00 »
Hola de nuevo. Ya he conseguido escribir de forma dinamica en la memoria de programa, de momento solo he simulado porque todavia no me ha llegado el micro, asi que no os puedo dar tiempos, pero por lo que he leido, es bastante lento y se detiene la ejecucion de programa hasta que la escritura del bloque ha finalizado.
Respecto al 16F no puedes escribir en memoria de programa como si lo hicieras en RAM, necesitas una determinada secuencia de instrucciones para hacerlo y en el manual del 16f877a en la página 38 tienes la rutina implementada.
Saludos.

Desconectado Modulay

  • Moderadores
  • DsPIC30
  • *****
  • Mensajes: 2651
RE: Programacion dinamica de datos sobre la memoria de programa de PIC18F
« Respuesta #5 en: 08 de Julio de 2004, 14:04:00 »
Ya le estoy echando un vistazo.
Se debe escribir en bloques de 4 words cada uno.Voy a meterle mano a esto que tiene buena pinta.
Gracias pako
   ¡¡Ya me queda menos para los 100 mensajes!!

Desconectado Modulay

  • Moderadores
  • DsPIC30
  • *****
  • Mensajes: 2651
RE: Programacion dinamica de datos sobre la memoria de programa de PIC18F
« Respuesta #6 en: 09 de Julio de 2004, 15:08:00 »
Toda la tarde y no he conseguido escribir un solo bit en la rom!!!
La rutina de lectura de la memoria de programa si me funciona bien,pero la de escritura no.Se supone que el loop debe ejecutarse 4 veces y sólo lo hace una.Les pasteo el código a ver si lo podemos arreglar.Lo he comentado lo mejor que he podido para que se pueda entender bien:
Codigo:

////////////////////////////////////// PREPROCESADO ///////////////////////////////////

#include <16F876A.h>
#use delay(clock=20000000)
#fuses HS,NOWDT,NOPUT,NOLVP,NOBROWNOUT,NOWRT
#include "lcd.c"

#ORG 0x1D00,0x1EFF {}   // 512 bytes reservados para el buffer

///////////////////////////////   REGISTROS Y GLOBALES ////////////////////////////////

#byte STATUS = 0x03
#byte INDF   = 0x100
#byte FSR    = 0x104
#byte EEDATA = 0x10C
#byte EEADR  = 0x10D
#byte EEDATH = 0x10E
#byte EEADRH = 0x10F
#byte INTCON = 0x18B
#byte EECON1 = 0x18C
#byte EECON2 = 0x18D

#byte ADDRH = 0x70  
#byte ADDRL = 0x71
#byte DATADDR = 0x72

/////////////////////////////////////// RUTINAS //////////////////////////////////////

void escribe_buffer(unsigned int dato,dir_H,dir_L)
   {
   unsigned int contador = 0;
   DATADDR = &dato;   // Ubicación en memoria del dato de origen
   ADDRH =  dir_H;    
   ADDRL =  dir_L;
   #ASM
         BSF      STATUS,6    //
         BCF      STATUS,5    // Banco 2
         MOVF     ADDRH,W     // Byte más significativo de la dirección de destino
         MOVWF    EEADRH
         MOVF     ADDRL,W     // Byte menos significativo de la dirección de destino
         MOVWF    EEADR
         MOVF     DATADDR,W   // Dirección inicial de los 4 bytes de origen
         MOVWF    FSR         // Apuntamos a dicha dirección inicial
   LOOP: INCF     contador,F      // Añadido para comprobar si se ejecuta las 4 veces
         MOVF     INDF,W      //
         MOVWF    EEDATA      // Cargamos el dato en el byte menos significativo
         MOVLW    0x00
         MOVWF    EEDATH      // Deshechamos (todos a 0) los 6 bits restantes de la WORD
         INCF     FSR,F       // Apuntamos a la siguiente dirección de origen
         BSF      STATUS,5    // Banco 3
         BSF      EECON1,7    // Accedemos a la memoria de programa
         BSF      EECON1,2    // Habilitamos escritura
         BCF      INTCON,7    // Deshabilitamos interrupciones
         MOVLW    0x55        // Secuencia de escritura
         MOVWF    EECON2      //
         MOVLW    0xAA        //
         MOVWF    EECON2      //
         BSF      EECON1,1    //
         NOP                  //
         NOP                  //
         BCF      EECON1,2    // Deshabilitamos escritura
         BSF      INTCON,7    // Habilitamos interrupciones
         BCF      STATUS,5    // Banco 2
         INCF     EEADR,F     // Incrementamos la dirección de destino...
         MOVF     EEADR,W
         ANDLW    0x03
         XORLW    0x03
         BTFSC    STATUS,2    // ...y comprobamos si ya se escribió todo el bloque...
         GOTO     LOOP        // NO! Aún no se escribieron los 4 datos
   #ENDASM
   printf(lcd_putc,"cont->%u ",contador);
   }


unsigned int lee_buffer(unsigned int dir_H,dir_L)
  {
  unsigned int numero;
  #ASM
     BSF     STATUS,6   //
     BCF     STATUS,5   // Banco 2
     MOVF    dir_H,W    
     MOVWF   EEADRH     // Byte más significativo de la dirección de lectura
     MOVF    dir_L,W
     MOVWF   EEADR      // Byte menos significativo
     BSF     STATUS,5   // Banco 3
     BSF     EECON1,7   // Acceso a memoria de programa
     BSF     EECON1,0   // Lectura
     NOP
     NOP
     BCF     STATUS,5   // Banco 2
     MOVF    EEDATA,W   // Tomamos el dato útil del byte menos significativo de la WORD
     MOVWF   numero     // Lo devolvemos
  #ENDASM
  return(numero);
  }

////////////////////////////////////// PRINCIPAL /////////////////////////////////////

void main()
   {
   unsigned int dato[4],dato2;
   dato[0] = 8;
   dato[1] = 9;
   dato[2] = 10;
   dato[3] = 11;
   lcd_init();
   escribe_buffer(dato[0],0x1D,0x00);    // Escribimos dato[0] en la dirección 0x1D00
   printf(lcd_putc,"Escr->%u",dato[0]);
   lcd_gotoxy(1,2);
   dato2 = lee_buffer(0x1D,0x00);        // Leemos la dirección 0x1D00
   printf(lcd_putc,"Leido -> %u",dato2);
   }



Desconectado Modulay

  • Moderadores
  • DsPIC30
  • *****
  • Mensajes: 2651
RE: Programacion dinamica de datos sobre la memoria de programa de PIC18F
« Respuesta #7 en: 10 de Julio de 2004, 16:12:00 »
Pues ya está solucionado.
El problema estaba en que la rutina de escritura que viene en el datasheet está mal.
Corregido y funcionando!!:]
Codigo:

////////////////////////////////////// PREPROCESADO ///////////////////////////////////

#include <16F876A.h>
#use delay(clock=20000000)
#fuses HS,NOWDT,NOPUT,NOLVP,NOBROWNOUT,NOWRT
#include "lcd.c"

#ORG 0x1D00,0x1EFF {}   // 512 bytes reservados para el buffer

///////////////////////////////   REGISTROS Y GLOBALES ////////////////////////////////

#byte STATUS = 0x03
#byte INDF   = 0x100
#byte FSR    = 0x104
#byte EEDATA = 0x10C
#byte EEADR  = 0x10D
#byte EEDATH = 0x10E
#byte EEADRH = 0x10F
#byte INTCON = 0x18B
#byte EECON1 = 0x18C
#byte EECON2 = 0x18D

#byte ADDRH   = 0x79
#byte ADDRL   = 0x7A
#byte DATADDR = 0x7B

/////////////////////////////////////// RUTINAS //////////////////////////////////////

void escribe_buffer(char *ptr,unsigned int dir_H,dir_L)
   {
   DATADDR = ptr;
   EEADRH = dir_H;
   EEADR = dir_L;
   #ASM
     INICIO: BSF      STATUS,6    ;
             BCF      STATUS,5    ; Banco 2
             MOVF     DATADDR,W   ; Dirección inicial de los 4 bytes de origen
             MOVWF    FSR         ; Apuntamos a dicha dirección inicial
       LOOP: MOVF     INDF,W
             MOVWF    EEDATA      ; Cargamos el dato en el byte menos significativo
             MOVLW    0x00
             MOVWF    EEDATH      ; Deshechamos (todos a 0) los 6 bits restantes de la WORD
             INCF     FSR,1       ; Apuntamos a la siguiente dirección de origen
             BSF      STATUS,5    ; Banco 3
             BSF      EECON1,7    ; Accedemos a la memoria de programa
             BSF      EECON1,2    ; Habilitamos escritura
             BCF      INTCON,7    ; Deshabilitamos interrupciones
             MOVLW    0x55        ; Secuencia de escritura
             MOVWF    EECON2
             MOVLW    0xAA
             MOVWF    EECON2
             BSF      EECON1,1
             NOP
             NOP
             BCF      EECON1,2    ; Deshabilitamos escritura
             BSF      INTCON,7    ; Habilitamos interrupciones
             BCF      STATUS,5    ; Banco 2
             INCF     EEADR,1     ; Incrementamos la dirección de destino...
             MOVF     EEADR,W
             ANDLW    0x04
             XORLW    0x04
             BTFSS    STATUS,2    ; ...y comprobamos si ya se escribió todo el bloque...
             GOTO     LOOP        ; NO! Aún no se escribieron los 4 datos
   #ENDASM
   }


char lee_buffer(unsigned int dir_H,dir_L)
  {
  EEADRH=dir_H;
  EEADR=dir_L;
  #ASM
     BSF     STATUS,6   //
     BSF     STATUS,5   // Banco 3
     BSF     EECON1,7   // Acceso a memoria de programa
     BSF     EECON1,0   // Lectura
     NOP
     NOP
  #ENDASM
  return(EEDATA);
  }

////////////////////////////////////// PRINCIPAL /////////////////////////////////////

void main()
   {
   char DATO[4],dat,*ptr;
   DATO[0] = "A";
   DATO[1] = "B";
   DATO[2] = "C";
   DATO[3] = "D";
   ptr = &DATO[0];
   lcd_init();
   escribe_buffer(ptr,0x1D,0x00);      // Escribimos en la dirección 0x1D00
   printf(lcd_putc,"Escrito-> %c%c%c%c",DATO[0],DATO[1],DATO[2],DATO[3]);
   lcd_gotoxy(1,2);
   dat = lee_buffer(0x1D,0x00);        // Leemos la dirección 0x1D00
   printf(lcd_putc,"Leido -> %c",dat);
   dat = lee_buffer(0x1D,0x01);        // Leemos la dirección 0x1D01
   printf(lcd_putc,",%c",dat);
   dat = lee_buffer(0x1D,0x02);        // Leemos la dirección 0x1D02
   printf(lcd_putc,",%c",dat);
   dat = lee_buffer(0x1D,0x03);        // Leemos la dirección 0x1D03
   printf(lcd_putc,",%c",dat);
   }