arduino DUE读写外置EEPROM-Arduino中文社区 - Powered by Discuz! Archiver

lmq21cn 发表于 2018-8-28 18:05

arduino DUE读写外置EEPROM

本帖最后由 lmq21cn 于 2018-8-28 18:13 编辑

电路:

当有数据需要存储时(如密码,设备参数等),相比于用SD卡,EEPROM可能更适合
由于arduino板上无EEPROM,需要外接EEPROM芯片。
在arduino CC上看到了两个示例,但这个示例比较容易理解,也简单一些。
做了一些修改,主要是增加了struct 结构体和数据处理,权当抛转引玉了,下面直接上代码:

虽然绝大部分代码是copy的,但是也有自己增加的部分,求个精!!!!!!!!!!!

//----------代码保留了原程序的所有注释------原程序地址:https://forum.arduino.cc/index.php?topic=62822.msg751697#msg751697--------
/*
*Use the I2C bus with small EEPROMs
*24C01, 20C02, 24C04, 24C08, 24C16
*Sketch:    I2C_EEPROM_Small.pde
*
*Derived from sketch for 24C64 devices posted on
*   http://www.arduino.cc/playground/Code/I2CEEPROM
*Fromhkhijhe   Date: 01/10/2010
*
*This one by davekw7x
*March, 2011
*
* For a single device, connect as follows:
* EEPROM 4 (GND) to GND
* EEPROM 8 (Vcc) to Vcc (5 Volts)(24C16手册上是3.3v)
* EEPROM 5 (SDA) to Arduino Analog Pin 4 (DUE Pin 20)
* EEPROM 6 (SCL) to Arduino Analog Pin 5    (DUE Pin21)
* EEPROM 7 (WP)to GND
* EEPROM 1 (A0)to GND (DUE , 不用接)
* EEPROM 2 (A1)to GND (DUE , 不用接)
* EEPROM 3 (A2)to GND (DUE , 不用接)
*/

/* Memory lenght in bytes
24C16 = 2048
24C08 = 1024
24C04 = 512
24C02 = 256
24C01 = 128
                     */

#define memorylenght 2048

#include <Wire.h>

const byte DEVADDR = 0x50;
struct GateInfo{
uint16_t SN;
uint16_t Width;
uint16_t stroke;
uint32_t EncoderOffset;
uint16_t FlumeOffset;
float testvalue;
uint32_t testv;
};

void setup()
{
   Wire.begin();
    Serial.begin(9600);
    char msg1[] = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris mollis leo sed odio fringilla consequat. Nulla egestas, turpis quis lacinia faucibus, lorem diam commodo dui, vel egestas lorem mi ac sem.";
    char msg2[] = "Message 1.";   // data to write
    char msg3[] = "Zaphod says yo";

    char msgf = {
      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
    };
    GateInfo gateInfo={8888,600,400,915000,250,10.56f,1000};
    char GateInfoBuff;
    memmove(GateInfoBuff,&gateInfo,sizeof(struct GateInfo));





    //
    // Change #if 0 to #if 1 and it will erase the
    // EEPROM pages that we are going to write to:
    //
    #if 0
      //eeprom_write_page(DEVADDR, 0x000, msgf, 16);
      //eeprom_write_page(DEVADDR, 0x010, msgf, 16);
      //eeprom_write_page(DEVADDR, 0x020, msgf, 16);
      //eeprom_write_page(DEVADDR, 0x100, msgf, 16);
      //eeprom_write_page(DEVADDR, 0x1f0, msgf, 16);
      //Serial.println("After erasing pages starting at 0x000, 0x100, and 0x1f0:");
          Serial.println("called #if 0");
      for (int erase = 0; erase < memorylenght; erase = erase + 16) {
      eeprom_write_pages(DEVADDR, erase, msgf, 16);

      }
      Serial.println("After erasing all pages:");
      eeprom_dump(DEVADDR, 0, memorylenght);
    #endif

    //
    // Change #if 1 to #if 0 so that it won't write over the stuff next time
    //
    #if 1
    // Write some stuff to EEPROM
      Serial.println("called #if 1");
    eeprom_write_pages(DEVADDR, 0x000, msg1, sizeof(msg1));
    eeprom_write_pages(DEVADDR, 0x100, GateInfoBuff, sizeof(GateInfoBuff));
    eeprom_write_pages(DEVADDR, 0x1e0, msg3, sizeof(msg3));
    #endif
    Serial.println("Memory written");
}

