Lector y grabador de EEPROM tipo 24LCxx

Hola:

Tengo dos EEPROM, la 24LC16 y la 24LC64. Puedes encontrar las de tipo 24LCxx en su Web oficial.

Mi idea por curiosidad y experimentación es lograr que Arduino se convierta en un grabador de EEPROM de la serie 24LCxx. Hay que hacer una interfaz para cargar el archivo hex o bin de la EEPROM y guardarlo en su interior, lo mismo para leer. No voy hacer un proyecto de guardar datos desde Arduino en la EEPROM como los LEd encendido la última vez que se apagó.

La interfaz que se usaba antes para otros microcontroladores es el famoso Ic-prog y el WinPic800.

La interfaz básica que he hecho hasta ahora es así, en fase alfa.

Quiero saber detalles, ideas de la gente y plasmarla aquí para hacerlo lo mejor posible.

¿Alguna sugerencia?

Saludos.

PD: Dejar claro que no es lo mismo archivo .hex que binario .bin.

1 Like

Metaconta:
Quiero saber detalles, ideas de la gente y plasmarla aquí para hacerlo lo mejor posible.

¿Con la interfaz o el programa en general?

Si no tienes nada hecho, se me ocurre que como la comunicación al PC siempre es por USART, dar las órdenes al Arduino mediante la técnica que yo llamo "petición y respuesta".
Para refrescarte la memoria, es el proceso de enviar un comando, que el Arduino lo interprete y accione como corresponda; y con base en el resultado devolver una respuesta. Ese flujo de datos PC-Arduino no necesariamente tiene que ser legible para un ser humano, por lo tanto sugiero que sea meramente binario (podría haber texto pero solo si es parte del contenido que va o viene de la EEPROM).

¿Esa serie 24LCxx es únicamente por I2C o también lo tienes que hacer compatible con los demás protocolos de comunicación serial?

Hola:

Esa serie es de I2C, es lo que tengo ahora físicamente y haré las cosas poco a poco. Cuando termine todo al 100 % con I2C ya me meteré con el SPI tipo 93LCxx. Leer y grabar EEPROM tipo 24LCxx, o lo que es lo mismo 24Cxx.

A buscar información por todas partes como se comunicar Arduino con I2C. Eso si, el hex se transfiere desde la Interfaz del ordenador o PC, pasa por Arduino UNO y lo graba en la EEPROM 24LCxx.

Web que he encontrado:

La pregunta es.

¿Se puede hacer un grabador de EEPROM con Arduino UNO desde una interfaz con el PC?

La interfaz de prueba la tengo hecha en C#. (Versión Alfa).
bbbbbbbbbbbbbbb12.png

Saludos.

PD: En este mismo momento, en paralelo estoy haciendo tutoriales en Java con Eclipse, luego paso a NetBeans sobre comunicación por el puerto serie. Ya he hecho tres medio rápido, con C++ Win32, Consola Visual Studio y Delphi que puedes ver en documentación.

PD2: No he olvidado lo que estábamos haciendo. Tengo claro que tendré la versión de Java sea como sea y su tutorial.

Metaconta:
La pregunta es.

¿Se puede hacer un grabador de EEPROM con Arduino UNO desde una interfaz con el PC?

Mi pregunta sería: ¿y por qué no?

Si hasta los desarrolladores crearon Arduino que programa Arduino con el ejemplo ArduinoISP, ¿por cuál razón no sería posible programar un EEPROM?

Metaconta:
La interfaz de prueba la tengo hecha en C#. (Versión Alfa).
bbbbbbbbbbbbbbb12.png

Vaya que sí es alfa, la escritura lleva un 4864% de progreso.
Por cierto me gusta hasta lo simplificado que se ve utilizar el programa: escoges el archivo a grabar (o la ruta dónde guardar la lectura), y luego con el par de botones decides si "Leer" (EEPROM a archivo) o "Grabar" (archivo a EEPROM).
Me recuerda mucho a la interfaz del Win32DiskImager antes de la versión 1.0, excepto que ahí hay que seleccionar la unidad de disco a trabajar.

Metaconta:
PD2: No he olvidado lo que estábamos haciendo. Tengo claro que tendré la versión de Java sea como sea y su tutorial.

Ja, esperaba que lo dijeras :smiley:

Hola:

A buscar información sobre I2C con Arduino.

Al menos para entender como funciona. Solo falta saber más datos que tengo que averiguar.

