Autor Tema: Error programa, recepción de string y grabar en eeprom interna  (Leído 4821 veces)

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

Desconectado Dani27v

  • PIC12
  • **
  • Mensajes: 73
Error programa, recepción de string y grabar en eeprom interna
« en: 27 de Agosto de 2008, 15:55:04 »
Hola, haber si me podeis echar una mano con este código, llevo pocos meses aprendiendo con el CCS, antes utilizaba mikrobasic y voy algo perdido, el siguiente código deberia leer una cadena de caracteres por el puerto serie y luego grabarla en la eeprom interna, realmente este programa sólo lo utilizo para probar y aprender mas cosas , pero me he quedado algo trabado en el.He intentando utilizar las interrupciones de fin de grabado eeprom y la de recepción por usart, el pic que utilizo es un 18f4520 a 8mhZ, aunq hay alguna entrada configurada o salida no las utilizo, solo utilizo el usart. Parece que si que recibe los valores pero luego escribe en la eeprom desperdigadamente y valores sin sentido, un saludo y gracias de antemano por vuestro tiempo.

Código: [Seleccionar]
#include "D:\PIC\movil\movil.h"
#include <string.h>
#include "glcd_modificada.c"
#include <stdlib.h>
#use rs232 (baud=9600 , xmit=pin_c6, rcv=pin_c7 , bits=8)
#define adrs 0x00
#byte TRISA=0xF92
#byte PORTA=0xF80
#byte TRISB=0xF93
#byte PORTB=0xF81




int const bufer= 100;

char valor[bufer];
int a=0;
int j=0;
int z=0;


#int_RDA

RDA_isr()
{
int i=0;
int k=0;
a=1;



do{

if(kbhit())  //compruebo si hay algún dato disponible
{

if(k=1){    //condición para ciclo continuo si el caracter es el deseado   
++i;       
}

valor[i]=getc(); // cojo el valor


if (valor[i]=0x0D) // compruebo si es el que espero
{
k=1;               // es el correto, activa flag para ciclo continuo
}
}
else{                //si no es el correcto,lo ponho a cero
valor[i]=0;
i=0;
}

if(i=101)          //para salir del ciclo despues de los 100 caracteres
{
z=1;
break;
}

}while(k=1);      //ciclo continuo si el caracter es el bueno



}


#int_EEPROM     // interupción final de escritura eeprom

eeprom_isr()

{

z=1;           //flag para saber q ha habido interrupción
}








void main()
{
TRISA=0xFF;
//TRISB=0x00;

   setup_adc_ports(NO_ANALOGS|VSS_VDD);
   setup_adc(ADC_OFF|ADC_TAD_MUL_0);
   setup_psp(PSP_DISABLED);
   setup_spi(SPI_SS_DISABLED);
   setup_wdt(WDT_OFF);
   setup_timer_0(RTCC_INTERNAL);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_timer_3(T3_DISABLED|T3_DIV_BY_1);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);
   enable_interrupts(INT_EEPROM);
   enable_interrupts(INT_RDA);
   enable_interrupts(GLOBAL);


   
 
   
 while(true)
 
 {
 if (a=1)            // si ha habido interrupción por usart
 {
 a=0;                // reseteo el flag
 
 if(z=1){                           // flag para saber si ha habido interrupcion
 write_eeprom (adrs+j,valor[j]);     //por fin de escritura eeprom
 ++j;
 z=0;                                //escribe en la eeprom
 
 }
 

 
 
 }
     
 } 
     
     
 
}



Un saludo,

Dani.

Desconectado RedPic

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 5544
    • Picmania by Redraven
Re: Error programa, recepción de string y grabar en eeprom interna
« Respuesta #1 en: 27 de Agosto de 2008, 19:19:37 »
Vamos a ver si soy capaz de armar un post que te clarifique los conceptos y no que por el contrario te los embrolle un pocos mas.  :mrgreen:

He estado mirando tu programa y es un poco-mucho confuso y voy a intentar rehacerlo desde el principio. Vamos a desbrozar primero qué vamos a hacer y después vamos a hacerlo.

Tendremos un buffer de 100 caracteres de largo sobre el que vamos a ir recibiendo, uno a uno, los caracteres transmitidos desde el PC, cuando recibamos el carácter especial 0x0D daremos por concluida la recepción y procederemos a escribir el contenido del buffer en la EEPROM del PIC, colocando el primer carácter en la dirección 0x00 de la misma, el segundo en la 0x01 y así sucesivamente. Una vez concluida la escritura reiniciamos todo y volvemos a empezar.

Vamos a aplicar un principio general que dice : "En una interrupción haz solo lo que tengas que hacer, el resto hazlo fuera de ella". Por ello vamos a construir nuestra interrupción #int_rda con lo mínimo imprescindible para nuestra aplicación y el resto lo colocaremos en el main().

Tendremos entonces tres variables en RAM: El buffer, el índice del mismo donde debe guardarse el siguiente carácter recibido y un flag que indique que ha acabado la recepción y podemos proceder a grabar en la EEPROM.

Código: C#
  1. char rx_buffer[100];    // Buffer de recepción
  2. int8 next_rx=0;         // siguiente posición a utilizar
  3. int1 flag_rx_complete=0 // flag que indica recepción completa

Es importante que al inicio tanto next_rx como flag_rx_complete estén inicializados a 0 para que su funcionamiento sea correcto desde el principio.

La rutina de recepción de caracteres queda como sigue:
Código: C#
  1. #int_RDA
  2. RDA_isr(void){
  3.    char c;
  4.  
  5.    if(kbhit()){                // Si hay algo pendiente de recibir ...
  6.       c=getc();                // lo recogemos sobre la variable c
  7.       if(c==0x0D){             // Si lo recibido es el carácter especial de fin ...
  8.          flag_rx_complete=1;   // marcamos el fin de la recepción y no hacemos nada mas.
  9.       }
  10.       else{                    // En caso contrario ...
  11.          rx_buffer[next_rx++]; // lo guardamos en la posición next_rx de rx_buffer e incrementamos next_rx
  12.       }
  13.    }
  14. }

Llegados a este punto tenemos el buffer con contenido y el flag_rx_complete marcará 1 cuando se reciba el carácter 0x0D. Vamos ahora al main() conde detectamos este estado del flag y hacemos lo que tengamos que hacer con el contenido del buffer.

Código: C#
  1. void main(){
  2. //////////////////////////////////////////////
  3. // Aqui va el bloque de nacionalización del PIC
  4. //////////////////////////////////////////////
  5.  
  6.    while(true){
  7.       if(flag_rx_complete==1){ // Si la recepción está completa ...
  8.          escribe_buffer_en_EEPROM(); // escribimos el contenido del buffer en la EEPROM y ...
  9.          next_rx=0;         // ponemos a cero la siguiente posición a utilizar y ...
  10.          flag_rx_complete=0 // ponemos a cero el flag que indica recepción completa.    
  11.       }
  12.    }
  13. }

Fíjate que en el momento de llamar a la función escribe_buffer_en_EEPROM(); (que todavía no hemos escrito) el buffer tiene todos los caracteres recibidos antes del último 0x0D y que next_rx tiene el número de caracteres recibidos. Esto es importante ya que es el número que vamos a utilizar para saber cuantos caracteres tenemos que escribir en la EEPROM y que solo DESPUES de escribirlos pondremos a cero next_rx para comenzar a recoger caracteres recibidos de nuevo desde el principio.

Para escribir la EEPROM vamos a construirnos dos funciones, la que ya hemos llamado escribe_buffer_en_EEPROM(); y otra que denominaremos escribe_byte_en_EEPROM() que escribirá un único carácter en una dirección dada de la EEPROM. Recibirá como parámetros el carácter a escribir y la dirección donde hacerlo y lo único que la diferenciará de la función estandar  write_eeprom() del CCS es que la nuestra hará uso de la interrupción #int_EEPROM para saber si es posible escribir ya que en caso contrario debe esperar a que se termine de escribir el anterior carácter.

La función escribe_buffer_en_EEPROM(); recorrerá todo el buffer rx_buffer desde la posición 0 hasta la next_rx menos uno llamando sucesivamente a escribe_byte_en_EEPROM():
Código: C#
  1. void escribe_buffer_en_EEPROM(void){
  2.    int8 i;
  3.    for(i=0;i< next_rx;i++){
  4.       escribe_byte_en_EEPROM(rx_buffer[i],i);
  5.    }
  6. }

Para utilizar la interrupción por fin de escritura de la EEPROM lo único que vamos a hacer es utilizar un flag para ponerlo en alto antes de mandar a escribir en la EEPROM y que sea la interrupción quien lo ponga a bajo cuando termine de escribir.

