Autor Tema: 18F97J60, escritura memoria externa I2C, 1Byte en menos de 25uS.  (Leído 2199 veces)

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

Desconectado andres6969

  • PIC10
  • *
  • Mensajes: 14
 Amigos de TODO PIC, estoy atascado en el siguiente paso.
Problema fácil de explicar, espero que la solución no sea muy compleja.   :oops: :oops: :oops:

Necesito escribir 1Byte en un Eeprom en menos de 25uS por I2C.   La memoria acepta escritura lectura con CLK de 1MHz, es una FRAM, muy rápida. Escribe a la velocidad del bus de comunicaciones i2c del PIC que es 1 MHz. 
Pero…………….  Creo que no es lo suficiente. ;-)   Porque para escribir 1byte por i2c es necesario 1Byte para seleccionar el dispositivo del bus i2c, 1Byte para direccion1, 1Byte para dirección2 y 1Byte de datos. Con lo cual son 4bytes en el bus para escribir 1Bute de datos + los retardos del bus, etc etc.   Aquí adjunto imagen del tiempo mínimo conseguido de este proceso de grabar 1byte en la memoria, tiempo empleado aprox de 60uS, necesito esto mismo en 25uS.   :lol: :lol: :lol:
Igual se puede optimizar el código de escritura por i2c, veo qué entre byte de dirección1, direccion2 y dato hay un tiempo de aproximadamente 8uS. 8us por 2 = 16uS.  Rascado algo de tiempo al principio de la selección del dispositivo y algo al final de la operación. Igual… se puede conseguir meter esto en 25uS.   
Igual todo esto es una locura imposible de conseguir y hay otras soluciones mucho más fáciles, más viables, etc. Soy todo oídos a estas nuevas soluciones, si existen…. ;-).
Si no se puede conseguir por I2C, igual por otro método de comunicaciones de este PIC 18F97J60.  Lo que si me gustaría mantener es el tipo de memoria, que sea un no volátil. ;-)
Espero vuestra ayuda.    Gracias. 
Saludos. Andrés.

Desconectado elreypic2

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1297
Re:18F97J60, escritura memoria externa I2C, 1Byte en menos de 25uS.
« Respuesta #1 en: 02 de Marzo de 2021, 12:04:48 »
Que tal andres6969,

En realidad lo queintentas hacer NO es posible y la respuesta es lógica. Veamos, el bus I2C que estas usando tiene una frecuencia de 1MHz, lo que te da un cilo de reloj de 1us (microsegundo), correcto? Entonces si necesitas 4 datos formados de:

1)slave address + ACK (9 ciclos de reloj)
2)Address MSB + ACK (9 ciclos de reloj)
3)Address LSB + ACK (9 ciclos de reloj)
4)Dato a escribir + ACK (9 ciclos de reloj)

Si no tuvieras ningún delay entre cada dato entonces el total de cilcos de reloj es de 9X4 = 36 ciclos de reloj, si cada ciclo de reloj es de 1us, entonces el tiempo mínimo en que podrás relizar la escritura de un solo byte en una dirección cualquiera de la FRAM (que no es una EEPROM) será de 36us.

Yo te recomiendo que uses una memoria con bus SPI, ese es mucho más rápido del orden de los MHz y ahí sí que lograrás la escritura en el tiempo que necesitas. De igual manera existen FRAM con bus SPI, y me imagino que estás usando una memoria FRAM de Cypress Semiconductor.

Saludos,

elreypic.

Desconectado remi04

  • PIC24F
  • *****
  • Mensajes: 657
Re:18F97J60, escritura memoria externa I2C, 1Byte en menos de 25uS.
« Respuesta #2 en: 02 de Marzo de 2021, 14:08:23 »
Si la FRAM permite escritura continua, y lo hará seguro, solo tienes que enviar Start + slave address + address h + address l una vez, luego le envías el paquete de bytes entero de forma contínua y el chip los irá metiendo en orden secuencial a partir de la dirección indicada.

En función de como sea la aplicación, yo barajaría la posibilidad de hacer un buffer en RAM y cuando esté lleno volcarlo en la FRAM entero en modo continuo:

start, slave address, address_h, address_l, byte1, byte2, byte3, byte4, byte5, byte6,................etc,etc,etc, stop.     

   Solo hay que tener en cuenta leer el ACK al final de cada byte, lo que sería solo un bit de más por cada byte.

  Así se van grabando en orden todo lo que le mandes. 

  Incluso sin buffer. El I2C no tiene timeout, por lo que puedes abrir la "veda" de escritura secuencial y le vas enviado los bytes cuando te vengan en gana. Hasta que no envíes la condicion de stop aquello no cambia. " Consulta no obstante el datasheet" por si acaso esa memoria si tuviese restricciones de tiempos máximos.

  Si no es viable así, la única forma de subir el clock es por SPI como ya sugiere ElreyPic
