您现在的位置: 主页 > 资讯 > atmel_AVR > I2C总线和EEPROM操作
本文所属标签:
为本文创立个标签吧:

I2C总线和EEPROM操作

来源:atmel 网络用户发布,如有版权联系网管删除 2018-07-19 

点击上方"STC单片机应用"关注公众号,每日一篇应用精选,满满的干货

1. I2C总线概述

1.1传输速率

1.2特点

1.3相关术语

1.4位的传输

1.5数据的传输

1.6寻址方式

1.7快速模式

1.8高速模式

1.9系统连接和开漏输出

2.STC单片机系统中使用I2C设备

3. STC单片机开发板中的I2C总线外设原理图

4. I2C接口的EEPROM芯片AT24C64D

5. I2C的底层操作和EEPROM的读写API函数

5.1 IO口操作

5.2发送起始位

5.3发送停止位

5.4发送一个字节并检查ACK应答位

5.5接收一个字节并应答ACK

5.6接收一个字节并应答NACK

5.7EEPROM中读取数据

5.8 EEPROM的写操作

6.测试EEPROM的代码

7.小结

8.源代码下载

1. I2C总线概述

I2CInter-Integrated Circuit)总线是由PHILIPS公司开发的两线式串行总线,用于连接微控制器及其外围设备。是微电子通信控制领域广泛采用的一种总线标准。它是同步通信的一种特殊形式,具有接口线少,控制方式简单,器件封装形式小,通信速率较高等优点。I2C总线支持任何IC生产工艺(CMOS、双极型)。通过串行数据(SDA)线和串行时钟SCL)线在连接到总线的器件间传递信息。每个器件都有一个唯一的地址识别(无论是微控制器-MCULCD驱动器、存储器或键盘接口),而且都可以作为一个发送器或接收器(由器件的功能决定)。例如LCD驱动器只能作为接收器,而存储器则既可以接收又可以发送数据。除了发送器和接收器外,器件在执行数据传输时也可以被看作是主机或从机。主机是初始化总线的数据传输并产生允许传输的时钟信号的器件。此时,任何被寻址的器件都被认为是从机。

1.1传输速率

I2C总线有三种数据传输速度:标准,快速模式和高速模式。标准的是100Kbps,快速模式为400Kbps,高速模式支持快至3.4Mbps的速度。所有的与次之传输速度的模式都是兼容的。I2C总线支持7位和10位地址空间设备和在不同电压下运行的设备。

1.2特点

  • 只要求两条总线线路:一条串行数据线SDA,一条串行时钟线SCL

  • 每个连接到总线的器件都可以通过唯一的地址和一直存在的简单的主机/从机关系软件设定地址,主机可以作为主机发送器或主机接收器;

  • 它是一个真正的多主机总线,如果两个或更多主机同时初始化,数据传输可以通过冲突检测和仲裁防止数据被破坏;

  • 串行的8位双向数据传输位速率在标准模式下可达100kbit/s,快速模式下可达400kbit/s,高速模式下可达3.4Mbit/s

  • 连接到相同总线的IC数量只受到总线的最大电容400pF限制。

  • 相关术语

  • 发送器:发送数据到总线的器件;

  • 接收器:从总线接收数据的器件;

  • 主机:启动数据传送并产生时钟信号的设备;

  • 从机:被主机寻址的器件;

  • 多主机:同时有多于一个主机尝试控制总线但不破坏传输;

  • 主模式:用I2CNDAT支持自动字节计数的模式;位I2CRM,I2CSTT,I2CSTP控制数据的接收和发送;

  • 从模式:发送和接收操作都是由I2C模块自动控制的;

  • 仲裁:是一个在有多个主机同时尝试控制总线但只允许其中一个控制总线并使传输不被破坏的过程;

  • 同步:两个或多个器件同步时钟信号的过程

1.4位的传输

有效数据位

