这是 北航士谔书院 的第 940 篇推送

北航士谔书院X大班提醒您:

道路千万条,学习第一条

不搞单片机,开学两行泪

——新春快乐,我们又回来了!

本文对 I²C 总线的协议做出详细的介绍,并对其在 51 单片机上的应用代码做出解析。

I²C 总线

集成电路间总线(Inter-Integrated Circuit Bus,I²C Bus,读做 I-squared-C 或 I 方 C)是一种连接多个集成电路的总线。它由 Philips Semiconductors(现 NXP Semiconductors)于 1982 年开发。

I²C 总线的特点

  1. 多对多。在单个 I²C 总线上,可以有多个主设备(Master Device)和多个从设备(Slave Device)。主设备通常是单片机,而从设备通常是简单的外围设备(如传感器、单色显示屏),不过从设备也可以是单片机。通信总是由主设备发起并主导。通常我们仅在 I²C 总线上安排单个主设备,本文也只讨论有单个主设备的情形。如果存在多个主设备,那么它们需要进行较复杂的时钟同步和使用权仲裁,在此暂不讨论。

  2. 简单、易实现。I²C 总线仅需两个引脚就可连接多达 112 个设备,而同类总线,如 SPI 等,则需要更多的引脚。I²C 协议简单直接,不需要复杂的逻辑。

  3. 低速。大多数 I²C 设备仅支持在 100 kbit/s 的标准模式(Standard Mode)工作;少数设备最高支持 1Mbit/s 的快速模式+(Fast Mode Plus)。比起其它总线,I²C 的速度是比较慢的。

  4. 短距离。I²C 允许的走线距离较短,它通常被用于同一块 PCB 板上的 IC 间互联。I²C 总线不适用于长距离传输。

I²C 总线的常见应用

I²C 总线通常被用于将低速的外围设备通过短距离的线路连接到微处理器(单片机)上。常见的外围设备有温度传感器、电流电压传感器、单色显示屏等。这些设备结构简单,且传输的数据量很少,因此适用 I²C 总线。需要较高传输速度的设备(如高分辨率彩色显示屏)通常使用更高速度的连接方式(如 SPI)。

I²C 总线的引脚组成及电气连接

一个 I²C 总线由两条总线(Serial Clock, SCL 和 Serial Data, SDA)组成。I²C 总线上的设备都直接连接到这两个总线上(如图所示)。

I²C 总线的连接方式。μC 即单片机

所有连接到 I²C 总线的设备均使用开漏(Open-Drain,OD)连接。每个 I²C 设备的电路可以简化为如下图的结构:

开漏连接

可以将每个 P 沟道 MOSFET(MOSFET-P)想象为由单片机内部端口控制的“开关”:

开关

可以观察到,如果 I²C 总线上只连接了设备,那么 I²C 总线不可能处于高电平(因为此时总线没有连接到电源 Vdd)。我们需要在 SDA、SCL 与 Vdd 间各增加一个上拉电阻(如上图 Rp),当“断开开关”时,可以得到高电平;当“合上开关”时,可以得到低电平。

完整的连接示意图

在下文中,我们将合上开关(使相应总线处于低电平)的动作称为“拉低”;断开开关的动作称为“释放”。由于所有设备都并联在总线上,所以若总线上有任意设备拉低总线,总线即处于低电平状态;只有当总线上的所有设备释放总线时,总线才能处于高电平状态。这就是所谓的 Wired-And。

I²C 通信协议概要

空闲状态

I²C 总线处于空闲状态时,所有设备都释放总线,SCL 与 SDA 均处于高电平状态。

起始条件

I²C 总线上的通信总是由主设备(Master)发起。当主设备希望通信时,它就会产生一个起始条件(Start Condition,S),作为开始通信的信号。

起始条件可以描述为:当 SCL 处于高电平时,SDA 由高电平向低电平转换。即,在 I²C 总线空闲状态下,主设备拉低 SDA,代表起始条件,开始一次通信。

在 I²C 协议中,传输总是以帧(frame)为单位进行的。一帧为 8bit,即一字节。主设备和从设备都可以发送帧。

在发送帧时,发送方会逐位 (bit) 发送一字节 (byte) 数据,且先发送最高位(most significant bit,MSB)。例如,如果发送方需要发送 183 = 10110111,则按 1,0,1,1,0,1,1,1(从左到右)的顺序发送。发送一位数据的过程如下:

  1. 主设备首先将 SCL 拉低。

  2. 发送方(主或从)在检测到 SCL 被拉低后,使 SDA 处于相应的电平:如果要发送 0,就拉低 SDA;如果要发送 1,就释放 SDA。

  3. 主设备等待一定的时长后,释放 SCL;此时发送方不改变 SDA 状态。

  4. 接收方在 SCL 为高电平时,读取 SDA 的状态,得到相应数据并存储下来。

发送完一位后,主设备再次拉低 SCL,进入下一个循环,发送方发送下一位数据,接收方读取下一位数据。如此循环 8 次,即完成发送一帧。

