【实验】ESP32S3 通过IIC读写EEPROM芯片24C08

设计简介

        本设计是选用的是ESP32S3的芯片学习IIC的使用,对EEPROM进行读写。

        本实验中开发板选用的是图灵哥TRGESP32S3拓展板,EEPROM芯片用的是板子上搭载的24C08

24C02芯片简介

24C08是一种常见的EEPROM(可擦可编程只读存储器)芯片,属于24C系列,由多个半导体公司生产,如Atmel(现为Microchip Technology的一部分)、STMicroelectronics等。广泛应用于数据存储领域,特别是在需要非易失性存储的嵌入式系统中以下是24C08芯片的一些基本特性和应用

特性

  1. 存储容量24C08提供8Kbit(即1KB)的存储空间。这通常被组织为128个字节页,每页8字节
  2. 接口:它通过I²C(Inter-Integrated Circuit)总线进行通信,这是一种简单的两线式串行接口,仅需时钟线(SCL)和数据线(SDA)即可实现数据的传输
  3. 电源电压:24C08支持多种电压等级,如2.5V、3.0V、3.5V和5V,这使得它能够适应不同的系统要求
  4. 封装:常见的封装形式有8引脚的DIP(双列直插式)封装、8引脚的SOIC(小外形集成电路)封装以及其他表面贴装技术封装
  5. 写保护功能:24C08通常包含一个写保护引脚(WP),当该引脚被拉高时,可以防止对存储器的意外写入,从而保护数据
  6. 数据保持:即使在电源被移除的情况下,24C08也能保持数据长达100年
  7. 擦写周期:24C08支持至少100,000次的擦写周期,适用于那些需要频繁更新数据的场合
  8. 操作速度:24C08支持标准的I²C总线速度,以及高达400kHz的快速模式

24C08的应用非常广泛,包括但不限于

  1. 存储配置数据
  2. 保存用户设置
  3. 数据日志记录
  4. 在系统编程(ISP)中的应用

在使用24C08时,通常需要编写相应的软件来通过I²C接口与芯片通信,进行数据的读写操作。由于I²C协议的通用性,许多MCU和处理器都提供了直接支持该协议的硬件模块,使得24C08等EEPROM芯片的集成和使用变得相对简单。

24C08的写入时序

24C08芯片的写入过程涉及通过I²C总线发送特定的序列来启动写入操作,并将数据传输到芯片中。以下是24C08写入过程的一般步骤

  1. 开始条件
    1. 主设备(通常是MCU)通过将SDA线从高电平拉至低电平,同时SCL线保持高电平来生成一个开始条件
  2. 发送设备地址:
    1. 主设备接着发送一个7位的设备地址,紧随其后的是一个读写位(R/W),其中0表示写操作
    2. 24C08支持多个设备地址,通过A0、A1和A2引脚的不同组合来选择不同的地址
    3. 主设备释放SDA线,允许从设备(24C08芯片)通过拉低SDA线来发送应答(ACK)
  3. 发送内存地址:
    1. 在接收到从设备的应答后,主设备发送一个16位的内存地址(对于24C08,通常只有低8位有效,因为它的存储空间小于256字节)
    2. 每发送一个字节后,主设备都会检查从设备的应答
  4. 写入数据
    1. 在发送完内存地址并获得应答后,主设备开始发送要写入的数据字节
    2. 每发送一个字节,主设备都需要检查从设备的应答
    3. 可以连续写入多个字节,直到达到页边界(对于24C08,每页8字节)
  5. 停止条件
    1. 写入完成后,主设备生成一个停止条件来结束数据传输,这是通过将SDA线从低电平拉至高电平,同时SCL线保持高电平来实现的

以下是写入过程的详细步骤

  1. 主设备产生开始条件
  2. 主设备发送设备地址和写操作位(0),并接收从设备的ACK
  3. 主设备发送内存地址的低8位,并接收从设备的ACK
  4. 主设备发送第一个数据字节,并接收从设备的ACK
  5. 如果需要,主设备继续发送更多的数据字节,直到达到页边界或完成所有数据的写入
  6. 在每个数据字节写入后,主设备都会收到从设备的ACK
  7. 完成数据写入后,主设备产生停止条件