在传输数据的时候,SDA线必须在时钟的高电平周期保持稳定,SDA的高或低电平状态只有在SCL线的时钟信号是低电平时才能改变

起始位

SCL线为高电平时,SDA线从高电平向低电平切换,这个情况表示起始条件;

停止位

SCL线为高电平时,SDA线由低电平向高电平切换,这个情况表示停止条件。

起始和停止条件一般由主机产生,总线在起始条件后被认为处于忙的状态。在停止条件的某段时间后总线被认为再次处于空闲状态。如果产生重复起始条件而不产生停止条件,总线会一直处于忙的状态,此时的起始条件(S)和重复起始条件(Sr在功能上是一样的。

1.5数据的传输

字节格式

发送到SDA线上的每个字节必须为8位,每次传输可以发送的字节数量不受限制。每个字节后必须跟一个响应位。首先传输的是数据的最高位(MSB),如果从机要完成一些其他功能后(例如一个内部中断服务程序)才能接收或发送下一个完整的数据字节,可以使时钟线SCL保持低电平,迫使主机进入等待状态,当从机准备好接收下一个数据字节并释放时钟线SCL后数据传输继续。

应答响应

数据传输必须带响应,相关的响应时钟脉冲由主机产生。在响应的时钟脉冲期间发送器释放SDA线(高)。在响应的时钟脉冲期间,接收器必须将SDA线拉低,使它在这个时钟脉冲的高电平期间保持稳定的低电平。通常被寻址的接收器在接收到的每个字节后,除了用CBUS地址开头的数据,必须产生一个响应。当从机不能响应从机地址时(例如它正在执行一些实时函数不能接收或发送),从机必须使数据线保持高电平,主机然后产生一个停止条件终止传输或者产生重复起始条件开始新的传输。如果从机接收器响应了从机地址,但是在传输了一段时间后不能接收更多数据字节,主机必须再一次终止传输。这个情况用从机在第一个字节后没有产生响应来表示。从机使数据线保持高电平,主机产生一个停止或重复起始条件。如果传输中有主机接收器,它必须通过在从机发出的最后一个字节时产生一个响应,向从机发送器通知数据结束。从机发送器必须释放数据线,允许主机产生一个停止或重复起始条件。

时钟同步

所有主机在SCL线上产生它们自己的时钟来传输I2C总线上的报文。数据只在时钟的高电平周期有效,因此需要一个确定的时钟进行逐位仲裁。时钟同步通过线与连接I2C接口到SCL线来执行。这就是说SCL线的高到低切换会使器件开始数它们的低电平周期,而且一旦器件的时钟变低电平,它会使SCL线保持这种状态直到到达时钟的高电平。但是如果另一个时钟仍处于低电平周期,这个时钟的低到高切换不会改变SCL线的状态。因此SCL线被有最长低电平周期的器件保持低电平。此时低电平周期短的器件会进入高电平的等待状态。当所有有关的器件数完了它们的低电平周期后,时钟线被释放并变成高电平。之后,器件时钟和SCL线的状态没有差别,而且所有器件会开始数它们的高电平周期。首先完成高电平周期的器件会再次将SCL线拉低。这样产生的同步SCL时钟的低电平周期由低电平时钟周期最长的器件决定,而高电平周期由高电平时钟周期最短的器件决定。

1.6寻址方式

7

第一个字节的头7位组成了从机地址,最低位(LSB)是第8位,它决定了传输的方向。第一个字节的最低位是“0”,表示主机会写信息到被选中的从机;“1”表示主机会向从机读信息,当发送了一个地址后,系统中的每个器件都在起始条件后将头7位与它自己的地址比较,如果一样,器件会判定它被主机寻址,至于是从机接收器还是从机发送器,都由R/W位决定的。

10

10位寻址和7位寻址兼容,而且可以结合使用。

10位寻址采用了保留的1111XXX作为起始条件(S)或重复起始条件(Sr)后第一个字节的头7位。10位寻址不会影响已有的7位寻址,有7位和10位地址的器件可以连接I2C总线10位地址格式到相同的I2C总线。它们都能用于标准模式(F/S)和高速模式(Hs)系统。保留地址位1111XXX8个组合,但是只有4个组合11110XX用于10位寻址,剩下的4个组合11111XX保留给后续增强的I2C总线。10位从机地址是由在起始条件(S或重复起始条件(Sr)后的头两个字节组成。第一个字节的头7位是11110XX的组合,其中最后两位(XX10位地址的两个最高位(MSB)。

第一个字节的第8位是R/W位,决定了传输的方向,第一个字节的最低位是“0”表示主机将写信息到选中的从机,“1”表示主机将向从机读信息。如果R/W位是“0”,则第二个字节是10位从机地址剩下的8位;如果R/W位是“1则下一个字节是从机发送给主机的数据。

1.7快速模式

快速模式器件可以在400kbit/s的速率下接收和发送。最小要求是:它们可以和400kbit/s传输同步,可以延长SCL信号的低电平周期来减慢传输。快速模式器件都向下兼容,可以和标准模式器件在0~100kbit/sI2C总线系统通讯。但是,由于标准模式器件不向上兼容,所以不能在快速模式I2C总线系统中工作。快速模式I2C总线规范与标准模式相比有以下特征:

  • 最大位速率增加到400kbit/s

  • 调整了串行数据(SDA和串行时钟(SCL)信号的时序;

  • 快速模式器件的输入有抑制毛刺的功能,SDASCL输入有施密特触发器;

  • 快速模式器件的输出缓冲器对SDASCL信号的下降沿有斜率控制功能;

  • 如果快速模式器件的电源电压被关断,SDASCLI/O管脚必须悬空,不能阻塞总线;

  • 连接到总线的外部上拉器件必须调整以适应快速模式I2C总线更短的最大允许上升时间。对于负载最大是200pF的总线,每条总线的上拉器件可以是一个电阻,对于负载在200pF~400pF之间的总线,上拉器件可以是一个电流源(最大值3mA)或者是一个开关电阻电路。

  • 高速模式

高速模式(Hs模式)器件对I2C总线的传输速度有巨大的突破。Hs模式器件可以在高达3.4Mbit/s的位速率下传输信息,而且保持完全向下兼容快速模式或标准模式(F/S模式)器件,它们可以在一个速度混合的总线系统中双向通讯。

Hs模式传输除了不执行仲裁和时钟同步外,与F/S模式系统有相同的串行总线协议和数据格式。

高速模式下I2C总线规范如下:

  • Hs模式主机器件有一个SDAH信号的开漏输出缓冲器和一个在SCLH输出的开漏极下拉和电流源上拉电路。这个电流源电路缩短了SCLH信号的上升时间,任何时候在Hs模式,只有一个主机的电流源有效;

  • 在多主机系统的Hs模式中,不执行仲裁和时钟同步,以加速位处理能力。仲裁过程一般在前面用F/S模式传输主机码后结束;

  • Hs模式主机器件以高电平和低电平是1:2的比率产生一个串行时钟信号。解除了建立和保持时间的时序要求;

  • 可以选择Hs模式器件有内建的电桥。在Hs模式传输中,Hs模式器件的高速数据(SDAH)和高速串行时钟(SCLH)线通过这个电桥与F/S模式器件的SDASCL线分隔开来。减轻了SDAHSCLH线的电容负载,使上升和下降时间更快;

  • Hs模式从机器件与F/S从机器件的唯一差别是它们工作的速度。Hs模式从机在SCLHSDAH输出有开漏输出的缓冲器。SCLH管脚可选的下拉晶体管可以用于拉长SCLH信号的低电平,但只允许在Hs模式传输的响应位后进行;

  • Hs模式器件的输出可以抑制毛刺,而且SDAHSCLH输出有一个施密特触发器;

  • Hs模式器件的输出缓冲器对SDAHSCLH信号的下降沿有斜率控制功能。

  • 系统连接和开漏输出

I2C总线是一个多主总线系统,理论上可以多个单片机和多个外设之间使用同一条总线相互通信,只要能否满足最大总线电容的要求。因为涉及到多主总线之间的通信仲裁等机制,实际的I2C总线协议是非常复杂的。但在工程实际中,I2C总线多用在单片机连接I2C接口的外设,在这种系统中只有一个主机(单片机),外面则可以挂载多个I2C接口的外设。由于单主机,所以实际编程中可以不用考虑多主仲裁等复杂的机制。

还需要特别注意的是,I2C总线的SCLSDA线由于要使用线与功能来表达信号,故单片机和I2C外设的I2C接口都是开漏输出的,在总线上面需要增加上拉电阻以保证线与功能的正常。

2.STC单片机系统中使用I2C设备

STC单片机中并没有集成I2C收发器,所以在STC单片机系统中如要控制I2C外设,是通过通用I/O口线模拟I2C时序来实现的。新兴的AVR PIC MSP430 ARM等单片机中基本上都把I2C收发器集成进去了,虽然如此,由于I2C总线的复杂性,有时使用寄存器级别的I2C操作也是一件繁琐的事情,在实际编程中经常看到有工程师弃集成的收发器不用,而像51单片机一样用GPIO模拟I2C总线时序的案例。

3. STC单片机开发板中的I2C总线外设原理图

B系列单片机开发板上面有两个I2C接口的外设,分别是EEPROM和实时时钟RTC芯片。

I2C接口的EEPROMAtmel公司的AT24C64D芯片,这是一款8K字节容量的EEPROM存储器。

I2C接口的RTC实时时钟芯片,NXP公司的PCF8563T,这是一款市面上广泛使用的实时时钟芯片。在实际应用中I2C接口的外设种类相当丰富,除了EEPROMRTC,常见的还有I2C接口的传感器、ADC、陀螺仪,加密芯片等等。从上图可以看出,SCLSDA上面各加了一个10K欧姆的电阻作为上拉。

4. I2C接口的EEPROM芯片AT24C64D

关于芯片的详细的说明请参考《AT24C64DDatasheet,此处仅以摘要的形式做一个大致的描述。AT24C64D的容量是8K字节,按照256页,每页32字节的方式来组织。读取的时候可以顺序读取,写入操作则受到页边界的限制。如果写入跨边界,则必须分页写入。

地址的低3位由A2 A1 A0三个管脚的输入电平决定,如下图所示:

在上节的原理图总可以看到A2 A1 A0都接地,所以写入时首字节是0xa0,读取时首字节是0xa1.

上图是字节写操作的时序。先是起始位,然后写设备地址字节并等待应答位,然后片内首地址字节并等待应答位,然后次地址字节并等待应答位,然后写入一个字节的数据并等待应答位。最后则是停止位。注意区分起始位后的地址字节是设备地址,后面的两个字节是EEPROM存储器片内地址。

上图是页写操作的时序。首先是起始位,接着是设备地址字节和等待应答位,然后是片内地址首字节并等待应答位,然后是第二个地址字节并等待应答位,然后就是要写入的n个字节,注意EEPROM芯片内部维护一个数据地址信息,每执行一次读写数据的操作,地址都会自动加1.但按页写的时候当数据地址增加到页边界的时候如果再写入就会回退到页首地址,故页写操作务必要避免跨边界。如果要一次性写入一个大的数据块,请把写操作进行拆分。

当前地址字节读操作,最为简单,首先是起始位,然后是设备地址字节并等待应答,然后则是读取一字节数据并不反馈应答位,然后发送停止位。

这个是随机读操作,首先执行一次dummy写操作,其目的实际上是为了指定要读取的字节的地址。然后再执行一次重新初始化后再读取数据。

顺序读操作,和字节读操作几乎一样,只不过是每读取一个字节后应答位是低电平,最后一个字节才是高电平。读操作和写操作不同之处在于读操作不受字节边界限制,可以顺序读完整个存储区。

5. I2C的底层操作和EEPROM的读写API函数

I2C总线协议虽然非常复杂,但就单主机系统而言,如果单片机IO口模拟产生时序的话,也并不复杂,可以归纳为以下几种原子操作:(1)发送起始位,(2)发送停止位,(3)发送一个字节并应答ACK,(4)发送一个字节并应答NACK. (5)接收一个字节并判断对方是否有应答。所有的读写操作都可用这5种原子操作组合而成。

5.1 IO口操作

上面所有的原子操作都是通过IO口模拟时序实现的,故需要SCL置高、SCL置低、SDA置高、SDA置低、读取SDA电平等几种操作。本来是很简单的一条语句,但此处封装成为函数,其目的是为了增加代码的可移植性,因为在ARM等平台上面,把IO口置高置低、设置输入输出是比较复杂的一件事情。

5.2发送起始位

起始位,在SCL为高电平期间,SDA从高到低的一个跳变被定义为一个起始位,对比代码:首先把SCL置高,然后把SDA置高、延时、置低、再延时,就用软件模拟产生了一个起始位的波形。

5.3发送停止位

上述代码是产生停止位的代码,同样对比上面的时序图。停止位的条件是在SCL为高电平期间SDA线上面一个从高到低的跳变。

5.4发送一个字节并检查ACK应答位

此处代码循环8次,把一个字节的8位数据依次发出来,然后检查ACK的应答情况并返回。

5.5接收一个字节并应答ACK

5.6接收一个字节并应答NACK

此函数通常用在仅仅读取一个字节,或者读取多个字节的最后一字节时,需要回复NACK信号,以告知从设备需要停止总线传送了。

5.7EEPROM中读取数据

inteeprom_Read(void*vbuf, uint16_t len, uint16_t addr)

{

uint8_t ack;

uint8_t *buf = (uint8_t *)vbuf;

uint16_t i;

if(len ==0)return0;

for(i=0;i<10;i++)

{

i2c_StartCondition();

ack =i2c_SendByteCheckAck(0xa0);

if((ack&0x80)==0)break;

i2c_StopCondition();

time_HoggingDelayMs(1);

}

if(i != 0)

{

printf("eeprom_Read try %u times.rn",i);

}

if(i == 10)

{

i2c_StopCondition();

return-1;

}

ack = i2c_SendByteCheckAck(addr>>8);

if((ack&0x80)!=0)

{

i2c_StopCondition();

return-2;

}

ack = i2c_SendByteCheckAck(addr);

if((ack&0x80)!=0)

{

i2c_StopCondition();

return-3;

}

SET_IIC_SDA();

time_HoggingDelayUs(6);

/*Restart for read*/

i2c_StartCondition();

ack = i2c_SendByteCheckAck(0xa1);

if((ack&0x80)!=0)

{

i2c_StopCondition();

return-4;

}

for(i=0;i

{

buf[i]=i2c_ReceiveByteWithAck();

}

buf[i] = i2c_ReceiveByteWithoutAck();

i2c_StopCondition();

return0;

}

首先入口参数中:int eeprom_Read(void *vbuf, uint16_t len, uint16_t addr) vbuf是存储读取数据的内存区地址,len是要读取的字节数,addr是要读取的起始字节地址。对于AT24C64D来说,可以取值08191。读取成功返回0,读取失败返回一个负数,并且不同的负数值代表不同的错误情况:

-1: EEPROM始终无应答。

-2 -3:发送片内地址后无应答。

代码流程分析,首先是发送设备地址,并等待应答,如果有应答则继续,如果没有应答则可能设备忙,需要重试,重试10次仍然失败则释放总线并返回。然后则是发送片内地址的高字节和低字节,然后重新发送起始位,并改变成读操作后依次读取len指定的字节数。

5.8 EEPROM的写操作

staticintPageProgram(uint16_t page,uint16_t offset,constuint8_t *buf, uint16_t len)

{

uint8_t ack;

uint16_t i;

uint16_t addr;

addr = (page << 5) + offset;

for(i=0;i<10;i++)

{

i2c_StartCondition();

ack = i2c_SendByteCheckAck(0xa0);

if((ack&0x80)==0)break;

i2c_StopCondition();

time_HoggingDelayMs(1);

}

if(i != 0)

{

printf("eeprom_Write try %u times.rn",i);

}

if(i == 10)

{

i2c_StopCondition();

return-1;

}

ack = i2c_SendByteCheckAck(addr>>8);

if((ack&0x80)!=0)

{

i2c_StopCondition();

return-2;

}

ack = i2c_SendByteCheckAck(addr);

if((ack&0x80)!=0)

{

i2c_StopCondition();

return-3;

}

for(i=0;i

{

ack = i2c_SendByteCheckAck(buf[i]);

if((ack&0x80)!=0)

{

i2c_StopCondition();

return-4;

}

}

i2c_StopCondition();

return0;

}

inteeprom_Write(constvoid*vbuf, uint16_t len, uint16_t addr)

{

constuint8_t *buf = (constuint8_t *)vbuf;

uint16_t page,startpos;

uint16_t nleft,nwrite;

intret;

page = addr / 32;

startpos = addr % 32;

nleft=len;

for(;nleft;)

{

if(nleft <= 32 - startpos)

nwrite = nleft;

else

nwrite = 32 - startpos;

ret = PageProgram(page,startpos,buf,nwrite);

if(ret != 0)returnret;

buf += nwrite;

nleft -= nwrite;

page ++;

startpos=0;

}

return0;

}

EEPROM的写操作稍显负责,int eeprom_Write(const void *vbuf, uint16_t len, uint16_t addr)其入口参数中vbuf指定要写入的数据的首地址,len指定要写入的字节数目,addr则是写入片内首地址。写操作的复杂性在于写操作是按照页来进行的,跨页边界就会导致出错,所以需要把线性的顺序写操作划分成多个页写操作来进行。

这段代码就是把线性操作转换为多个页操作的代码。除了第一页和最后一页的startposnwrite比较特殊外其他中间页都是正常的页操作。

这个页操作函数,传入的参数已经由主调函数处理好,不存在跨边界的情况。故按正常页写流程进行就可以。同样也是首先起始位,然后写入设备地址0xa0,然后判断是否正常应答,正常则往下,否则循环等待10次。设备地址正常写入后则写入片内地址的高字节和低字节,同样需要检查ACK是否正常,最后再把待写入数据依次写入页内。

6.测试EEPROM的代码

这里通过控制台敲入命令的方式来执行一个测试程序。关于串口和和控制台的详情请参考《SA16008-串口-底层驱动和上层应用》一文。此处仅给出测试代码:

在命令行上面输入一个字符串,test-eeprom命令会把此字符串写入到EEPROM中,然后再读出来看是否正确。

以上是仿真终端上面的执行结果,可以看出EEPROMAPI函数是正确执行了的。

7.小结

本文描述了i2C总线协议的细节,开发板上面的I2C外设连接的原理图。并对STC芯片使用IO口模拟产生I2C时序,对EEPROM的操作API函数进行了详细的讲解。EEPROM通常用于存储掉电后仍需要长久保存的数据,在实践中有着广泛的用途。由于STC单片机内部也内置了EEPROM,因此外置EEPROM的应用呈减少趋势,但对于一些大容量数据存储的场合,其可靠性,大容量等仍然有着不可替代的优势。





              查看评论 回复

游客   2018-07-19 15:02:08
iic芯片24c04
1楼 回复本楼


嵌入式交流网主页 > 资讯 > atmel_AVR > I2C总线和EEPROM操作
 模式 总线 字节

"I2C总线和EEPROM操作"的相关文章

网站地图

围观()