TAG | EEPROM
如果你的Arduino中要做少量的数据存储,那么使用EEPROM可能是最简单易行的做法了。其实Arduino所使用的芯片ATmega本身就具备一定的EEPROM存储器,只不过数量有限罢了。我们设计的这款外置式EEPROM存储模块使用I2C总线来与Arduino进行连接,并且采用可插拔的芯片,直插式系列,这样在扩展容量时会比较容易,基本上只需要按一个更大容量的EEPROM芯片就可以了。
该存储模块上使用的是AT24C系列的EEPROM芯片,其I2C基地址为0×50,最后三位地址可以根据应用需要进行设置。因此使用时我们首先要对其地址的最后三位进行设置,这是通过4位拨码开关上的A2,A1和A0来完成的,其中A0表示地址的最后一位。拨码开关向上推时相应的位为1,向下推时相应的位为0。也就是说,如果将A2,A1,A0都拨到上方时,相应的地址为0×57;而如果将A2,A1,A0都拨到下方时,相应的地址为0×50。
该存储模块上另外一个需要设置的地方就是开关RS,它是用来设置是否往I2C总线上的SDA和SCL上接入板载的上拉电阻。我们知道,I2C之所以被称为总线,就是因为可以连接多个I2C设备,接照I2C协议的规定,只允许在离控制器最近的一个I2C设备处接上拉电阻。说到这里你可能已经明白了,如果有多个这个的存储模块连接到Arduino的I2C总线上时,我们必须将第一个(离Arduino最近)存储模块的RS开关设置到ON的位置,而其它存储模块上的RS则不能设置到ON的位置:
如果使用的是Arduino专用传感器扩展扩展板V4,注意IIC/COM跳线的位置要设置到IIC这一边,因为此时我们需要用到I2C连接方式:
上述设置完成之后,我们只需要用I2C/COM连接线将EEPROM存储模块连接到传感器扩展板上就完成硬件的连接了:
至于软件部分,Arduino的官方网站上提供了两个不错的链接:I2CEEPROM和TWIPROM,需要的话可以参考。下面是我们测试时所用的代码:
#include <Wire.h> #define EEPROM_ADDR 0x50 // I2C Buss address of 24LC256 256K EEPROM void setup() { Wire.begin(); // join I2C bus (address optional for master) Serial.begin(9600); // TESTS FOR EACH FUNCTION BEGIN HERE Serial.println("Writing Test:"); for (int i=0; i<20; i++){ // loop for first 20 slots i2c_eeprom_write_byte(EEPROM_ADDR,i,i+65); // write address + 65 A or 97 a Serial.print(". "); delay(10); // NEED THIS DELAY! } Serial.println(""); delay(500); Serial.println("Reading Test:"); for (int i=0; i<20; i++){ // loop for first 20 slots Serial.print(i2c_eeprom_read_byte(EEPROM_ADDR, i),BYTE); Serial.print(" "); } // setup for page tests . . . byte PageData[30]; // array that will hold test data for a page byte PageRead[30]; // array that will hold result of data for a page for (int i=0; i<30; i++){ // zero both arrays for next test PageData[i] = 0; PageRead[i] = 0; } Serial.println(""); for (int i=0; i<30; i++) PageData[i] = i+33; // fill up array for next test char 33 = ! Serial.println("Writing Page Test:"); i2c_eeprom_write_page(EEPROM_ADDR, 100, PageData, 28 ); // 28 bytes/page is max Serial.println("Reading Page Test:"); i2c_eeprom_read_buffer( EEPROM_ADDR, 100, PageRead, 28); for (int i=0; i<28; i++){ Serial.print(PageRead[i],BYTE); // display the array read Serial.print(" "); } } void loop() { } void i2c_eeprom_write_byte( int deviceaddress, unsigned int eeaddress, byte data ) { int rdata = data; Wire.beginTransmission(deviceaddress); Wire.send((int)(eeaddress >> 8)); // Address High Byte Wire.send((int)(eeaddress & 0xFF)); // Address Low Byte Wire.send(rdata); Wire.endTransmission(); } // Address is a page address, 6-bit (63). More and end will wrap around // But data can be maximum of 28 bytes, because the Wire library has a buffer of 32 bytes void i2c_eeprom_write_page( int deviceaddress, unsigned int eeaddresspage, byte* data, byte length ) { Wire.beginTransmission(deviceaddress); Wire.send((int)(eeaddresspage >> 8)); // Address High Byte Wire.send((int)(eeaddresspage & 0xFF)); // Address Low Byte byte c; for ( c = 0; c < length; c++) Wire.send(data[c]); Wire.endTransmission(); delay(10); // need some delay } byte i2c_eeprom_read_byte( int deviceaddress, unsigned int eeaddress ) { byte rdata = 0xFF; Wire.beginTransmission(deviceaddress); Wire.send((int)(eeaddress >> 8)); // Address High Byte Wire.send((int)(eeaddress & 0xFF)); // Address Low Byte Wire.endTransmission(); Wire.requestFrom(deviceaddress,1); if (Wire.available()) rdata = Wire.receive(); return rdata; } // should not read more than 28 bytes at a time! void i2c_eeprom_read_buffer( int deviceaddress, unsigned int eeaddress, byte *buffer, int length ) { Wire.beginTransmission(deviceaddress); Wire.send((int)(eeaddress >> 8)); // Address High Byte Wire.send((int)(eeaddress & 0xFF)); // Address Low Byte Wire.endTransmission(); Wire.requestFrom(deviceaddress,length); //int c = 0; for ( int c = 0; c < length; c++ ) if (Wire.available()) buffer[c] = Wire.receive(); }
上述代码运行时的效果如下图所示:

