TODOPIC

Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: jfmateos2 en 19 de Enero de 2008, 17:14:04

Título: Demora/pausa/retraso de write_eeprom
Publicado por: jfmateos2 en 19 de Enero de 2008, 17:14:04
Según leo en el manual de CCS, la función write_eeprom podría requerir varios milisegundos para ejecutarse.

¿Qué quiere decir esto?

¿Quiere decir que el programa permanecerá detenido en ese punto hasta que termine la grabación?

¿Quiere decir que debo incluir una pausa (delay_ms) detrás de write_eeprom para dar tiempo a su terminación; si es así, cuál sería un valor seguro para esta pausa?

¿Quiere decir que el programa seguirá ejecutándose normalmente pero que no puedo volver a acceder a la EEPROM (en lectura ni escritura) hasta que pasen unos milisegundos?
Título: Re: Demora/pausa/retraso de write_eeprom
Publicado por: RedPic en 19 de Enero de 2008, 17:21:09
Juan-Fran:

Significa que tarda unos 5 milisegundos en grabar correctamente el dato en la EEPROM. Si no vas a grabar otro antes de esos 5 ms no tienes por que poner un delay pero si estás escribiendo todo un string si debes incluir el delay entre cada escritura de byte y el siguiente.

De todas formas te aconsejo otra técnica mucho mas eficaz, que es utilizar la interrupción de Fin de Escritura de la EEPROM.

Voy a ver por donde la he puesto y te pongo la referencia.



Título: Re: Demora/pausa/retraso de write_eeprom
Publicado por: RedPic en 19 de Enero de 2008, 17:27:30
Estas son las rutinas de escritura que yo uso.

Me declaro un flag llamado flag_Writing_INTERNAL_EEPROM que me indica si estoy escribiendo la EEPROM, y me aseguro de que está inicializado a cero. Cuando voy a escribir un Byte lo pongo a 1 y habilito la interrupción por fin de escritura, y ahora espero a que vuelva a ponerse a cero indicándome así que ha terminado.

De esta forma no tengo que decidir cuantos milisegundos voy a poner de delay entre dos escrituras sucesivas, sino que tardará lo que tenga que tardar y es el PIC quien me avisa de que ha terminado.

Como esta rutina de escritura quiero que sea muy segura tras escribir un Byte determinado lo leo para comprobar que he escrito lo que quería escribir. Si es distinto vuelvo a intentar escribirlo de nuevo, volviendo después a leerlo y así tantas veces como indique EEINT_max_num_write_retrys.


Código: C#
  1. int1   flag_Writing_INTERNAL_EEPROM=0;
  2. const int8 EEINT_max_num_write_retrys=3;
  3. #int_eeprom
  4. /** \brief Interrupción por : Fin escritura EEPROM interna.
  5.   *
  6.   */
  7. void interrupt_service_rutine_eeprom(void) {
  8.  
  9.    flag_Writing_INTERNAL_EEPROM=0;
  10.  
  11. }
  12.  
  13. /** \brief Función para la escritura de un byte dando su valor y su dirección absoluta.
  14.   *
  15.   * Esta función utiliza la interrupción INTEEPROM en main.c que indica cuando ha finalizado la escritura de la EEPROM.
  16.   *
  17.   * \param memAddress Dirección absoluta de 8 bits a escribir (rango de 00h a FFh).
  18.   * \param data Valor del byte a escribir (rango de 00h a ffh).
  19.   *
  20.   * \return int1 0 Write Ok, 1 Write Error
  21.   */
  22. int1 writeByteINTEEPROM(int8 memAddress, int8 data){
  23.  
  24.    int1 ret;
  25.    int8 count;
  26.    int8 datatest;
  27.  
  28.    ret=0; count=1;
  29. write_1:
  30.    flag_Writing_INTERNAL_EEPROM=1;
  31.    enable_interrupts(int_eeprom);
  32.    write_eeprom (memAddress, data);
  33.    while(flag_Writing_INTERNAL_EEPROM==1){/*Wait for write finish*/}
  34.    disable_interrupts(int_eeprom);
  35. test_1:
  36.    datatest = readByteINTEEPROM(memAddress);
  37.    if(datatest != data){
  38.       if(++count==EEINT_max_num_write_retrys){
  39.          ret = 1;
  40.          goto exit_1;
  41.       }
  42.       goto write_1;
  43.    }
  44. exit_1:
  45.    return ret;
  46. }
Título: Re: Demora/pausa/retraso de write_eeprom
Publicado por: jfmateos2 en 19 de Enero de 2008, 17:31:29
Gracias RedPIC, precisamente ha sido investigando en tu web como me ha surgido la duda.

Por cierto, si notas un incremento del consumo del ancho de banda en tu web, no te preocupes que no es ningún ataque  :lol:, soy yo que me la estoy estudiando de cabo a rabo.

Enhorabuena por tu trabajo y por compartirlo.
Título: Re: Demora/pausa/retraso de write_eeprom
Publicado por: Leon Pic en 19 de Enero de 2008, 17:32:51
Hola. Efectivamente como te lo indica RedPic peo no tiene nada que ver con el lenguaje, si no con el hardware (PIC).
Título: Re: Demora/pausa/retraso de write_eeprom
Publicado por: Cryn en 19 de Enero de 2008, 17:34:01
muy buen dato Diego, gracias

