I2C协议—读写EEPROM(详细讲解+代码)

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

IIC 总线使设计人员和厂商都得益

在消费者电子、电讯和工业电子中 看上去不相关的设计里经常有很多相似的地方 例如几乎每个系
统都包括
一些智能控制 通常是一个单片的微控制器
通用电路 例如 LCD 驱动器 远程 I/O RAM EEPROM 或数据转换器
面向应用的电路 譬如收音机和视频系统的数字调谐和信号处理电路 或者是音频拨号电话的
DTMF 发生器
为了使这些相似之处对系统设计者和器件厂商都得益 而且使硬件效益最大电路最简单.  Philips 开发
了一个简单的双向两线总线 实现有效的 IC 之间控制 这个总线就称为 Inter IC I 2 C 。

一、IIC的优势

符合 I 2 C 总线的 IC 允许系统设计快速向前推进,直接从功能结构图到原型。 此外,由于它们直接“剪贴”到 I 2 C 总线,没有任何额外的外部接口,所以允许简单地通过从或者向总线“剪贴”或“不剪贴” IC 来修改或升级原型系统

符合 I 2 C 总线的 IC 还有一些功能特别吸引设计人员:

结构图的功能模块与实际的 IC 对应 设计快速从结构图向最后的原理图推进
不需要设计总线接口 因为 I 2 C 总线接口已经集成在片上
集成的寻址和数据传输协议允许系统完全由软件定义
相同类型的 IC 经常用于很多不同的应用
• 由于设计人员快速熟悉了用兼容 I 2 C 总线的 IC 表示经常使用的功能模块 使设计时间减少
在系统中增加或删除 IC 不会影响总线的其他电路
故障诊断和调试都很简单 故障可被立即寻迹
通过聚集一个可再使用的软件模块的库 减少软件开发时间

除了这些优点外

符合 I 2 C 总线的 CMOS IC 还向设计者在特别吸引的可移植装置和电池供电系统方
面提供了特殊的功能
它们都有:
极低的电流消耗
抗高噪声干扰
• 电源电压范围宽
工作的温度范围广

二、IIC总线的概念

                I2C 通讯协议(Inter- Integrated Circuit) 是由 Phiilps 公司开发的, 由于它引脚少,硬件实现简单,可扩展性强,不需要USART CAN 等通讯 协议的外部收发设备,现在被广泛地使用在系统内多个集成电路(IC) 间的通 讯。
                I2C 总线支持任何 IC 生产过程 ( NMOS CMOS 双极性)。 两线――串行数据 SDA 和串行时钟 SCL 线在连接到总线的器件间传递信息  。每个器件都有 一个唯一的地址识别  (无论是微控制器、 LCD、驱动器、存储器或键盘接口), 而且都可以作为一个发送器或接收器 (由器件的功能决定)。

        1 I2 C 总线术语的定义

三、IIC物理层

  IIC物理层的特点

•      它是一个支持多设备的总线。“总线”指多个设备共用的信号线。 在一个I2C 通讯总线中,可连接多个 I2C 通讯设备,支持多个通讯 主机及多个通讯从机。
•     一个I2C总线只使用两条总线线路, 一条双向串行数据线(SDA) 一条串行时钟线 (SCL)数据线即用来表示数据,时钟线用于数 据收发同步
•     每个连接到总线的设备都有一个 独立的地址 ,主机可以利用这个 地址进行不同设备之间的访问。
•     总线通过 上拉电阻 接到电源。 当I2C设备空闲时,会输出高阻态,而当 所有设备都空闲,都输出高阻态时,由上拉电阻把总线拉成高电平
•     多个主机同时使用总线时,为了防止数据冲突,会利用仲裁方式决定由 哪个设备占用总线。
•     具有三种传输模式:标准模式传输速率为 100kbit/s ,快速模式为 400kbit/s ,高速模式下可达 3.4Mbit/s ,但目前大多 I 2 C 设备尚不支持高 速模式。
•     连接到相同总线的 IC 数量受到总线的最大电容 400pF 限制 。

四、IIC协议层

 数据的有效性

        SDA 线上的数据必须在时钟的高电平周期保持稳定,数据线的高或低电平状态只有在 SCL 线的时钟信号是低电平时才能改变(见下图)

 

                                                 IIC总线的位传输

 起始、停止条件及应答信号

在 I 2 C 总线中 唯一出现的是被定义为 起始 S 和停止 P 条件 的情况,另外还有个应答信号ACK。
当SCL 线是 高电平 时,SDA 线从 高电平向低电平切换 这个情况表示 起始条件S (起始信号), 开始传输数据
当 SCL 是 高电平 时 ,SDA 线由 低电平向高电平切换 表示 停止条件P (停止信号), 停止传输数据
应答信号:接收数据的 IC 在接收到 8bit 数据后,向发送数据的 IC 发出特定的低电平脉冲,表示已收到数据。CPU 向受控单元发出一个信号后,等待受控单元发出一个应答信号,CPU 接收到应答信号后,根据实际情况作出是否继续传递信号的判断。若未收到应答信号,由判断为受控单元出现故障。

