加饭 发表于 2014-8-28 11:38:30

求教Arduino外置EEPROM的代码

手上有一块UNO,记录编码器数据和运行时间,UNO内部EEPROM有点小,想拓展至外部EEPROM,用<EEPROM.h>库是不是只能写在UNO内部?怎样才能写到外部EEPROM中?

Youyou 发表于 2014-8-28 13:19:21

本帖最后由 Youyou 于 2014-8-28 13:28 编辑

      你好,你是打算外扩什么样的芯片呢?如果是AT24CXX系列,比如AT24C32,操作挺简单的,直接用I2C的库进行操作就好了。具体的代码,可以自己看下收据手册来写,或者在github上找相关的代码。
      这段关于I2C的EEPROM代码你可以参考下:https://github.com/Soshimo/I2C-Serial-EEPROM-Arduino-Library

加饭 发表于 2014-8-28 17:31:16

Youyou 发表于 2014-8-28 13:19
你好,你是打算外扩什么样的芯片呢?如果是AT24CXX系列,比如AT24C32,操作挺简单的,直接用I2C的 ...

感谢大神的提点,现在遇到一个问题(我用的是AT24C#include <Wire.h>
#include <i2cEEPROM.h>

i2cEEPROMClass(rom);

void setup()
{
Serial.begin(9600);

rom.begin(0);
rom.writeByte(0,0xaa); delay(10);
}

void loop()
{
byte a = rom.readByte(0); delay(10);

Serial.println(a); delay(10);
delay(1000);
}
02N),根据你提供的库写代码,却无法将数据写入EEPROM中,每次读取都为255,求指点

Youyou 发表于 2014-8-28 18:08:15

加饭 发表于 2014-8-28 17:31
感谢大神的提点,现在遇到一个问题(我用的是AT24C
02N),根据你提供的库写代码,却无法将数据写入EEPRO ...

你的器件地址设置错误,你对照下数据手册和自己的接线方法,把AT24C02的地址确定下来,这个地址在I2C通讯中用来寻址。
void begin(int deviceId);这条函数就是用来设置地址的,但你却填了0,从机的地址错了,那肯定读和写都是错误的。

加饭 发表于 2014-8-28 18:47:35

Youyou 发表于 2014-8-28 18:08
你的器件地址设置错误,你对照下数据手册和自己的接线方法,把AT24C02的地址确定下来,这个地址在I2C通讯 ...

我将AT24C02的A0~A2都接地,那int deviceId = 0 ?

加饭 发表于 2014-8-29 10:32:53

Youyou 发表于 2014-8-28 18:08
你的器件地址设置错误,你对照下数据手册和自己的接线方法,把AT24C02的地址确定下来,这个地址在I2C通讯 ...

经过查证,地址修改为0x50,但读取数据后,Wire.endTransmission()为0,数据依旧是0xFF,错在哪里?

Youyou 发表于 2014-8-29 11:17:07

加饭 发表于 2014-8-29 10:32
经过查证,地址修改为0x50,但读取数据后,Wire.endTransmission()为0,数据依旧是0xFF,错在哪里? ...

把你的完整代码还有完整的连线图发上来看看,不然很难知道哪个细节出了问题。

加饭 发表于 2014-8-29 12:15:28

Youyou 发表于 2014-8-29 11:17
把你的完整代码还有完整的连线图发上来看看,不然很难知道哪个细节出了问题。 ...

经过部分修改,能写入24C02中,但读取出问题——不管读取#include <Wire.h>
#include <i2cEEPROM.h>

i2cEEPROMClass(rom);
int R_W=2;         // LOW is write data ; HIGH is read data
void setup()
{
Serial.begin(9600);
pinMode(R_W,OUTPUT);

rom.begin(0x57);
digitalWrite(R_W,LOW);
rom.writeByte(1,0xaa); delay(10);
rom.writeByte(10,0xbb); delay(10);
rom.writeByte(2,0xcc); delay(10);


/* writeString(2,"star");
delay(10);
writeString(3,"end");
delay(10);*/
}

