软件模拟IIC同步串行通信协议

文章截图来自芯片技术手册(已附链接),仅用于个人学习记录。

IIC串行通信协议(摘自网络):

       I2C(Inter-Integrated Circuit)是一种串行通信协议,由Philips公司于1980年代初开发。它使用两个线路进行全双工通信,分别为:Serial Clock线(SCL)和Serial Data线(SDA)。I2C协议主要应用于系统中不同模块之间的数字数据传输,如芯片、传感器等设备。

I2C协议的基本特点:

  1. I2C是一种同步串行通信协议。在通信时钟的控制下,从设备通过SDA线发送响应数据给主设备,主设备控制通信时钟的速率。

  2. I2C协议可以同时连接多个设备。每个设备都有一个唯一的地址,主设备可以根据地址选取相应的从设备进行通信。

  3. I2C协议支持收发数据的操作,包括读和写。主设备可以向从设备发送命令或数据,也可以从从设备读取数据。

  4. I2C协议支持硬件层面的“应答”机制。即,从设备在接收到命令或数据后,需要给主设备发送确认信号。这种机制可以保证通信过程的正确性。

I2C协议的基本通信流程:

  1. 主设备发送起始信号(Start Condition)。

  2. 主设备发送从设备地址和通信方向(读或写)。

  3. 从设备发送确认信号(ACK)。

  4. 主设备发送数据或命令。

  5. 从设备发送确认信号(ACK)。

  6. 重复步骤4和5,直到通信结束。

  7. 主设备发送停止信号(Stop Condition)。

I2C协议的数据传输是由主设备控制的,每个从设备都有一个唯一的地址。在通信时,主设备通过SCL线产生时钟信号来同步从设备的数据传输;通过SDA线向从设备发送命令或数据;从设备则通过SDA线发送响应数据给主设备。

总之,I2C是一种使用两根线路进行同步串行通信的协议,支持同时连接多个设备,并且具有硬件层面的“应答”机制。I2C协议在数字系统中广泛应用于不同模块之间的数字数据传输。

详细讲解文章:

STM32单片机初学4-IIC通信(软件模拟)_软件模拟iic_Vector_potential的博客-CSDN博客

 EEPROM读写操作过程:

字节写:

 随机读:

 芯片中文手册:

AT24C02_Datasheet_IDCHIP_英锐芯-icspec芯片规格书搜索工具

有关AT24CXX读写地址部分代码的解读:

关于原子哥提供的AT24CXX代码中的读写一个字节代码,有关根据不同型号芯片读写地址的那一部分代码(也就是下面的代码,以写部分代码来讲解),有点难以理解,因为这牵扯到了不同容量的AT24CXX字节地址问题。

为便于解读此部分代码,忽略无关的代码后,将其分为三部分:

AT24CXX不同型号的存储结构:

  根据使用芯片型号的不同,可以将芯片与这三部分匹配为:

(1). if(EE_TYPE>AT24C16)(大于24c16容量的芯片)的型号,即:24c32、24c64

匹配代码的第一、三部分

(2).else(小于等于24c16容量的芯片)的型号,即:24c02、24c04、24c08、24c16

匹配代码的第二、三部分
1.由于本代码使用的是EE_TYPE==24C02,因此先讨论(2)型号的芯片部分代码:
        IIC_Send_Byte(0XA0+((WriteAddr/256)<<1));    //第二部分

