浅尝IIC

浅尝IIC

在称为嵌入式驱动工程师的道路上,IIC协议是我必须掌握的一个协议,我打算这周末为深入学习IIC协议,并且完成实验以及独立编写IIC驱动代码。

前言:

参考**《STM32库开发实战指南》**以及《_Z小旋的博客-CSDN博客_i2c通信的详细讲解》

在计算机科学中,大部分复杂问题都可以通过分层来简化。如Linux嵌入式设备,可分为硬件层、裸机层、内核层、应用层。芯片被分为内核层和片上外设(比如usart等)。

对于通信协议,我们也通过分层的方式来理解,最基本的分为软件层协议层

简单来说,硬件层规定我们是使用嘴巴说还是肢体表示,而协议层规定我们使用英语还是汉语交流。 ——STM32库开发实战指南(火哥)

IIC物理层:

1)它是一个支持设备的总线。支持多个设备公用,但只有一个主设备。基本上谁控制时钟线(即控制SCL的电平高低变换)谁就是主设备。

2)只有两个信号线,一个是双向串行数据线(SDA),一个是串行时钟线(SCL)。

3)每个连接到总线的设备都有一个独立的地址,主机可以利用这个地址访问不太的设备。

4)总线通过上拉电阻接到了电源,为了保证信号线稳定。因为IIC设备都空闲时,会输出高阻态,相当于所有的设备都和两根总线断开了,上拉电阻会把总线拉到高电平。 如果不接上拉电阻,那么信号线就相当于浮空会变得不稳定。(下面有开漏模式的基本解释)。

5)同一个IIC总线上的设备不能超过使两个线之间的等效电容超过400PF?

6)为了避免总线信号的混乱,要求各设备连接到总线的输出端时必须是漏极开路(OD)输出或集电极开路(OC)输出。除了主设备

开漏模式:配置到IO口后,只能输出/输入低电平和高阻态,高阻态顾名思义,就是非常高(大)的阻值,即断路

开漏在IIC的作用:

将IO口设置为开漏后,io口可以输出/输入低电平高阻态,主要目的是为了防止总线信号的混乱,如为了使空闲设备不再接受总线上的信号,将空闲设备io口设置为了高阻态,它就不会总线上的信号影响。其他正在用的设备并不会收到干扰。

总结物理层:

IIC有有两根信号总线,都带有一个上拉电阻到高电平为了设备空闲保证信号稳定,然后所有的设备都被设置为了开漏模式(不论输出输入)。

IIC协议层:

在这里插入图片描述

开始信号:
//I2C总线启动
void I2CStart(void)
{
	SDA_Output(1);delay1(500);
	SCL_Output(1);delay1(500);
	SDA_Output(0);delay1(500);
	SCL_Output(0);delay1(500);//提前拉低SCL,准备传输数据
}
停止信号:
//I2C总线停止
void I2CStop(void)
{
	SCL_Output(0); delay1(500);
	SDA_Output(0); delay1(500);
	SCL_Output(1); delay1(500);
	SDA_Output(1); delay1(500);

}

一般延时时间(>4.7us)

在起始条件产生后,总线处于忙状态,由本次数据传输的主从设备独占,其他I2C器件无法访问总线;而在停止条件产生后,本次数据传输的主从设备将释放总线,总线再次处于空闲状态。

一般下只有在SCL信号为0时,SDA才能变化。数据的传输时通过SDA的电平变化来传输的。如果在SCL信号为1时,SDA信号仍然发生电平变化,说明是起始信号或者停止信号。

感到疑惑的地方:

有些IIC驱动的负责发送起始信号的函数后面还跟着一个将SCL拉低的操作,实测起始不要拉低也可以,这里最好也拉低,如果不拉低,造成数据误判。
在这里插入图片描述

应答信号:

每当主机向从机发出一个字节的数据信号后,主机总是需要等待从机传回一个应答信号,以确定从机是否收到数据。

应答信号:主机SCL拉高,读取从机SDA的电平,为低电平表示产生应答

//发送应答位
void I2CSendAck(void)
{
	SDA_Output(0);delay1(500);
	delay1(500);
	SCL_Output(1); delay1(500);
	SCL_Output(0); delay1(500);

}

//
void I2CSendNotAck(void)
{
	SDA_Output(1);
	delay1(500);
	SCL_Output(1); delay1(500);
	SCL_Output(0); delay1(500);

}
IIC数据传送信号:

在这里插入图片描述

SDA线上的数据在SCL时钟“高”期间必须是稳定的,只有当SCL线上的时钟信号为低时,数据线上的“高”或“低”状态才可以改变。输出到SDA线上的每个字节必须是8位,数据传送时,先传送最高位(MSB),每一个被传送的字节后面都必须跟随一位应答位(即一帧共有9位)。