« Última modificación: 02 de Marzo de 2021, 14:17:27 por remi04 »

Desconectado andres6969

  • PIC10
  • *
  • Mensajes: 14
Re:18F97J60, escritura memoria externa I2C, 1Byte en menos de 25uS.
« Respuesta #3 en: 03 de Marzo de 2021, 11:58:05 »
Hola a todos. Gracias a elreypic2 y remi04. Gracias por vuestra respuesta. Mil gracias.
De estar en callejón sin salida a tener 2 opciones para resolver el problema planteado. Gracias.  ((:-)) ((:-)) ((:-)) ((:-)) ((:-))

# La solución que planteas “elreypic2”, es muy interesante, sería la opción futura y final que tengo que implementar si no consigo hacerlo por I2C.  El problema es que tengo que modificar el Hardware, la PCB y si no hay más remedio tendré que utilizar una memoria SPI. Como solución final es perfecta. Gracias elreypic2.  ;-)

# La solución de “remi04”, la veo interesante ya que no cuesta nada probarla, NO tengo que modificar la PCB, etc.   El modelo de memoria I2C que utilizo como bien ha indicado "intuido" elreypic2 es una FM24W256 del fabricante Cypress Semiconductor. Y creo que SI soporta la escritura secuencial, pag 6 -> “Any number of sequentialbytes may be written.”, que según el datasheet creo que lo indica como “Multi-Byte Write”en la pag 7,  adjunto link del datasheet.       https://www.cypress.com/file/136451/download
Pero tengo que verificar que "yo puedo" escribir Byte a Byte de forma secuencial sin tener que enviar nuevamente los otros campos a la I2C.   De esta forma igual si puedo meter 1byte en menos de 25uS.   Gracias remi04.  :lol: :lol:

Necesito un poco de tiempo para implementar estas soluciones y posteo los resultados por aquí. Gracias.  De verdad, GRACIAS.
Saludos. Andrés.

Desconectado remi04

  • PIC24F
  • *****
  • Mensajes: 657
Re:18F97J60, escritura memoria externa I2C, 1Byte en menos de 25uS.
« Respuesta #4 en: 03 de Marzo de 2021, 16:12:31 »
Hola a todos. Gracias a elreypic2 y remi04. Gracias por vuestra respuesta. Mil gracias.
De estar en callejón sin salida a tener 2 opciones para resolver el problema planteado. Gracias.  ((:-)) ((:-)) ((:-)) ((:-)) ((:-))

# La solución que planteas “elreypic2”, es muy interesante, sería la opción futura y final que tengo que implementar si no consigo hacerlo por I2C.  El problema es que tengo que modificar el Hardware, la PCB y si no hay más remedio tendré que utilizar una memoria SPI. Como solución final es perfecta. Gracias elreypic2.  ;-)

# La solución de “remi04”, la veo interesante ya que no cuesta nada probarla, NO tengo que modificar la PCB, etc.   El modelo de memoria I2C que utilizo como bien ha indicado "intuido" elreypic2 es una FM24W256 del fabricante Cypress Semiconductor. Y creo que SI soporta la escritura secuencial, pag 6 -> “Any number of sequentialbytes may be written.”, que según el datasheet creo que lo indica como “Multi-Byte Write”en la pag 7,  adjunto link del datasheet.       https://www.cypress.com/file/136451/download
Pero tengo que verificar que "yo puedo" escribir Byte a Byte de forma secuencial sin tener que enviar nuevamente los otros campos a la I2C.   De esta forma igual si puedo meter 1byte en menos de 25uS.   Gracias remi04.  :lol: :lol:

Necesito un poco de tiempo para implementar estas soluciones y posteo los resultados por aquí. Gracias.  De verdad, GRACIAS.
Saludos. Andrés.

  Por supuesto que puedes.  Si usas CCS y usas sus funciones de manejo del modulo i2c harías así:

 