void loop()
{
rom.begin(0x57);
digitalWrite(R_W,HIGH);
byte a = rom.readByte(10); delay(10);

Serial.println(Wire.endTransmission());delay(10);
Serial.println(a,HEX); delay(10);
delay(1000);

}
地址为多少,读取结果为最后一个写入结果,代码及电路图如下,求赐教

Youyou 发表于 2014-8-29 16:39:50

本帖最后由 Youyou 于 2014-8-29 22:52 编辑

你的连线图没有问题,按照此图,你的地址0X57也是对的。你参考下我的代码试试看,我经过测试,成功写入并读取的。
我的连线是:A0到A2全部接地,WP管脚也接地。串口看读取的值,每一次按下复位键,打印的值就会增长一次。
#include "Wire.h"
#include "i2cEEPROM.h"
void setup()
{
i2cEEPROM.begin(0x50);
byte num = i2cEEPROM.readByte(0)+1;
i2cEEPROM.writeByte(0,num);
Serial.begin(9600);
}
void loop()
{
Serial.println(i2cEEPROM.readByte(0));
delay(1000);
}

注:该连线图只适用于Arduino UNO!

顺便说一下,我发现如果先初始化串口再初始化I2C,在这中间需要加入一些延时,否则读出的数据也不对,一直是255。
也就是说,需要改成这样:
void setup()
{
Serial.begin(9600);
delay(10);
i2cEEPROM.begin(0x50);
byte num = i2cEEPROM.readByte(0)+1;
i2cEEPROM.writeByte(0,num);
}





加饭 发表于 2014-8-29 19:53:51

Youyou 发表于 2014-8-29 16:39
你的连线图没有问题,按照此图,你的地址0X57也是对的。你参考下我的代码试试看,我经过测试,成功写入并读 ...

这次串口读取的数据一直都是255...更换两颗能正常使用的AT24C02,结果都一样~:dizzy: :'(请问你用的是什么板子?我用的是某宝山寨的MEGA2560~

Youyou 发表于 2014-8-29 22:50:25

加饭 发表于 2014-8-29 19:53
这次串口读取的数据一直都是255...更换两颗能正常使用的AT24C02,结果都一样~ 请问你用的是什 ...

我用的是Arduino UNO,所以,SDA和SCL就是A4和A5。
你用的是mega2560,那么SDA和SCL就是D20和D21,注意板子的区别。你修改下连线。
还有,根据你的连线图,AT24C02的地址设置管脚(A0A1A2)都接成了高电平,那么器件地址就是0x57。我的连线方式是将他们全部置为低电平,所以器件地址为0x50。你修改下代码就可以用了。

加饭 发表于 2014-9-1 11:08:41

本帖最后由 加饭 于 2014-9-1 11:15 编辑

Youyou 发表于 2014-8-29 22:50
我用的是Arduino UNO,所以,SDA和SCL就是A4和A5。
你用的是mega2560,那么SDA和SCL就是D20和D21,注意板 ...
我不用那个库文件,改用共用体,但出了个奇怪的问题——我AT24C02明明全接低电平(代码中硬件地址应该0x50),但经过write_data(0x57 ,0x00 ,0x11);这一句后,读取的内容变成0x11,怎么会这样呢?而且,只要软件中编写硬件地址在0x50~0x57之间,都能写入EEPROM中,已经确定SDA和SCL的引脚没有接错,求大神指点</blockquote></div><div class="blockcode"><blockquote>#include <Wire.h>
// 从指定位置写一个数据
void setup()
{
Serial.begin(9600);
delay(10);
Wire.begin();
}

byte val = 0;
int index = 0;
void loop()
{
byte a0 = 0x00;
byte b0 = 0x00;
write_data(0x50 ,0x00 ,0xbb);
write_data(0x57 ,0x00 ,0x11);

a0 = read_data(0x50 ,0x00);
b0 = read_data(0x57 ,0x00);

Serial.print("a=");delay(10);
Serial.println(a0,HEX);delay(1000);      
Serial.print("b=");delay(10);
Serial.println(b0,HEX);delay(1000);
}

