# 5. EEPROM（电擦除存储器）

EEPROM的用法同Arduino UNO一样，分为读和写两种操作。

读取操作：

* EEPROM存储器的I2C地址
* EEPROM内部地址（存储数据的地址）
* 读取数值

写入操作：

* EEPROM存储器的I2C地址
* EEPROM内部地址（存储数据的地址）
* 写入数值

在BiBoard的例程中，我们的EEPROM在I2C总线上的地址是0x54，容量为8192Bytes（64Kbit）。我们往EEPROM里从第一个地址开始顺序写入0到15一共16个数值，然后再读出来进行对比。理论上EEPROM写入的数值和对应的地址应该相同。

在NyBoard出厂测试中，我们也是使用这种方法，只不过更复杂一些。我们会使用固定列表填满EEPROM再读取出来进行对比。

```
#include <Wire.h>

#define EEPROM_ADDRESS 0x54
#define EEPROM_CAPACITY 8192       // 64Kbit
#define EEPROM_TESTBYTES 16

// write 1 byte EEPROM by address
void writeEEPROM(int deviceaddress, unsigned int eeaddress, byte data ) 
{
  Wire.beginTransmission(deviceaddress);
  Wire.write((int)(eeaddress >> 8));   // MSB
  Wire.write((int)(eeaddress & 0xFF)); // LSB
  Wire.write(data);
  Wire.endTransmission();
 
  delay(5);
}

// read 1 byte EEPROM by address
byte readEEPROM(int deviceaddress, unsigned int eeaddress ) 
{
  byte rdata = 0xFF;
 
  Wire.beginTransmission(deviceaddress);
  Wire.write((int)(eeaddress >> 8));   // MSB
  Wire.write((int)(eeaddress & 0xFF)); // LSB
  Wire.endTransmission();
 
  Wire.requestFrom(deviceaddress,1);
 
  if (Wire.available()) 
    rdata = Wire.read();
  return rdata;
}

void testI2CEEPROM(){

    byte tmpData = 0;

    Serial.println("EEPROM Testing...");
    
    // write EEPROM from 0 to EEPROM_TESTBYTES
    for(int i = 0; i < EEPROM_TESTBYTES; i++){
        writeEEPROM(EEPROM_ADDRESS, i, i % 256);
        delay(1);
    }

    Serial.println();
    
    // read from 0 to EEPROM_TESTBYTES
    for(int i = 0; i < EEPROM_TESTBYTES; i++){
        tmpData =  (int)readEEPROM(EEPROM_ADDRESS, i);
        Serial.print(tmpData);
        Serial.print("\t");
    }
}


void setup(){

    Serial.begin(115200);
    Wire.begin();
    
    testI2CEEPROM();
}

void loop(){
  
}
```

最后一点需要注意，EEPROM的操作，尤其是写入操作一般不会放入loop()循环当中。虽然EEPROM很耐擦写（10万次），但如果在loop循环中频繁写入某一个块，会导致EEPROM出故障的。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.petoi.com/chinese/biboard/li-cheng/5.-eeprom-dian-ca-chu-cun-chu-qi.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