Así en la RAM declararemos:
Código: C#
  1. int1  flag_Writing_INTERNAL_EEPROM;

Y nuestra interrupción de Fin de Escritura de EEPROM será simplemente:
Código: C#
  1. #int_eeprom
  2. void eeprom_isr(void){
  3.    flag_Writing_INTERNAL_EEPROM=0;
  4. }

Y por fin la función para escribir un carácter en la EEPROM quedaría de esta forma:
Código: C#
  1. void escribe_byte_en_EEPROM( char data, int8 memAddress){
  2.  
  3.    flag_Writing_INTERNAL_EEPROM=1; // Ponemos en alto el flag de fin de escritura
  4.    enable_interrupts(int_eeprom); // Habilita la interrupción de fin de escritura de la EEPROM
  5.    write_eeprom (memAddress, data); // Escribe el dato en la dirección indicada
  6.    while(flag_Writing_INTERNAL_EEPROM==1){/*Espera hasta finalizar la escritura*/}
  7.    disable_interrupts(int_eeprom); // Deshabilita la interrupción de fin de escritura de la EEPROM
  8. }

Y ya tenemos todos los elementos para poder construir nuestro programa. Que apilado todo sería:
Código: C#
  1. char rx_buffer[100];    // Buffer de recepción
  2. int8 next_rx=0;         // siguiente posición a utilizar
  3. int1 flag_rx_complete=0 // flag que indica recepción completa    
  4. int1  flag_Writing_INTERNAL_EEPROM; // flag que indica fin de escritura de EEPROM
  5.  
  6. #int_RDA
  7. RDA_isr(void){
  8.    char c;
  9.  
  10.    if(kbhit()){                // Si hay algo pendiente de recibir ...
  11.       c=getc();                // lo recogemos sobre la variable c
  12.       if(c==0x0D){             // Si lo recibido es el carácter especial de fin ...
  13.          flag_rx_complete=1;   // marcamos el fin de la recepción y no hacemos nada mas.
  14.       }
  15.       else{                    // En caso contrario ...
  16.          rx_buffer[next_rx++]; // lo guardamos en la posición next_rx de rx_buffer e incrementamos next_rx
  17.       }
  18.    }
  19. }
  20.  
  21. #int_eeprom
  22. void eeprom_isr(void){
  23.    flag_Writing_INTERNAL_EEPROM=0;
  24. }
  25.  
  26. void escribe_byte_en_EEPROM( char data, int8 memAddress){
  27.  
  28.    flag_Writing_INTERNAL_EEPROM=1;
  29.    enable_interrupts(int_eeprom);
  30.    write_eeprom (memAddress, data);
  31.    while(flag_Writing_INTERNAL_EEPROM==1){/*Espera hasta finalizar la escritura*/}
  32.    disable_interrupts(int_eeprom);
  33. }
  34.  
  35. void escribe_buffer_en_EEPROM(void){
  36.    int8 i;
  37.    for(i=0;i< next_rx;i++){
  38.       escribe_byte_en_EEPROM(rx_buffer[i],i);
  39.    }
  40. }
  41.  
  42. void main(){
  43.  
  44.    enable_interrupts(INT_RDA);
  45.    enable_interrupts(GLOBAL);
  46.  
  47.    while(true){
  48.       if(flag_rx_complete==1){ // Si la recepción está completa ...
  49.          escribe_buffer_en_EEPROM(); // escribimos el contenido del buffer en la EEPROM y ...
  50.          next_rx=0;         // ponemos a cero la siguiente posición a utilizar y ...
  51.          flag_rx_complete=0 // ponemos a cero el flag que indica recepción completa.    
  52.       }
  53.    }
  54. }

Ponle lo específico de tu PIC y debería funcionarte todo.  :mrgreen:

Nota: He escrito todo el código C de cabeza sin compilarlo por lo que puede tener errores de sintaxis.

« Última modificación: 28 de Agosto de 2008, 09:55:01 por RedPic »
Contra la estupidez los propios dioses luchan en vano. Schiller
Mi Güeb : Picmania

Desconectado Dani27v

  • PIC12
  • **
  • Mensajes: 73
