Arduino AT24C02详解读写地址位

本文通过示例程序和实际通讯波形详细解释了AT24C02的I2C通信过程,包括硬件地址的确定、写入数据的步骤以及如何避免地址冲突。通过分析源码,揭示了0x50和0xA0地址之间的关系,并介绍了如何挂载多个AT24C02芯片。同时,强调了在Arduino平台上进行I2C通信时,地址左移一位的原因。
摘要由CSDN通过智能技术生成

AT24C02详解读写地址位


如果光看AT24C02的文档,很抽象,难弄懂。结合程序和实际通讯波形;来描述。
在这里插入图片描述

  • 购买回来默认是接GND的,所以安装上AT24C02芯片后地址就是:0xA0

在这里插入图片描述

示例程序(写入一个字符为例来展开讲解)

/*
 * Wire库I2C基本读写程序
 * AT24C02读写操作
 *
*/

#include <Wire.h>                           // 使用Wire库,需要包含头文件
const int16_t I2C_ADDR = 0x50;              // AT24C02的IIC器件地址0x50,这个地址可以通过I2C扫描程序搜索到。
#define button 7

bool buttonState = true; 
/* 描述:AT24C02写入一个字节函数
 * 参数:date_wr:    要写入的值
 *      WriteAddr:  要写入的地址
 * 返回值:通信成功:0 
 *        通信失败:1->数据溢出   2->发送addtess时从机接受到NACK 
 *                3->发送数据时接受到NACK  4->其他错误
 */
uint8_t at24c02_write(char data_wr, uint8_t WriteAddr)
{
  /* 1. 开始一次传输,设置I2C器件地址 */
  Wire.beginTransmission(I2C_ADDR);
  /* 2. 需要写入的位置 */
  Wire.write(WriteAddr);
  /* 3. 需要写入的值 */
  Wire.write(data_wr);
  /* 4. 完成一次I2C通信,默认发送一个停止位 */
  return Wire.endTransmission();
}
/* 描述:AT24C02读取一个字节函数
 * 参数:date_wr:    要读出值的存放指针
 *      WriteAddr:  要读出的地址
 * 返回值:通信成功:0  
 *        通信失败:1->数据溢出   2->发送address时从机接受到NACK 
 *                3->发送数据时接受到NACK  4->未接受到数据  5->其他
 */
uint8_t at24c02_read(char *data_wr, uint8_t ReadAddr)
{
  uint8_t t = 200;
  uint8_t ret = 0;
  /* 1. 开始一次传输,设置I2C器件地址 */
  Wire.beginTransmission(I2C_ADDR);

  /* 2. 需要读出的位置 */
  Wire.write(ReadAddr);

  /* 3. 完成一次I2C通信,发送一个开始位(即重发码) */
  ret = Wire.endTransmission(false);

  /* 4. 开始一次读取,设置I2C器件地址,读取AT24C02一个字节 */
  Wire.requestFrom(I2C_ADDR, 1);

  /* 5. 读出AT24C02返回的值,成功读取后写入缓存变量处,读取失败返回失败码 */
  while (!Wire.available()) 
  {
    t--;
    delay(1); 
    if(t == 0)
    {
      return 1;
    }
  }
  *data_wr= Wire.read(); // receive a byte as character
  return ret;
}

void setup() {
  /* 初始化串口波特率为115200 */
  Serial.begin(115200); 
  digitalWrite(LED_BUILTIN, LOW);//板子led,作为观察数据发射状态
  pinMode(button,INPUT);
  digitalWrite(button,HIGH);
  /* 初始化IIC接口,不写入地址则默认为主设备 */  
  Wire.begin();
}

void loop() {
 buttonState = digitalRead(button);
    if(buttonState == LOW){
      delay(250);
          if(buttonState == LOW){
            char str0 = 'H';
      uint8_t Write = at24c02_write(str0, 0);
       Serial.println("Trigger!!!");
       Serial.println(Write);
       digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
       delay(2000);
//      char*str2;
//     uint8_t Read = at24c02_read(str2,0);
//      Serial.println(*str2);Serial.println(Read);
    }    
    }
}


IIC通讯讲解

要想硬件之间建立通讯,需要知道对方的地址。

就像打电话,打电话前,你必须知道对方的电话号码才行。

  • 确定访问AT24C02的硬件地址(AT24C02手册)
    在这里插入图片描述

代码上面定义AT24C02的硬件信息填写:

const int16_t I2C_ADDR = 0x50;// AT24C02的IIC器件地址0x50,这个地址可以通过

为什么是0x50的16进制这个地址而不是1010 0000的16进制0xA0呢?
解析:如果CPU读设备,那么读设备地址 = 设备地址 <<1.所以,0x50左移移位就变成了0xA01

  • 源码函数

C:\Users\Administrator\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.3\libraries\Wire\src\utility

