声明

本文大部分内容为转载,因此标定为转载

源地址:

http://www.cnblogs.com/zym0805/archive/2011/07/31/2122890.html

http://blog.csdn.net/lxl123/article/details/22884719

I2C协议

简介

I2C是由Philips公司发明的一种串行数据通信协议,仅使用两根信号线:SerialClock(简称SCL)和SerialData(简称SDA)。I2C是总线结构,1个Master,1个或多个Slave,各Slave设备以7位地址区分,地址后面再跟1位读写位,表示读(=1)或者写(=0),所以我们有时也可看到8位形式的设备地址,此时每个设备有读、写两个地址,高7位地址其实是相同的。

数据格式

I2C数据格式如下:

无数据:SCL=1,SDA=1;

开始位(Start):当SCL=1时,SDA由1向0跳变;

停止位(Stop):当SCL=1时,SDA由0向1跳变;

数据位:当SCL由0向1跳变时,由发送方控制SDA,此时SDA为有效数据,不可随意改变SDA;

当SCL保持为0时,SDA上的数据可随意改变;

地址位:定义同数据位,但只由Master发给Slave;

应答位(ACK):当发送方传送完8位时,发送方释放SDA,由接收方控制SDA,且SDA=0;

否应答位(NACK):当发送方传送完8位时,发送方释放SDA,由接收方控制SDA,且SDA=1。

传输过程

当数据为单字节传送时,格式为:

开始位,8位地址位(含1位读写位),应答,8位数据,应答,停止位。

当数据为一串字节传送时,格式为:

开始位,8位地址位(含1位读写位),应答,8位数据,应答,8位数据,应答,……,8位数据,应答,停止位。

注意事项

  1. SCL一直由Master控制,SDA依照数据传送的方向,读数据时由Slave控制SDA,写数据时由Master控制SDA。当8位数据传送完毕之后,应答位或者否应答位的SDA控制权与数据位传送时相反。
  2. 开始位“Start”和停止位“Stop”,只能由Master来发出。
  3. 地址的8位传送完毕后,成功配置地址的Slave设备必须发送“ACK”。否则否则一定时间之后Master视为超时,将放弃数据传送,发送“Stop”。
  4. 当写数据的时候,Master每发送完8个数据位,Slave设备如果还有空间接受下一个字节应该回答“ACK”,Slave设备如果没有空间接受更多的字节应该回答“NACK”,Master当收到“NACK”或者一定时间之后没收到任何数据将视为超时,此时Master放弃数据传送,发送“Stop”。
  5. 当读数据的时候,Slave设备每发送完8个数据位,如果Master希望继续读下一个字节,Master应该回答“ACK”以提示Slave准备下一个数据,如果Master不希望读取更多字节,Master应该回答“NACK”以提示Slave设备准备接收Stop信号。
  6. 当Master速度过快Slave端来不及处理时,Slave设备可以拉低SCL不放(SCL=0将发生“线与”)以阻止Master发送更多的数据。此时Master将视情况减慢或结束数据传送。

伪代码实现

起始位,停止位

/*
函数:I2C_Start()
功能:产生I2C总线的起始状态
说明:
SCL处于高电平期间,当SDA出现下降沿时启动I2C总线
不论SDA和SCL处于什么电平状态,本函数总能正确产生起始状态
本函数也可以用来产生重复起始状态
本函数执行后,I2C总线处于忙状态
*/
void I2C_Start()
{
EA=0; I2C_SCL = 1;
I2C_Delay();
I2C_SDA = 1;
I2C_Delay(); //起始条件建立时间大于4.7us延时
I2C_SDA = 0; //发送起始信号
I2C_Delay();
I2C_SCL = 0; //钳住I2C总线,准备发送或接收数据
I2C_Delay();
I2C_Delay();
I2C_Delay();
} /*
函数:I2C_Stop()
功能:产生I2C总线的停止状态
说明:
SCL处于高电平期间,当SDA出现上升沿时停止I2C总线
不论SDA和SCL处于什么电平状态,本函数总能正确产生停止状态
本函数执行后,I2C总线处于空闲状态
*/
void I2C_Stop()
{
unsigned int t = I2C_STOP_WAIT_VALUE; I2C_SDA = 0; //发送结束条件的数据信号
I2C_Delay(); I2C_SCL = 1; //发送结束条件的时钟信号
I2C_Delay();
I2C_SDA = 1; //发送I2C总线结束信号
I2C_Delay();
EA=1;
while ( --t != 0 ); //在下一次产生Start之前,要加一定的延时
}