这部分代码是发送器件地址,这句话的意思是,发送一个字节0XA0+((WriteAddr/256)<<1),对于0XA0这个字节我们根据通信的协议知道,它是器件地址,并且前四位“A”是固定不变的,最后一位(R/W)是读写方向位,如果是读则配置为1,如果是写则配置为0,并且根据硬件配置接地,所以A2、A1、A0这三位都为0。那么对于24c02的器件地址的配置就是0XA0,那么你此时就会有两个疑惑:

           第一,P0、P1、P2是什么,为什么24c02没有;24c04只有P0;24c08却有P0,P1;24c016却有P0,P1,P2?

           第二,+((WriteAddr/256)<<1部分的代码有何作用?

要想解除这两点疑惑,我们首先要明白三个基本点:

一、IIC_Send_Byte()函数一次性发送一个字节,而0XA0已经是一个字节了,那么+((WriteAddr/256)<<1部分代码的作用就是改变0XA0,并且是改变R/W位前面的那三位(这一点后面会说到)

二、上面一行红字部分说明了你的两个疑惑之间有某种关联 。

三、我们都知道一个字节对应着一个地址。WriteAddr是写入数据的地址,这个变量的数据范围是和你选的芯片容量有关的,比如说24c02是总容量2k,其中有32页,每一页包含8个字节,这也就是说,24c02有32*8=256个地址,所以WriteAddr的范围就是0~255。

在明白上面三个基本点后,就可以解答你的两个疑惑了:

+((WriteAddr/256)<<1部分的代码的作用就是改变P0、P1、P2位的值;

而24c02没有这三位,是因为如果你使用的是24c02,那么由于24c02只有256个地址,所以你输入的WriteAddr的范围就是0~255,将WriteAddr的值带入(WriteAddr/256)<<1,得到的结果就是0,对于0XA0没有影响;

而24c04只有P0,是因为如果你使用的是24c04,那么由于24c04有32*16=512个地址,所以你输入的WriteAddr的范围就是0~511,将WriteAddr的值带入(WriteAddr/256)<<1,得到的结果就是可能是0,也可能是1,如果是0的话,那么对于0XA0没有影响,但是如果是1的话,就会改变P0位的值(P0置一),也就是0XA0变成了0xA2。这么说来P0位就是用来对于24c04的255地址之后的判断,如果P0置一,就说明,我们要写入的地址在255地址之后,即如果WriteAddr=321(注意由于是24c04,所以范围可以是0~511),则需要将数据写入的地址在第二个地块(每256个地址一个地块)。

那么问题又来了,当我们选择的芯片是24c08的话,就会有64*16=1024个地址,也就是4个地块,那么显然对于24c04有两个地块,一个P0位就可以说明,4个地块的话一个P0位肯定是不够的,因此需要加入P1位,P0、P1两个位刚好可以说明4个地块,这就很好的解决了确定地址属于哪个地块的问题。

因此,总结来说,P0、P1、P2就是用来确定你想将数据写入的地址属于哪个地块(+((WriteAddr/256)<<1这部分的代码就是实现修改这几位的值的)。当然确认完地块后,还需要再确定是在地块上的哪个位置,这就是第三部分代码需要完成的任务了。

               IIC_Send_Byte(WriteAddr%256);  //第三部分

这部分代码就是说明数据的具体地址,也就是哪个地块上的位置。

比如说我们选的芯片是24c08,需要将数据写入的地址是898(WriteAddr=898),那么利用WriteAddr/256=3(取整),得到我们需要将数据存储在地块3上面,因此利用0XA0+((WriteAddr/256)<<1)将P1置一、P1置零(最后得到器件地址0xA4),然后将器件地址0xA4发送给24c08芯片,等待回应后,再将WriteAddr%256=130(也就是说在第三块上的地址是130)发送给24c08芯片来确定数据需要写入的位置,等待回应后,就开始了数据的传输。

2.对于(3)型号的芯片部分代码:

由于将P0、P1、P2都置一后,能确定的地块才是8个地块,而24c32需要128*32/256=16个地块,因此不能采用上述通过置位P0、P1、P2的策略,实现地址的确定。那么该如何是好呢?

此时我们想到既然不能通过置位P0、P1、P2的策略完成位置的确定,那么干脆就不采取设置器件地址位P0、P1、P2的方法,直接将器件地址设置成和24c02一样的固定值0xA0。那么接着怎么办呢?芯片仍然无法确定你要讲数据写进哪个地块中啊!向芯片发送完器件地址后,等待芯片回应后,再向芯片发送一个字节,告诉它我要将数据写入哪个地址块!然后等待芯片回应后(第一部分代码功能完成),再告诉它我要写入地址块中的哪个位置(第三部分代码功能完成),然后在此等待回应,开始传输数据。

举例说明:

比如说我们选的芯片是24c32(代码:if(EE_TYPE>AT24C16)),需要将数据写入的地址是3832(WriteAddr=3832),那么首先向芯片发送固定的器件地址0xA0(代码:IIC_Send_Byte(0XA0);),然后等待芯片回应(代码:IIC_Wait_Ack();),芯片回应后,向芯片发送我要将数据写入的地块的地址3832>>8=0x0E(相当于3832/256之后的值取整,然后转换成16进制,代码:IIC_Send_Byte(WriteAddr>>8);),等待回应后,再将WriteAddr%256=248(也就是说在第14块上的地址是248)发送给24c32芯片来确定数据需要写入的位置,等待回应后,就开始了数据的传输。

 以上是我个人的理解,还有一篇前辈写的文章值得借鉴:

IIC_Send_Byte(0XA0+((ReadAddr/256)<<1))解释_weixin_43853738的博客-CSDN博客

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值