需要注意的是,24C08的写入周期通常需要一些时间(例如,5毫秒)来完成,因此在写入操作后应等待足够的时间比如加入一段延时,以确保数据正确地写入存储器。此外,如果在写入过程中需要跨页写入数据,必须先停止当前页的写入,然后重新发送新的内存地址以开始下一页的写入

部分程序源码

24c02.cpp

/**
****************************************************************************************************
 * @file      24c02.cpp
 * @author    Turinger Software
 * @version   V1.0
 * @date      2024-09-20
 * @brief     EEPROM实验
 * 实验平台    图灵哥 TRGESP32S3探索板
 *
****************************************************************************************************
 */

#include "24c02.h"
#include <Wire.h>

/**
 * @brief     初始化EEPROM器件
 * @param       无
 * @retval      无
 */
void at24c02_init(void)
{
    Wire.begin(IIC_SDA, IIC_SCL, 400000);    /* 初始化IIC连接 */
}

/**
 * @brief     在AT24C02指定地址读出一个数据
 * @param       addr: 开始读取数据的地址
 * @retval      读到的数据 / 0xFF:未接收到数据
 */
uint8_t at24c02_read_one_byte(uint8_t addr)
{
    Wire.beginTransmission(EEPROM_ADDR);      /* 发送从机的7位器件地址到发送队列 */
    Wire.write(addr);                         /* 发送要读取从机数据的地址到发送队列 */
    Wire.endTransmission(0);                  /* IIC 发送 发送队列的数据(传参为0,表示重新发送一个start信号,保持IIC总线有效连接) */

    Wire.requestFrom(EEPROM_ADDR, 1);         /* 主机向从机发送数据请求,并获取到数据 */
    if (Wire.available() != 0)                /* 得到已经接收到的数据字节数 */
    {
        return Wire.read();                   /* 到数据缓冲区读取数据 */
    }

    return 0xFF;
}

/**
 * @brief     在AT24C02指定地址写入一个数据
 * @param       addr: 写入数据的目的地址
 * @param       data: 要写入的数据
 * @retval      无
 */
void at24c02_write_one_byte(uint8_t addr, uint8_t data)
{
    Wire.beginTransmission(EEPROM_ADDR);    /* 发送从机的7位器件地址到发送队列 */
    Wire.write(addr);                       /* 发送要写入从机数据的地址到发送队列 */
    Wire.write(data);                       /* 发送要写入从机数据到发送队列 */
    Wire.endTransmission(1);                /* IIC 发送 发送队列的数据(传参为1,表示发送stop信号,结束传输) */

    delay(10);    /* 注意: EEPROM 写入比较慢,必须等到10ms后再写下一个字节 */
}

/**
 * @brief     检查AT24C02是否正常
 *   @note      检测原理: 在器件的末地址写如0X55, 然后再读取, 如果读取值为0X55
 *              则表示检测正常. 否则,则表示检测失败.
 *
 * @param       无
 * @retval      检测结果
 *              0: 检测成功
 *              1: 检测失败
 */
uint8_t at24c02_check(void)
{
    uint8_t temp;

    temp = at24c02_read_one_byte(255);      /* 避免每次开机都写AT24CXX */

    if (temp == 0X55)                       /* 读取数据正常 */
    {
        return 0;
    }
    else                                    /* 排除第一次初始化的情况 */
    {
        at24c02_write_one_byte(255, 0X55);  /* 先写入数据 */
        temp = at24c02_read_one_byte(255);  /* 再读取数据 */
        
        if (temp == 0X55) 
        {
            return 0;
        }
    }

    return 1;
}

/**
 * @brief     在AT24C02里面的指定地址开始读出指定个数的数据
 * @param       addr    : 开始读出的地址 对24c02为0~255
 * @param       pbuf    : 数据数组首地址
 * @param       datalen : 要读出数据的个数
 * @retval      无
 */
void at24c02_read(uint8_t addr, uint8_t *pbuf, uint8_t datalen)
{
    while (datalen--)
    {
        *pbuf++ = at24c02_read_one_byte(addr++);
    }
}

/**
 * @brief     在AT24C02里面的指定地址开始写入指定个数的数据
 * @param       addr    : 开始写入的地址 对24c02为0~255
 * @param       pbuf    : 数据数组首地址
 * @param       datalen : 要写入数据的个数
 * @retval      无
 */
