以下内容,将解释以下几个问题
1.IIC协议是什么?
2.IIC协议用来干什么?
3.IIC协议的通信过程?

==============================================================
1.IIC协议是什么?
IIC,即I²C,全称 Inter-Integrated Circuit,字面上的意思是集成电路之间,它其实是I²C Bus简称,所以中文应该叫 集成电路总线 ,它是一种串行通信总线,使用多主从架构,由飞利浦公司在1980年代为了让主板、嵌入式系统或手机用以连接低速周边设备而发展。(百度百科)

2.IIC协议用来干什么?
简单地说,IIC就是一种通信协议,是为了能让主板,或嵌入式系统等与其他外设模块进行通信而进行开发的。玩过stm32开发板的同学都知道,对于一块stm32核心开发板而言,要想使用其他的外设模块,就肯定要经过接线,写代码,烧录运行的这个过程。其实这个过程,就是一个stm32与外设模块通信的过程。接线,就是搭建通信的线路。写代码,就是制定通信的传输协议。烧录运行,就是正式的通信过程。只不过有的模块通信过程很简单,大家感觉不出来。外设和芯片间的通信可以形象地比喻成两个人讲话:i、你说的别人得能听懂:双方约定信号的协议。ii、你的语速别人得能接受:双方满足时序要求。但是随着科技的发展,模块越来越多,总不可能,每个模块都要制定一种通信协议,这样不现实。所以,总要有一些代表性的协议能够适应大部分的模块的通信。IIC这是这样一种协议,一个IIC总线上,可以挂载多个外接设备
常用的串行通信协议有:
①UART串口通信
②IIC协议
③SPI协议
④USB协议(很难)
常用的并行通信协议有:
①8080
②6800

