EEPROM是"可电擦除只读存贮器"的简写。虽然名字叫只读存贮器,但它是可以写入的,只不过写入的速度比不上随机存贮器那么快。这种存贮器所存贮的数据可以在没有电源供电的情况下予以保存,所以在工业控制领域得到广泛的应用。其中,以AT24CXX系列芯片是最为常见。 |
AT24CXX系列芯片又叫串行EEPROM,因为它采用了I2C串行接口以减小封装。常见的封装形有:SOIC、TSSOP等形式,整个芯片只有8个引脚。 |
|
图(1) |
管脚 | 功能 |
A0 | A2、A1、A0 为总线地址设置管脚,它们共同决定了芯片的总线地址:1 0 1 0 A2 A1 A0 |
A1 | 见 A0 引脚。 |
A2 | 见 A0 引脚。 |
GND | 地 |
SDA | I2C总线接口的数据信号,与SCL共同构成I2C总线接口。 |
SCL | I2C总线接口的时钟信号,与SDA共同构成I2C总线接口。 |
WP | 写保护引脚,高有效。当WP置"1"时,芯片处于只读状态。 |
VCC | 电源 |
表(1) |
AT24CXX的通信接口是标准的I2C接口。具有I2C接口的芯片可以挂接在I2C总线上,通过I2C总线与其它芯片交换数据。 |
I2C总线是双线总线,由两路信号线构成:时钟线SCL和数据线SDA。时钟线SCL用来传递同步时钟信号,数据线SDA用来以同步时钟信号的节拍传递数据信号。同时挂在I2C总线上的I2C接口可以有很多,这些接口以I2C总线地址加以区分。根据不同版本的协议,I2C总线地址有7位地址和10位地址之分。其中7位地址是在基本的I2C总线协议中定义的,10位地址则是在7位地址的基础上扩展而来。这里我们的目标是对EEPROM进行读写,所以内容仅限于7位地址的基本I2C协议范围。 |
|
图(2) |
I2C接口对总线的高、低电平的驱动是有区别的。对低电平的驱动是强驱动,用MOS管来驱动;对高电平的驱动是弱驱动,用上拉电阻来驱动。于是,所有挂在I2C总线上的接口形成了"线与"的关系。这样,就从电路属性上保证了各个接口可以同时对总线加以驱动,而不用担心高、低电平之间发生短路的问题。总线上实际表现出的逻辑值,是所有接口输出的逻辑值的"与"运算。 |
I2C接口通过I2C总线交换数据的过程中,需要参与通信的接口分别扮演各自的角色。要完成一次通信,总线上需有1个接口作为Master端出现,其余的接口则是Slave端。当然,挂在总线上的I2C接口,由于物理设计原因,有些只能做Master端,有些只能做Slave端,有些则是可以在Master端和Slave端自动切换。每次通信总是由总线上的1个Master端接口发起,并由其对总线进行管理,Slave端则是被动的收发数据。当有多个Master端试图接管总线时,由仲裁机制决定哪个端口胜出,失败者自动切换回Slave模式,等待下一次机会。这里不对仲裁机制展开介绍,只考虑单一Master的总线通信情况。 |
当一个Master端口接管总线之后,总线的时钟信号由该端口发出。数据信号则根据传输方向而定,可以是Master端驱动,也可以是Slave端驱动。 |
每次数据交换,总是以总线的起始条件开始,以总线的停止条件结束。总线的起始条件和停止条件匀由Master端接口产生。起始条件是SDA信号在SCL信号的高电平期间发生一个下降沿跳变,停止条件则是SDA信号在SCL高电平期间发生一个升沿跳变。 |
|
图(3) |
I2C总线上的数据传输是以8个数据位组成的字节为基本单位的。字节的各个数据位在总线上的传递次序是MSB在前,也就是先传高位,后传低位。每个数据位要在SCL信号的高电平期间保持稳定,数据位之间的切换发生在SCL信号的低电平期间。总线上每传送1个字节的数据,接收方要给出1个数据的应答,ACK或NACK。ACK代表要求继续传递下一个字节的数据,NACK则是表示不再需要下一个字节的数据。 |
|
图(4) |
在Master端发出起始条件后,新的一次数据交换开始。紧随起始条件之后的第1个字是由Master端发出的。这个字节的高7位是Slave端的I2C总线地址,用于选择和哪个Slave接口进行通信。最低位是数据传输方向控制位,该位低电平代表随后的数据由Master端发送,由Slave端接收;高电平则代表随后的数据由Slave端发送,由Master端接收。 |
|
图(5) |
每个Slave端I2C接口都会分配1个或多个I2C总线地址,Master端则根据总线地址选则与哪个Slave端接口通信。I2C协议中还规定了一些特殊的地址,如下: |
地址 | RW | 描述 |
0000000 | 0 | 广播地址 |
0000000 | 1 | 起始字节 |
0000001 | X | CBUS地址 |
0000010 | X | 保留 |
0000011 | X | 保留 |
00001XX | X | HS主机模式 |
11111XX | X | 保留 |
11110XX | X | 10位从机寻址 |
AT24CXX有3个管脚用于设置该芯片的I2C总线地址的最低3位,而其地址的高4位固定为1010。在与单片机进行通信时,AT24CXX作为Slave端出现,而单片机则是Master端。 |
单片机向AT24CXX写入数据的总线数据流如图(6)所示。 |
|
图(6) |
起始条件之后,第1个字节是I2C总线地址和传输方向控制位。控制位RW为0表示随后的数据是从单片机传送给AT24CXX的。再后面的两个字节是AT24CXX的存贮单元地址,告诉AT24CXX随后的数据存贮在哪里。最后一个字节是写入的数据。每当1个字节的数据传送完,AT24CXX送出1个ACK应答。全部数据传送完成之后,单片机发送1个停止条件,结束本次通信。 |
对于AT24CXX来说,也可以一次写入多个数据。在一次写入多个数据时,AT24CXX内部的存贮单元地址寄存器会在每写入一个字节数据后自动加1,新接收的数据则写到新的地址中去。需要注意的是,AT24CXX的存贮单元是按页来组织的,每页64个字节。当地址寄存器遇到了页的边缘的时候,新地址并不会指向下一页的起始,而是回到本页的起始。所以,如果一次写入的数据多于64个字节时,就会发生数据覆盖现象。最先写入的若干字节被覆盖掉,只保留了最后写入的64个字节。另外,AT24CXX并不会自动的从一个页的起始地址开始写入数据。所以,如果发给AT24CXX的地址不是一个页的起始地址,则数据会从给定的地址开始写入,在遇到本页边缘时再回到本页的起始地址。这样,最后写入的数据会保存在本页的前部。 |
|
图(7) |
从AT24CXX中读回1个字节的数据的总线数据流如图(8)所示。所读回的数据的是当前AT24CXX内部地址寄存器所指向的存贮器单元的内容,读出后地址寄存器自动加1。 |
|
图(8) |
如果想从指定的存贮单元的地址读数据,可按图(9)的时序操作。先发起一个写入操作,在传送完存贮器地址后重新以一个起始条件开始读出操作。这样,读出的数据就是所传入地址单元上的数据。 |
|
图(9) |
当然,也可以一次读出多个数据。每读出一个字节的数据,AT24CXX内部的存贮单元地址寄存器会自动加1。这样,下一个读出的数据就是下一个地址单元的内容。与写入不同的是,在读出数据时,存贮单元地址寄存器的值会跨跃页的边缘,一直增大到整个存贮器的最高地址,然后回到0地址。所以,在读出操作时,可以一次读出多于64个字节的数据。 |
AT24CXX直接由89C52管理,其通信管脚与89C52的连接方式如下: |
P1.4 ----> WP |
P1.3 ----> SCL |
P1.2 <---> SDA |
注:89C52的P1.4管脚也兼作TLC0832的CS信号,所以AT24CXX和TLC0832不能在同一时间访问 |
启动读操作的示例代码如下: |
|
读一个数据页的示例代码如下: |
|
结束对AT24CXX访问的示例代码如下: |
|
启动写操作的示例代码如下: |
|
写一个数据页的示例代码如下: |
|
完整的范例程序可点击 这里 下载,范例程序的使用方法可参见:Hello World 程序 |