me ha surgido una pregunta, y en las memorias i2c, como va el asunto? tb se espera un tiempo entre escrituras, recuerdo haber leido por aca o en la hoja de datos que deben ser unos 10ms de espera, eso es verdad??
Título: Re: Demora/pausa/retraso de write_eeprom
Publicado por: RedPic en 19 de Enero de 2008, 17:39:51

me ha surgido una pregunta, y en las memorias i2c, como va el asunto? tb se espera un tiempo entre escrituras, recuerdo haber leido por aca o en la hoja de datos que deben ser unos 10ms de espera, eso es verdad??


Si, Cryn. Aunque lo de los 10 ms dependerá de la EEPROM que uses.

Yo en mis 24AA1025 uso solo 5 ms y van bien. Te pongo la misma rutina que la anterior para la EEPROM interna pero para las externas.

Código: C#
  1. /** \brief Función para la escritura de un byte dando su valor y su dirección absoluta en las 24AA1025 sin conmutación de canal I2C.
  2.   *
  3.   * Esta función incluye \c <b>delay</b> de 5 milisegundos tras su ejecución ¡NO DISMINUIR!.
  4.   * \param Address Dirección absoluta de 32 bits a escribir (rango de 000000h a 080000h).
  5.   * \param data Valor del byte a escribir (rango de 00h a ffh).
  6.   *
  7.   * \return int1 0 Write Ok, 1 Write Error
  8.   */
  9. int1 writeByteEXTEEPROM(int32 Address, int8 data){
  10.  
  11.    int1  ret;
  12.    int8  controlByte;
  13.    int16 relativeAddress;
  14.    int8  count;
  15.    int8  datatest;
  16.  
  17.    ret = 0; count=1;
  18.    absoluteAddress_to_relativeAddressAndControlByteEXTEEPROM(Address,relativeAddress,controlByte);
  19.  
  20. write_2:
  21.    i2c_start();
  22.    i2c_write(controlByte);
  23.    i2c_write(relativeAddress>>8);
  24.    i2c_write(relativeAddress);
  25.    i2c_write(data);
  26.    i2c_stop();
  27.    delay_ms(5);
  28. test_2:
  29.    datatest = readByteEXTEEPROM(Address);
  30.    if(datatest != data){
  31.       if(++count==EEEXT_max_num_write_retrys){
  32.          ret = 1;
  33.          goto exit_2;
  34.       }
  35.       goto write_2;
  36.    }
  37. exit_2:
  38.    return ret;
  39. }
Título: Re: Demora/pausa/retraso de write_eeprom
Publicado por: Cryn en 19 de Enero de 2008, 17:48:06
ok, gracias, este ultimo funcionaria sin problemas para una memoria 24LCxxx

porque me late que tengo la mayoria de ese tipo :mrgreen:
Título: Re: Demora/pausa/retraso de write_eeprom
Publicado por: RedPic en 19 de Enero de 2008, 18:01:07

... este ultimo funcionaria sin problemas para una memoria 24LCxxx


No lo se Cryn, la rutina que te he puesto la he escrito leyendo directamente el Datasheet de ella y no se si coincide con la de las 24LC (pero imagino que no debe ser muy distinta si es que lo es)
Título: Re: Demora/pausa/retraso de write_eeprom
Publicado por: Cryn en 19 de Enero de 2008, 18:27:57
ok, muchas gracias por la respuesta :mrgreen:

cuando tenga el hardware armado lo probare

un saludo
Título: Re: Demora/pausa/retraso de write_eeprom
Publicado por: Braulio en 28 de Mayo de 2011, 14:56:41
Esto es terrible, miren: la instrucción write_eeprom() de CCS incluye dentro de su código en ensamblador la consulta del bit WR antes de continuar:

00BC:  BSF    1C.1
00BD:  BTFSC  1C.1
00BE:  GOTO   0BD

1C.1 es el bit WR del registro EECON1 (Banco 1), el cual se pone a 1 para empezar la escritura de la EEPROM y por hardware se pone a 0 cuando esta termina, es decir, el PIC se queda preguntando si ha terminado la escritura TODO EL TIEMPO QUE DURA LA ESCRITURA, lo cual es una gran pérdida de tiempo (entre 4 y 8ms según DS), pues bien se puede escribir el siguiente byte en la rutina de interrupción de la EEPROM y así nuestro PIC nunca esta sin hacer nada y hace una escritura segura de cuantos bytes querramos en la EEPROM...

¿Habrá alguna forma de evitar esto? he intentado habilitar previamente la interrupción, poner la rutina antes y nada, es decir, evitar que CCS coloque las 2 últimas instrucciones mensionadas.

De antemano gracias por vuestra ayuda. Salu2.
Título: Re: Demora/pausa/retraso de write_eeprom
Publicado por: Suky en 28 de Mayo de 2011, 15:09:59
Incrustar ASM en CCS y hacerlo a tu gusto  ;-) O también está la posibilidad de usar #byte y #bit para trabajar con los registros.