这些信号中,起始信号是必需的,结束信号和应答信号,都可以不要。
 
如图所示: IIC时序图
img

下面我们来逐步分析IIC通信的处理流程(附代码)

初始(空闲)状态

因为IIC的 SCL 和SDA 都需要接上拉电阻,保证空闲状态的稳定性

所以IIC总线在空闲状态下SCL 和SDA都保持高电平

代码:

void BE_I_init(void)
{   
    I2C_CLK_1();                 // CLK=1
    Delay_Unit5us();
    I2C_SDA_1();                 // SDA=1
    Delay_Unit5us();
}

开始信号

SCL保持高电平,SDA由高电平变为低电平后,延时(>4.7us),SCL变为低电平。

代码:
void BE_I_Start(void)
{   
    I2C_SDA_1();                 // SDA=1
    I2C_CLK_1();                 // CLK=1
    Delay_Unit5us();                // start hold 保持时间,必须大于4.7us
    I2C_SDA_0();                 // SDA=0
    Delay_Unit5us();                // start hold 保持时间,必须大于4.7us
    I2C_CLK_0();                 // CLK=0
    Delay_Unit5us();                // start hold 保持时间,必须大于4.7us
}

结束信号

SCL保持高电平。SDA由低电平变为高电平。

 代码:

void BE_I_Stop(void)
{

    I2C_SDA_0();                 // SDA=0
    Delay_Unit5us();
    I2C_CLK_1();                 // CLK=1
    Delay_Unit5us();
    I2C_SDA_1();                 // SDA=1
    Delay_Unit5us();
    I2C_CLK_0();                 // CLK=0 

}

 应答信号

数据传输必须带响应,相关的响应时钟脉冲由主机产生。在响应的时钟脉冲期间,发送器释放 SDA线(高)
在响应的时钟脉冲期间,接收器必须将 SDA 线拉低 。使它在这个时钟脉冲的高电平期间保持稳定的低电平
下面来看一下这张图:

这表示IIC的应答机制

  • 下面的波形:SCL,主机产生的时钟脉冲
  • 上面的波形:SDA,主机发送的8位数据
  • 中间的波形:SDA,从机在第9个时钟信号进行拉低回应,表示收到了主机发来的数据,拉高则表示不应答

1、ACK

代码:

void BE_I_ACK(void)
{
    I2C_CLK_0();                 // SCK=0
    I2C_SDA_0();                 // SDA=0
    I2C_CLK_1();                 // SCK=1
    Delay_Unit5us();
    I2C_CLK_0();                 // SCK=0
}

2、NACK

代码:

void BE_I_NAK(void)
{
    I2C_CLK_0();                 // SCK=0
    I2C_SDA_1();                 // SDA=1
    I2C_CLK_1();                 // SCK=1
    Delay_Unit5us();
    I2C_CLK_0();                 // SCK=0
}

注:实际上,上面和中间是同样的SDA线,这里只是分开示意。因为IIC应答是一种相互关系,单片机发数据给IIC器件,IIC器件要进行应答,表示收到了数据,同样,单片机接收IIC器件的数据后,也要给IIC器件一个应答。

如果不需要继续读取数据,可发送非应答信号。

五、IIC的数据传输格式

IIC分为7位寻址和10位寻址,因大多数都是7位寻址,这里不过多介绍10位寻址,想了解的小伙伴自己去了解一下

传输数据

字节格式

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

 如上图所示:

  • 当产生一个起始信号(S)后,开始数据传输,SAD先输出为高电平,SCL后输出为高电平,紧接着发送了一个从机地址,这个地址共有 7 位。紧接着的第 8 位是数据方向位(R/W)-------’0‘表示发送(写),’1‘表示接受数据(读)。然后主设备释放SDA(在响应的时钟脉冲期间 接收器必须将 SDA 线拉低),SCL电平由低变高,从设备产生ACK信号。每个字节的传输都要跟随有一个应答位,整个过程以接收到停止信号(P)为结束。
  • 所有的SDA 信号变化都要在SCL 时钟为低电平时进行,除了开始和结束标志

IIC基本读写过程

        数据由主机传输至从机                         S : 传输开始信号 (S)       

                                                                                   SLAVE_ADDRESS: 从机地址

         数据由从机传输至主机                         R/W:传输方向选择位,1为读,0为写        

                                                                                    A/A:应答(ACK)或非应答(NACK)信号
                                                                                    P:停止传输信号(P)                                    

IIC的读写操作

上面介绍的是IIC的基本读写过程,下面我们来详细讲述一下IIC写操作的时序逻辑(附代码)

