Almacenamiento de información (parte 3)


GENERANDO NÚMERO ALEATORIOS

Antes de continuar con el método de almacenamiento de información, necesitaremos tener un código que genere números aleatorios y los almacene en memoria temporal. Puedes modificar estos programas para almacenarlo en la memoria EEPROM interna.







Generaremos números aleatorios con la función random de PICAXE, pero la cual nos da una secuencia de valores aleatorios, así que si quieres que te salga valores más variados debes cambiar el valor de la variable antes de la función random para cambiar dicho valor. El comando sertxd sirve para enviar datos del PICAXE al PC y que se puedan desplegar en la ventana de PICAXE presionando F8.

main:
            random b0
            sertxd("valor aleatorio: ",#b0,13,10)
            pause 150       
goto main

Con memoria EEPROM interna:

for b0 = 0 to 10
            random b1
            write b0,b1
next b0

pause 2500

for b0=0 to 10
            read b0,b2
            sertxd("dato: ",#b2,13,10)
next b0







Se generarán 20 números aleatorios usando la función rand(), la cual es dividida por 1767 para colocar número inferiores de 20 en el arreglo. La función rand() al igual que la de PICAXE, genera números aleatorios en secuencia, así que si se quiere variar más los números se debe utilizar el comando srand().

int aleatorio[21],i;
char info[8], inf2[8];

void main(){
     Lcd_Init(&PORTB);
     Lcd_Cmd(Lcd_CLEAR);
     Lcd_Cmd(Lcd_CURSOR_OFF);

     for (i=0; i<=20;i++){
          aleatorio[i] = (rand()/1767);  //1767 es un valor para reducir el número aleatorio
          Lcd_out (1,1, "posicion: ");
          IntToStr(i,info); //convierte valor entero a char
          Lcd_out (1,11, info);
          IntToStr(aleatorio[i],inf2);
          Lcd_out (2,4,inf2);
          delay_ms(1000);
          Lcd_Cmd(Lcd_CLEAR);
     }
}











Utilizamos la función que proporciona el lenguaje para generar un número aleatorio y almacenarlo en un arreglo de 10 posiciones. Cabe destacar que la funcion Random siempre tiene la misma secuencia, así que si quieres que en tu programa genere varias veces números al azar y que no sean los mismos, debes usar randomSeed(valordereferencia) para hacer que se ajuste la aleatorización.

int datos[10],val;

void setup() {
  Serial.begin(9600);
  for (int j=0;j<11;j++){
    randomSeed(j+val);
    datos[j] = random(0, 50);
    val++;
    }
  for (int i=0;i<11;i++){ 
    Serial.println(datos[i]);
  }
  Serial.println("-----------");
}

void loop() {
 
}

BUSQUEDA DE INFORMACIÓN

Cuando almacenamos de una forma desordenada los datos en el microcontrolador, no tenemos un orden o un carácter de criterio para almacenar. A este tipo de arreglo de datos se les llama “Arreglos desordenados”.

Imaginemos el siguiente ejemplo: hemos creado un arreglo y queremos que a través de un ID tag busquemos el valor censado en el arreglo y si lo encuentra enciende un LED verde. Sino un LED rojo.

Así que tenemos que implementar una búsqueda, en un arreglo desordenado. La búsqueda se utiliza generalmente para recuperar datos que se habían almacenado antes. Los métodos de búsqueda pueden ser internos y externos.

La búsqueda interna trabaja con los elementos almacenados en la memoria del microcontrolador.

La búsqueda externa trabaja con los elementos almacenados en una memoria externa.

El único método que podemos utilizar (y el que pensamos utilizar casi intuitivamente) en un arreglo desordenado es una búsqueda secuencial desordenada. La cual consiste en revisar elemento tras elemento hasta encontrar el dato.

BUSQUEDA SECUENCIAL DESORDENADA – MEMORIA EEPROM INTERNA

El siguiente algoritmo muestra una búsqueda secuencial desordenada, en la cual lo que se busca comprobar es la posición del dato en el arreglo.

I: variable tipo entero.
X: elemento de un arreglo desordenado
V: arreglo
N: datos

Hacer I = 0
Mientras ((I<=N)y(v[I]<>X)) repetir
            Hacer I = I +1
{fin del ciclo}
Si (I>N)
            Entonces
                        Escribir: “no se encuentra la información”
            Si no
                        Escribir: “la información se encuentra en la posición: “, I
{fin de condición}

Ahora traducimos el algoritmo a cada uno de los microcontroladores que utilizamos:








Utilizaremos la función generadora de valores aleatorios y almacenaremos 11 datos al azar, buscaremos un número específico (11) y comprobaremos la funcionalidad del algoritmo. Debido a que PICAXE no tiene para arreglos, el programa se probará en la memoria EEPROM interna y además el algoritmo sufre un leve cambio ya que no se pueden implementar arreglos en este lenguaje.

#no_data 'no sobrescribe la EEPROM al momento de grabar este programa

pause 2500

b3 = 0
b5 = 0
do
            read b5,b4
            b3 = b3+1
            b5 = b5+1
loop while b3<=10 and b4<>11

if b3 > 10 then
            sertxd ("dato no encontrado")
else
            sertxd ("dato encontrado en posición: ", #b3,13,10)
endif







Utilizamos el código para generar números aleatorios, y comprobaremos la funcionalidad del algoritmo, buscando el número 7. El proceso lo realizaremos en memoria RAM, se hace esto para reducir el uso en la memoria EEPROM del microcontrolador.

int aleatorio[21],i,j;
char info[8],inf2[8];

void main(){
     TRISA.F0 = 0;
     Lcd_Init(&PORTB);
     Lcd_Cmd(Lcd_CLEAR);
     Lcd_Cmd(Lcd_CURSOR_OFF);
     PORTA.F0=0;

     for (j=0; j<=20;j++){
          aleatorio[j] = (rand()/1767);  //1767 es un valor para reducir el número aleatorio
     }

     /*for (i=0; i<=20;i++){  //se puede usar este ciclo para desplegar el arreglo y comprobar en que posición esta el número 7
          aleatorio[i] = (rand()/1767);
          Lcd_out (1,1, "posicion: ");
          IntToStr(i,info);
          Lcd_out (1,11, info);
          IntToStr(aleatorio[i],inf2);
          Lcd_out (2,4,inf2);
          delay_ms(1000);
          Lcd_Cmd(Lcd_CLEAR);
     } */

    
     delay_ms(750);
    
     i = 0;
     while ((i<=20) && (aleatorio[i]!=7)) {
           i++;
     }
     if (i>20){
        Lcd_Out(1,1,"no encontrado");
        }
     else{
        PORTA.F0=1;
        Lcd_Out(1,1,"posicion:");
        IntToStr(i, info);
        Lcd_Out(1,10,info);
     }
}












Utilizaremos la función generadora de valores aleatorios y almacenaremos 60 datos al azar, buscaremos un número específico (30) y comprobaremos la funcionalidad del algoritmo. El proceso lo realizaremos en memoria RAM.

int datos[60],val;

void setup() {
  Serial.begin(9600);
  for (int j=0;j<61;j++){ //generación de número aleatorios
    randomSeed(j+val);
    datos[j] = random(0, 80);
    val++;
    }
  for (int i=0;i<61;i++){   //despliega el arreglo
    Serial.print(i);
    Serial.print(": ");
    Serial.println(datos[i]);
  }
  Serial.println("-----------");
  int I = 1;  //algoritmo de búsqueda
  while (I<61 && datos[I]!=30)
  {
    I++;
  }
  if (I > 60)  {
    Serial.println("dato no encontrado");
    }
  else{
    Serial.print("la informacion se encuentra en la posicion: ");
    Serial.println(I);
  }   
}

void loop() {
 
}

El algoritmo anterior esta diseñado para buscar el primer valor y desplegarlo o si no se encontró, el siguiente algoritmo posee recursividad, lo cual significa que aunque encontró un valor, buscará los demás que son iguales.

I: variable tipo entero que inicia en 0.
X: elemento de un arreglo desordenado
V: arreglo
N: datos

Si (I>N)
            Entonces
                        Escribir: “información no encontrada”
            Si no
                        Si (V[I]=X)
                                   Entonces
                                               Escribir: “la información se encuentra en la posición”, I
                        {fin de la condición}
                        I = I +1
                        Regresar al paso 1 del algoritmo
{fin de la condición}







Generaremos 60 valores aleatorios y se realizará una búsqueda para encontrar el número 11 y que despliegue en pantalla en donde se encontró. Se ha agregado un ciclo para desplegar los valores y así comprobar la efectividad del ciclo de búsqueda.

for b0 = 0 to 60 'almacena valores
            random b1
            write b0,b1
next b0

'pause 1000   'ciclo para mostrar los valores almacenados (opcional)
'sertxd("datos",13,10)

'for b0=0 to 60
'           read b0,b2
'           sertxd("dato: ",#b2,13,10)
'next b0

pause 2500
sertxd ("buscando...",13,10)

b2= 0 'ciclo de busqueda
ciclo: if b2 > 60 then
                        sertxd("busqueda finalizada")
             else
                        read b2,b3
                        if b3 = 11 then
                                   sertxd("información encontrada en ",#b2,13,10)
                        endif
                        b2 = b2 +1
                        goto ciclo
             endif
stop







Se generan 20 números aleatorios, de los cuales se buscarán todos los números 7. Se esta utilizando un arreglo, así que si quieres hacer pruebas con la EEPROM del microcontrolador, debes modificar un poco el código. NOTA: el algorimo se modifico un poco, específicamente en la parte del salto para volver al primer paso del algoritmo. Se utilizo una sentencia while y un if.

int aleatorio[21],i,j;
char info[8],inf2[8];

void main(){
     TRISA.F0 = 0;
     Lcd_Init(&PORTB);
     Lcd_Cmd(Lcd_CLEAR);
     Lcd_Cmd(Lcd_CURSOR_OFF);
     PORTA.F0=0;

     for (j=0; j<=20;j++){
          aleatorio[j] = (rand()/1767);  //1767 es un valor para reducir el número aleatorio
     }

     /*for (i=0; i<=20;i++){  //se puede usar este ciclo para desplegar el arreglo y comprobar en que posición esta el número 7
          aleatorio[i] = (rand()/1767);
          Lcd_out (1,1, "posicion: ");
          IntToStr(i,info);
          Lcd_out (1,11, info);
          IntToStr(aleatorio[i],inf2);
          Lcd_out (2,4,inf2);
          delay_ms(1000);
          Lcd_Cmd(Lcd_CLEAR);
     }*/

     delay_ms(750);

     i = 0;          // ciclo de búsqueda
     while (i <= 20){
           if (aleatorio[i] == 7 ){
                    Lcd_Cmd(Lcd_CLEAR);
                    Lcd_Out(1,1,"posicion:");
                    IntToStr(i, info);
                    Lcd_Out(1,10,info);
                    delay_ms(700);
           }
           i++;
     }
     if (i > 20){
        Lcd_Cmd(Lcd_CLEAR);
        Lcd_Out(1,1,"busqueda fin.");
     }
}











Grabaremos 60 números aleatorios, de los cuales desplegaremos todos los números 4 que se encuentren  y se desplieguen en el monitor serial de Arduino. NOTA: el código para esta búsqueda tiene el mismo cambio que el que se hizo para PIC.

int datos[60],val;

void setup() {
  Serial.begin(9600);
  for (int j=0;j<61;j++){ //generación de número aleatorios
    randomSeed(j+val);
    datos[j] = random(0, 80);
    val++;
    }
  for (int i=0;i<61;i++){   //despliega el arreglo
    Serial.print(i);
    Serial.print(": ");
    Serial.println(datos[i]);
  }
  Serial.println("-----------");
 
  int I = 0; //algoritmo de búsqueda
  while (I <= 60){
    if (datos[I] == 4){
      Serial.print("posicion: ");
      Serial.println(I);
    }
    I++;
  }
  if (I > 60){
    Serial.println("busqueda finalizada");
   }
}

void loop() {
 
}

BUSQUEDA SECUENCIAL DESORDENADA – MEMORIA EEPROM EXTERNA

Para realizar una búsqueda externa se requiere de más tiempos de proceso por lo que la búsqueda es más lenta, si queremos optimizar y reducir el tiempo de lectura y escritura, debemos ordenar la memoria (tema que discutiremos en otra entrada).

El algoritmo para una búsqueda externa es el mismo para ambos casos, salvo que en este tipo de búsqueda se necesita identificar qué dispositivo externo es por lo tanto debemos utilizar correctamente el CS (bus SPI) o la dirección del dispositivo por I2C.







Utilizaremos el algoritmo de generación de números aleatorios y de búsqueda secuencial desordenada, almacenará 35 datos en la memoria EEPROM 24LC256 y buscará el número 11.



hi2csetup i2cmaster, %10100000, i2cslow, i2cword
pause 1500

main:
            for b1 = 0 to 35 'ciclo de almacenamiento aleatorio
                        random b0
                        sertxd("valor aleatorio ",#b1,": ",#b0,13,10)
                        hi2cout b1,(b0)
                        pause 10
            next b1

            b3 = 0 'ciclo de búsqueda
            b5 = 0
            sertxd(“buscando…”,13,10)
            do
                        hi2cin b5,(b4)
                        if b4 <> 11 then
                                   b3 = b3+1
                                   b5 = b5+1
                        endif
            loop while b3<=35 and b4<>11

            if b3 > 35 then
                        sertxd ("dato no encontrado")
            else
                        sertxd ("dato encontrado en posición: ", #b3,13,10)
            endif

El siguiente código es para la búsqueda secuencial desordenada con recursividad, con la misma configuración de datos de búsqueda del algoritmo pasado.

hi2csetup i2cmaster, %10100000, i2cslow, i2cword
pause 1500

main:
            for b1 = 0 to 35 'ciclo de almacenamiento aleatorio
                        random b0
                        sertxd("valor aleatorio ",#b1,": ",#b0,13,10)
                        hi2cout b1,(b0)
                        pause 10
            next b1

            sertxd ("buscando...",13,10)

            b2= 0 'ciclo de busqueda
            ciclo: if b2 > 35 then
                                   sertxd("busqueda finalizada")
                         else
                                    hi2cin b2,(b3)
                                   if b3 = 11 then
                                               sertxd("información encontrada en ",#b2,13,10)
                                   endif
                        b2 = b2 +1
                        goto ciclo
             endif
stop











El siguiente programa almacena 10 datos aleatorios en la memoria EEPROM 25LC256 y realiza una búsqueda secuencial desordenada. Pon atención en como esta trabajando el código y sus cambios que sufre al convertirse de un arreglo a un dispositivo externo SPI. Observa que hay un cambio en el algoritmo para incrementar I.



#include <SPI.h>
int datos,val,resultado=0;

void setup() {
  Serial.begin(9600);
  pinMode(10,OUTPUT);
  pinMode(2,OUTPUT);
  digitalWrite(10, HIGH);
  digitalWrite(2, HIGH);
  SPI.begin(); 
  SPI.setDataMode(SPI_MODE3);  //configura protocolo SPI
  SPI.setClockDivider(SPI_CLOCK_DIV2); // 10 Mhz max para 25LC256
  SPI.setBitOrder(MSBFIRST);
 
  digitalWrite(10, LOW);
  SPI.transfer(6);  // escritura habilitada 6
  digitalWrite(10, HIGH);
 
  digitalWrite(10, LOW);
  SPI.transfer(1); // remueve protección de bloque 1,0
  SPI.transfer(0);
  digitalWrite(10, HIGH);
  delay(5);
 
  for (int j=0;j<11;j++){ //generación de número aleatorios
    randomSeed(j+val);
    datos = random(0, 80);
   
    digitalWrite(10, LOW);
    SPI.transfer(6); // escritura habilitada 6
    digitalWrite(10, HIGH);
     
    digitalWrite(10, LOW);
    SPI.transfer(2); // write 2,0
    SPI.transfer(0);
    SPI.transfer(j); // registro
    SPI.transfer(datos); // dato a almacenar
    digitalWrite(10, HIGH);
    delay(5);
     
    digitalWrite(10, LOW);
    SPI.transfer(6); // escritura habilitada 6
    digitalWrite(10, HIGH);
   
    val++;
    Serial.print(j); //despliega el arreglo
    Serial.print(": ");
    Serial.println(datos);
    }
  digitalWrite(10, LOW);
  SPI.transfer(4); // escritura deshabilitada 4
  digitalWrite(10,HIGH);
  Serial.println("--------");
 
  int I = 0;  //algoritmo de búsqueda secuencial   
  while (I<11 && resultado!=56) //se busca el número 56
  {
    digitalWrite(10, LOW);
    SPI.transfer(3); // lee 3,0
    SPI.transfer(0);
    SPI.transfer(I);
    resultado = SPI.transfer(0x00);
    digitalWrite(10, HIGH);
   
    if (resultado != 56){ //si se cambia el número de búsqueda, cambiarlo también aquí
      I++;
    }
  }
  if (I > 10)  {
    Serial.println("dato no encontrado");
    }
  else{
    Serial.print("la informacion se encuentra en la posicion: ");
    Serial.println(I);
  }
}

void loop() {
}

Espera la próxima entrada y la última de almacenamiento de información, donde hablaremos sobre los arreglos ordenados.

Almacenamiento de información (parte 2)


Retomando el tema de almacenamiento de información, hablaremos de la memoria EEPROM externa.

Memoria EEPROM por I2C

¿Qué es el protocolo I2C (Inter-Integrated circuit)? es un protocolo que se usa ampliamente para enviar o recibir la información de varios microcontroladores en un mismo bus o algún otro hardware, en este caso una memoria EEPROM (24LC256, 24LC16B, etc.). Este protocolo se caracteriza porque tiene un bus de datos de 2 hilos SDA y SCL, además que los dispositivos esclavos tienen una identificación única en el bus (ej: %10101110), algunas veces esta dirección esta asignada por defaul dentro del IC.

El protocolo I2C puede trabajar a ciertas velocidades máximas de 100Khz, 400Khz y 1Mhz (según la EEPROM). Visita el sitio I2C para más información sobre el protocolo I2C.

Aquí tenemos algunas características de las EEPROM 24LCxxx:
  • La dirección de las 24LCxxx siempre empieza con %1010.
  • El pin WP (pin 7) es un pin de protección de escritura, si el pin esta conectado a 5v se activa la protección de escritura, si esta a GND se habilita la escritura.
  • Los pines A0, A1, A2 son los que definen la dirección de la memoria EEPROM.
  • Las memorias tienen una página de almacenamiento para evitar desbordamientos o que se atrase, aproximadamente una memoria EEPROM se tarda 10 ms en grabar un dato.

Te recomiendo que revises los laboratorios de PICAXE sobre protocolo I2C para mayor explicación de su implementación y de sus comandos.

Diagrama a utilizar:

CÓDIGO FUENTE (maestro escribe PICAXE20X2):
hi2csetup i2cmaster, %10100000, i2cslow, i2cword
low c.7
main:
for b1 = 0 to 15
b1=b1+3
hi2cout 0,(b1)
pause 12
next b1

CÓDIGO FUENTE (maestro lee PICAXE20X2):
hi2csetup i2cmaster, %10100000, i2cslow, i2cword
main:
for b1 = 0 to 15
b1=b1+3
hi2cin 0,(w2)
sertxd ("dato: ", #w2, 13,10)
pause 12
next b1




CÓDIGO FUENTE (maestro lee y escribe):


Diagrama a utilizar (Tomado del ejemplo de laboratorios para Arduino):


#include <Wire.h>
#define eeprom 0x50    //Dirección de la memoria 24LC256
int estado1, estado2, estado3, busqueda;
int luz = LOW;
byte valormem = 0xFF;
unsigned int direccion = 0;
void setup(void){
  pinMode (8,INPUT);
  pinMode (9,INPUT);
  pinMode (10,INPUT);
  pinMode (13,OUTPUT);
  Wire.begin();
}
void loop(){
  estado1 = digitalRead(8);
  if (estado1 == HIGH)
  {
    delay(150);
    estado1 = digitalRead(8);
    if (estado1 == LOW)
    {
       writeEEPROM(eeprom, direccion, 78);
    }
  }
  estado2 = digitalRead(9);
  if (estado2 == HIGH)
  {
    delay(150);
    estado2 = digitalRead(9);
    if (estado2 == LOW)
    {
       writeEEPROM(eeprom, direccion, 66);
    }
  }
  estado3 = digitalRead(10);
  if (estado3 == HIGH)
  {
    delay(150);
    estado3 = digitalRead(10);
    if (estado3 == LOW)
    {
      Wire.beginTransmission(eeprom);
      Wire.write((int)(direccion >> 8));   // MSB
      Wire.write((int)(direccion & 0xFF)); // LSB
      Wire.endTransmission();
      Wire.requestFrom(eeprom,1);
      if (Wire.available()) valormem = Wire.read();
      if (valormem == 78)
      {
       for (int ciclo=0;ciclo <21;ciclo++)
       {
         luz = !luz;
         digitalWrite(13,luz);
         delay (300);
         valormem = 0;
       }
      }
    }
  }
}
void writeEEPROM(int deviceaddress, unsigned int eeaddress, word data ) {
  Wire.beginTransmission(deviceaddress);
  Wire.write((int)(eeaddress >> 8));   // MSB
  Wire.write((int)(eeaddress & 0xFF)); // LSB
  Wire.write(data);
  Wire.endTransmission();
  delay(5);
}

Memoria EEPROM por SPI

¿Qué es el protcolo SPI (Serial Peripheral Interface)? Es bus de comunicación asincrónico que opera en el modo full duplex, emplea un simple registro de desplazamiento para transmitir la información. El bus SPI puede operar con un solo maestro o varios, los pines SPI son identificados MOSI (master output, slave input), MISO (master input, slave output), SCLK (serial clock) y SS (slave select). El bus SPI emplea un simple registro de desplazamiento para transmitir la información.

Para la 25LC256 su frecuencia máxiama de trabajo es 10 Mhz. Visita el sitio SPI para leer más del protocolo SPI.






PICAXE posee 2 métodos de comunicación por SPI, la primera es por software (podemos asignar los pines que deseemos para la comunicación) y la segunda por hardware.

  • spiout y spiin: son comandos por software para PICAXE, con los cuales podemos utilizar para comunicarnos con la memoria.
  • hspiout y hspiin: son comandos por hardware para PICAXE, donde únicamente nosotros tenemos que seleccionar el pin CS y los demás pines ya estan predefinidos. También este comando es más rapido en la comunicación que el de por software.

CÓDIGO FUENTE – SPI por SOFTWARE (maestro escribe y lee PICAXE20X2):


Diagrama a utilizar:

high b.7
pause 50
b0 = 0 'byte inferior de dirección
b1 = 0 'byte superior de dirección
b2 = 35 'dato a guardar
b3 = 3
main:
'habilita escritura spi
low b.7
spiout c.3,c.5,MSBFIRST_L,(6,2)
high b.7
'escribir el estado 0 al registro para desbloquear
low b.7
spiout c.3,c.5,MSBFIRST_L,(1,0)
high b.7
pause 5
'habilita escritura
low b.7
spiout c.3,c.5,MSBFIRST_L,(6)
high b.7
'escribe en EEPROM spi
low b.7
spiout c.3,c.5,MSBFIRST_L,(2,b1,b0,b2,b3)
high b.7
pause 5
debug
pause 500
'lee
low b.7
spiout c.3,c.5,MSBFIRST_L,(3,b1,b0)
spiin c.3,c.4, MSBPRE_L,(b6,b7)
high b.7
'habilita escritura
low b.7
spiout c.3,c.5,MSBFIRST_L,(6)
high b.7
'deshabilitar escritura
low b.7
spiout c.3,c.5,MSBFIRST_L,(4)
high b.7
'debug
debug
pause 1000
inc b2
inc b3
inc b0
goto main
CÓDIGO FUENTE – SPI por HARDWARE (maestro escribe):

Diagrama a utilizar (este circuito cambia al anterior):

NOTA: el LED en B.0 es un indicador cuando se ha terminado el ciclo:

b1 = 0
b0 = 0
hspisetup spimode11e, spimedium ; spi mode 1,1

low c.0
hspiout (6) ; envia escritura habilitada
high c.0

low c.0
hspiout (1,0) ; remueve protección de bloque
high c.0
pause 5

for b2 = 0 to 9
low c.0
hspiout (6) ; envia escritura habilitada
high c.0

low c.0
hspiout (2,0,b0,b1) ; Escribe b1 en la posición b0
high c.0
pause 5

low c.0
hspiout (6) ; envia escritura habilitada
high c.0

low c.0
hspiout (4) ; envia escritura deshabilitada
high c.0

inc b0
b1 = b1+8
debug
pause 1000
next b2

CÓDIGO FUENTE – SPI por HARDWARE (maestro lee):


hspisetup spimode11e, spimedium ; spi mode 1,1

pause 1000

for b3 = 0 to 9

low c.0
hspiout (3,0,b0) ; envia el comando de lectura a la dirección b0
hspiin (b2) ; almacena en b2
high c.0

inc b0
debug
pause 1000

next b3










Arduino posee una librería específica para protocolo SPI, la cual me causó un poco de confusión al momento de hacerla, por lo cual cree una entrada en el foro de Arduino, en la cual tuve el soporte necesario, puedes verlo dando click aquí FORO.

El algoritmo de programación para grabar en la memoria EEPROM es el mismo, únicamente había que adaptarlo al lenguaje de programación de Arduino.

Los pines para conectar SPI con Arduino son: pin digital 10 (SS), 11 (MOSI), 12 (MISO), y 13 (SCK). En el Arduino Mega: 50 (MISO), 51 (MOSI), 52 (SCK), y 53 (SS). El pin 10 (en el caso de Arduino UNO o el 50 para el Mega) debe configurarse con pinMode(10,OUTPUT); y cada vez que se mande una instrucción se pone digitalWrite(10,LOW); y cuando termina el comando se cierra con digitalWrite(10,HIGH);.

Para saber más de la librería SPI, visita http://arduino.cc/en/Reference/SPI.

Diagrama a Utilizar:




CÓDIGO FUENTE – SPI (maestro lee y escribe):
#include <SPI.h>
int variable = 2;
int resultado, registro=0;

void setup() {
  pinMode(10,OUTPUT);
  digitalWrite(10, HIGH);
  Serial.begin(9600);
  SPI.begin();
  SPI.setDataMode(SPI_MODE3);  //configura protocolo SPI
  SPI.setClockDivider(SPI_CLOCK_DIV2); // 10 Mhz max para 25LC256
  SPI.setBitOrder(MSBFIRST);

  digitalWrite(10, LOW);
  SPI.transfer(6);  //escritura habilitada 6
  digitalWrite(10, HIGH);

  digitalWrite(10, LOW);
  SPI.transfer(1); //remove block protection 1,0
  SPI.transfer(0);
  digitalWrite(10, HIGH);
  delay(5);

  for(int j=0; j<9; j++)
  {
      digitalWrite(10, LOW);
      SPI.transfer(6); //escritura habilitada 6
      digitalWrite(10, HIGH);
   
      digitalWrite(10, LOW);
      SPI.transfer(2); // escribe 2,0
      SPI.transfer(0);
      SPI.transfer(registro); // registro
      SPI.transfer(variable); // data
      digitalWrite(10, HIGH);
      delay(5);
   
      digitalWrite(10, LOW);
      SPI.transfer(6); // escritura habilitada 6
      digitalWrite(10, HIGH);
   
      digitalWrite(10, LOW);
      SPI.transfer(3); // lee 3,0
      SPI.transfer(0);
      SPI.transfer(registro); // registro
      resultado = SPI.transfer(0x00);
      digitalWrite(10, HIGH);
   
      Serial.print("direccion");
      Serial.print(registro);
      Serial.print(" : ");
      Serial.println(resultado);
      registro++;
      variable++;
  }
  digitalWrite(10, LOW);
  SPI.transfer(4); // escritura deshabilitada 4
  digitalWrite(10, HIGH);
}

void loop() {}

CÓDIGO FUENTE – SPI (maestro escribe):

NOTA: el LED en el pin digital 2 es un indicador cuando se ha terminado el ciclo. 
#include <SPI.h>
int variable = 56;
int resultado, registro=0;
void setup() {
  pinMode(10,OUTPUT);
  pinMode(2,OUTPUT);
  digitalWrite(10, HIGH);
  digitalWrite(2, HIGH);
  SPI.begin();
  SPI.setDataMode(SPI_MODE3);  //configura protocolo SPI
  SPI.setClockDivider(SPI_CLOCK_DIV2); // 10 Mhz max para 25LC256
  SPI.setBitOrder(MSBFIRST);

  digitalWrite(10, LOW);
  SPI.transfer(6);  // escritura habilitada 6
  digitalWrite(10, HIGH);

  digitalWrite(10, LOW);
  SPI.transfer(1); // remueve protección de bloque 1,0
  SPI.transfer(0);
  digitalWrite(10, HIGH);
  delay(5);

  for(int j=0; j<9; j++)
  {
      digitalWrite(10, LOW);
      SPI.transfer(6); // escritura habilitada 6
      digitalWrite(10, HIGH);
   
      digitalWrite(10, LOW);
      SPI.transfer(2); // write 2,0
      SPI.transfer(0);
      SPI.transfer(registro); // registro
      SPI.transfer(variable); // dato a almacenar
      digitalWrite(10, HIGH);
      delay(5);
   
      digitalWrite(10, LOW);
      SPI.transfer(6); // escritura habilitada 6
      digitalWrite(10, HIGH);
      registro++;  // +1
      variable++;  // +1
  }
  digitalWrite(10, LOW);
  SPI.transfer(4); // escritura deshabilitada 4
  digitalWrite(10, HIGH);
}
void loop() {
digitalWrite(2, LOW);
}

CÓDIGO FUENTE – SPI (maestro lee):
#include <SPI.h>
int resultado, registro=0;

void setup() {
  pinMode(10,OUTPUT);
  pinMode(2,OUTPUT);
  digitalWrite(10, HIGH);
  digitalWrite(2, HIGH);
  Serial.begin(9600);
  SPI.begin();
  SPI.setDataMode(SPI_MODE3);  //configura protocolo SPI
  SPI.setClockDivider(SPI_CLOCK_DIV2); // 10 Mhz max para 25LC256
  SPI.setBitOrder(MSBFIRST);

  for(int j=0; j<9; j++)
  {
      digitalWrite(10, LOW);
      SPI.transfer(3); // lee 3,0
      SPI.transfer(0);
      SPI.transfer(registro);
      resultado = SPI.transfer(0x00);
      digitalWrite(10, HIGH);
   
      Serial.print("direccion");
      Serial.print(registro);
      Serial.print(" : ");
      Serial.println(resultado);
      registro++;
  }
}

void loop() {
digitalWrite(2, LOW);
}