在发送完一帧的 8 字节后,主设备会将 SCL 再拉低一次。接收方在检测到 SCL 第 9 次被拉低后:

  • 如果接收当前帧成功,则会将 SDA 拉低,表示自己成功收到了数据,这称作一个 ACK 信号(acknowledgement signal)。

  • 如果没有成功接收当前帧,则在 SCL 为低电平时,接收方不会作出任何动作,而使 SDA 保持在释放状态,这称作一个 NACK 信号(not acknowledgement signal)。NACK 信号并不是“主动发出”的,只要接收方没有作出任何反应,就代表一个 NACK 信号。

如果总线上没有任何设备,或者相应的接收方没有正常工作,则发送方会收到一个 NACK。

I²C 帧的传输流程

可以观察到,在传输帧时,SDA 仅在 SCL 为低电平时发生变化。如果当 SCL 为高电平时 SDA 发生变化,则会构成起始条件或停止条件。

停止条件与重复起始条件

在传输完一帧后,主设备可以选择继续传输帧,也可以选择停止传输,还可以选择从头开始一次新的传输。

如果它希望停止传输,则需要产生一个停止条件(Stop Condition,P),其可以描述为:当 SCL 处于高电平时,SDA 由低电平向高电平转换。

如果它希望从头开始新的传输,则需要产生一个重复起始条件(Repeated Start Condition,Sr)。重复起始条件与起始条件是相同的。

起始条件和停止条件

SCL、SDA 名称的含义

有同学可能会对 Serial Clock 和 Serial Data 名称的含义感到不解。

SCL 总是由主设备控制,且它以几乎固定的频率切换,因此它被称作 clock。SDA 则负责传输数据,因此被称作 data。

Serial 的含义是“串行”,即同一时间只能发送一位(one bit),而要传输的许多位数据“排队”被传输。与“串行”(serial)相对应的是“并行”(parallel)。并行总线通常由多根数据线组成,它一次能够发送多位数据。并行总线看似效率更高,但实际上它面临电平问题和串扰问题。

目前的计算机板卡互联协议中,串行协议占据统治地位。PCI-E、SATA 等都是串行传输的。一些较老的传输协议是并行协议,如 AGP、PCI 和 IDE。有关串行和并行传输方式的更多内容,可以参见这个知乎问题。

I²C 从设备地址

每个 I²C 从设备均有一个(在单个总线上)独一无二的 7 位从设备地址(slave address),该地址由设备厂商决定,不过有时也可以由用户自行定义其中的某些位,以允许在同一个 I²C 总线上同时存在相同的多个设备。具体的地址可以在芯片数据手册中找到。

通常在从设备地址后会附加一个数据方向位(data direction bit),一共 8 位数据,构成一个完整的帧。通常数据方向位为 0 时表示主设备发送、从设备接收,称为 WRITE;数据方向位为 1 时表示主设备接收、从设备发送,称作 READ。

以蓝桥杯开发板 CT107D 上的 PCF8591 芯片为例。该芯片是一个具有 I²C 功能的模数转换芯片(Analog to Digital Converter,ADC),用于将模拟信号(analog signal,如通过光敏电阻的电流)转换为数字信号(digital signal,由具体二进制表示的电压大小),相当于一个电压表(将电压转换为具体的读数)。

PCF8591 完整脚位图

在 PCF8591 数据手册 8.1 Addressing 一节及 Table 5, 6 中,我们可以找到有关芯片地址的详细信息。

如表格所示, PCF8591 的地址为 1001xxx,其中最后 3 位由 A2 – A0 脚(即脚位图中的 5 – 7 脚)决定。如果相应的脚为低电平,则对应的位为 0;否则对应的位为 1。例如如果这三个脚都是高电平,则芯片的地址是 1001111。

一次完整的 I²C 传输

  1. 主设备产生起始条件,代表一次通信的开始。

  2. 主设备发送一帧,表示需要通信的从设备地址和数据方向位。如果相应地址的从设备存在,则从设备将 SDA 拉低,发出 ACK 信号;如果没有相应地址的从设备存在,则主设备会收到 NACK 信号。

  3. 主设备和从设备以帧为单位进行通信;除最后一帧外,每帧传送完后,接收方需发送 ACK 信号以确认。具体的通信过程需要参照相应设备的数据手册,具体细节一般在数据手册的 Functional description 中。PCF8591 数据手册的第 8 节即为 Functional description。

  4. 在最后一帧传送完后,接收方不发出 ACK,此时主设备作出以下动作:

  • 若希望与其他从设备通信,则产生一个重复起始条件,然后继续进行第 2 步;

  • 若希望停止通信,则产生一个停止条件。产生停止条件后,两条数据线均被释放,I²C 总线进入空闲状态。

接下来我们以 PCF8591 和 51 单片机为例,看看如何使用 I²C 总线通信。

(未完待续)

图文|田韵豪

排版|李亦龙

出品|士谔书院X大班