void at24c02_write(uint8_t addr, uint8_t *pbuf, uint8_t datalen)
{
    while (datalen--)
    {
        at24c02_write_one_byte(addr, *pbuf);
        addr++;
        pbuf++;
    }
}

24c02.h

/**
 ****************************************************************************************************
 * @file      24c02.h
 * @author    Turinger Software
 * @version   V1.0
 * @date      2024-09-20
 * @brief     EEPROM实验
 * 实验平台    图灵哥 TRGESP32S3探索板
 *
 ****************************************************************************************************
 */

#ifndef __24C02_H
#define __24C02_H

#include "Arduino.h"

/* 引脚定义 */
#define IIC_SCL     42
#define IIC_SDA     41

#define EEPROM_ADDR 0x50    /* 7位器件地址 */

/* 函数声明 */
void at24c02_init(void);                                            /* 初始化IIC */
uint8_t at24c02_check(void);                                        /* 检查器件 */
uint8_t at24c02_read_one_byte(uint8_t addr);                        /* 指定地址读取一个字节 */
void at24c02_write_one_byte(uint8_t addr,uint8_t data);             /* 指定地址写入一个字节 */
void at24c02_write(uint8_t addr, uint8_t *pbuf, uint8_t datalen);   /* 从指定地址开始写入指定长度的数据 */
void at24c02_read(uint8_t addr, uint8_t *pbuf, uint8_t datalen);    /* 从指定地址开始读出指定长度的数据 */

#endif

iic_eeprom.ino

/**
 ******************************************************************************
 * @file      iic_eeprom.ino
 * @author    Turinger Software
 * @version   V1.0
 * @date      2024-09-20
 * @brief     EEPROM 实验
 ******************************************************************************
 * 实验平台    图灵哥 TRGESP32S3探索板
 * 实验目的    学习IIC外设的使用,对EEPROM器件进行读写操作
 *
 * 硬件资源及引脚分配: 
 * 1,    KEY --> ESP32S3 IO
 *       KEY --> IO0
 * 2,  UART0 --> ESP32S3 IO
 *      TXD0 --> IO43
 *      RXD0 --> IO44
 * 3, EEPROM --> ESP32S3 IO
 *       SCL --> IO42
 *       SDA --> IO41
 * 
 * 实验现象:
 * 1, 检测IIC总线上是否有24C08器件,按下KEY会写入数据到EEPROM,每隔1秒钟会打印出EEPROM的0地址开始存放的有效内容
 * 
 * 注意事项:
 * 无
 *
 ******************************************************************************
 */
 
#include "24c02.h"
#include "key.h"
#include "uart.h"


const uint8_t g_text_buf[] = {"ESP32S3 IIC TEST"};  /* 要写入到24c02的字符串数组 */
#define TEXT_SIZE   sizeof(g_text_buf)              /* TEXT字符串长度 */
uint8_t datatemp[TEXT_SIZE];                        /* 从EEPROM读取到的数据 */

/**
 * @brief    当程序开始执行时,将调用setup()函数,通常用来初始化变量、函数等
 * @param    无
 * @retval   无
 */
void setup() 
{
    key_init();               /* KEY初始化 */
    uart_init(0, 115200);     /* 串口0初始化 */
    at24c02_init();           /* 初始化24CXX */
    
    while (at24c02_check())   /* 检测不到24c02 */
    {
        Serial.println("24C02 Check Failed!");
        delay(500);
    }
    Serial.println("24C02 Ready!");
}

/**
 * @brief    循环函数,通常放程序的主体或者需要不断刷新的语句
 * @param    无
 * @retval   无
 */
void loop() 
{
    at24c02_read(0, datatemp, TEXT_SIZE);                       /* 从24C02的0地址处中读取TEXT_SIZE长度数据 */
    Serial.printf("The Data Readed Is:%s \r\n", datatemp);

    if (KEY == 0)
    {
        at24c02_write(0, (uint8_t *)g_text_buf, TEXT_SIZE);     /* 向24C02的0地址处写入TEXT_SIZE长度数据 */
        Serial.printf("24C02 Write %s Finished! \r\n", g_text_buf);
    }

    delay(1000);
}

实验结果

检测IIC总线上是否有24C08器件,按下KEY会写入数据到EEPROM,每隔1秒钟会打印出EEPROM的0地址开始存放的有效内容

实验到此结束,感谢观看。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值