I2C通信基本原理及其实现
I2C是一种总线式结构,它只需要SCL时钟信号线与SDA数据线,两根线就能将连接与总线上的设备实现数据通信,由于它的简便的构造设计,于是成为一种较为常用的通信方式。
由于I2C采用的是主从式通信方式,所以,通信的过程完全由主设备仲裁。在通信之前,必须由主设备发送一个起始信号,决定数据是否可以开始传送,并且在结束通信时,必须再由主设备发送一个结束信号,以表示通信已经结束。

因为,通信之前,主设备需要发送一个起始信号,所以,先讲一下起始信号。通过上面的图就可以知道(上图中的第一个波形图是SDA数据线,第二个波形图是SCL时钟信号线),起始信号是在SCL时钟信号线处于高电平时,SDA数据线由高电平转换为低电平,也就是产生一个下降沿,就意味着起始信号已经发送,数据的通信可以进行了。代码如下:
void I2C_Start()
{
I2C_SDA = 1;
I2C_Delay10us();
I2C_SCL = 1;
I2C_Delay10us();//建立时间是I2C_SDA保持时间>4.7us
I2C_SDA = 0;
I2C_Delay10us();//保持时间是>4us
I2C_SCL = 0;
I2C_Delay10us();
}
同样的,由上图可知:结束信号,就是在SCL时钟信号线处于高电平时,SDA数据线由低电平变为高电平 ,也就是,SDA数据线产生一个 上升沿。代码如下:
void I2C_Stop()
{
I2C_SDA = 0;
I2C_Delay10us();
I2C_SCL = 1;
I2C_Delay10us();//建立时间大于4.7us
I2C_SDA = 1;
I2C_Delay10us();
}

