27867浏览
查看: 27867|回复: 17

[讨论] 求教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
  1. #include <Wire.h>
  2. #include <i2cEEPROM.h>
  3. i2cEEPROMClass(rom);
  4. void setup()
  5. {
  6.   Serial.begin(9600);
  7.   
  8.   rom.begin(0);
  9.   rom.writeByte(0,0xaa); delay(10);
  10. }
  11. void loop()
  12. {
  13.   byte a = rom.readByte(0); delay(10);
  14.   
  15.   Serial.println(a); delay(10);
  16.   delay(1000);
  17. }
复制代码

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中,但读取出问题——不管读取
  1. #include <Wire.h>
  2. #include <i2cEEPROM.h>
  3. i2cEEPROMClass(rom);
  4. int R_W=2;         // LOW is write data ; HIGH is read data
  5. void setup()
  6. {
  7.   Serial.begin(9600);
  8.   pinMode(R_W,OUTPUT);
  9.   
  10.   rom.begin(0x57);
  11.   digitalWrite(R_W,LOW);
  12.   rom.writeByte(1,0xaa); delay(10);
  13.   rom.writeByte(10,0xbb); delay(10);
  14.   rom.writeByte(2,0xcc); delay(10);
  15.   
  16.   
  17. /* writeString(2,"star");
  18.   delay(10);
  19.   writeString(3,"end");
  20.   delay(10);*/
  21. }
  22. void loop()
  23. {
  24.   rom.begin(0x57);
  25.   digitalWrite(R_W,HIGH);
  26.   byte a = rom.readByte(10); delay(10);
  27.   
  28.   Serial.println(Wire.endTransmission());delay(10);
  29.   Serial.println(a,HEX); delay(10);
  30.   delay(1000);
  31.   
  32. }
复制代码

地址为多少,读取结果为最后一个写入结果,代码及电路图如下,求赐教
QQ图片20140829120855.jpg
回复

使用道具 举报

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外置EEPROM的代码图1

注:该连线图只适用于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~
QQ图片20140829194752.jpg
回复

使用道具 举报

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的引脚没有接错,求大神指点
  1. </blockquote></div><div class="blockcode"><blockquote>#include <Wire.h>
  2. // 从指定位置写一个数据
  3. void setup()
  4. {
  5.   Serial.begin(9600);  
  6.   delay(10);
  7.   Wire.begin();
  8. }
  9. byte val = 0;
  10. int index = 0;
  11. void loop()
  12. {
  13.   byte a0 = 0x00;
  14.   byte b0 = 0x00;
  15.   write_data(0x50 ,0x00 ,0xbb);
  16.   write_data(0x57 ,0x00 ,0x11);
  17.   
  18.   a0 = read_data(0x50 ,0x00);
  19.   b0 = read_data(0x57 ,0x00);
  20.   
  21.   Serial.print("a=");delay(10);
  22.   Serial.println(a0,HEX);delay(1000);      
  23.   Serial.print("b=");delay(10);
  24.   Serial.println(b0,HEX);delay(1000);
  25. }
  26. void write_data(byte num ,byte add ,byte data)
  27. {
  28.   // write
  29.   Wire.beginTransmission(int(num));
  30.   Wire.write(add);delay(10);            // send  address   ww
  31.   Wire.write(data);delay(10);            // send  data ww
  32.   Wire.endTransmission();     //
  33.   delay(10);  //very import ww
  34. }
  35. byte read_data(byte num ,byte add)
  36. {
  37.   // read
  38. Wire.beginTransmission(int(num));
  39.   Wire.write(add);            // send  address
  40.   Wire.endTransmission();     //
  41.   Wire.requestFrom(int(num), 1);    // request 2 bytes from slave device #112
  42.   if(Wire.available())
  43.   {
  44.       val = Wire.read();  // receive high byte (overwrites previous reading)
  45.   }
  46.   delay(10);
  47.   return val;
  48. }
复制代码





回复

使用道具 举报

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的芯片中? ...
下面这段代码按照你的风格来写的,测试通过,你可以试下。
  1. #include <Wire.h>
  2. void setup()
  3. {
  4.   Wire.begin();
  5.   Serial.begin(9600);
  6. }
  7. void loop()
  8. {
  9.   byte a0,b0;
  10.   writeData(0x50,0x00,0xbb);
  11.   writeData(0x57,0x00,0x11);
  12.   a0 = readData(0x50,0x00);
  13.   b0 = readData(0x57,0x00);
  14.   Serial.println(a0);
  15.   Serial.println(b0);
  16.   delay(3000);
  17.   
  18. }
  19. void writeData(int m_deviceid,int add,byte data)
  20. {
  21.   Wire.beginTransmission(m_deviceid);
  22.   Wire.write(add>>8);
  23.   Wire.write(add & 0xFF);
  24.   Wire.write(data);
  25.   Wire.endTransmission();
  26.   delay(10);
  27. }
  28. byte readData(int m_deviceid,int add)
  29. {
  30.   byte result;        
  31.   Wire.beginTransmission(m_deviceid);
  32.   Wire.write(add>>8);
  33.   Wire.write(add & 0xFF);        
  34.   Wire.endTransmission();
  35.   Wire.requestFrom(m_deviceid, 1);
  36.   result = Wire.read();         
  37.   return result;
  38. }
复制代码
回复

使用道具 举报

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;
}
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

为本项目制作心愿单
购买心愿单
心愿单 编辑
[[wsData.name]]

硬件清单

  • [[d.name]]
btnicon
我也要做!
点击进入购买页面
上海智位机器人股份有限公司 沪ICP备09038501号-4

© 2013-2024 Comsenz Inc. Powered by Discuz! X3.4 Licensed

mail