第12/15原创:事无巨细,IIC总线协议与AT24C02
[复制链接]
事无巨细,IIC协议与EEPROM 24C02
在前面的一系列文章中,我们从最简单的开发环境开始到上一节的片外DAC的使用为止,算是AVR单片机中比较简单但是绝对是比较全面的内容了。如果你能够独立掌握了前面的这些内容,我们现在可以开始进入CEPARK AVR开发板上最后的三个最难的内容:存储芯片AT24C02的IIC总线协议,时钟芯片DS1302的SPI总线协议,还有温度传感器DS18B20的单总线协议。
今天我们来讲存储芯片AT24C02的IIC总线协议。(也称I^2 C总线协议)
IIC的概念:
IIC,英文全称为Inter-Integrated Circuit,即内置集成电路。所以IIC总线协议,就是指内置集成电路总线协议。我理解为集成电路直接用以数据传输的线路。
IIC的发展:
IIC总线产生于在80年代,最初为音频和视频设备开发,如今主要在服务器管理中使用,其中包括单个组件状态的通信。例如管理员可对各个组件进行查询,以管理系统的配置或掌握组件的功能状态,如电源和系统风扇。可随时监控内存、硬盘、网络、系统温度等多个参数,增加了系统的安全性,方便了管理。
IIC的特点:
IIC总线最主要的优点是其简单性和有效性。由于接口直接在组件之上而且只有两根信号线,因此I2C总线占用的空间非常小,减少了电路板的空间和芯片管脚的数量,降低了互联成本。总线的长度可高达25英尺,并且能够以10Kbps的最大传输速率支持40个组件。I2C总线的另一个优点是,它支持多主控(multimastering), 其中任何能够进行发送和接收的设备都可以成为主总线。一个主控能够控制信号的传输和时钟频率。当然,在任何时间点上只能有一个主控。
IIC总线操作方法:
IIC总线在传送数据过程中共有三种类型信号, 它们分别是:开始信号、结束信号和应答信号。笔者分别配合时序图来说明:
1、开始信号与结束信号:
开始信号:SCL为高电平时,SDA由高电平向低电平跳变,开始传送数据。
结束信号:SCL为低电平时,SDA由低电平向高电平跳变,结束传送数据。
一定要注意时序的精准性!这两个信号成功的关键是:
① 在SDA的整个变化期间,SCL是一直保持稳定的高电平的。SCL监视SDA的整个变化而不只是开始信号中的负跳变或者结束信号的正跳变。
② 要注意到IIC总线的传输速度为Kbps级,而AVR单片机工作频率为Mbps级,所以必不可少的要用us级延时函数_delay_us()将单片机速度降下来配合IIC时序。
2、应答信号
首先要知道器件发送数据到总线上,则定义为发送器,器件接收数据则定义为接收器。如上应答信号时序,SCL线为主机(微控制器)控制,DATA IN表示从机接受数据情况,DATA OUT表示从机发送数据情况。如图可见,在START信号之后,从器件在8个时钟脉冲的控制下接受数据,在此期间从机并未发出任何信号!而在第9个时钟期间,从机将SDA线拉低表示应答。
所以,应答信号:接收数据的IC在接收到8bit数据后,向发送数据的IC发出特定的低电平脉冲,表示已收到数据。
关于SDA上的数据变化
如上图所见,当SCL为高电平时要求DATA STABLE即数据稳定,而在SCL低电平时才可以DATA CHANGE即数据改变。所以IIC总线协议要求只有在SCL为低电平是SDA上的数据才可以改变。因为若SCL处于高电平期间,SDA上的电平无论发生上升沿还是下降沿,都会被识别为一次开始或结束信号。
4、字节传输时序
上时序是一个个完整的IIC字节写周期,有左往右,起始信号之后:
如果是写字节,前8个时钟周期中的SCL上升沿将数据写入数据接收方,接着在第九个周期数据接收方发出应答信号;
而如果是读字节,前8个时钟周期中的SCL上升沿将数据从数据发送方读出到SDA线上,并且数据接收方在第九个周期选择发送怎样的应答信息到SDA线上;
如果使用中断方式的IIC,要把上图中的英文字看明白。
CEPARK AVR开发板上集成了Two-wire Serial EEPROM 24C02,全面兼容IIC协议,具有256X8 bit存储空间,也就是2k位(注意是2K位不是2K字节)。我们来看看CEPARK AVR 开发板的AT24C02模块原理图:
看上图,
A0、A1、A2三个引脚为AT24C02的硬件地址线,根据引脚上的电平决定当前器件的硬件地址。
WP为AT24C02的写保护引脚,当该引脚为高电平时,器件只读不写。
SCL、SDA分别为器件的IIC协议接口。
注意到SCL和SDA分别接了两个10K上拉电阻,我想重点讲讲这两个上拉的作用。
我们有上面的几个时序可以看到,IIC传输的基本模式是“起始信号——数据传输——应答——结束”,那么要在我们的AVR Mega16上应用,毫无疑问,连接SDA的IO口要适当的在输出口和输入口两个状态间改变。这样就显得比较繁琐。然而我们可以巧妙地利用IO口的原理和这两个上拉电阻。听我说来:
首先,AVR单片机的IO口具有三态输出,高电平,低电平,高阻态。无论你水平多低,至少肯定知道前面两个。什么是高阻态呢?就是电阻无限大,你可以想象IO内部连接了一个无限大的电阻,对外表现近似开路;
其次,我们还知道器件的IO口一般都具有线与的关系,即有“0”得“0”;
好了,知道以上两条就够了。SCL和SDA两条线,具体说来一共就是五种操作:SCL拉高、SCL置低、SDA输出高、SDA输出低、还有SDA设置为输入口,来看程序怎么做:
PORTx=0x00;//先把PORTx寄存器永远配置为0,不再改变
DDRx=0xff;//IO设置为输出口,则IO输出低电平
DDRx=0x00;//IO设置为输入口,而此时IO输出高电平
前面两句应该很容易理解,但是第三句为什么将IO设置为输入口会使IO输出高电平呢?
其实此处的“将IO设置为输入口”,并不是指我们真的将要读取数据,刚才说明的“首先…..”道出了缘由:当IO设置为PORTx=0;DDRx=0;时,IO口对外呈现高阻态,近似开路。所以外部电路其实是通过10K的上拉电阻接在了5V电源上,把IO“拉”成了高电平。所以我们若要IO输出高电平,即将其设置为高阻态就可以了。
当IO用确切做输入口的时候,上拉确实是把IO拉成了高电平,会不会影响数据读取呢?看到上面强调的“即有’0’得’0’”,明白了么?电路被电源拉成了高电平,但是线路上最终的电平状态还是取决于IIC器件发出的数据“是否有0”。所以外部上拉并不会影响IO做输入状态用。
所以我们只需要用三句程序,就可以借助外部上拉完成IIC的五个操作。即(SCL拉高、SCL置低、SDA输出高、SDA输出低、还有SDA设置为输入口)
AT24C02的读写时序完全遵循标准的IIC读写时序,但是我们接下来还要了解AT24C02的器件操作方法:
上图为AT24C系列的地址寄存器,AT24C02具有2K bit,所以看到第一行。我们看到写地址寄存器的数据,最高位MSB永远是1,高四位为固定值,接下来A2,A1,A0就是前面说到的器件硬件地址,如果你写(A2,A1,A0)=(0,0,0)就对应到器件此三个引脚都接到地的那个器件。
最低位LSB是读写命令位,如果为1则表示“将要对这个器件进行‘读’操作”,反之为“写”。
这个是AT24C02的字节写时序,很清晰,由左到右(我写中文):
“起始信号——指定器件(写)——从器件应答——再写存储器内部空间地址——从器件应答——写数据到指定器件指定存储地址——从器件应答——结束信号”
注意:
MSB指最高位,LSB指最低位,上图看出数据传输都是从最高位开始;
R/W表示低电平为“写”(Write)高电平为读“Read”;
AT24C02的存储空间是2K bit,即256个字节。所以存储器寻址空间为0~255(0x00~0xff),上图的星号所以表示不需要第九位数据来寻址(但是更大容量器件就需要);
上图是AT24C02随机地址读时序,就是任意指定一个地址位置读出数据:
“起始信号——器件地址(写)——应答——指定存储空间地址——应答——起始信号——器件地址(读)——应答——读出数据——不需要应答——结束信号”
同样:
我们看到,随机读时序还是以写器件的硬件地址和存储空间地址为前提;
注意后一个器件地址,末位为“读”命令;
读出的数据仍然是高位MSB开始
读取完之后,数据读取方(也就是AVR单片机)并不需要产生应答信号
上述就是笔者的程序用到的两个时序,实现了“对AT24C02的任意地址写,并再从任意地址读”的功能。本来,存储器嘛,不是读就是写咯。以下附上详细注释的源程序:
main.rar
(1.37 KB, 下载次数: 315)
最后是程序注意事项:
笔者大部分地方都用了10us的延时来配合IIC的时序;
要十分注意每次IIC时序之后的SCL和SDA线的状态,最好SCL保持低电平,以免产生不必要的起始和结束信号;
主机读取应答信号时,要将IO置为输入状态,要注意DDRx的延迟效应;
要注意任意两次完整的读写之间一定要有至少10ms的延时;(我就是卡在这点上,因为根本无资料可查,当时是靠感觉才加了20ms的延迟,没想到真的是这个原因)
写在最后:其实AVR单片机是自带了IIC接口的,叫TWI。并且IDE提供了调用函数,某种程度上来说用起来也许更为方便。但是此处仍然用IO口模拟IICj接口的方法,是觉得这样更能够掌握到IIC的底层协议,更有助于对IIC协议的理解。仁者见仁吧!
希望能给有需要的朋友一点帮助
赞赏
1
查看全部赞赏