写单个字节

  1.  开始写操作时,主机先发出起始信号(S),表示开始数据传输。
  2. 主机发出设备地址(7位)+写操作‘0’(1位)共八位数据,并等待从机应答信号。
  3. 在收到从机的应答信号之后,继续发送数据(8位),表示需要访问从机的哪一个地址,并等待应答信号。
  4. 接收到从机的应答信号后,接着发送8位需要写入的数据,随后等待应答信号。
  5. 写单个字节结束,主机发送停止信号(P)。
uint8 BE_I_WriteB(uint8 data1)
{
    uint8 i;
    uint8 errFg;

    uc_BeWrData = data1;                
    I2C_CLK_0();                     // SCK=0
    I2C_SDA_0();                     // SDA=0 

    for (i=0; i<8; i++)              // send One byte
    {
        I2C_CLK_0();                 // SCK=0
        if (uc_BeWrData & 0x80)      //获取最高位
        {
            I2C_SDA_1();             // DA=1 
        }                               
        else                            
        {
            I2C_SDA_0();             // DA=0 
        }                               
        uc_BeWrData <<= 1;
        Delay_Unit5us();
        I2C_CLK_1();                 // SCK=1
        Delay_Unit5us();
    }
    if (I2C_SDA_ST)                  //读取ACK
        {
            errFg = 1;              // 返回是1,为NAK
        }                              
    else                                
        {
            errFg = 0;              // 返回0为ACK
        }                                   
    I2C_CLK_0();                    // SCK=0
    return errFg;

}

连续写入多个字节

 

连续写入多个字节,大致时序同单字节写入一样,可在发送完第一个8位数据,并等待ACK信号后,再次写入一个8位数,并等待ACK信号。直到主机发送停止信号(P)后,停止数据传输。

读单个字节

  1. 首先由主设备产生起始信号,然后发送从设备地址位和一个写数据位‘0’,等待应答
  2. 然后发送寄存器地址,才能开始读寄存器(主机要改变通信模式(主机将由发送变为接收
  3. 收到应答信号后,主设备再发一个开始信号,然后发送从设备地址位和一个读数据位‘1’
  4. 然后,从设备产生应答信号并开始发送寄存器中的数据
  5. 通信以主设备产生的拒绝应答信号(nACK)和结束标志(Stop)结束
  6. 拒绝应答信号(nACK)产生定义为SDA 数据在第9 个时钟周期一直为高

 代码:

uint8 BE_I_ReadB(unsigned char ack)
{
    uint8 i;                            //
    I2C_CLK_0();                     // sclk=0 
    I2C_SDA_IN();                    //设为输入
    _BeRdData =0;                     //
    for (i=0;i<8;i++)                    //
    {
        I2CCLK_0();                 // sclk=0
        Delay_Unit5us();
        I2C_CLK_1();                 // sclk=1
        _BeRdData <<= 1;              // Clock high time
        if (I2C_SDA_ST)               // 接收到1
        {
            uc_BeRdData |= 0x01;        // 数据末位置1 (+1)
        }                               //
    }                                   //
    I2C_CLK_0();                     // sclk=0
     if (!ack)
        IIC_NAck();        //发送nACK
    else
        IIC_Ack();         //发送ACK  
    return uc_BeRdData;                //
}

连续读多个字节

通信时序与上面的“读一个字节”类似,上面是读一个字节后就nAck叫停,若要连续写,则发送Ack,直到不需要继续读时再回复nAck。

六、硬件IIC与软件IIC

一:模拟IIC与硬件IIC定义?


模拟I2C一般是用GPIO管脚,用软件控制管脚状态以模拟I2C通信波形。
硬件I2C对应芯片上的I2C外设,有相应I2C驱动电路,其所使用的I2C管脚也是专用。

二:优缺点


1.硬件I2C的效率要远高于软件的,而软件I2C由于不受管脚限制,接口比较灵活。
2.模拟I2C 是通过GPIO,软件模拟寄存器的工作方式,而硬件(固件)I2C是直接调用内部寄存器进行配置。如果要从具体硬件上来看,可以去看下芯片手册。因为固件I2C的端口是固定的,所以会有所区别。

三:如何区分它们

可以看底层配置,比如IO口配置,如果配置了IO口的功能(IIC功能)那就是固件IIC,否则就是模拟

可以看IIC写函数,看里面有木有调用现成的函数或者给某个寄存器赋值,如果有,则肯定是固件IIC功能,没有的话肯定是数据一个bit一个bit模拟发生送的,肯定用到了循环,则为模拟。

根据代码量判断,模拟的代码量肯定比固件的要大。


总结

以上就是IIC的全部内容,本文简单介绍了IIC的使用,希望对大家有帮助!

  • 43
    点赞
  • 86
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值