IIC总线

一、背景介绍

现今,在低端数字通信应用领域,我们随处可见IIC (Inter-Integrated Circuit) 和 SPI (Serial Peripheral Interface)的身影。原因是这两种通信协议非常适合近距离低速芯片间通信。Philips(for IIC)和Motorola(for SPI) 出于不同背景和市场需求制定了这两种标准通信协议。

IIC 开发于1982年,当时是为了给电视机内的CPU和外围芯片提供更简易的互联方式。电视机是最早的嵌入式系统之一,而最初的嵌入系统是使用内存映射(memory-mapped I/O)的方式来互联微控制器和外围设备的。要实现内存映射,设备必须并联入微控制器的数据线和地址线,这种方式在连接多个外设时需大量线路和额外地址解码芯片,很不方便并且成本高。

为了节省微控制器的引脚和和额外的逻辑芯片,使印刷电路板更简单,成本更低,位于荷兰的Philips实验室开发了 ‘Inter-Integrated Circuit’ ,这是一种只使用二根线连接所有外围芯片的总线协议。最初的标准定义总线速度为100kbps,历经几次修订,主要是1995年的400kbps,1998的3.4Mbps。

二、基本概念

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

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

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

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

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

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

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

物理接口:SCL + SDA

  1. SCL(serial clock):时钟线,传输CLK信号,一般是I2C主设备向从设备提供时钟的通道
  2. SDA (serial data)  :数据线,I2C通信的通信数据都通过SDA线来传输

三、IIC的起始与停止信号

I2C通信的时候,通信双方地位是不对等的,而是分为主设备和从设备。通信由主设备发起,由主设备主导,从设备只是按照I2C协议被动的接收主设备的通信,并及时响应。

一个典型的IIC接口如下图

主设备和从设备进行数据传输时遵循以下协议格式。数据通过一条SDA数据线在主设备和从设备之间传输01的串行数据。串行数据序列的结构可以分为,开始条件,地址位,读写位,应答位,数据位,停止条件。

读写位

该位指定数据传输的方向。

  • 如果主设备需要将数据发送到从设备,则该位设置为 0
  • 如果主设备需要往从设备接收数据,则将其设置为 1

ACK/NACK

主机每次发送完数据之后会等待从设备的应答信号ACK。

  • 在第9个时钟信号,如果从设备发送应答信号ACK,则SDA会被拉低;
  • 若没有应答信号NACK,则SDA会输出为高电平,这过程会引起主设备发生重启或者停止;

四、开始通讯

当主设备决定开始通讯时,需要发送开始信号,需要执行以下动作:

  • 先将SDA线从高电平切换到低电平;
  • 然后将SCL从高电平切换到低电平;

在主设备发送开始条件信号之后,所有从机即使处于睡眠模式也将变为活动状态,并等待接收地址位。具体如下图所示:

IIC通信在字节级的传输中,有固定的时序要求。I2C通信的起始信号(Start)后,首先要发送一个从机的地址,这个地址一共有 7位,紧跟着的第 8 位是数据方向位(R/W),“0”表示接下来要发送数据(写),‘“1”表示接下来是请求数据(读)。

我们知道,打电话的时候,当拨通电话,接听方捡起电话肯定要回一个“喂”,这就是告诉拨电话的人,这边有人了。同理,这个第九位 ACK 实际上起到的就是这样一个作用。当我们发送完了这 7 位地址和 1 位方向后,如果发送的这个地址确实存在,那么这个地址的器件应该回应一个 ACK(拉低 SDA 即输出“0”),如果不存在,就没“人”回应 ACK(SDA将保持高电平即“1”)。

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

五、IIC的读写

5.1、读数据

要想读设备,首先要知道将要所读取设备的地址告诉从设备,从设备才能将数据放到(发送)SDA上使主设备读取,从设备将数据放入SDA上的过程,由硬件主动完成,不用人为的写入。所以首先先写入从机地址,然后+写控制命令,从机应答,应答成功,表示有这个设备,然后写入内部寄存器地址,此时不用再加写命令控制字,从机应答,应答成功,表示设备内有这个地址。然后主机继续发出:写入从机地址,然后+读命令,从机应答,应答成功,此时便可以读取数据了,从设备已经将数据放入到SDA上了。地址跟设备已经验证了,不用再进行验证。