合泰单片机做电压表_启士 | 蓝桥杯零基础单片机教程9 I2C介绍(上)相关推荐

  1. 串口中断和定时器中断_启士 | 蓝桥杯单片机教程12 中断与定时器 (上)

    这是 北航士谔书院 的第 949 篇推送 本文介绍中断(interrupt)的基本概念,并演示定时器中断.外部中断的使用方法.如果同学们对文章内容有疑问,或发现文中有任何不妥之处,请点击"阅 ...

  2. 蓝桥杯物联网基础图文教程——GPIO输出控制LD5亮灭

    蓝桥杯物联网基础教程--GPIO输出控制LD5亮灭 (本系列教程针对一些有stm32基础的同学,需要参加蓝桥杯物联网竞赛的,对HAL库感兴趣的同学提供参考,本文不再详细赘述关于stm32基础原理指导) ...

  3. 生日祝福小程序_广告配音剪映零基础入门教程第二十六篇:如何给朋友制作生日祝福视频...

    经常听到小伙伴问到生日祝福视频怎么做,当然我想既然要为他人做生日祝福视频,那么这个人必定是自己身边比较重要的人,而生日又是每个人都是非常重要的,在这种充满意义的时刻,我们想给自己极其重要的人送上一份祝 ...

  4. 合泰单片机做电压表_合泰单片机使用总结

    之前一直用ARM 系列的单片机,现在因为产品需要,用了一款合泰单片机(HT67F2360),整个开发过程中发现还是有很多差异. 一.开发环境中的一些差异# arm 系列单片机,直接用keil 接 选用 ...

  5. 合泰单片机做电压表_合泰单片机基础教程

    137********/0757-******** 1 第一章 一. 概念与分类 单片机又称 微控制器 ( M icro C ontroller U nit) ,包含:中央处理单元.程序 存储器.数据 ...

  6. 合泰单片机做电压表_合泰单片机总结

    <合泰单片机总结>由会员分享,可在线阅读,更多相关<合泰单片机总结(11页珍藏版)>请在人人文库网上搜索. 1.合泰单片机总结-测试环境C编译器V21. Debug2.3. . ...

  7. java 龟兔赛跑预测_Java实现 蓝桥杯VIP 基础练习 龟兔赛跑预测

    题目描述 话说这个世界上有各种各样的兔子和乌龟,但是 研究发现,所有的兔子和乌龟都有一个共同的特点--喜欢赛跑.于是世界上各个角落都不断在发生着乌龟和兔子的比赛,小华对此很感兴趣,于是决定研究不同兔 ...

  8. 第十二届_国赛蓝桥杯个人模板_基础篇

    第十二届_国赛蓝桥杯个人模板_网格图_DFS/BFS篇 第十二届_国赛蓝桥杯个人模板_全排列_DFS/BFS篇 第十二届_国赛蓝桥杯个人模板_DP篇 第十二届_国赛蓝桥杯个人模板_数论篇 第十二届_国 ...

  9. 蓝桥杯国信长天单片机--LED灯模块(五)

    LED等内部连接示意图 整体思路 通过74HC138芯片及74HC02芯片输入高低电平,来控制Y4C为1或0.当Y4C为1时,方可通过P0端口来控制LED灯的亮灭.当Y4C为0时,无法控制LED灯的亮 ...

最新文章

  1. 分割字符串_[话俾你知]Python使用正则处理字符串技巧(分割、替换)
  2. C#中判断文件夹或文件是否存在的方法
  3. 645. Set Mismatch(python)
  4. Java 数组升序降序排列Arrays.sort( )通俗易懂
  5. JSON.stringify()方法
  6. 新建虚拟机update时出现不能得到锁问题
  7. 练习2.13 不用库函数,写一个高效计算ln N的C函数
  8. node js的模块化的分类
  9. 重启模块与及关开邮件存储设置功能页面-PHP-shell-py
  10. FIFO队列 ADT接口 链表实现
  11. cshop是什么开发语言_mes用什么语言开发?mes开发平台
  12. (一)CentOS Docker 安装
  13. 装linux后分区丢失吗,找到了linux分区顺序错乱修复方法
  14. Python一周小结
  15. PHPProxy建立代理服务器
  16. 读《谁说大象不能跳舞》
  17. ubuntu手动设置ip地址和网关
  18. 7-22 龟兔赛跑 (超简单详细思路)
  19. Virtualbox虚拟机安装win10系统卡顿
  20. 30秒教会您Orange一键资源采集功能

热门文章

  1. python方向键键值_python字典键值对的添加和遍历方法
  2. python中遇到循环import即circular import的问题原理剖析及解决方案
  3. 修改软件服务器json返回数据格式,AngularJS处理服务器端返回的JSON数据的格式问题...
  4. java jvm目录,JVM(Java虚拟机)中过程工作目录讲解
  5. 最新进展 | 深度学习在天气预测中的应用
  6. 卫星系统——酒店后端全链路日志收集工具介绍
  7. 图谱实战 | 徐美兰:深度应用驱动的医学知识图谱构建
  8. 如何关闭docker容器里的进程
  9. 十分钟搞定特征值和特征向量
  10. Android官方开发文档Training系列课程中文版:构建第一款安卓应用之创建用户界面