Enviar archivo hex a Arduino que son tramas de Bytes y se va guardando en la EEPROM. Lo mismo para lectura.

¿Cómo funciona por dentro?

No lo se, al menos por ahora, ajjajajaja.

Me imagino que por cada Byte enviado desde el ordenador o PC, lo guarda en memoria, en una variable de Arduino y lo va escribiendo a la EEPROM.

Ahora a buscar ejemplos por todas partes como trabaja para poder ser capaz de enviar y recibir datos desde la EEPROM.

En cuanto a la interfaz alfa, en realidad el % es la cantidad de Bytes transmitido en este caso al pulsar el botón Grabar. Ya lo corregí, ahora pone Bytes en vez del %. :wink:

Saludos.

Edito:

Ver enlace.

Desarga ejemplo Ardino y Proteus.

Por lo que veo, usa velocidad muy lento a 9600 baudios.

Arduino EEPROM I2C.zip (38.5 KB)

Metaconta:
¿Cómo funciona por dentro?

No lo se, al menos por ahora, ajjajajaja.

Me imagino que por cada Byte enviado desde el ordenador o PC, lo guarda en memoria, en una variable de Arduino y lo va escribiendo a la EEPROM.

Algo así. De hecho el concepto es similar al de cómo transmitir un archivo. La idea de "petición y respuesta" se debe al simple hecho de que el Arduino necesita saber si el flujo de datos viene o va a la EEPROM, además de opcionalmente poder escuchar la petición de cancelar la transmisión mientras esta ocurre (ya sea por decisión del usuario o por el manejo de una excepción); porque si por alguna razón el programa deja de recibir, el Arduino se bloquearía hasta lograr iterar por toda la EEPROM (aunque en vano eso sí).

Lo difícil va a ser cómo cancelar un grabado de EEPROM, porque recuerda que un flujo binario es completamente arbitrario (enviarle un código de paro no es posible porque el Arduino creerá que es parte del contenido a grabar). Una posible solución sería aprovechar el mecanismo de "timeout" que proveen las clases que extienden de Stream (ejemplo: Serial); si el programa dejara de transmitir durante unos segundos, se asume que el grabado se canceló (aquí es necesario que el Arduino envíe una respuesta para indicarle al programa en PC que reconoció el fin de la transmisión y que está listo para recibir otra orden).

Lo que acabo de decir es apenas "una probadita" de lo que tengo en mente de cómo podría funcionar por el lado de Arduino.

Metaconta:
Por lo que veo, usa velocidad muy lento a 9600 baudios.

9600 / 11 (una trama "8N1" del protocolo UART necesita al menos 11 bits para transmitir un byte: 2 bits de inicio, 8 bits de datos y 1 de parada) = 873 B/s (bytes por segundo).

Estoy de acuerdo que 873 B/s es extremadamente lento (una EEPROM de 2 Mbits tomaría casi 5 minutos en volcarse o grabarse); sin embargo 115200 bps muy probablemente más bien sea demasiado.
Dependiendo del ritmo de escritura de estas EEPROM, no podremos darnos el lujo de acelerar la comunicación serial; o podría ocurrir una pérdida de bytes durante la grabación.

Buenas:

No había caído sobre la cancelación de las EEPROM. IC-Prog, WinPic800 y PonyProg estén leyendo o grabando, se puede cancelar sin problemas y también verificar, que esto es comprobar pero no se su forma interna.

Voy a informarme bien sobre interrumpir la transferencia de escritura o lectura desde Visual Studio, porquemientras envíe datos, no se como interrumpirlo. Cuando lo consiga, pongo el código aquí para que lo sepan.

Poco a poco vamos avanzando. :wink:

En cuanto a la velocidad de los baudios, tendré en cuenta cual acepta las EEPROM y desde VB .net, con posibilidad de cambiar su velocidad.

Saludos.

Metaconta:
y también verificar, que esto es comprobar pero no se su forma interna.

Usualmente existen dos métodos de verificación:

  • Comprobar igualdad entre el byte ingresado y recuperado: es una verificación que se hace "al vuelo" de la escritura. La IDE de Arduino utiliza este método para verificar el programa a subir (nótese que es por algo que ambos LEDs TX y RX se encienden durante este proceso).
  • Verificación post-proceso: como el nombre lo dice, es grabar e inmediatamente realizar un proceso de lectura. Al final también es comparar contenido en la fuente y destino, generando un código hash. Si estos códigos coinciden, todo bien; caso contrario algo salió mal durante la grabación.