void twi_setAddress(uint8_t address)
{
  // set twi slave address (skip over TWGCE bit)
  TWAR = address << 1;
}
  • 原理图1,将A2,A1,A0都接GND,那么自定义的地址位就都是000,加上第八位确定读写位,如果是读就是1,写就是0,本实例演示的是写数据,那就是确定要写,那么就是0,所以地址就是1010 0000,转换为16进制就是0xA0
    在这里插入图片描述
  • 示波器捕获到单片机和AT24C02通讯时的波形,紫色代表SDA,黄色代表SCL
    在这里插入图片描述
    对应代码:
  /* 1. 开始一次传输,设置I2C器件地址 */
  Wire.beginTransmission(I2C_ADDR);
  • 如果你想挂载8个AT24C02器件,可以根据以下来连接,各器件IIC地址:0x50 - 0x57

下面的AT24C02的地址,只适用于Arduino 平台开发时使用,才对应的上,移位底层函数在封装的时候,会将这个地址左移移一位,具体看上面的原函数,这一点刚刚开始也让我很困惑,当查看原函数的时候,才发现原因。

在这里插入图片描述

  • 根据A2,A1,A0,不同的组合,我们可以确定一条总线上可以挂载多少个AT24C02,从而不会导致地址重复或者冲突。最多挂载8个:
    在这里插入图片描述
    有道翻译:
设备/页地址(A2、A1和A0): A2、A1和A0引脚是设备地址输入
它们是AT24C02的硬线。82K设备可以在一个总线系统上寻址
(设备寻址将在设备寻址部分详细讨论)。
AT24C04使用A2和A1输入进行硬线寻址,总共有44K设备
在一个单一的总线系统上被处理。A0引脚是无连接的,可以连接到GND。
AT24C08只使用A2输入进行硬线寻址,总共有两个8K设备
在一个单一的总线系统上寻址。A0和A1引脚没有连接,可以连接
GND。
AT24C16不使用设备地址引脚,这限制了总线上单个设备的数量
。A0、A1和A2引脚没有连接,可以连接到地。

第二阶段,写数据地址位。

就比如送快递,将物品送入到某个小区单元还不够,你还要知道具体到,某个单元里的某一栋的门牌号,也就是具体到存储的地址位。

  /* 2. 需要写入的位置 */
  Wire.write(WriteAddr);

在这里插入图片描述

第三阶段,将具体的数据写入到地址位中去,才算完成。

  Wire.write(data_wr);
  /* 4. 完成一次I2C通信,默认发送一个停止位 */

在这里插入图片描述

  • 4
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
以下是使用Arduino UNO和AT24C02存储器进行读写实验,并通过液晶显示取的数据的示例代码。 首先,需要连接AT24C02存储器和液晶显示器到Arduino UNO上。AT24C02使用I2C协议连接到Arduino UNO的A4和A5引脚。液晶显示器则连接到数字引脚2、3、4、5、11和12。 示例代码如下: ```C++ #include <Wire.h> #include <LiquidCrystal.h> LiquidCrystal lcd(2, 3, 4, 5, 11, 12); // 设置液晶显示器引脚 #define EEPROM_ADDR 0x50 // AT24C02存储器地址 void setup() { Serial.begin(9600); Wire.begin(); lcd.begin(16, 2); // 初始化液晶显示器 lcd.setCursor(0, 0); lcd.print("AT24C02 Test"); } void loop() { int value = random(256); // 随机生成一个0到255的整数 writeEEPROM(0, value); // 写入AT24C02存储器 int readValue = readEEPROM(0); // 从AT24C02存储器取数据 lcd.setCursor(0, 1); lcd.print("Value: "); lcd.print(readValue); delay(5000); // 延迟5秒 } void writeEEPROM(int address, int data) { Wire.beginTransmission(EEPROM_ADDR); Wire.write((int)(address >> 8)); Wire.write((int)(address & 0xFF)); Wire.write(data); Wire.endTransmission(); delay(5); } int readEEPROM(int address) { int value = 0; Wire.beginTransmission(EEPROM_ADDR); Wire.write((int)(address >> 8)); Wire.write((int)(address & 0xFF)); Wire.endTransmission(); Wire.requestFrom(EEPROM_ADDR, 1); if (Wire.available()) { value = Wire.read(); } return value; } ``` 在setup函数中,初始化串口和液晶显示器,并显示一个欢迎消息。在loop函数中,生成一个随机整数,并将其写入AT24C02存储器中。然后,从存储器中取数据并在液晶显示器上显示。最后,延迟5秒以等待下一个循环。 writeEEPROM函数用于将数据写入AT24C02存储器中。它接受两个参数:地址和要写入的数据。它首先发送存储器地址,然后发送要写入的数据。最后,它结束传输并延迟5毫秒以确保数据被写入存储器。 readEEPROM函数用于从AT24C02存储器中取数据。它接受一个参数:地址。它首先发送存储器地址,然后请求一个字节的数据。如果数据可用,则将其取并返回。 在液晶显示器上,第一行显示欢迎消息,第二行显示从存储器中取的数据。 注意:在使用AT24C02存储器之前,请确保将其正确连接到Arduino UNO,并确保I2C地址正确。如果您遇到问题,请参阅AT24C02数据表以获取更多信息。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值