void loop()
{
    //
    // Read the first page in EEPROM memory, a byte at a time
    //
    Serial.println("eeprom_read_byte, starting at 0");
    for (int i = 0; i < 16; i++) {
      char b = eeprom_read_byte(DEVADDR, i);
      Serial.print(b, HEX);
      Serial.print(' ');
    }
    Serial.println();

    //
    // Read the first page using the read_buffer function
    //
    Serial.println("eeprom_read_buffer, starting at 0");
    char buffer;
    eeprom_read_buffer(DEVADDR, 0, buffer, sizeof(buffer));

    //
    //First print the hex bytes on this row
    //
    for (int i = 0; i < sizeof(buffer); i++) {
      char outbuf;
      sprintf(outbuf, "%02X2 ",buffer);
      Serial.print(outbuf);
    }
    Serial.println();

    //
    // Now print the char if printable ASCII
    // otherwise print '.'
    //
    for (int i = 0; i < sizeof(buffer); i++) {
      if (isprint(buffer)) {
            Serial.print(buffer);
      }
      else {
            Serial.print('.');
      }
    }
    Serial.println();

    // Now dump 512 bytes
    Serial.print("eeprom_dump(DEVADDR, 0, ");
    Serial.println(memorylenght);
    eeprom_dump(DEVADDR, 0, memorylenght);
    Serial.println();
    Serial.println("Read GateInfo Data");
    Serial.println("sizeof(struct GateInfo)");
   Serial.println(sizeof(struct GateInfo));
struct GateInfo *gateInfo2=(struct GateInfo*)malloc(sizeof(struct GateInfo));//={0,0,0,0,0};
   char buffer2;
   Serial.println("sizeof(buffer2)");
   Serial.println(sizeof(buffer2));
eeprom_read_buffer(DEVADDR, 0x100, buffer2, sizeof(struct GateInfo));

   memmove(gateInfo2,buffer2,sizeof(struct GateInfo));
   Serial.print("gateInfo2.SN");
Serial.println( gateInfo2->SN);
Serial.print("gateInfo2.Width");
Serial.println( gateInfo2->Width);
Serial.print("gateInfo2.stroke");
Serial.println( gateInfo2->stroke);
   Serial.print("gateInfo2.EncoderOffset");
    Serial.println(gateInfo2->EncoderOffset);
    Serial.print("gateInfo2.FlumeOffset");
Serial.println( gateInfo2->FlumeOffset);
Serial.print("gateInfo2.testvalue");
Serial.println( gateInfo2->testvalue);
Serial.print("gateInfo2.testv");
Serial.println( gateInfo2->testv);
    delay(20000);

    while (true) {};

}

void eeprom_write_byte(byte deviceaddress, int eeaddress, char data)
{
    // Three lsb of Device address byte are bits 8-10 of eeaddress
    byte devaddr = deviceaddress | ((eeaddress >> 8) & 0x07);
    byte addr    = eeaddress;
    Wire.beginTransmission(devaddr);
    Wire.write(int(addr));
    Wire.write(char(data));
    Wire.endTransmission();
    delay(10);
}


void eeprom_write_page(byte deviceaddress, unsigned eeaddr,
                     const char * data, byte length)
{
    // Three lsb of Device address byte are bits 8-10 of eeaddress
    byte devaddr = deviceaddress | ((eeaddr >> 8) & 0x07);
    byte addr    = eeaddr;
    Wire.beginTransmission(devaddr);
    Wire.write(char(addr));
    for (int i = 0; i < length; i++) {
      Wire.write(data);
    }
    Wire.endTransmission();
    delay(10);
}