Para efectos de este proyecto, sugeriría que el método de verificación sea el segundo. La lectura de esas EEPROM es a nivel de bytes, pero la escritura es a nivel de bloques (de 64 bytes); el sobrecargo sería enorme si se intenta verificar "al vuelo".

Metaconta:
Voy a informarme bien sobre interrumpir la transferencia de escritura o lectura desde Visual Studio, porquemientras envíe datos, no se como interrumpirlo. Cuando lo consiga, pongo el código aquí para que lo sepan.

Inténtalo; yo ya más o menos te dije cómo por el lado de Arduino.

Buenas:

Haciendo pruebas, se me cancela al segundo clic, ejjejeje. Deja ver si lo logro, parece que al final tengo que hacer Thread.

            for (int i = 0; i <= archivo.GetUpperBound(0); i++)
            {
                serialPort1.Write(archivo, i, 1);
                progressBar_barrra_progreso.Value = i;
                label_Bytes_transmitidos.Text = i.ToString() + " Bytes.";
                Application.DoEvents();
                if (interrumpir) break;
            }

Saludos.

¿Porqué otro hilo? El clicar el mismo botón debería disparar un evento (función) donde se modifica el valor de interrumpir.

Hola:

Ya funciona, ajajajaj ajjaja, por fin, ya puedo enviar y cancelar.

        bool alto = false;

        private void TestDoEvents()
        {
            byte[] archivo = File.ReadAllBytes(textBox_ubicacion_archivo.Text); // Carga el archivo en el array.

            progressBar_barrra_progreso.Maximum = archivo.Length; // Hasta donde llegue el tamaño del archivo.

            for (int i = 0; i <= archivo.GetUpperBound(0); i++)
            {
                serialPort1.Write(archivo, i, 1);

                progressBar_barrra_progreso.Value = i;

                label_Bytes_transmitidos.Text = i.ToString() + " Bytes.";

                Application.DoEvents();
                if (alto == true)
                {
                    alto = false;
                    break; // TODO: might not be correct. Was : Exit For
                }
            }
            button_Cancelar.Text = "Arranque";

        }

Botón.

        private void button_Cancelar_Click(object sender, EventArgs e)
        {
            if (button_Cancelar.Text == "Arranque")
            {
                button_Cancelar.Text = "Cancelar";
                TestDoEvents();
                progressBar_barrra_progreso.Value = 0; // Resetear progressBar a 0.
                label_Bytes_transmitidos.Text = "0";
            }
            else
            {
                if (alto == true)
                {
                    alto = false;
                }
                else
                {
                    alto = true;
                    button_Cancelar.Text = "Arranque";
                }
            }
        }

Me falta el santo 100 % que no me sale bien, pero si el conteo de los Bytes.

Metaconta:
Me falta el santo 100 % que no me sale bien, pero si el conteo de los Bytes.

Eso se resuelve con una función similar al map en Arduino (regla de tres). Si tuviera la estructura de la función de Arduino, sería como:

map(i, 0, archivo.Length, 0, 100);

PD1: creo que también debe solicitar cuál EEPROM exactamente se está programando; no solo varían en capacidad, sino que también en el tamaño de página de escritura. El búfer de salida del I2C es de 32 bytes, espero que eso no implique que no se puedan enviar 64 bytes (tamaño de página de escritura de la de 256 Kbit) en una sola transmisión. Recuerda que en esas EEPROM es más eficiente escribir por páginas (bloques) que por bytes individuales.

PD2: la lectura podría ir tan rápido como lo permita el bus de I2C a 400 KHz; pero la escritura no. Según los datasheets, escribir una página le toma máximo 5 ms; para ir a la segura es mejor mantenerse a ese ritmo.
Como no escribimos un byte cada 5 milisegundos, sino al menos 16 por transmisión; creo que es posible hasta ir más allá de 9600 bps. ¿Hasta dónde? Eso será con prueba y ensayo; si vamos demasiado rápido, se llena el búfer RX de Arduino y se pierden bytes.

bbbbbbbbbbbbbbb14.png

Por fin me salió el porcentaje de las narices. El map de Arduino no lo tiene C# ni por asomo.

