A EEPROM(Electrically-Erasable Programmable Read-Only) é uma memória que permite escrita e gravação e seus dados não são apagados quando não há energia. As memórias flash(pen driver, SD e outros), são uma evolução desse tipo de memória. A EEPROM pode ser utilizada para armazenar algumas informações do seu programa que precisam ser salvas quando não houver energia. Para mais informações sobre esse tipo de memória, consulte aqui.
Os micro-controladores que estão presentes nas mais diversas versões do Arduíno, têm diferentes quantidades de memória EEPROM disponíveis.
- ATmega328 - 1KB (1024 bytes)
- ATmega168 e ATmega8 - 512 bytes
- ATmega1280 e ATmega2560 - 4 KB (4096 bytes)
É possível acessar a EEPROM dos micro-controladores e há uma biblioteca disponível para isso na própria IDE do Arduíno. A documentação pode ser encontrada aqui.
Mas, neste post, iremos focar no uso de EEPROMs externas que utilizam o barramento I²C para leitura e escrita.
Existem no mercado diversas marcas e modelos de memória, com os mais diversos tamanhos e para cada uma delas, há um protocolo definido para se comunicar e por isso, é difícil ter um código genérico de acesso. Esse exemplo funcionará para as EEPROMs do tipo 24C16,que são bem comuns.
EEPROM 24C16WP
Essa memória tem 16 Kbits (2 Kbytes) de armazenamento, permitindo a leitura e escrita byte-a-byte ou em blocos (páginas). Aqui, iremos abordar a leitura e escrita byte-a-byte.
Montagem
Segue a lista de materiais utilizados:
- 1 Memória EEPROM 24C16WP
- 1 Arduíno Uno
- 1 Protoboard
- Alguns fios
Segue abaixo os pinos da memória:
Pinagem 24C16WP
Os pinos 6 (SCL) e 5 (SDA), são utilizados para o barramento I²C e devem ser conectados aos pinos analógicos do Arduíno A4 (SDA - Data ) e A5 (SCL - Clock)
O endereçamento I²C da memória inicia em 0x50 e vai até 0x57. Os pinos NC são utilizados para o ajustar esse endereçamento se aterrados(GND) ou ligados ao VCC.
Exemplo:
- NC - 0, NC - 0, NC - 0 -> Endereço da memória 0x50
- NC - 0, NC - 0, NC - 1 -> Endereço da memória 0x51
- NC - 0, NC - 1, NC - 0 -> Endereço da memória 0x52
Essa configuração é interessante, pois podemos colocar até 8 memórias no mesmo barramento.
O pino 7(WC), é utilizado para indicar se a memória está protegida contra gravação ou não. Se "0" - ligado ao GND, a memória pode ser escrita. Se "1" - ligada ao VCC, protegida contra gravação.
Para o nosso exemplo, utlizaremos os pinos abaixo:
EEPROM | Arduíno |
6(SCL) | A5(SCL) |
5(SDA) | A4(SDA) |
8(VCC) | VCC |
4(VSS) | GND |
7(WC) | GND |
Segue abaixo do esquemático:
Esquema feito no programa Fritzing
Vamos ao programa:
#include ‹Wire.h›
#define i2cAddress 0x50 //Endereço da memoria
void setup(void)
{
Serial.begin(115200);
Wire.begin(); //inicializando I2C
int sizeBuf = 21;
char buf[sizeBuf] = "teste gravando eeprom";
Serial.print("Gravando... \n");
for(int i = 0; i < sizeBuf; i++)
{
writeI2CEEPROM(i2cAddress,i,buf[i]);
}
Serial.print("Lendo... \n");
for(int i = 0; i < sizeBuf; i++)
{
Serial.print((char)readI2CEEPROM(i2cAddress,i));
}
Serial.print("\nFim... \n");
}
void loop(){}
void writeI2CEEPROM(int i2cAddr, byte memoryAddress, byte data)
{
Wire.beginTransmission(i2cAddr);//iniciando barramento para o endereco I2C da memoria
Wire.write(memoryAddress);//informando endereco da memoria
Wire.write(data);//dados
Wire.endTransmission();//finalizando transmissao do emissor
delay(5);
}
byte readI2CEEPROM(int i2cAddr, byte memoryAddress)
{
byte data = 0xFF;
Wire.beginTransmission(i2cAddr);//iniciando barramento para o endereco I2C da memoria
Wire.write(memoryAddress);//informando endereco da memoria
Wire.endTransmission();//finalizando transmissao do emissor
Wire.requestFrom(i2cAddr,1);//avisando a memoria que espera-se dado (1 byte)
if (Wire.available()){
data = Wire.read();
}
return data;
}
No código acima, iremos escrever na memória a frase "teste gravando eeprom" e na sequência, os valores serão recuperados.
Vamos explicar alguns pontos do código.
void writeI2CEEPROM(int i2cAddr, byte memoryAddress, byte data)
{
Wire.beginTransmission(i2cAddr);//iniciando barramento para o endereco I2C da memoria
Wire.write(memoryAddress);//informando endereco da memoria
Wire.write(data);//dados
Wire.endTransmission();//finalizando transmissao do emissor
delay(5);
}
O método writeI2CEEPROM tem três parâmetros:
- i2cAddr - Endereço I²C da memória
- memoryAddress - endereço da memória (0 até 255)
- data - byte que será gravado
Como já citado anteriormente, essa memória suporta até 2 Kbytes e por isso, ela terá 256 endereços para escrita e leitura (de 0 atá 255). Para escrever na memória, é necessário iniciar a transmissão, indicar o endereço da memória, enviar o byte e finalizar a transmissão. Esse protocolo, está definido no datasheet da memória, que pode ser consultado aqui.
byte readI2CEEPROM(int i2cAddr, byte memoryAddress)
{
byte data = 0xFF;
Wire.beginTransmission(i2cAddr);//iniciando barramento para o endereco I2C da memoria
Wire.write(memoryAddress);//informando endereco da memoria
Wire.endTransmission();//finalizando transmissao do emissor
Wire.requestFrom(i2cAddr,1);//avisando a memoria que espera-se dado (1 byte)
if (Wire.available()){
data = Wire.read();
}
return data;
}
- i2cAddr - Endereço I²C da memória
- memoryAddress - endereço da memória (0 até 255)
Assim como na escrita, o protocolo de leitura está definido no datasheet da memória mas, de maneira resumida temos: inicio da transmissão, envia-se o endereço, finalização a transmissão, requisita-se a resposta e faz-se a leitura do valor se estiver disponível.
Segue a saída desse programa:
Para comprovar a a gravação, você pode comentar o trecho que faz a gravação. Ficando assim:
Sem comentários:
Enviar um comentário