void write_data(byte num ,byte add ,byte data)
{
// write
Wire.beginTransmission(int(num));
Wire.write(add);delay(10);            // sendaddress   ww
Wire.write(data);delay(10);            // senddata ww
Wire.endTransmission();   //
delay(10);//very import ww
}

byte read_data(byte num ,byte add)
{
// read
Wire.beginTransmission(int(num));
Wire.write(add);            // sendaddress
Wire.endTransmission();   //

Wire.requestFrom(int(num), 1);    // request 2 bytes from slave device #112
if(Wire.available())
{
      val = Wire.read();// receive high byte (overwrites previous reading)
}
delay(10);
return val;
}





Youyou 发表于 2014-9-4 13:25:13

加饭 发表于 2014-9-1 11:08
我不用那个库文件,改用共用体,但出了个奇怪的问题——我AT24C02明明全接低电平(代码中硬件地址应该0x50 ...

这个是你写程序实现的功能,write_data(0x57 ,0x00 ,0x11)这条函数,其中0x57表示器件地址,0x00表示数据写入的地方,0x11是写入的数据,因此经过这个操作后,0x11已经吸入了,那么你再读取,读到的值就是0x11了。

加饭 发表于 2014-9-5 09:27:55

Youyou 发表于 2014-9-4 13:25
这个是你写程序实现的功能,write_data(0x57 ,0x00 ,0x11)这条函数,其中0x57表示器件地址,0x00 ...

我只有一块AT24C02,而且器件地址是0x50,那么地址为0x57的数据怎么会写入到地址为0x50的芯片中?

Youyou 发表于 2014-9-5 11:37:35

加饭 发表于 2014-9-5 09:27
我只有一块AT24C02,而且器件地址是0x50,那么地址为0x57的数据怎么会写入到地址为0x50的芯片中? ...

我用你的代码实验了下,应该是有问题的,读出来就是FF,不管是a还是b。

Youyou 发表于 2014-9-5 12:20:50

本帖最后由 Youyou 于 2014-9-5 12:25 编辑

加饭 发表于 2014-9-5 09:27
我只有一块AT24C02,而且器件地址是0x50,那么地址为0x57的数据怎么会写入到地址为0x50的芯片中? ...下面这段代码按照你的风格来写的,测试通过,你可以试下。
#include <Wire.h>
void setup()
{
Wire.begin();
Serial.begin(9600);
}
void loop()
{
byte a0,b0;
writeData(0x50,0x00,0xbb);
writeData(0x57,0x00,0x11);
a0 = readData(0x50,0x00);
b0 = readData(0x57,0x00);
Serial.println(a0);
Serial.println(b0);
delay(3000);

}

void writeData(int m_deviceid,int add,byte data)
{
Wire.beginTransmission(m_deviceid);
Wire.write(add>>8);
Wire.write(add & 0xFF);
Wire.write(data);
Wire.endTransmission();
delay(10);
}

byte readData(int m_deviceid,int add)
{
byte result;      
Wire.beginTransmission(m_deviceid);
Wire.write(add>>8);
Wire.write(add & 0xFF);      
Wire.endTransmission();
Wire.requestFrom(m_deviceid, 1);
result = Wire.read();         
return result;
}

Yifery 发表于 2018-11-19 22:11:06

这个问题解决了吗? 我也出现了这种情况,从0x50 到0x57都能读到数据255 但是我接线是按照0x50接的

Abelwong 发表于 2019-4-24 01:57:59

本帖最后由 Abelwong 于 2019-4-24 01:59 编辑

目前手中僅有24LC02,實測24C02改善讀取一直都是0xFF的方式是必須修改read的地址設定方式才能正常讀取,讀取部分如下:

byte readData(unsigned int address) {
    byte result;

    Wire.beginTransmission(0x50);
    Wire.write(address);
    Wire.endTransmission();//此行務必要在Wire.write(address)之後
    Wire.requestFrom(0x50, 1);   
    result = Wire.read();
    return result;
}
页: [1]
查看完整版本: 求教Arduino外置EEPROM的代码