Código C#:

   // Variables.
        bool alto = false;
        int N = 0;
        int P = 0;
        int resul = 0;

        private void TestDoEvents()
        {
            // Carga el archivo en el array.
            byte[] archivo = File.ReadAllBytes(textBox_ubicacion_archivo.Text);

            // Hasta donde llegue el tamaño del archivo.
            progressBar_barrra_progreso.Maximum = archivo.Length;

            // Guarda la cantidad de Bytes del archivo en la variable.
            N = archivo.Length - 1; 

            // Transmite byte en byte los datos del archivo al puerto serie.
            for (int i = 0; i <= archivo.GetUpperBound(0); i++)
            {
                // Enviando archivo al puerto serie.
                serialPort1.Write(archivo, i, 1);
                
                // Números de Bytes.
                P = i;
                
                // Resultado de la regla de tres. Cálculo del porcentaje de la barra de progreso.
                resul = 100 * i / N;
                
                // Muestra barra del progreso.
                progressBar_barrra_progreso.Value = i;

                // Muestra la cantidad de Bytes enviados.
                label_Bytes_transmitidos.Text = i.ToString() + " Bytes.";

                // Muestra la cantidad en porciento archivo enviado.
                label_Por_ciento.Text = resul + " %";

                // Evento de cancelación.
                Application.DoEvents();
                if (alto == true)
                {
                    alto = false;
                    break; // TODO: might not be correct. Was : Exit For
                }
            }
            button_Cancelar.Text = "Arranque";
        }

        private void button_Cancelar_Click(object sender, EventArgs e)
        {
            if (button_Cancelar.Text == "Arranque")
            {
                button_Cancelar.Text = "Cancelar";
                TestDoEvents();
                progressBar_barrra_progreso.Value = 0; // Resetear progressBar a 0.
                label_Bytes_transmitidos.Text = "0";
            }
            else
            {
                if (alto == true)
                {
                    alto = false;
                }
                else
                {
                    alto = true;
                    button_Cancelar.Text = "Arranque";
                }
            }
        }

En cuanto a lsa EEPOM, no sabía que por cada una hay diferente tamaño de la página.

Ver lista EEPROM I2C.

Pues mira que lo tengo progamado enviar todo de golpe. Jajajajaajjajjjja, hasta el final no para de enviar archivos bytes por bytes.

Enviar archivo hex al puerto serie en C#:

    private void button_Grabar_Click(object sender, EventArgs e)
        {
            byte[] archivo = File.ReadAllBytes(textBox_ubicacion_archivo.Text); // Carga el archivo en el array.
        }

El libro morado de Enrique Palacios sobre PIC16F84A explica muy bien la EEPROM 24LC256, de 64 páginas. Voy a leer bien las hojas de datos de cada modelo, concretamente los que yo tengo, 24LC16B y el 24LC64. Por supuesto que también los demás y pongo aquí en resumen tamaño y paginación de cada uno de ellos.

EEPROM protocolo I2C:

EEPROM - CAPACIDAD - PAGINACIÓN

24LC00 - 128 bit - 0 Bytes.
24LC01B - 1 Kbit - 8 Bytes.
24LC02B - 2 Kbit - 8 Bytes.
24LC04B - 4 Kbit - 16 Bytes.
24LC08B - 8 Kbit - 16 Bytes.
24LC16B - 16 Kbit - 16 Bytes.
24LC32A - 32 Kbit - 32 Bytes.
24LC64 - 64 Kbit - 32 Kbytes.
24LC128 - 128 Kbit - 64 Bytes.
24LC256 - 256 Kbit - 64 Bytes.
24LC512 - 512 Kbit - 128 Bytes.
24LC1025 - 1025 Kbit - 128 Bytes.
24LC1026 - 1026 Kbit - 128 Bytes.
AT24CM02 - 2 Mbit - 256 Bytes.

Casi no acabo de escribir todo esto.

Cuando pula un poco más el programa, tendré que remplantearme la forma de escribir código para cada dispositivo.

Hay que tener cosas claras. Desde C#, selección de dispositivo y bien programado para cada uno de ellos. Incluido paginación, y el array de datos a enviar, por ejemplo, 64 Kbit, así que tendrá un máximo y graba hasta ahí.

Si no hay que grabar Byte por Byte que es lo que estaba haciendo.

¿Cómo haces la manera que dices para grabar EEPROM?

Por ejemplo, el 24LC256. ¿Tengo que enviar 64 bytes por 64 bytes?

¿Así?

Envío 64 Bytes.
Delay o timer (5 ms (Mili segudnos)).
Envío 64 Bytes.
Timer (5 ms).
Envío 64 Bytes.
Timer (5 ms).
Envío 64 Bytes.
Timer (5 ms).
Envío 64 Bytes.