接下来就是该讲一下,I2C数据的发送问题了。由于I2C是主从式通信,也就意味着一根总线上可以挂载多个从设备,那么主设备如何区分这些从设备呢?主设备如何知道是在与哪一个从设备在通信呢?答案是:通过地址。每一个从设备都有自己的地址编码,也就是说,主设备在与具体的某一个从设备通信之前,必须先发送地址,以表示与主设备通信的是该设备。从上图可知,主设备在发送完起始信号后,立刻开始了发送从设备的地址。那么如何发送数据地址呢?首先,在SCL时钟信号线处于低电平时,SDA数据线上的地址信息要开始准备了。I2C通信一个必须注意的点就是,在传送地址信息时,都是从高位开始传送,
I2C_SDA = dat >> 7;
dat = dat << 1;
接着,SCL时钟信号线开始由低电平向高电平转换,这个时候,SDA数据线上的数据开始在传送了,当SCL时钟信号线上的信号再由高电平转换位低电平的时候,一个Bit位的数据已经传送完毕。在地址信息传送完毕之后,还会有一个应答信号,因为,为了确保从设备接收到已经发送的数据,从设备就会向主设备发送一个应答信号,若主设备接收到应答信号则说明数据传送成功,否则数据传送失败。很重要的一点是,总线一直是由主设备控制,那么当从设备想要向主设备发送一个应答信号时,主设备需要是释放总线,将总线权限交给从设备。
所以,从设备在向主设备发送应答信号时,主设备应该释放总线,代码如下:
I2C_SDA = 1;
接着,由上图可知,当SCL时钟信号线再次拉高时,就进入了第9个时钟周期,也就是此时开始传送应答信号。当成功应答时,返回1,否则返回0。完整代码如下:
I2C_SDA = 1;
I2C_Delay10us();
I2C_SCL = 1; while(I2C_SDA && (ack == 1))
{
b++;
if(b > 200)
{
I2C_SCL = 0;
I2C_Delay10us();
return 0;
}
} I2C_SCL = 0;
I2C_Delay10us();
return 1;
}
最后,就是I2C设备(也就是主设备)数据的接收。此时,从设备发送数据给主设备,也就是,主设备进行数据的接收。那么,主设备同样要释放总线权限。也就是
I2C_SDA = 1;
首先,SCL时钟信号线为低电平,这时,SDA数据线要准备好数据了,接着,SCL时钟信号线由低电平变为高电平,此时,数据传送开始了,当SCL时钟信号线再次变为低电平是,一个Bit的数据传送结束。代码如下:
uchar I2C_ReadByte()
{
uchar a = 0,dat = 0;
I2C_SDA = 1; I2C_Delay10us();
//I2C_SCL = 0;
for(a=0; a<8; a++)
{
I2C_SCL = 1;
I2C_Delay10us();
dat <<= 1;
dat |= I2C_SDA;
I2C_Delay10us();
I2C_SCL = 0;
I2C_Delay10us();
}
return dat;
}
I2C的底层时序到这里基本上就已经结束了。
I2C通信基本原理及其实现的更多相关文章
- MCU开发之I2C通信
程序状态字PSW是8位寄存器,用于存放程序运行的状态信息,PSW中各位状态通常是在指令执行的过程中自动形成的,但也可以由用户根据需要采用传送指令加以改变.各个标志位的意义如下: PSW.7(Cy):进 ...
- 【转载】GPIO模拟i2c通信
I2C总线的通信过程(见图4-8)主要包含三个主要阶段:起始阶段.数据传输阶段和终止阶段. 1. 起始阶段 在I2C总线不工作的情况下,SDA(数据线)和SCL(时钟线)上的信号均为高电平.如果此时主 ...
- 由于用mpu6050模块,所以要用上i2c通信原理。
i2c通信原理 i2c总线只有两根双向信号线,一根是数据线SDA,一根是时钟线SCL. 每个接到i2c总线上的器件都有唯一的地址,主机与其他器件之间的数据传送可以是由主机发送给其他器件.主机为发送器, ...
- AT24C0X I2C通信原理
/********************************************************************** * AT24C0X I2C通信原理 * 说明: * 之前 ...
- 【转】三种方法让你在I2C通信中同时和多个从机通信
ref:http://tieba.baidu.com/p/3769008030 对于不同地址的模块就不用多说了,直接分别对其地址进行通信即可.那么若拿到相同地址的模块,或者直接是相同的多个模块怎么办呢 ...
- ESP8266开发之旅 基础篇⑤ ESP8266 SPI通信和I2C通信
设备与设备之间的通信往往都伴随着总线的使用,而用得比较多的就当属于SPI总线和I2C总线,而恰巧NodeMcu也支持这两种总线通信,所以本章的主要内容就是讲解ESP8266 SPI和I2C总线 ...
- Socket通信基本原理
Http通信: http连接使用的是“请求—响应方式”,即在请求时建立连接通道,当客户端向服务器发送请求后,服务器端才能向客户端返回数据. Socket通信: Socket通信则是在双方建立起连接后就 ...
- STM32的I2C通信
I2C总线是由NXP(原PHILIPS)公司设计,有十分简洁的物理层定义,其特性如下: 只要求两条总线线路:一条串行数据线SDA,一条串行时钟线SCL: 每个连接到总线的器件都可以通过唯一的地址和一直 ...
- ARM学习笔记15——串口通信基本原理【转】
计算机串口基本理论 1.什么是串口? 2,什么是RS-232? 3,什么是RS-422? 4,什么是RS-485? 5,什么是握手? 1,什么是串口? 串口是计算机上一种非常通用的设备通信的协议(不要 ...
随机推荐
- Scrapy:配置日志
Scrapy logger 在每个spider实例中提供了一个可以访问和使用的实例,方法如下: import scrapy class MySpider(scrapy.Spider): name = ...
- django 之MTV模型
一个小问题: 什么是根目录:就是没有路径,只有域名..url(r'^$') 补充一张关于wsgiref模块的图片 一.MTV模型 Django的MTV分别代表: Model(模型):和数据库相关的,负 ...
- git总结一、工作中常用基础命令
首先来了解两个概念: 工作区:比如你的项目目录 暂存区:git和其他版本控制系统的不同之处就是有这个暂存区的概念. .git不是工作区,而是git 版本库,在版本库中存放着很多东西,比如暂存区(sta ...
- 使用jquery移除前面通过onclick绑定的元素的事件,然后重新绑定别的函数来执行onclick事件。
http://caibaojian.com/css3/experience/bugs.htm 使用jquery移除前面通过onclick绑定的元素的事件,然后重新绑定别的函数来执行onclick事件. ...
- android 调用 screenrecord 实现录屏
首先要说明的是并未实现,本文讲一下自己的思路. adb 使用shell 命令 screenrecord 可录屏. 自己写了个app,通过Process p = Runtime.getRuntime() ...
- js中字符串可以调用的方法
var s = "hello,world" //定义一个字符串 s.length() // => 11 s.charAt(0) ...
- app Inventor
什么是App Inventor ? MIT 官方网站 http://ai2.appinventor.mit.edu/Ya_tos_form.html 广州中文镜像网站 http://app.gzjk ...
- MySQL单表查询
MySQL之单表查询 创建表 # 创建表 mysql> create table company.employee5( id int primary key AUTO_INCREMENT not ...
- ArrayDataProvider数据分页
模型 public function search($page=10){ $lists = self::find()->orderBy('id DESC')->all(); $dataPr ...
- 3d
http://jokerwang.com/diy-3d%E6%89%93%E5%8D%B0%E6%9C%BA1-%E7%A1%AC%E4%BB%B6%E7%AF%87/