3 .IIC协议的通信过程( 此处重点

接线:要搭建IIC的通信线路,出除去电源之外,还需要两条线,分别是SDA和SCLK
SDA:数据信号线,用于传输数据
SCLK:时钟信号线,用于产生时钟频率,控制时序,实现协议过程
由此可以看出,由于是单总线进行数据传输,所以IIC协议是半双工的。
这里我们使用软件方式模拟IIC协议。

搭建好线路之后,就要进行具体的通信了。
要通信,总得先发个开始信号吧。就像你要和别人说话,总要先喊他一声一样。如下图所示,协议规定,当SCLK时钟信号一直处于高电平状态时,SDA线由高电平跳变到低电平这个动作,表示起始信号。注意此时就算SDA数据线的电平跳变完,SCLK线依然是高电平哦。当连接在IIC总线上的外设模块检测到这个信号时,就知道数据要开始传输了。对于结束信号同理,协议规定,当SCLK时钟信号一直处于高电平状态时,SDA线由低电平跳变到高电平这个动作,表示结束信号

在明白如何开始之后,就要开始进行数据的传输了。
协议规定,在数据的传输过程中,SCLK为高电平时,外设模块开始采集SDA数据线上的数据,此时要求SDA数据线上的电平状态必须稳定(不然鬼知道这一位数据是0还是1),当SCLK为低电平时才允许SDA线上的数据跳变成另外一种状态
以下以传输1个bit的数据为例,如下图所示:
现在,我想传输1bit数据,该位数据为1,从上文知道,我们在发完开始信号之后,此时SDA数据线的电平状态为低电平,SCLK信号依然是高电平。难道这个时候外设就要开始读取数据了吗?这显然不是的,从发完开始信号到真正的数据传输之间,会有一段缓冲时间,让我们去准备数据,在准备数据阶段,先将SCLK信号拉低一段时间,在这期间将SDA数据线拉高一段时间(即数据1),然后再将SCLK信号拉高,此时这个时钟信号的高电平被外设检测到的话,外设就知道要读取数据了,从而SDA上的数据就会被外设读到了。依次类推,传输下一位数据。

一般,传输完1个字节(即8bit,高位先入)的数据,才算做一次完整的数据传输,因为对存储单元而言,最小的单位便是字节。那如何确定,每次都完好地传输了一个字节呢?
这种情况就需要外设来做出回应了,就像打点电话一样,如果对方不在,或不想听,说再多也没用啊。那么外设如何做出回应呢?协议规定,主机每传完一个字节的数据即外设每收到一个字节的数据,外设就要在第9个时钟脉冲到来的时候,将SDA数据线拉低进行应答(ACK),且必须是稳定的低电平,表示已经收到了一个字节的数据,拉高表示不进行应答(NACK;注意这里是外设将SDA数据线拉低,不是主机了哦。如下图所示:

所以在主机传完一个字节的数据之后,就应该释放总线(协议规定,当SDA和SCLK同时为高时,表示空闲状态)然后把SDA数据线连接的IO口从输出模式转换成输入模式,这样才能拿到SDA数据线上的应答信号。这样,一个字节的数据就从主机到外设传输完毕了。

既然IIC是双向通信的,那主机肯定也是需要从外设读取数据的,那这个读取的过程又是怎么实现的呢?毕竟外设对于我们而言是不能直接操作的,我们能操作的只有stm32。我们知道,一个IIC总线上,可以挂载多个设备,那么stm32如何确定是哪个外设正在跟我进行通信呢。对于此,那些生产外设模块的厂商们就约定,要是这个设备使用IIC协议进行通信,那么就要给这个设备指定一个器件地址,以供芯片访问。这个器件地址会在你购买其模块的时候在使用手册上注明。所以,要跟哪个模块通信,就一定要通过查阅其使用手册,找到它的器件地址。
所以,在上文所述的最开始的一个字节的数据传输过程中,这一个数据往往是器件地址。这样,对应的外设才知道,是要跟我进行通信。读取数据,也是同理,要想从外设中读取到数据,主机要明确三点:从哪个外设中的哪个地方读取数据,读取到的数据要存到哪里。
所以主机,在开始读数据之前,主机必须要先给外设发器件地址,数据所在的地址,外设才会知道你要从该地址读取数据,从而把数据通过SDA线传出来。至于具体的每个字节的传输过程,和上面所讲的从主机到外设的过程差不多,只不过反了一个反向而已,并且主机的等待应答变成了主动应答。

以下是IIC协议代码


/*设置SDA总线为输出模式参数值:NULL返回值:NULL
*/void IIC_setSDAMode_Out()
{GPIO_InitTypeDef GPIO_IIC; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE);GPIO_IIC.GPIO_Mode  = GPIO_Mode_OUT;              //输出GPIO_IIC.GPIO_OType = GPIO_OType_PP;               //推挽GPIO_IIC.GPIO_Pin   = GPIO_Pin_15;                 //引脚GPIO_IIC.GPIO_PuPd  = GPIO_PuPd_UP;                //上拉GPIO_IIC.GPIO_Speed = GPIO_Speed_25MHz;                //输出GPIO_Init(GPIOE, &GPIO_IIC);
}/*设置SDA总线为输入模式参数值:NULL返回值:NULL
*/void IIC_setSDAMode_In()
{GPIO_InitTypeDef GPIO_IIC;RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE);GPIO_IIC.GPIO_Mode  = GPIO_Mode_IN;                     //输出GPIO_IIC.GPIO_Pin   = GPIO_Pin_15;                     //引脚GPIO_IIC.GPIO_PuPd  = GPIO_PuPd_UP;                    //上拉GPIO_Init(GPIOE, &GPIO_IIC);}/*IIC开始信号参数值:NULL返回值:NULL
*/void IIC_Start()
{IIC_setSDAMode_Out();IIC_SDA_OUT(1);                             //总线释放状态IIC_SCL_OUT(1);delay_us(5);IIC_SDA_OUT(0);                             //SDA跳变为低电平delay_us(5);IIC_SCL_OUT(0);        delay_us(5);}/*IIC停止信号参数值:NULL返回值:NULL
*/void IIC_Stop()
{IIC_setSDAMode_Out();IIC_SDA_OUT(0);          IIC_SCL_OUT(0);delay_us(5);IIC_SCL_OUT(1);                              //SDA跳变为高电平delay_us(5);IIC_SDA_OUT(1);        delay_us(5);}/*主机写入数据到外设中参数值:data  要写入的一个字节返回值:NULL
*/void IIC_writeByte(u8 data)
{IIC_setSDAMode_Out();IIC_SCL_OUT(0);                                 //只有时钟线拉低,SDA上的数据才允许写入delay_us(5);//将数据一位一位的发出去for(int i =0;i<8;i++){if(data&(0x1<<(7-i)))               //高位先入{IIC_SDA_OUT(1);}else{IIC_SDA_OUT(0);}IIC_SCL_OUT(1);                 //让外设读取数据delay_us(5);IIC_SCL_OUT(0);                 //重新拉低,准备写入下一位数据delay_us(5);}
}/*主机从外设中读取一个字节的数据参数值:NULL返回值:NULL
*/u8 IIC_readByte()
{u8 data = 0;IIC_setSDAMode_In();IIC_SCL_OUT(0);                  //先拉低,为读取数据做准备delay_us(5);for(int i=0;i<8;i++){IIC_SCL_OUT(1);         // SCL为高期间才可以读取数据delay_us(5);if(IIC_SDA_IN){data|=(0x01<<(7-i));}else{data &= ~(0x1<<(7-i));}  IIC_SCL_OUT(0);delay_us(5);}return data;}/*主机等待应答参数值:NULL返回值:ack     0  应答   1 不应答
*/u8 IIC_waitAck()
{u8 ack =0;IIC_setSDAMode_In();IIC_SCL_OUT(0);             //准备时序delay_us(5);IIC_SCL_OUT(1);delay_us(5);if(IIC_SDA_IN){ack =1;}else{ack =0;  }IIC_SCL_OUT(0);              //拉低,表示应答完成delay_us(5);return  ack;}/*主机主动应答参数值:ack  0 应答 1 不应答返回值:NULL
*/void IIC_Ack(u8 ack)
{IIC_setSDAMode_Out();IIC_SCL_OUT(0);delay_us(5);if(ack){IIC_SDA_OUT(1);}else{IIC_SCL_OUT(0);}IIC_SCL_OUT(1);delay_us(5);IIC_SCL_OUT(0);delay_us(5);    }

IIC协议超详细解释(适合小白入门)相关推荐

  1. 【java】调用百度开发平台ai接口,完成人脸识别(人脸搜索、人脸对比、人脸检测等)功能--------超详细,适合小白

    基本流程理解: 我们要使用百度提供的接口去实现某些功能,大致流程如下: 1.注册百度开放平台帐号: 浏览器打开http://ai.baidu.com/,进入百度ai的页面,点击右上角的控制台按钮进行登 ...

  2. 注册Github账号详细教程【超详细篇 适合新手入门】

    目录 一.GitHub的简介 1.大概介绍 2.详细介绍 二.如何注册自己的GitHub账户 1.进入github的官网 2.点击右上角注册按钮sign up,来到注册页面 3.在光标处输入自己的邮箱 ...

  3. Python多线程编程(详细:适合小白入门)

    目录 前言 一.进程 1.多任务 2.进程 3.多进程完成多任务 3.1进程的创建步骤 3.2通过进程类创建进程对象 3.3创建进程和启动的代码 4. 进程执行带有参数的任务 5.获取进程编号 6.进 ...

  4. Qt项目-----简易QQ(超详细,适合小白)

    创建新项目 新建项目,以Qt Widgets Application为模板 选择QWidget为基类 建立完成后,项目视图如下所示: 注意:建立好项目后,可以先编译运行下,确定建立的项目没有问题. 创 ...

  5. 关于三次握手与四次挥手的超详细解释

    关于三次握手与四次挥手的超详细解释 看了很多博客的文章,再结合自己想要知道的知识,发现还是需要东看一下西看一下,才能明白大概的过程.所以这里博主决定来小小的结合一下自己记录的内容.来写一个容易看明白并 ...

  6. 【PMP考试扫盲】超详细的PMP项目管理入门基础知识,考证必看

    我今年 6 月刚考过 PMP,发现很多小伙伴都对 PMP 还不了解,这篇文章就是对 PMP 基础知识的一个全面解答,文章有点长,先给大家上个目录,方便大家直接查看对应内容~ 目录 [PMP考试扫盲]超 ...

  7. 切分数据集(train_test_split),思路分享及手打代码和介绍sklearn中train_test_split,适合小白入门

    本篇博客介绍train_test_split,步骤1-4是自己手打代码和思路分享,步骤5介绍如何使用sklearn中的train_test_split,步骤3有介绍随机种子哦,简单易懂,适合小白入门 ...

  8. C++引用的超详细解释及误区纠正,不看后悔哦(中)

    书接上文,这次我想向大家谈一谈关于函数引用返回的问题 非引用返回,非引用接收: 首先我们来看这样一段代码: #include<iostream> using namespace std; ...

  9. C++引用的超详细解释及误区纠正,不看后悔哦(上)

    首先,我们来谈一谈什么是引用以及为什么存在? 引用:即为对象起立另一个名字,引用类型引用另一种类型. 基于C语言的指针,C++将其封装并创建出新的类型--引用.熟悉C语言的小伙伴们会发现,在C语言中指 ...

  10. 超详细讲解C语言入门函数(一)

    解析已经很详细了,可以说相当入门级别了,如果喜欢的话那就请支持一下,后续会继续更新~ 代码网上搜索,并加以更改,侵权请联系删除,谢谢~ 部分例子没有详细解释是因为前面的例子已经说过了 3×4矩阵求最大 ...

最新文章

  1. dokuwiki导航的研究
  2. 7篇必读ACM MM 2019论文:图神经网络+多媒体
  3. 【音视频安卓开发 (零)】用 Android NDK 编译 FFmpeg 与 X264
  4. htmlspecialchars() 函数过滤XSS的问题
  5. ONNX系列四 --- 使用ONNX使TensorFlow模型可移植
  6. 如何在缺乏商业项目经验的前提下成功通过面试,兼说我如何甄别非商业项目经验...
  7. How do you simple use git repository
  8. php curl array,PHP curl_setopt_array函数有什么用
  9. java工作流框架jbpm_Jbpm工作流与ssh框架集成
  10. python3的spyder安装_Python开发环境Spyder安装教程
  11. 小书MybatisPlus第9篇-常用字段默认值自动填充
  12. 领域驱动设计——项目分层与项目落地
  13. 一起来学自然语言处理----语料库和词汇资源
  14. Apache ServiceComb Kie | 一个语义型配置中心
  15. Zeppelin Job monitor打开
  16. 卸载 windows 2003 自带 .NET Framework (dotnetfx cleanup tool)
  17. Three.js实现台灯的灯光效果
  18. Python 图片处理模块之PIL
  19. 关于bat中set /p=前面加空格的bug修复方法
  20. C#设置默认打印机界面

热门文章

  1. 微电子基础物理(二)
  2. android 通用驱动程序下载,安卓手机通用驱动官方下载-安卓手机通用驱动(Universal Adb Driver)下载v2017 官方最新版-当易网...
  3. 汽车启动/停止系统电源方案
  4. java中的抽象工厂模式
  5. 给定一个邻接矩阵,求可达矩阵及强连通、单向连通、弱连通、不连通的判断
  6. 查看路由器内宽带账号密码(D-link,TP-Link)
  7. 假如时光能够倒流, 我会这么学习Java
  8. lumia 1520Android刷机包,诺言基亚Lumia 1520官方体系破开格提升固件释出产
  9. (2022.9)raspberry 4安装HP 1020 plus打印机,利用树莓派4制作无线打印服务器
  10. 计算机机房需求调查表,弱电工程设计流程及客户需求调研表