Cuando digo 5 ms, me imagino que es su descando, es decir, no enviar nada hasta que pase ese tiempo, luego vuelve a enviar 64 Bytes eguidos, luego descansa otros 5 ms sin enviar nada y así hasta veces cuanta.

24LC256 32K Bytes x 8 bits = 256 Kbits.

32 KBytes divididos en 64 páginas de 256 Bytes cada una.

Me confirma como ejemplo, la realidad de como hacerlo. Luego lo haré en programación y lo pongo aquí.

Saludos.

Metaconta:
El map de Arduino no lo tiene C# ni por asomo.

Es obvio que no (o al menos no con ese nombre), porque es un implementación aparte de lo que suele traer C++:

long map(long x, long in_min, long in_max, long out_min, long out_max)
{
  return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}

En AVR eso equivale a tantas instrucciones máquina que a 16 MHz debe tomarle al menos medio milisegundo (o más si lidiar con signos es otro sobrecargo).

Metaconta:
Cuando pula un poco más el programa, tendré que remplantearme la forma de escribir código para cada dispositivo.

O puedes delegar esa responsabilidad al Arduino. Podemos implementar un comando que establezca la EEPROM que tiene conectada; así después el mismo Arduino se va a encargar de manejar la capacidad y el tamaño de las páginas.

Metaconta:
Si no hay que grabar Byte por Byte que es lo que estaba haciendo.

Ni loco. Cada vez que el maestro finaliza la trasmisión (indiferentemente de cuántos bytes se hayan transmitido), la misma EEPROM realiza una escritura de la página completa. Si lo haces así con una de página de 128 bytes, estarías sobrescribiendo el mismo bloque 128 veces (y tardaría 640 ms en vez de 5 ms en una sola pasada).

Metaconta:
¿Cómo haces la manera que dices para grabar EEPROM?

Por ejemplo, el 24LC256. ¿Tengo que enviar 64 bytes por 64 bytes?

¿Así?

Envío 64 Bytes.
Delay o timer (5 ms (Mili segudnos)).
Envío 64 Bytes.
Timer (5 ms).
Envío 64 Bytes.
Timer (5 ms).
Envío 64 Bytes.
Timer (5 ms).
Envío 64 Bytes.

Cuando digo 5 ms, me imagino que es su descando, es decir, no enviar nada hasta que pase ese tiempo, luego vuelve a enviar 64 Bytes eguidos, luego descansa otros 5 ms sin enviar nada y así hasta veces cuanta.

Es correcto. Observa que casualmente el búfer RX también es de 64 bytes; si en un lapso de 5 ms se nos llena, se pueden perder bytes. El flujo debe ser constante pero a la vez que se pueda consumir con rapidez; el balance debe quedar de tal forma que la transmisión no sea lenta, pero a la vez que nunca llegue a llenar el búfer. Recuerda que en ese lapso de 5 ms el Arduino no puede consumir los bytes del búfer RX.

Otra preocupación está en I2C; sé que la librería implementa búferes de 32 bytes para los dos sentidos, pero lo que no sé es si los bytes se encolan hasta el endTransmission(), o si se consumen al vuelo. Los recibidos mediante requestFrom() se consumen mediante Wire.read().

PD: para programar una comunicación "petición-respuesta", debes definir muchas constantes. Puedes ya sea crearlas en líneas #define, o empaquetarlas en enumeraciones. La idea es tener una base que nos facilite este desarrollo. Por ejemplo:

// Comandos

/* Establece la EEPROM a trabajar.
Sintaxis: 1 byte que representa el índice de la EEPROM.
Respuesta: 1 byte, puede ser OK o INVALID_ARGUMENT.
*/
#define SET_EEPROM 0x01

/* Ordena al Arduino a volcar la EEPROM.
Sintaxis: N/A.
Respuesta: 5 bytes: un unsigned long que representa el tamaño de la EEPROM (en bytes), luego un WAITING.
*/
#define READ_EEPROM 0x02

/* Ordena al Arduino a grabar en la EEPROM.
Sintaxis: 4 bytes: un unsigned long que representa el tamaño real del archivo que va a recibir.
Respuesta: 1 byte: puede ser READY, SMALLER_THAN_EEPROM_WARNING o LARGER_THAN_EEPROM_WARNING.
*/
#define WRITE_EEPROM 0x03

/* Ordena al Arduino a abortar el volcado de la EEPROM o tarea preasignada.
Sintaxis: N/A.
Respuesta: ABORTED.
*/
#define ABORT_OPERATION 0x10