Re: Error programa, recepción de string y grabar en eeprom interna
« Respuesta #2 en: 28 de Agosto de 2008, 04:47:01 »
Hola, muchisimas gracias por tu respuesta,cuando llege a casa lo pruebo. Gracias por tu claridad,(impresionante hasta un zoquete como yo lo entiende y eso ya es mucho) ahora me doy cuento de lo que me habia complicado la vida.... Pruebo y me pasoa otro reto ( despues probare a mosdtrar los caracteres con la GLCD)


Un saludo,

Dani.




Desconectado Dani27v

  • PIC12
  • **
  • Mensajes: 73
Re: Error programa, recepción de string y grabar en eeprom interna
« Respuesta #3 en: 28 de Agosto de 2008, 09:38:01 »
Hola de nuevo, mi gozo en un pozo..... algo tengo q estar haciendo mal seguro, he copiado el código anterior y lo compilo bien, pero cuando le envio cualquier trama  la eeprom se llena de ceros y caracteres sin sentido,pasos q sigo: compilo bien, grabo el pic, luego con el usart terminal q incorpora  el mikrobasic ( me es mas comodo q el del ccs) le envio por ejemplo: 0123456789 x10 ( para tener los cien caracteres) tengo configurado a 9600 sin paridad 8bits 1bit de stop,(activado CR y LF) luego con el programador le doy para leer la eeprom del pic y me aperece todo ceros y algún q otro numero desperdigado y de valores estraños.... es que soy un negado ....

Este es el código tal como lo tengo ahora:
Código: [Seleccionar]
#include "D:\PIC\movil\movil.h"
#include <string.h>
#include "glcd_modificada.c"
#include <stdlib.h>
#use rs232 (baud=9600 , xmit=pin_c6, rcv=pin_c7 , bits=8)
//#byte TRISA=0xF92
//#byte PORTA=0xF80
//#byte TRISB=0xF93
//#byte PORTB=0xF81


char rx_buffer[100];         // Buffer de recepción
int8 next_rx=0;             // siguiente posición a utilizar
int1 flag_rx_complete=0;     // flag que indica recepción completa   
int1  flag_Writing_INTERNAL_EEPROM; // flag que indica fin de escritura de EEPROM
   
   #int_RDA
   RDA_isr(void){
      char c;
   
      if(kbhit()){                // Si hay algo pendiente de recibir ...
         c=getc();                // lo recogemos sobre la variable c
         if(c==0x0D){             // Si lo recibido es el carácter especial de fin ...
           flag_rx_complete=1;   // marcamos el fin de la recepción y no hacemos nada mas.
         }
         else{                    // En caso contrario ...
            rx_buffer[next_rx++]; // lo guardamos en la posición next_rx de rx_buffer e incrementamos next_rx
         }
      }
   }
   
   #int_eeprom
   void eeprom_isr(void){
      flag_Writing_INTERNAL_EEPROM=0;
   }
   
   void escribe_byte_en_EEPROM( char data, int8 memAddress){
   
      flag_Writing_INTERNAL_EEPROM=1;
      enable_interrupts(int_eeprom);
      write_eeprom (memAddress, data);
      while(flag_Writing_INTERNAL_EEPROM==1){/*Espera hasta finalizar la escritura*/}
      disable_interrupts(int_eeprom);
   }
   
   void escribe_buffer_en_EEPROM(void){
      int8 i;
      for(i=0;i< next_rx;i++){
         escribe_byte_en_EEPROM(rx_buffer[next_rx++],i);
      }
   }
   
   void main(){
     

   setup_adc_ports(NO_ANALOGS|VSS_VDD);
   setup_adc(ADC_OFF|ADC_TAD_MUL_0);
   setup_psp(PSP_DISABLED);
   setup_spi(SPI_SS_DISABLED);
   setup_wdt(WDT_OFF);
   setup_timer_0(RTCC_INTERNAL);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_timer_3(T3_DISABLED|T3_DIV_BY_1);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);
   enable_interrupts(INT_RDA);
   enable_interrupts(GLOBAL);
   
      while(true){
         if(flag_rx_complete==1){ // Si la recepción está completa ...
            escribe_buffer_en_EEPROM(); // escribimos el contenido del buffer en la EEPROM y ...
            next_rx=0;         // ponemos a cero la siguiente posición a utilizar y ...
            flag_rx_complete=0; // ponemos a cero el flag que indica recepción completa.   
         }
      }
   }
   


Gracias de antemano por vuestra paciencia.

Un saludo,

Dani.