Código: C
  1. i2c_start();              // Condición de Start
  2.  i2c_write(slave address);   // Llama al dispositivo exclavo.  
  3.  i2c_write(address_high_byte);  // Dirección a escribir byte alto
  4.  i2c_write(address_low_byte);   // Direccion a escribir byte bajo
  5.  i2c_write(byte1);                     // dato para la dirección indicada.
  6.  i2c_write(byte2);                     // dato para la dirección indicada + 1.
  7.  i2c_write(byte3);                     // dato para la dirección indicada + 2.
  8.  i2c_write(byte4);                     // dato para la dirección indicada + 3.
  9.  i2c_write(byte5);                     // etc....
  10.  i2c_stop();                             // Condición de Stop.

   Puedes mandar lo que quieras mientras no le envíes la condición de stop. Una vez que envías STOP entonces todo termina y de nuevo tienes que enviar start+slave_address+addressH+addressL.  Eso es si por ejemplo tienes que dejar de escribir y pasar el "cursor" a otra posición de memoria y seguir escribiendo a partir de la otra.


  Si no usas CCS, puedes manejar directamente el modulo del pic que uses. En el datasheet viene todo explicado.  La forma de proceder al final es la misma.

  Ahí la precaución es leer siempre el ACK que te envía el slave tras cada octeto, ya que si hay un problema con alguna transmisión de un byte, el slave te enviaría NO_ACK, si le sigues enviando lo continuará grabando pero tendrás un "escalón" en la memoria, es decir 1 byte perdido, y todo en adelante adelantado una posición respecto de la que crees.

  El ACK, en el caso de las funciones de CCS se leen con el retorno de la funcion write_i2c(int byte); Esta funcion hace dos cosas:

 1- Enviar el byte del argunmento.
 2- retornar el ACK. Si la funcion devuelve 0 = ACK correcto.
 Si devuelve 1, No hay ACK valido.
 Si devuelve 2, colisión detectada.

Ya tendrias que plantear el envío y la comprobación.
Una forma por ejemplo podría ser:

Código: C
  1. int1 send_i2c_byte(int _byte) {   // Envía el byte indicado por I2C.
  2.   if (i2c_write(_byte) != 0)        // ¿No hay ACK?  
  3.     return 1;                        // Retorna 1 (condición de error)
  4.   else
  5.     return 0;                       // Si hay ACK, retorna 0. (Condición de conforme).
  6. }

  Un saludo.
 
« Última modificación: 03 de Marzo de 2021, 16:15:48 por remi04 »

Desconectado andres6969

  • PIC10
  • *
  • Mensajes: 14
Re:18F97J60, escritura memoria externa I2C, 1Byte en menos de 25uS.
« Respuesta #5 en: 06 de Marzo de 2021, 16:29:56 »

Hola remi04, muchas gracias. 
Ok, perfecto.  Con la escritura secuencial que has comentado, en mi caso, en poco más de 12uS está escrito 1Byte por I2C.  Perfecto.  ;-) Gracias.  ((:-)) ((:-)) ((:-)) ((:-)) ((:-)) ((:-)) ((:-)) ((:-)) ((:-)) ((:-)) ((:-))
Ahora voy con lo que comenta elreypic2, ya metido en este lio, voy a intentar hacerlo en menos tiempo. ;-).  Las memorias SPI nuca las he utilizado y desconozco por completo las comunicaciones por SPI.  Voy a utilizar una memoria SPI, para ver en cuanto tiempo “menos” de 12uS es capaz de escribir un 1 Byte en una memoria FRAM SPI.   No sé si hay mucha diferencia del I2C al SPI para esto que quiero hacer. Entiendo que sí hay diferencia en la velocidad, por lo poco que he leído I2C a 400KHz-1MHz y SPI a 10MHz.  Por aventurarme en algo, si esto va 10 veces más rápido supongo que en 1,2uS -1,6uS está escrito 1 Byte con una FRAM SPI. ;-). Igual esto es último que he dicho es una “Burrada”. No lo sé.   :oops: :oops: :oops: :oops: :oops: :oops: :oops: :oops:
Gracias por vuestra ayuda.   Adjunto la escritura secuencial por I2C comentada. ;-)
Saludos. Andrés.   :-) :-)

Desconectado remi04

  • PIC24F
  • *****
  • Mensajes: 657
Re:18F97J60, escritura memoria externa I2C, 1Byte en menos de 25uS.
« Respuesta #6 en: 06 de Marzo de 2021, 19:40:55 »
En SPI la ventaja no solo son los 10 MHZ, sino que además te ahorras el slave address.  En SPI el slave se llama poniendo su CS a nivel bajo. 

 Solo tienes que enviar dos bytes de address y el dato.  A partir de aquí también los puedes enviar secuencial.

  Si no has tocado nunca SPI te recomiendo leas algunos tutoriales, sobre todo para que no te vuelvas loco por la forma de trabajar que tiene en cuanto a los registros de desplazamientos y el modo de realizar cada transferencia. Sobre todo la recepción de datos cuando veas que si quieres recibir algo siempre tienes que enviar algo a cambio.

 Además para que conozcas los distintos modos de SPI que hay y cuál tienes que adoptar para esa memoria (te lo dice su datasheet).