/* Le indica al Arduino que prosiga con la tarea preasignada. Se recibe cuando este haya respondido con WAITING
Sintaxis: N/A.
Respuesta: N/A.
*/
#define PROCEED 0x00

// Respuestas

#define OK 0x00 // Indica que el comando fue recibido o que la tarea se completó exitosamente.
#define UNKNOWN_COMMAND 0x01 // Indica que se recibió un comando desconocido, o inválido para el contexto actual.
#define INVALID_ARGUMENT 0x02 // Indica que alguno de los valores de la sintaxis es inválido; o que se superó el timeout antes de recibir la cantidad de bytes esperada.
#define ABORTED 0x03 // Indica que la operación en proceso fue abortada exitosamente.
#define WAITING 0x10 // Indica que el Arduino está esperando un acuerdo con el programa que lo manipula. Se suele usar para esperar a que el programa controlador esté listo para recibir un flujo de bytes.
#define READY 0x11 // Indica que el Arduino está listo para recibir un flujo de bytes entrante.
#define SMALLER_THAN_EEPROM_WARNING 0x12 // Funciona igual que READY, con la salvedad de que además advierte que el archivo a grabar tiene menor tamaño que la EEPROM a trabajar.
#define LARGER_THAN_EEPROM_WARNING 0x13 // Funciona igual que READY, con la salvedad de que además advierte que el archivo a grabar tiene mayor tamaño que la EEPROM a trabajar.

Eso como ejemplo; aquí faltaría definir una tabla de valores que se asignaría a cada EEPROM y documentar cómo funciona cada operación que se le podría ordenar al Arduino.

A la la interfaz de prueba le falta a la izquierda las posiciones en hexa que ayuden a entender donde estas parado y también agregaría una opción de EDICION.

Hola:

@Lucario448:
Haz usado el DEFINE. Prodías como haz dicho también usar enumeraciones. ¿Se puede usar diccionario en Arduino?
Con C# lo estoy usando con este ejemplo. Estoy haciendo un desensamblador del PIC16F84A.

Ejemplo usando Diccionario en C#:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Descompilar_02_cs
{
    class Instrucciones
    {
        // Diccionarios.
        private Dictionary<int, string> orientadoBytes = new Dictionary<int, string>();
        private Dictionary<int, string> orientadoBits = new Dictionary<int, string>();
        private Dictionary<int, string> controlLiteral = new Dictionary<int, string>();
        private Dictionary<int, string> saltos = new Dictionary<int, string>();

        public Instrucciones()
        {
            // Llamar funcionar.
            Orientado_Bytes();
            Orientado_Bits();
            Control_Literal();
            Saltos();
        }

        #region Llamar conjuntos de instrucciones.
        public string GetorientadoBytes(int value)
        {
            return orientadoBytes[value];
        }

        public string GetorientadoBits(int value)
        {
            return orientadoBits[value];
        }

        public string GetcontrolLiteral(int value)
        {
            return controlLiteral[value];
        }

        public string GetSaltos(int value)
        {
            return saltos[value];
        }

        #endregion

        // OP CODE, códigos de operaciones.
        #region Instrucciones orientadas a registros.
        private void Orientado_Bytes()
        {
            // orientadoBytes[0x00] = MOVWF y NOP  Al descompilar.
            // orientadoBytes[0x01] = CLRF y CLRW  Al descompilar.

            orientadoBytes[0x02] = "SUBWF";     // 00 0010 dfffffff.
            orientadoBytes[0x03] = "DECF";      // 00 0011 dfffffff.
            orientadoBytes[0x04] = "IORWF";     // 00 0100 dfffffff. 
            orientadoBytes[0x05] = "ANDWF";     // 00 0101 dfffffff.
            orientadoBytes[0x06] = "XORWF";     // 00 0110 dfffffff.
            orientadoBytes[0x07] = "ADDWF";     // 00 0111 dfffffff.
            orientadoBytes[0x08] = "MOVF";      // 00 1000 dfffffff. 
            orientadoBytes[0x09] = "COMF";      // 00 1001 dfffffff.
            orientadoBytes[0x0A] = "INCF";      // 00 1010 dfffffff.
            orientadoBytes[0x0B] = "DECFSZ";    // 00 1011 dfffffff. 
            orientadoBytes[0x0C] = "RRF";       // 00 1100 dfffffff.
            orientadoBytes[0x0D] = "RLF";       // 00 1101 dfffffff.
            orientadoBytes[0x0E] = "SWAPF";     // 00 1110 dfffffff.
            orientadoBytes[0x0F] = "INCFSZ";    // 00 1111 dfffffff. 
        }
        #endregion

        #region Instrucciones orientadas al bit.

        private void Orientado_Bits()
        {
            orientadoBits[0x04] = "BCF";        // 01 00bb bfffffff.
            orientadoBits[0x05] = "BSF";        // 01 01bb bfffffff.
            orientadoBits[0x06] = "BTFSC";      // 01 10bb bfffffff.
            orientadoBits[0x07] = "BTFSS";      // 01 11bb bfffffff.
        }
        #endregion

        #region Instrucciones literales y control.
        private void Control_Literal()
        {
            controlLiteral[0x08] = "RETURN";    // 00 0000 0000 1000.
            controlLiteral[0x09] = "RETFIE";    // 00 0000 0000 1001.
            controlLiteral[0x0C] = "MOVLW";     // 11 00xx kkkk kkkk.
            controlLiteral[0x0D] = "RETLW";     // 11 01xx kkkk kkkk.
            controlLiteral[0x1E] = "SUBLW";     // 11 110x kkkk kkkk.
            controlLiteral[0x1F] = "ADDLW";     // 11 111x kkkk kkkk.   
            controlLiteral[0x38] = "IORLW";     // 11 1000 kkkk kkkk.
            controlLiteral[0x39] = "ANDLW";     // 11 1001 kkkk kkkk.
            controlLiteral[0x3A] = "XORLW";     // 11 1010 kkkk kkkk.
            controlLiteral[0x63] = "SLEEP";     // 00 0000 0110 0011.
            controlLiteral[0x64] = "CLRWDT";    // 00 0000 0110 0100.
        }
        #endregion

        #region Instrucciones de saltos.
        private void Saltos()
        {
            saltos[0x04] = "CALL";              // 10 0kkk kkkk kkkk.
            saltos[0x05] = "GOTO";              // 10 1kkk kkkk kkkk.
        }
        #endregion
    }
}

