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:
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):
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.
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
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);.
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);
}
No hay comentarios:
Publicar un comentario