单字节读和写

/*
函数:I2C_Write()
功能:向I2C总线写1个字节的数据
参数:
dat:要写到总线上的数据
*/
void I2C_Write(unsigned char dat)
{
/*发送1,在SCL为高电平时使SDA信号为高*/
/*发送0,在SCL为高电平时使SDA信号为低*/
unsigned char t ;
for(t=0;t<8;t++)
{ I2C_SDA = (bit)(dat & 0x80);
I2C_Delay();
I2C_SCL = 1; //置时钟线为高,通知被控器开始接收数据位
I2C_Delay();
I2C_SCL = 0;
I2C_Delay();
dat <<= 1;
} } /*
函数:I2C_Read()
功能:从从机读取1个字节的数据
返回:读取的一个字节数据
*/
unsigned char I2C_Read()
{
unsigned char dat=0;
unsigned char t ;
bit temp;
I2C_Delay();
I2C_Delay();
I2C_SDA = 1; //在读取数据之前,要把SDA拉高 I2C_Delay(); for(t=0;t<8;t++)
{
I2C_SCL = 0; /*接受数据*/
I2C_Delay();
I2C_SCL = 1;//置时钟线为高使数据线上升沿数据有效
I2C_Delay();
temp = I2C_SDA;
dat <<=1;
if (temp==1) dat |= 0x01;
} I2C_SCL = 0;
I2C_Delay(); return dat;
}

ACK & NACK

/*
函数:I2C_GetAck()
功能:读取从机应答位
返回:
0:从机应答
1:从机非应答
说明:
从机在收到每个字节的数据后,要产生应答位
从机在收到最后1个字节的数据后,一般要产生非应答位
*/
bit I2C_GetAck()
{
bit ack;
unsigned char Error_time=255; I2C_Delay();
I2C_SDA = 1; /*8位发送完后释放数据线,准备接收应答位 释放总线*/
I2C_Delay();
I2C_SCL = 1; /*接受数据*/
I2C_Delay();
do
{
ack = I2C_SDA;
Error_time--;
if(Error_time==0)
{
I2C_SCL = 0;
I2C_Delay();
return 1;
}
}while(ack); //判断是否接收到应答信号 I2C_SCL = 0; //清时钟线,钳住I2C总线以便继续接收
I2C_Delay();
I2C_Delay();
I2C_Delay();
return 0;
} /*
函数:I2C_PutAck()
功能:主机产生应答位或非应答位
参数:
ack=0:主机产生应答位
ack=1:主机产生非应答位
说明:
主机在接收完每一个字节的数据后,都应当产生应答位
主机在接收完最后一个字节的数据后,应当产生非应答位
*/
void I2C_PutAck(bit ack)
{ I2C_SDA = ack; //在此发出应答或非应答信号
I2C_Delay();
I2C_SCL = 1; //应答
I2C_Delay(); I2C_SCL = 0; //清时钟线,钳住I2C总线以便继续接收 ,继续占用
I2C_Delay(); //等待时钟线的释放
I2C_Delay();
I2C_Delay();
I2C_Delay(); }

多字节读和写