Referencia Arduino.

Voy a averiguar como se envía en 64 Bytes en 64 Bytes por cada 5 ms. A lo mejor debo partir el archivo a cachos. Cuando lo averigue, lo hago saber por aquí.

@surbyte:
Por supuesto que se hará como debe ser. Precisamente ese detalle lo haré al final, ya que solo tengo dos manos por decirlo de alguna manera y estoy haciendo el funcionamiento interno primero.

Ahora toca controlar el puerto serie enviando 64 Bytes en 64 Bytes cada 5 ms según la EEPROM. Cuando ya me funcione una EEPROM, la que sea. Haré el Editor como debe ser, a parte de esto, mucho más grande, estamos en fase muy alfa. :wink:

Sigo investigando, va tomando forma...

Fue solo una sugerencia nada mas.

surbyte:
Fue solo una sugerencia nada mas.

Esa sugerencia la haré si o si, siempre y cuando el funcionamiento real de lo que estamos haciendo, funciona. :wink:

Gracias por la sugerencia. :wink:

La prioridad base es grabar y leer EEPROM tipo I2C, más adelante si todo anda bien, los SPI.

En este momento averiguando como partir un archivo hex para enviar páginas por páginas. Me centré en el 24LC256, los que tengo son el 24LC16B y el 24LC64. Voy a por ellos o si no me vuelvo loco.

Usaré Arduino UNO r3 y el KeyPad Shield de RF Robot que es el que tengo en este momento para hacer pruebas.

Hay que tener claro que pines a usar tanto para el I2C como el SPI para más adelante, ya que quiero incorporar todo junto.

Toda sugerencia bienvenida. :wink:

Saludos.

Edito:
Microchip 24LC16B - 16 Kbit - 16 Bytes.
CSI 24LC64LI - 64 Kbit - 32 Kbytes. Por lo que veo, me di cuenta que no tengo el de Microchip, sino otra empresa en el cual no lo encuentro por Internet. Lo más parecido que he visto es esta hoja de datos.

http://docs-europe.electrocomponents.com/webdocs/1573/0900766b81573771.pdf

Dejo claro que debo enviar Bytes por Bytes a Arduino, en este caso usando el 24LC16, 16 Bytes por cada 5 ms.

En C# ms = 1000, es lo mismo que 1 segundo. 5000 ms es igual a 5 segundos.

¿5 ms es igual a 0.005 segundos?