// Be aware that you cannot write pages that are between bloks of 256 bytes
// They are in different addresses.
void eeprom_write_pages(byte deviceaddress, unsigned eeaddr,
                     const char * data, byte length)
{
//Serial.println("In writepages");
if ( length <= 16 ) {
    //Serial.println("In short");
    eeprom_write_page(deviceaddress, eeaddr, data, length);
    //Serial.println("Out short");
} else {
    //Serial.println("in Long");
    byte posizione = 0;
    unsigned my_eeaddr = eeaddr;
    while ( posizione < length ) {
      //Serial.println("start while posizione");
      char my_string;
      byte avanza = 0;
      while ( avanza < 16 ) {
   //Serial.println("start while 16");
      my_string = data;
      //Serial.println(avanza);
      //Serial.println(posizione);
      avanza++;
      posizione++;
      if ( posizione == length ) {
          //Serial.println("Brecco");
          break;
      }
      //Serial.println("End while 16");
      }
      eeprom_write_page(deviceaddress, my_eeaddr, my_string, avanza);
      my_eeaddr = my_eeaddr + 16;
      //Serial.println(avanza);
      //Serial.println(posizione);
      //Serial.println("End while posizione");
    }
//Serial.println("Out long");
}
}

// TODO: Change to integer data type and return -1 if can't
// read.
//
char eeprom_read_byte(byte deviceaddress, unsigned eeaddr)
{
    byte rdata = -1;

    // Three lsb of Device address byte are bits 8-10 of eeaddress
    byte devaddr = deviceaddress | ((eeaddr >> 8) & 0x07);
    byte addr    = eeaddr;

    Wire.beginTransmission(devaddr);
    Wire.write(int(addr));
    Wire.endTransmission();
    Wire.requestFrom(int(devaddr), 1);
    if (Wire.available()) {
      rdata = Wire.read();
    }
    return rdata;
}

//
// Returns number of bytes read from device
//
// Due to buffer size in the Wire library, don't read more than 30 bytes
// at a time!No checking is done in this function.
//
// TODO: Change length to int and make it so that it does repeated
// EEPROM reads for length greater than 30.

int eeprom_read_buffer(byte deviceaddr, unsigned eeaddr,
                        char * buffer, byte length)
{
    // Three lsb of Device address byte are bits 8-10 of eeaddress
    byte devaddr = deviceaddr | ((eeaddr >> 8) & 0x07);
    byte addr    = eeaddr;

    Wire.beginTransmission(devaddr);
    Wire.write(int(addr));
    Wire.endTransmission();

    Wire.requestFrom(devaddr, length);
    int i;
    for (i = 0; i < length && Wire.available(); i++) {
      buffer = Wire.read();
    }
    return i;
}

//
// The display is like hexdump -C.It will always
// begin and end on a 16-byte boundary.
//

void eeprom_dump(byte devaddr, unsigned addr, unsigned length)
{
    // Start with the beginning of 16-bit page that contains the first byte
    unsigned startaddr = addr & (~0x0f);

    // stopaddr is address of next page after the last byte
    unsigned stopaddr= (addr + length + 0x0f) & (~0x0f);

    for (unsigned i = startaddr; i < stopaddr; i += 16) {
      char buffer; // Hold a page of EEPROM
      char outbuf;//Room for three hex digits and ':' and ' ' and '\0'
      sprintf(outbuf, "%03x: ", i);
      Serial.print(outbuf);
      eeprom_read_buffer(devaddr, i, buffer, 16);
      for (int j = 0; j < 16; j++) {
            if (j == 8) {
                Serial.print(" ");
            }
            sprintf(outbuf, "%02x ", byte(buffer));
            Serial.print(outbuf);            
      }
      Serial.print(" |");
      for (int j = 0; j < 16; j++) {
            if (isprint(buffer)) {
                Serial.print(buffer);
            }
            else {
                Serial.print('.');
            }
      }
      Serial.println("|");
    }
}

zgy2018 发表于 2018-9-7 23:49

好东西,留个足迹,谢谢分享

新海蓝光 发表于 2018-12-5 17:43

ArduinoUNO可以吗?

A.Maker 发表于 2019-7-24 13:30

为什么器件地址是0X50,不是0XA0,根据官方手册中介绍bit7~bit4应该是1010而不是0101

qingyi1207 发表于 2022-7-12 22:42

mark一下,以后有用
页: [1]
查看完整版本: arduino DUE读写外置EEPROM