/*
函数:I2C_Puts()
功能:主机通过I2C总线向从机发送多个字节的数据
参数:
SlaveAddr:从机地址(高7位是从机地址,最低位是写标志0)
SubAddr:从机的子地址
Size:数据的字节数
*dat:要发送的数据
返回:
0:发送成功
1:在发送过程中出现异常
*/
bit I2C_Puts(unsigned char SlaveAddr, unsigned char SubAddr, unsigned char Size, char *dat)
{
//检查长度
if ( Size == 0 ) return 0;
//确保从机地址最低位是0
SlaveAddr &= 0xFE;
//启动I2C总线
I2C_Start();
//发送从机地址
I2C_Write(SlaveAddr);
if ( I2C_GetAck() )
{
I2C_Stop();
return 1;
}
//发送子地址
I2C_Write(SubAddr);
if ( I2C_GetAck() )
{
I2C_Stop();
return 1;
}
//发送数据
do
{
I2C_Write(*dat++);
if ( I2C_GetAck() )
{
I2C_Stop();
return 1;
}
} while ( --Size != 0 );
//发送完毕,停止I2C总线,并返回结果
I2C_Stop();
return 0;
} /*
函数:I2C_Put()
功能:主机通过I2C总线向从机发送1个字节的数据
参数:
SlaveAddr:从机地址(高7位是从机地址,最低位是写标志0)
SubAddr:从机的子地址
dat:要发送的数据
返回:
0:发送成功
1:在发送过程中出现异常
*/
bit I2C_Put(unsigned char SlaveAddr, unsigned char SubAddr, char dat)
{
return I2C_Puts(SlaveAddr,SubAddr,1,&dat);
} /*
函数:I2C_Gets()
功能:主机通过I2C总线从从机接收多个字节的数据
参数:
SlaveAddr:从机地址(高7位是从机地址,最低位是读标志1)
SubAddr:从机的子地址
Size:数据的字节数
*dat:保存接收到的数据
返回:
0:接收成功
1:在接收过程中出现异常
*/
bit I2C_Gets(unsigned char SlaveAddr, unsigned char SubAddr, unsigned char Size, unsigned char *dat)
{ //检查长度
if ( Size == 0 ) return 0;
//确保从机地址最低位是0
SlaveAddr &= 0xFE; //确保最低位是0
//启动I2C总线
I2C_Start();
//发送从机地址
I2C_Write(SlaveAddr);
if ( I2C_GetAck() )
{
I2C_Stop();
return 1;
}
//发送子地址
I2C_Write(SubAddr);
if ( I2C_GetAck() )
{
I2C_Stop();
return 1;
}
//发送重复起始条件
I2C_Start();
//发送从机地址
SlaveAddr |= 0x01;
I2C_Write(SlaveAddr);
if ( I2C_GetAck() )
{
I2C_Stop();
return 1;
}
//接收数据
for (;;)
{
*dat++ = I2C_Read();
if ( --Size == 0 )
{
I2C_PutAck(1);
break;
}
I2C_PutAck(0);
} //接收完毕,停止I2C总线,并返回结果
I2C_Stop();
return 0;
} /*
函数:I2C_Get()
功能:主机通过I2C总线从从机接收1个字节的数据
参数:
SlaveAddr:从机地址(高7位是从机地址,最低位是读标志1)
SubAddr:从机的子地址
*dat:保存接收到的数据
返回:
0:接收成功
1:在接收过程中出现异常
*/
bit I2C_Get(unsigned char SlaveAddr, unsigned char SubAddr, unsigned char *dat)
{
return I2C_Gets(SlaveAddr,SubAddr,1,dat);
}