这里介绍一个单片机读操作的流程:首先单片机发送起始信号,接着使用写操作进行芯片寻址0xa0,接着定位片内子地址address,因为我们要读数据,但是刚才使用的是写操作进行芯片寻址,我们要把R/W位设置成读操作才可以对address处数据进行读操作,所以接下来需要重新发送一个起始位,接着使用读操作进行芯片寻址0xa1,接着单片机从IIC总线中读取8位数据保存到变量中,最后单片机发送一个结束信号完成整个读过程,其中中间夹杂着应答过程。

unsigned char x24c08_read(unsigned char address)  // 从24c02的地址address中读取一个字节数据
{
   unsigned char i;
   start(); // 向IIC总线发送一个起始位
   writex(0xa0); // 芯片寻址,向IIC总线写入0xa0,即10100000,R/W位是0,代表写操作
   clock(); // 等待AT24C02应答
   writex(address);// 片内子地址寻址,将address写入IIC总线,AT24C02下次将操作此地址处的数据
   clock(); // 等待AT24C02应答
   start(); // 向IIC总线发送一个起始位
   writex(0xa1); // 芯片寻址,向IIC总线写入0xa0,即10100001,R/W位是1,代表读操作
   clock(); // 等待AT24C02应答
   i = readx(); // 单片机从IIC总线中读取8位数据放入i中
   stop(); // 向IIC总线发送一个停止位
   delay(10); // 此处延时是为了系统稳定
   return(i); // 将读到的数值返回
}

 5.2、写数据

开始信号:主机+从设备地址+写命令,从机应答,应答成功,表示有这个设备,然后主机+设备内部寄存器地址,此时不用再加写命令控制字,从机应答,应答成功,表示设备内有这个地址,主机写入数据,从机应答,是否继续发送,不发送的话,发送停止信号P。

单片机写数据的流程:首先发送起始信号,接着使用写操作芯片寻址0xa0,接着进行片内子地址寻址address,接着向address写入info,最后发送停止信号,其中中间夹杂着应答的过程。

void x24c08_write(unsigned char address,unsigned char info)// 向2402的address地址中写入一个字节数据
{
    start(); // 向IIC总线发送一个起始位
    writex(0xa0); // 芯片寻址,向IIC总线写入0xa0,即10100000,R/W位是0,代表写操作
    clock();//等待AT24C02应答
    writex(address); // 片内子地址寻址,将address写入IIC总线,AT24C02下次将操作此地址处的数据
    clock(); //等待AT24C02应答
    writex(info);//将info写入AT24C02的address处
    clock(); //等待AT24C02应答
    stop(); //向IIC总线发送一个停止位
    delay(10); //此处延时是为了系统稳定
}

5.3、细节

具体的,在I2C总线上传送的每一位数据都有一个时钟脉冲相对应(或同步控制),即在SCL串行时钟的配合下,在SDA上逐位地串行传送每一位数据。进行数据传送时,在SCL呈现高电平期间,SDA上的电平必须保持稳定,低电平为数据0,高电平为数据1。只有在SCL为低电平期间,才允许SDA上的电平改变状态。逻辑0的电平为低电压,而逻辑1则为高电平。时序如下图所示

步骤:(主机——>从机)
1. 发送slave address字节 + ack(在此寻址)
2. 发送command + ack(0x01为读;0x02为写)
3. 发送address + ack(读写data的address)
4. 发送data + ack(传输数据)
 

参考:

https://blog.csdn.net/Lingdongtianxia/article/details/81135456?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.control&dist_request_id=&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.control

https://blog.csdn.net/chm880910/article/details/80086052

http://www.elecfans.com/emb/danpianji/201912031128051.html

https://www.cnblogs.com/SmileXiaoxiao/p/9582775.html

https://blog.csdn.net/xx_0305401/article/details/81914528

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值