Saludos!
Título: Re: Demora/pausa/retraso de write_eeprom
Publicado por: maunix en 28 de Mayo de 2011, 15:20:07
¿Habrá alguna forma de evitar esto? he intentado habilitar previamente la interrupción, poner la rutina antes y nada, es decir, evitar que CCS coloque las 2 últimas instrucciones mensionadas.

A lo sugerido por suky le agrego que hagas tu propia rutina paso a paso en C; no hace falta que sea en assembly. 

De hecho en el foro de microchip los más gurús muchas veces dan por sentado que para muchos desarrollos las rutinas estándar de las librerías no son utiles y hacen las suyas propias, asi que no seria raro pensar que te hagas las tuyas. 

Las funciones embebidas del CCS es todo un tema, sobre todo porque no está el código fuente disponible como sí esta en C18.
Título: Re: Demora/pausa/retraso de write_eeprom
Publicado por: Suky en 28 de Mayo de 2011, 18:06:58
¿Habrá alguna forma de evitar esto? he intentado habilitar previamente la interrupción, poner la rutina antes y nada, es decir, evitar que CCS coloque las 2 últimas instrucciones mensionadas.
A lo sugerido por suky le agrego que hagas tu propia rutina paso a paso en C; no hace falta que sea en assembly.  

Claro, es la segunda opción, en CCS podes utilizar #byte y #bit para acceder a los registros utilizando C.  ;-) Por ejemplo creando una claseestructura:

Código: C
  1. struct {
  2.   unsigned RD:1;
  3.   unsigned WR:1;
  4.   unsigned WREN:1;
  5.   unsigned WRERR:1;
  6.   unsigned :3;
  7.   unsigned EEPGD:1;
  8. }EECON1BITS;
  9. #byte EECON1bits=GETENV("SFR:EECON1")


Saludos!
Título: Re: Demora/pausa/retraso de write_eeprom
Publicado por: maunix en 28 de Mayo de 2011, 18:25:49
muy bien aclarado suky

Por ejemplo creando una clase:

Eso es una estructura para ser una clase le hace falta tomar muuucha sopa  :D :D

Título: Re: Demora/pausa/retraso de write_eeprom
Publicado por: Suky en 28 de Mayo de 2011, 18:30:06
Por ejemplo creando una clase:

Eso es una estructura para ser una clase le hace falta tomar muuucha sopa  :D :D
:D :D :D  :oops: No se de donde saque eso!  :D Bastante más sopa! Es que vengo emocionado, BARCELONA CAMPEON!!! QUE PASEO LE DIO AL MANCHESTER... perdón el off topic  :oops: :mrgreen:
Título: Re: Demora/pausa/retraso de write_eeprom
Publicado por: Braulio en 30 de Mayo de 2011, 16:33:53
Muchas Gracias Maunix y Suky por vuestras respuestas. Teneis razón hacerlo a mano es la solución.

Elegí programar en C la secuencia de escritura de la EEPROM, y ya que Suky me puso el ejemplo con una estructura, intenté declarar por primera vez en mi vida una estructura... pero con nefastos resultados. Este es mi código:

Código: C
  1. #BYTE    EECON2       = getenv("SFR:EECON2")
  2. #BYTE    EEDATA       = getenv("SFR:EEDATA")
  3. #BYTE    EEADR        = getenv("SFR:EEADR")
  4. #BIT     GIE          = getenv("SFR:INTCON").7
  5.  
  6. typedef struct
  7.    {
  8.    boolean  RD    : 1;
  9.    boolean  WR    : 1;
  10.    boolean  WREN  : 1;
  11.    boolean  WRERR : 1;
  12.    unsigned       : 4;
  13.    }
  14. EECON1bits;
  15.  
  16. #BYTE    EECON1bits    =  getenv("SFR:EECON1")
  17.  
  18. void escribir_eeprom(void)
  19.    {
  20.    EEADR = dir_ee;
  21.    EEDATA= val_ee;
  22.    EECON1bits.WREN  = 1;
  23.    deshab_int:
  24.    GIE   = 0;
  25.    if(GIE) goto deshab_int;
  26.    EECON2= 0x55;
  27.    EECON2= 0xAA;
  28.    EECON1bits.WR    = 1;
  29.    GIE   = 1;  
  30.    }

Y me salen 3 errores:

* Luego de la linea 16 (#BYTE EECON1bits...): "Expecting a variable"
* En las lineas 22 y 28 (donde uso EECON1bits.XX) "Expecting an Identifier"

Se que puedo utilizar simplemente #bit para identificar a WR y WREN, como lo he hecho siempre, pero quisiera saber porque no funciona mi estructura, Ojala me puedan ayudar. Gracias de antemano por la ayuda. Salu2

Título: Re: Demora/pausa/retraso de write_eeprom
Publicado por: Suky en 30 de Mayo de 2011, 17:50:20
Te esta sobrando un typedef, o sea, hay que crear la estructura y después asignarle la posición de memoria mediante #byte.


Saludos!