i2c协议简要分析(转载)的更多相关文章

  1. InnoDB多版本(MVCC)实现简要分析(转载)

    http://hedengcheng.com/?p=148 基本知识 假设对于多版本(MVCC)的基础知识,有所了解.InnoDB为了实现多版本的一致读,采用的是基于回滚段的协议. 行结构 InnoD ...

  2. 微店APP协议简要分析

    1.通过抓包软件charles进行抓包,点击微信收款后,抓包内容都是加密处理过  2.加载分析定位这些字段的加密函数. WDTNThorParameterProcessor HTTPBody:task ...

  3. I2C总线协议图解(转载)

    转自:http://blog.csdn.net/w89436838/article/details/38660631 另外,https://blog.csdn.net/qq_38410730/arti ...

  4. iNode协议再次分析

    iNode协议再次分析 声明: 1)本报告由博客园bitpeach撰写,版权所有,免费转载,请注明出处,并请勿作商业用途. 2)若本文档内有侵权文字或图片等内容,请联系作者bitpeach删除相应部分 ...

  5. 转:InnoDB多版本(MVCC)实现简要分析

    InnoDB多版本(MVCC)实现简要分析 基本知识 假设对于多版本(MVCC)的基础知识,有所了解.InnoDB为了实现多版本的一致读,采用的是基于回滚段的协议. 行结构 InnoDB表数据的组织方 ...

  6. Android IOS WebRTC 音视频开发总结(八十六)-- WebRTC中RTP/RTCP协议实现分析

    本文主要介绍WebRTC中的RTP/RTCP协议,作者:weizhenwei ,文章最早发表在编风网,微信ID:befoio 支持原创,转载必须注明出处,欢迎关注我的微信公众号blacker(微信ID ...

  7. (原创) 巩固理解I2C协议(MCU,经验)

        题外话:这几天天气突然转冷了.今天已是11月23日了,查查黄历,昨天(11月22日)刚好是小雪,一夜温度骤降,果然老祖先的经验有灵验!冬天来了,还是多加加衣服,注意保暖! 1.Abstract ...

  8. Google发布SSLv3漏洞简要分析报告

    今天上午,Google发布了一份关于SSLv3漏洞的简要分析报告.根据Google的说法,该漏洞贯穿于所有的SSLv3版本中,利用该漏洞,黑客可以通过中间人攻击等类似的方式(只要劫持到的数据加密两端均 ...

  9. CVE-2015-5122 简要分析(2016.4)

    CVE-2015-5122 简要分析 背景 最近在学习Flash漏洞的分析,其与IE漏洞的分析还是有诸多的不同(不便)之处,折腾了一阵子终于克服了没有符号表.Flash的超时定时器等问题.所以找到了去 ...

随机推荐

  1. 怎样把excel的数据导入到sqlserver2000数据库中

    在做程序的时候有时需要把excel数据导入到sqlserver2000中,以前没从外部导入过数据,今天刚做了一下导入数据,感觉还是蛮简单的,没做过之前还想着多么的复杂呢,下面就来分享一下我是如何把ex ...

  2. QT总结第3篇:如何在QT中添加.lib,.dll还有.h文件

    因为我在工作的过程中,使用的是第三方提供的库,但是如何将这些库添加到QT的工程中,是个问题,让我恼火了很久,怎么弄都是错的. 下面,我会对这个问题,进行叙述,希望其他人第一次遇到这种问题的时候,可以轻 ...

  3. flex acionscript png图片去除多余空白,生成合适大小图片

    //最小矩形(非透明最小区域) public static function getMinRect(target:BitmapData):Rectangle{   return target.getC ...

  4. ASPNET_MVC学习中的疑问

    1.在mvc..net4.5.Entity Framewor都提供了多种验证规则.  请问,其中不需要提交到服务器验证的验证,是否是在客户端就完成的,还是说像之前的aspnet一样,都得提交到服务器验 ...

  5. mongoosejs model mapping to collection name

    mongoosejs 是一个对象模型工具,将mongodb的collection中的Document映射为Model 典型用法如下 var mongoose = require('mongoose') ...

  6. 在亚马逊amazon的AWS上安装Node和MongoDB服务器

    在亚马逊amazon的AWS上安装Node和MongoDB服务器 在建立AWS上账号.创建EC2 ,用putty链接上之后,就可以用下面的方法开始安装. !!! 如果不是是自己建立的EC2, 而是由B ...

  7. ACM知识点

    基础算法 高精 模拟 分治 贪心 排序 DFS 迭代加深搜索 BFS 双向BFS 动态规划 DAG上DP 树上DP 线性DP 图算法 最短路 FLYD DJATL BF 最大流 Dinic ISAP ...

  8. 显示全部select change 异常

    异常信息(异常类型:Genersoft.Platform.Core.Error.GSPException)异常提示:调用方法SelectChange发生异常,详细请看内部异常信息!异常信息:调用方法S ...

  9. c代码读取目录信息

    #include <stdio.h> #include <sys/types.h> #include <dirent.h> int main(void) { DIR ...

  10. c# mybatis net +mysql

    1找到  mybatis.net最好有个例子 http://www.codeproject.com/Articles/894127/WebControls/#_comments  在这里... 这是一 ...