第二十章 IIC_EEPROM实验
1)实验平台:正点原子DNESP32S3开发板
2)章节摘自【正点原子】ESP32-S3使用指南—IDF版 V1.6
3)购买链接:https://detail.tmall.com/item.htm?&id=768499342659
4)全套实验源码+手册+视频下载地址:http://www.openedv.com/docs/boards/esp32/ATK-DNESP32S3.html
5)正点原子官方B站:https://space.bilibili.com/394620890
6)正点原子DNESP32S3开发板技术交流群:132780729
本章将介绍使用ESP32-S3驱动板载的EEPROM进行读写操作。通过本章的学习,读者将学习到使用IIC接口驱动24C02器件。
本章分为如下几个小节:
20.1 24C02简介
20.2 硬件设计
20.3 程序设计
20.4 下载验证
20.1 24C02简介
24C02是一个2K bit的串行EEPROM存储器,内部含有256个字节。在24C02里面还有一个8字节的页写缓冲器。该设备的通信方式IIC,通过其SCL和SDA与其他设备通信,芯片的引脚图如图35.1.2.1所示。
图20.1.1 24C02引脚图
上图的WP引脚是写保护引脚,接高电平只读,接地允许读和写,我们的板子设计是把该引脚接地。每一个设备都有自己的设备地址,24C02也不例外,但是24C02的设备地址是包括不可编程部分和可编程部分,可编程部分是根据上图的硬件引脚A0、A1和A2所决定。设备地址最后一位用于设置数据的传输方向,即读操作/写操作,0是写操作,1是读操作,具体格式如下图20.1.2所示:
图20.1.2 24C02设备地址格式图
根据我们的板子设计,A0、A1和A2均接地处理,所以24C02设备的读操作地址为:0xA1;写操作地址为:0xA0。
在前面已经说过IIC总线的基本读写操作,那么我们就可以基于IIC总线的时序的上,理解24C02的数据传输时序。
下面把实验中到的数据传输时序讲解一下,分别是对24C02的写时序和读时序。24C02写时序图见图20.1.3所示:
图20.1.3 24C02写时序图
上图展示的主机向24C02写操作时序图,主机在IIC总线发送第1个字节的数据为24C02的设备地址0xA0,用于寻找总线上找到24C02,在获得24C02的应答信号之后,继续发送第2个字节数据,该字节数据是24C02的内存地址,再等到24C02的应答信号,主机继续发送第3字节数据,这里的数据即是写入在第2字节内存地址的数据。主机完成写操作后,可以发出停止信号,终止数据传输。
上面的写操作只能单字节写入到24C02,效率比较低,所以24C02有页写入时序,大大提高了写入效率,下面看一下24C02页写时序图,图20.1.4所示。
图20.1.4 24C02页写时序
在单字节写时序时,每次写入数据时都需要先写入设备的内存地址才能实现,在页写时序中,只需要告诉24C02第一个内存地址1,后面数据会按照顺序写入到内存地址2,内存地址3等,大大节省了通信时间,提高了时效性。因为24C02每次只能8bit数据,所以它的页大小也就是1字节。页写时序的操作方式跟上面的单字节写时序差不多,所以不作过多解释了。参考以上说明去理解页写时序。
说完两种写入方式之后,下面看一下图20.1.5关于24C02的读时序:
图20.1.5 24C02读时序图
24C02读取数据的过程是一个复合的时序,其中包含写时序和读时序。先看第一个通信过程,这里是写时序,起始信号产生后,主机发送24C02设备地址0xA0,获取从机应答信号后,接着发送需要读取的内存地址;在读时序中,起始信号产生后,主机发送24C02设备地址0xA1,获取从机应答信号后,接着从机返回刚刚在写时序中内存地址的数据,以字节为单位传输在总线上,假如主机获取数据后返回的是应答信号,那么从机会一直传输数据,当主机发出的是非应答信号并以停止信号发出为结束,从机就会结束传输。
20.2 硬件设计
20.2.1 例程功能
通过按下KEY0~4按键来控制蜂鸣器和LED灯开关状态,KEY0和KEY1控制蜂鸣器开与关;KEY2和KEY3控制LED灯开与关。
20.2.2 硬件资源
- LED
LED- IO1
- 独立按键
KEY0(XL9555)- IO1_7
KEY1(XL9555)- IO1_6
- UART_NUM_0(U0TX、U0RX连接至板载USB转串口芯片上)
U0TXD- IO43
U0RXD- IO44
- 24C02
IIC_SCL- IO42
IIC_SDA- IO41
20.2.3 原理图
本章实验使用了板载的24C02芯片,该芯片是一个EEPROM,MCU是通过两个GPIO与该EEPROM进行连接与通信的,该EEPROM与MCU的连接原理图,如下图所示:
图20.1.3.1 24C02与MCU的连接原理图
20.3 程序设计
20.3.1 程序流程图
程序流程图能帮助我们更好的理解一个工程的功能和实现的过程,对学习和设计工程有很好的主导作用。下面看看本实验的程序流程图:
图20.3.1.1 24C02实验程序流程图
20.3.2 IIC_EEPROM函数解析
ESP-IDF提供了一套API来配置IIC。要使用此功能,需要导入必要的头文件:接下来,作者将介绍一些常用的ESP32-S3中的IIC函数,以及24C02中用到的函数,这些函数的描述及其作用如下:
1,设置IIC初始化参数
该函数用给定的配置,来配置IIC总线,该函数原型如下所示:- esp_err_t i2c_param_config(i2c_port_t i2c_num, const i2c_config_t *i2c_conf);
复制代码 该函数的形参描述如下表所示:
表20.3.2.1 i2c_param_config函数形参描述
返回值:ESP_OK表示配置成功。其他表示配置失败。
该函数使用i2c_config_t类型的结构体变量传入,该结构体的定义如下所示:
表20.3.2.2 i2c_config_t结构体参数值描述
完成上述结构体参数配置之后,可以将结构传递给 i2c_param_config() 函数,用以实例化IIC并返回IIC句柄。
2,安装IIC驱动
该函数设置某个管脚的中断服务函数,该函数原型如下所示:- esp_err_t i2c_driver_install(i2c_port_t i2c_num,
- i2c_mode_t mode,
- size_t slv_rx_buf_len,
- size_t slv_tx_buf_len,
- int intr_alloc_flags);
复制代码 该函数的形参描述如下表所示:
表20.3.2.3 i2c_driver_install()函数形参描述
返回值:ESP_OK表示配置成功。其他表示配置失败。
3,IIC读写操作
根据函数功能,以下函数可以归为一类进行讲解,下面将以表格的形式逐个介绍这些函数的作用与参数。
表20.3.2.4 IIC读写操作函数描述
4,初始化24C02的IIC引脚
在配置24C02芯片引脚之前,需要对IIC初始化进行一个判断。因为ESP32系统不支持同一个外设进行两次初始化,否则会出现系统不断复位的现象。因此,我们需要在24C02的初始化前面添加IIC端口判断。
5,在指定地址写入数据
该函数用于在24C02指定地址写入一个数据,其函数原型如下所示:- voidat24cxx_write_one_byte(uint16_t addr, uint8_t data);
复制代码 该函数的形参描述,如下表所示:
表20.3.2.5 函数at24cxx_write_one_byte ()形参描述
返回值:无。
6,在指定地址读出数据
该函数用于在24C02指定地址读出一个数据,其函数原型如下所示:- uint8_tat24cxx_read_one_byte(uint16_t addr);
复制代码 该函数的形参描述,如下表所示:
表20.3.2.6 函数at24cxx_read_one_byte ()形参描述
返回值:读取的数据。
7,检查24C02是否正常
在器件的末地址写如:0X55,然后再读取, 如果读取值为0X55则表示检测正常。否则,则表示检测失败,其函数原型如下所示:- uint8_t at24cxx_check(void);
复制代码 返回值:1表示检验成功。0表示检验失败。
8,在指定地址读出数据
在24C02里面的指定地址开始读出指定个数的数据,其函数原型如下所示:- void at24cxx_read(uint16_t addr, uint8_t *pbuf, uint16_t datalen);
复制代码 该函数的形参描述,如下表所示:
表20.3.2.7 函数at24cxx_read()形参描述
返回值:无。
9,在指定地址读出数据
在24C02里面的指定地址开始读出指定个数的数据,其函数原型如下所示:- void at24cxx_write(uint16_t addr, uint8_t *pbuf, uint16_t datalen);
复制代码 该函数的形参描述,如下表所示:
表20.3.2.8 函数at24cxx_write ()形参描述
返回值:无。
20.3.3 IIC_EEPROM驱动解析
在IDF版的10_iic_eeprom例程中,作者在10_iic_eeprom \components\BSP路径下新增了一个24CXX文件夹,用于存放24cxx.c和24cxx.h这两个文件。其中,24cxx.h文件负责声明24CXX相关的函数和变量,而24cxx.c文件则实现了24CXX的驱动代码。下面,我们将详细解析这两个文件的实现内容。
1,24cxx.h文件
为了使代码功能更加健全,所以在24cxx.h中宏定义了不同容量大小的24C系列型号,具体定义如下:- #define AT24C01 127
- #define AT24C02 255
- #define AT24C04 511
- #define AT24C08 1023
- #define AT24C16 2047
- #define AT24C32 4095
- #define AT24C64 8191
- #define AT24C128 16383
- #define AT24C256 32767
- /* 开发板使用的是24c02,所以定义EE_TYPE为AT24C02 */
- #define EE_TYPE AT24C02
复制代码 2,24cxx.c文件
在24cxx.c文件中,读/写操作函数对于不同容量大小的24Cxx芯片都有相对应的代码块解决处理。下面先看一下at24cxx_write_one_byte函数,实现在AT24Cxx芯片指定地址写入一个数据,代码如下:
[code]/*** @brief 在AT24CXX指定地址写入一个数据* @param addr: 写入数据的目的地址* @param data:要写入的数据* @retval 无*/voidat24cxx_write_one_byte(uint16_t addr, uint8_t data){ i2c_cmd_handle_t cmd = i2c_cmd_link_create(); i2c_master_start(cmd); if(EE_TYPE > AT24C16) { i2c_master_write_byte(cmd, (AT_ADDR > 8, ACK_CHECK_EN); /* 发送高地址 */ } else { i2c_master_write_byte(cmd,0XA0 + ((addr/256) 8, ACK_CHECK_EN); /* 发送高地址 */ } else { i2c_master_write_byte(cmd, 0XA0 + ((addr / 256) |