IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> 浅尝IIC -> 正文阅读

[嵌入式]浅尝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();			//主设备接受一个字节的数据
	I2CSendAck();					//主机发送非应答信号,表示不在接收数据
	
	return data;
}
  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-05-10 12:04:54  更:2022-05-10 12:06:10 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/30 1:11:54-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码