Enío un archivo que pesa 16 Kbit = 2048 Byte. Hay que enviar 16 Bytes por página. Para que se entienda.

Archivo pesa 2048 Bytes.

Hay que enviar 16 Bytes.

Timer(5 ms) o Delay (5 ms). (Mejor usar timer porque el delay deja esclavo al programa, es decir, que no se interrumpe hasta que se acabe el tiempo).

Como el total es de 2048 Bytes, que debo enviarlo cada 5 ms 16 Bytes hasta llegar el tope, sería 2048 / 16 = 128 veces enviando 16 Bytes.

Para que te hagas una idea.

Envio 16 Bytes.
Descansa 5 ms con el timer.
Envio 16 Bytes.
Timer(5 ms).
Envio 16 Bytes.
Timer(5 ms).
Envio 16 Bytes.
Timer(5 ms).
...

Así son unas 128 veces enviando 16 Bytes y completa los 2048 Bytes en total.

Se que suena royo.

Saludos.

Metaconta:
En este momento averiguando como partir un archivo hex para enviar páginas por páginas.

Nada del otro mundo; si el manejo de las páginas se lo dejaras al Arduino, lo único que tienes que hacer es enviar partes del archivo poco a poco.

Metaconta:
Por lo que veo, me di cuenta que no tengo el de Microchip, sino otra empresa en el cual no lo encuentro por Internet. Lo más parecido que he visto es esta hoja de datos.

http://docs-europe.electrocomponents.com/webdocs/1573/0900766b81573771.pdf

24C64 Datasheet, PDF - Alldatasheet

Podrá ser de un fabricante distinto, pero básicamente todas las hojas de datos coinciden: misma capacidad, mismo tamaño de página, mismo... todo.

Metaconta:
Dejo claro que debo enviar Bytes por Bytes a Arduino, en este caso usando el 24LC16, 16 Bytes por cada 5 ms.

16, 32, 64 o 128; eso depende del tamaño de la página. Es evidente que cuanto más grande sea, más rápido puede grabarse la EEPROM.

Metaconta:
En C# ms = 1000, es lo mismo que 1 segundo. 5000 ms es igual a 5 segundos.

¿5 ms es igual a 0.005 segundos?

No has fallado ni una sola jaja :smiley:

Metaconta:
(Mejor usar timer porque el delay deja esclavo al programa, es decir, que no se interrumpe hasta que se acabe el tiempo)..

Si quieres, aunque 5 ms son imperceptibles para cualquier ser humano. Cualquier otro mecanismo podría ser simplemente una sobrecomplicación.

Metaconta:
Para que te hagas una idea.

Envio 16 Bytes.
Descansa 5 ms con el timer.
Envio 16 Bytes.
Timer(5 ms).
Envio 16 Bytes.
Timer(5 ms).
Envio 16 Bytes.
Timer(5 ms).
...

Así son unas 128 veces enviando 16 Bytes y completa los 2048 Bytes en total.

Se que suena royo.

Si lo analizas bien, no es para tanto. Da la impresión de ser un procedimiento ineficiente; sin embargo vas a ver que no es así:

Un Arduino puede consumir 16 bytes del búfer RX en 1/8 de milisegundo, y el mayor retraso ocurre al esperar que la EEPROM escriba la página.
Si un evento casi instantáneo solo puede ocurrir cada 5 ms, entonces eso quiere decir que ocurre 1000 / 5 = 200 veces por segundo.
Si por "evento" se transfieren 16 bytes, eso quiere decir que efectivamente se escriben 16 * 200 = 3200 bytes por segundo.

Así como lo acabas de leer, 3200 B/s es la velocidad máxima efectiva de escritura de la EEPROM.
Aún con los sobrecargos adicionales de la CPU y la velocidad por defecto del bus I2C, ¡me atrevería a decir que es posible grabar la EEPROM de 2 KB en apenas un segundo!

Buenas gente del foro:

serialPort1.Write(archivo, 2048, 16);

serialPort1.Write(archivo, posicion, pagina);

archivo Variable tipo Byte[], simplemente un array que contiene la cantidad de Bytes.

2048 Bytes. Posición. En este ejemplo está ya al final. En realidad empezar con el 0.

16 Bytes. Envía 16 Bytes en 16 Bytes. Son 16 páginas.

Con el timer(5 ms).

Tengo que averiguar como implmentarlo porque e4stoy liado, ajjajaa ajajjajaja. No olvidar que estamos hablando del 24LC16B.

Saludos.