Desconectado RedPic

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 5544
    • Picmania by Redraven
Re: Error programa, recepción de string y grabar en eeprom interna
« Respuesta #4 en: 28 de Agosto de 2008, 09:51:10 »
Estos son los problemas del Copy&Paste AND NOT Compile.  :D

Cambia la línea de la función escribe_buffer_en_EEPROM()
Código: C#
  1. escribe_byte_en_EEPROM(rx_buffer[next_rx++],i);

por esta otra:
Código: C#
  1. escribe_byte_en_EEPROM(rx_buffer[i],i);

Error mío al Copypastear  :?
« Última modificación: 28 de Agosto de 2008, 09:57:33 por RedPic »
Contra la estupidez los propios dioses luchan en vano. Schiller
Mi Güeb : Picmania

Desconectado Dani27v

  • PIC12
  • **
  • Mensajes: 73
Re: Error programa, recepción de string y grabar en eeprom interna
« Respuesta #5 en: 28 de Agosto de 2008, 15:44:08 »
Gracias por tu rapida respuesta, alfinal tampoco ha funcionado y me he vuelto loco esta tarde, pero lo bueno esq asi  he aprendido bastantes cosas, he consegido q funcione modificando esta linea:
Código: [Seleccionar]
#int_RDA
   RDA_isr(void){
      char c;
   
      if(kbhit()){                // Si hay algo pendiente de recibir ...
         c=getc();                // lo recogemos sobre la variable c
         if(c==0x0D){             // Si lo recibido es el carácter especial de fin ...
           flag_rx_complete=1;   // marcamos el fin de la recepción y no hacemos nada mas.
         }
         else{                    // En caso contrario ...
        (rx_buffer[next_rx++]); // lo guardamos en la posición next_rx de rx_buffer e incrementamos next_rx
         }

por esta otra:
Código: [Seleccionar]
#int_RDA
   RDA_isr(void){
      char c;
   
      if(kbhit()){                // Si hay algo pendiente de recibir ...
         c=getc();                // lo recogemos sobre la variable c
         if(c==0x0D){             // Si lo recibido es el carácter especial de fin ...
           flag_rx_complete=1;   // marcamos el fin de la recepción y no hacemos nada mas.
         }
         else{                    // En caso contrario ...
        (rx_buffer[next_rx++])=c; // lo guardamos en la posición next_rx de rx_buffer e incrementamos next_rx
         }

Al principio me fije q me rellenaba las 100 primeras posiciones de la memoria con ceros, pero no con valores,estuve repasando el código y creo q es porque el valor  de c ( q es el valor q recojo) no lo almacenaba en rex_buffer, y cuando llegaba el caracter  0x0D me rellenaba la memoria con el valor que tenía ese momento, q era cero. Tengo la dudad si se pone solo un symbolo de = o si son dos ==, creo q según la ayuda son dos, pero  he visto  codigos con los dos y el compilador no me da error si lo cambio.  Aprobecho para preguntar si no es mucho abusar....  como lo haria para visualizar el valor de rx_buffer en un glcd, en un lcd lo tengo claro, haria un  ciclo con un for,pero con un glcd....??

Espero q tambien le sirva de ayuda este tema a alguien.

Un saludo,

Dani

Desconectado scientist

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 999
Re: Error programa, recepción de string y grabar en eeprom interna
« Respuesta #6 en: 07 de Septiembre de 2008, 19:43:00 »
Hola, solo escribo para corregir un pequeño detalle que se le ha pasado a el maestro RedPic y que por eso al amigo anterior no le ha salido este excelente ejemplo, sobre el cual yo me he basado para hacer una pequeña practica con el puerto usb, manejandolo como CDC, y es este trozo

Código: [Seleccionar]

rx_buffer[next_rx++]; ///escribio el maestro RedPic, se le paso poner lo que estabamos recibiendo

rx_buffer[next_rx++]=c; ///ahora si funciona


solo me queda decir, gracias Profe Redpic, saludos
NO le digas a DIOS que tienes un gran problema, dile a tu problema que tienes un GRAN DIOS!!
Alma mia y castillo mio, mi Dios en quien yo confiare....

Desconectado RedPic

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 5544
    • Picmania by Redraven
Re: Error programa, recepción de string y grabar en eeprom interna
« Respuesta #7 en: 08 de Septiembre de 2008, 05:51:20 »
Hola, solo escribo para corregir un pequeño detalle que se le ha pasado a el maestro RedPic ...

Eso es lo que os decía en mi Nota: He escrito todo el código C de cabeza sin compilarlo por lo que puede tener errores de sintaxis. Quedo corregido y satisfecho.  :mrgreen:
Contra la estupidez los propios dioses luchan en vano. Schiller
Mi Güeb : Picmania

Desconectado Marttyn

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1835
    • IDEAA
Re: Error programa, recepción de string y grabar en eeprom interna
« Respuesta #8 en: 19 de Enero de 2009, 01:23:50 »
Diego, nunca habia usado la INT_EEPROM, pero lo pones tan simple que creo que lo voy a implementar  :mrgreen: Hace falta desactivar la interrupcion cuando no la usamos?

Código: C#
  1. void escribe_byte_en_EEPROM( char data, int8 memAddress){
  2.     flag_Writing_INTERNAL_EEPROM=1; // Ponemos en alto el flag de fin de escritura
  3.     enable_interrupts(int_eeprom); // Habilita la interrupción de fin de escritura de la EEPROM
  4.     write_eeprom (memAddress, data); // Escribe el dato en la dirección indicada
  5.     while(flag_Writing_INTERNAL_EEPROM==1){/*Espera hasta finalizar la escritura*/}
  6.     disable_interrupts(int_eeprom); // Deshabilita la interrupción de fin de escritura de la EEPROM
  7. }

Salu2
La gente ve las cosas que existen y se pregunta por qué.
Yo prefiero imaginar lo que no existe y preguntarme por qué no.

Desconectado RedPic

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 5544
    • Picmania by Redraven
Re: Error programa, recepción de string y grabar en eeprom interna
« Respuesta #9 en: 19 de Enero de 2009, 18:19:03 »
No Marttyn, no tienes porqué hacerlo. Fíjate que en la misma función escribe_byte_en_EEPROM() se habilita y deshabilita justo el tiempo que hace falta.

Lo que si es muy importante es no poner esta función sola, sin su correspondiente #int_eeprom. Porque entonces el flag_Writing_INTERNAL_EEPROM nunca se pondría a 0 y entonces el bucle while(flag_Writing_INTERNAL_EEPROM==1) nunca tendría fin.

Fíjate que podemos describir lo que hace escribe_byte_en_EEPROM() en la forma:

Pongo a 1 el flag de escritura, habilito la interrupción por fin de escritura de la EEPROM, escribo la EEPROM, espero a que salte la interrupción indicando que he acabado, que lo hace poniendo a 0 el flag y deshabilito la interrupción.

Como te he comentado antes si no escribo la parte en que la interrupción pone a 0 el flag éste se quedará siempre a 1 y la espera será infinita ( o hasta que el Watchdog te saque de ahí).

La gran utilidad de esta forma de escribir la EEPROM es que no tienes que evaluar un tiempo de retardo para darle el tiempo suficiente a la EEPROM para ser escrita, tiene exactamente el tiempo que requiere, sea éste el que sea.

Escribes y esperas a que termine de escribir, eso es todo.  :mrgreen:
Contra la estupidez los propios dioses luchan en vano. Schiller
Mi Güeb : Picmania

Desconectado Marttyn

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1835
    • IDEAA
Re: Error programa, recepción de string y grabar en eeprom interna
« Respuesta #10 en: 19 de Enero de 2009, 18:54:13 »
Si, el flag esta claro que hace falta, pero me referia a los enable/disable_interrupt(INT_EEPROM).
Si no escribo nada en la eeprom, la interrupcion no saltara, entonces me puedo ahorrar la pareja de enable/disable?
Gracias Diego!
La gente ve las cosas que existen y se pregunta por qué.
Yo prefiero imaginar lo que no existe y preguntarme por qué no.

Desconectado RedPic

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 5544
    • Picmania by Redraven
Re: Error programa, recepción de string y grabar en eeprom interna
« Respuesta #11 en: 19 de Enero de 2009, 19:20:31 »
Si no escribes nada en la EEPROM entonces ... no te hace falta nada de nada, ni los enables y disables ni nada del resto. Ja, ja, ja  :D :D :D

Lo que quiero decir es que si solo escribes un byte cada 15 o 20 ms no necesitas nada de esto, con solo el write_eeprom (memAddress, data) tienes suficiente. Escribes tu byte de data en la dirección memAddress de la EEPROM y en paz.

El problema se suscita cuando quieres escribir un string con n bytes, uno detrás de otro.

Entonces entre cada byte y el siguiente es necesario esperar un corto periodo de tempo, que necesita la EEPROM para realizar la función física de escritura. Esto oscila entre unos 3 ó 4 ms, que es necesario esperar antes de poder escribir el siguiente. Este tiempo difiere en cada tipo de EEPROM, en cada modelo de PIC y casi en cada PIC del mismo modelo.

Si utilizas write_eeprom (memAddress, data)  sin esperar estos ms de separación puedes perder información y es mas que probable que muchos bytes no se escriban realmente.

Una solución posible sería ejecutar siempre la secuencia write_eeprom (memAddress, data); delay_ms(5); y así estaríamos tranquilos de que cada byte se escribe, de que le damos tiempo al PIC a "tostar" eléctricamente el byte en la EEPROM.

Pero este método a pesar de ser "seguro" es ineficiente, porque si la EEPROM necesita sólo 3 ms, por ejemplo, para ser "tostado", estaríamos perdiendo 2 ms por cada byte. Por el contrario si la EEPROM necesitase 6 ms es casi seguro que perderíamos un byte de vez en cuando, incluso sería probable que no se escribiese bien un byte de cada dos, uno si otro no, uno si otro no. Esto lo he visto yo con mis ojos al poner menos ms de los necesarios.

La solución que propongo con la interrupción es un método para que solo se escriba un byte únicamente cuando el anterior ha sido correctamente escrito, o sea cuando el PIC nos diga que ha sido escrito. Tarde 3, 4, 5 ó 6 ms.

Pero para que esto funcione se debe llamar a escribe_byte_en_EEPROM() y no a write_eeprom () directamente, y entonces mas que necesarios el flag, la interrupción y los enable/disable son imprescindibles.  :mrgreen:


 
« Última modificación: 19 de Enero de 2009, 19:25:31 por RedPic »
Contra la estupidez los propios dioses luchan en vano. Schiller
Mi Güeb : Picmania

Desconectado Marttyn

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1835
    • IDEAA
Re: Error programa, recepción de string y grabar en eeprom interna
« Respuesta #12 en: 19 de Enero de 2009, 20:02:34 »
Todo claro: el porque de la interrupcion, el flag, la funcion...  :P
Pero si pongo enable_interrupts(INT_EEPROM) al inicio del main no hace falta luego deshabilitarlo... Puedo hacer:

Código: C#
  1. void escribe_byte_en_EEPROM( char data, int8 memAddress){
  2.     flag_Writing_INTERNAL_EEPROM=1; // Ponemos en alto el flag de fin de escritura
  3.     write_eeprom (memAddress, data); // Escribe el dato en la dirección indicada
  4.     while(flag_Writing_INTERNAL_EEPROM==1){/*Espera hasta finalizar la escritura*/}
  5. }

habilitar la interrupcion antes de escribir, y luego desabilitarla cuando haya finalizado no me parece muy util. esa era mi pregunta original: si puedo quitarlos para reducir las lineas de codigo  :mrgreen:
La gente ve las cosas que existen y se pregunta por qué.
Yo prefiero imaginar lo que no existe y preguntarme por qué no.

Desconectado RedPic

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 5544
    • Picmania by Redraven
Re: Error programa, recepción de string y grabar en eeprom interna
« Respuesta #13 en: 19 de Enero de 2009, 20:37:03 »
Si, a todo. Si dejas en el main() el enable puedes quitar el enable y el disable de la función.

Es solo una manía mía que habilito las interrupciones solo cuando me hacen falta. Es deformación profesional.  :mrgreen:
Contra la estupidez los propios dioses luchan en vano. Schiller
Mi Güeb : Picmania

Desconectado Marttyn

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1835
    • IDEAA
Re: Error programa, recepción de string y grabar en eeprom interna
« Respuesta #14 en: 19 de Enero de 2009, 23:22:54 »
Yo por ahora soy nuevito en esto. Intentare pillar pocas manias, pero hay una de la que ya no me puedo deshacer: ahorrar lineas de codigo  :D  Cada vez me acerco mas  a ASM 8)
Gracias maestro por la ayuda!
La gente ve las cosas que existen y se pregunta por qué.
Yo prefiero imaginar lo que no existe y preguntarme por qué no.