然后数据传送信号 有分成了两种信号,一个是器件地址数据传送信号,一个是数据传送信号。

在起始信号后必须传送一个从机的地址(7位) 1~7位为7位接收器件地址,第8位为读写位,用“0”表示主机发送数据(W)(一帧一共9位),“1”表示主机接收数据 (R), 第9位为ACK应答位,紧接着的为第一个数据字节(8位),然后是一位应答位(也是一帧9位),后面继续第2个数据字节。

IIC写入数据:

主机要向从机写数据时:

1、起始信号,打开iic总线

2、发生地址位控制位,发送从设备地址到总线上,地址一共7位,后面跟上一位控制字在(0)写入还是写出的位(W/R),(中间将SDA引脚设置为了下拉输入),然后等待一位应答位(输入)(当对应从机接受到主机要访问它的信号时,它就会把SDA拉低,为成功应答),然后在进行下一步。

3、收到应答后,发送具体你要访问的从设备的地址,也是和数据信号一样,先发一个8bin地址,然后等待一个应答信号(输入)

4、收到应答后,发送数据信号,包括一个8字节的数据信号,然后等待一个应答信号(输入)

5、收到应答后,发送一个结束信号

打个比方来说

主机和从机为蓝天白云两个人在打仗,然后他们之间通过一个对讲机沟通

1、蓝天想联系白云时,他会在对讲机的频道中喊道“白云,在吗?!”,然后等待白云回应“白云,收到”,(这一步是为了确认白云存活)

2、当白云回应蓝天后(收到应答信号),蓝天会继续喊道“请移动到1314.1111点”,然后等待白云回应“白云,收到”(这里一步是告诉了白云具体的坐标)

3、当白云回应蓝天后(收到应答信号),蓝天会继续喊道“请释放烟雾弹”,然后等待白云回应“白云,收到”(这里一步是告诉了白云在当前位置需要做什么事情)

4、当白云回应蓝天后(收到应答信号),停止通讯。

void x24_write(u8 add,u8 data)
{
	I2CStart();				//开始信号
	
	I2CSendByte(0xa0);		//发送从设备地址
	I2CWaitAck();			//等待从设备应答
	
	I2CSendByte(add);		//发送具体要访问从设备的哪个地址(或寄存器)
	I2CWaitAck();			//等待从设备应答
	
	I2CSendByte(data);		//发送要写入从设备这个地址(或寄存器)中的值
	I2CWaitAck();			//等待从设备应答
	
	I2CStop();				//结束信号
}

IIC读数据:

1、发送起始信号,打开IIC总线

2、发送从设备的地址(7位)加上一位读取位,加上0(代表向从设备写入),然后等待应答

3、收到应答后,发送具体你要访问的从设备中的地址,先发一个8bin地址,然后等待一个应答信号(输入)

4、收到应答后,重新发出起始信号,然后发送访问的从设备的地址,跟上一个1(代表读操作),然后等待应答信号

5、收到应答后,重新发送起始信号,然后发送从设备的地址(7位)加上一位读取位,加上1(代表向从设备读取),等待应答

6、收到应答后,然后将主设备SDA设置为输入,从设备设置为输出,开始接受数据,当读取完一个字节后,主设备发送非应答信号

同样用蓝天白云来说明:

1、蓝天想联系白云时,他会在对讲机的频道中喊道“白云,在吗?!”,然后等待白云回应“白云,收到”,(这一步是为了确认白云存活)

2、当白云回应蓝天后(收到应答信号),蓝天会继续喊道“请移动到1314.1111点”,然后等待白云回应“白云,收到”(这里一步是告诉了白云具体的坐标)

3、当白云回应蓝天后(收到应答信号),蓝天给白云,请汇报你现在的情况,等待回应

4、当白云回应蓝天后(收到应答信号),开始给蓝天汇报情况

5、在蓝天收到完整的一个情报后,蓝天回复白云“收到”,结束通讯。

u8 x24_read(u8 add)
{
	u8 data;
	
	I2CStart();						//开始信号
	
	I2CSendByte(0xa0);				//发送从设备的地址,并且是写操作
	I2CWaitAck();
	
	I2CSendByte(add);				//发送要进行操作的地址
	I2CWaitAck();

	I2CStart();						//重新发送开始信号
	I2CSendByte(0xa1);				//告诉从设备要进行读操作
	I2CWaitAck();					//等待从设备应答
	
	data=I2CReceiveByte();			//主设备接受一个字节的数据
	I2CSendNotAck();					//主机发送非应答信号,表示不在接收数据
	
	return data;
}
  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值