前言:
本文是根据哔哩哔哩网站上“正点原子[第二期]Linux之ARM(MX6U)裸机篇”视频的学习笔记,在这里会记录下正点原子 I.MX6ULL 开发板的配套视频教程所作的实验和学习笔记内容。本文大量引用了正点原子教学视频和链接中的内容。
引用:
正点原子IMX6U仓库 (GuangzhouXingyi) - Gitee.com
《【正点原子】I.MX6U嵌入式Linux驱动开发指南V1.5.2.pdf》
正点原子资料下载中心 — 正点原子资料下载中心 1.0.0 文档
正文:
本文是 “正点原子[第二期]Linux之ARM(MX6U)裸机篇--第23讲 I2C驱动。本节将参考正点原子的视频教程第23讲和配套的正点原子开发指南文档进行学习。
0. 概述
I2C 是最常用的通信接口,众多的传感器都会提供 I2C 接口来和主控相连,比如陀螺仪、加速度计、触摸屏等等。所以 I2C 是做嵌入式开发必须掌握的, I.MX6U 有 4 个 I2C 接口,可以通过这 4 个 I2C 接口来连接一些 I2C 外设。 I.MX6U-ALPHA 使用 I2C1 接口连接了一个距离传感器 AP3216C,本章我们就来学习如何使用 I.MX6U 的 I2C 接口来驱动 AP3216C,读取AP3216C 的传感器数据。
1. I2C简介
I2C是一种很常见的总线协议,I2C是NXP公司设计的,I2C使用的两条线在主控制器和从机之间通信。一条是SCL(串行时钟线),另外一条是SDA(串行数据线),这两条数据线需要接上拉电阻,总线空闲的时候SCL和SDA都处于高电平。I2C总线标准模式下速度可以达到100Kbp/S,款速模式下可以达到400Kb/s。I2C总线工作是按照一定的协议来运行的,接下来就看一下I2C协议。
I2C是支持多从机的,也就是一个I2C控制器下可以挂多个I2C从设备,这些不同的I2C从设备有不同的器件地址,这样I2C主控制器就可以通过i2C设备的器件地址访问指定的I2C设备了,一个I2C总线连接多个I2C从设备如下图所示:
图中SDA和SCL这两根线必须要接一个上拉电阻,一般是4.7K。其它的I2C设备都挂接在SDA和SCL这两根线上,这样就可以通过SDA和SCL这两根线来访问多个I2C设备。
1.1 I2C协议的有关术语
1.1.1 起始位
顾名思义,也就是I2C通信的起始标志,通过这个起始位就可以告诉I2C从机,“我”要开始进行I2C通信了。在SCL为高电平的时候,SDA从高电平变为低电平出现下降沿就表示起始位,如下图所示。
1.1.2 停止位
停止位就是停止I2C通信的标志位,和起始位的功能相反。在SCL为高电平的时候,SDA出现上升沿(从低电平变为高电平)就表示为停止位,如下图所示:
1.1.3 数据传输
I2C总线在数据传输的时候要保证在SCL高电平期间,SDA上的数据稳定,因此SDA上的数据变化只能出现在SCL低电平期间发生,如下图所示:
1.1.4 应答信号
当I2C主机发送完8个数据位之后会将SDA设置为输入状态,等待I2C从机的应答,也就是等到I2C从机高速主句它接收到了数据了。应答信号是由从机发出的,主句需要提供应答信号所需的时钟,主机发送完8位数据以后紧跟着的一个时钟信号就是给应答信号用的。从机通过将SDA拉低表示发出了应答ACK信号,表示通信成功,从机没有拉低SDA表示发送的N-ACK信号,表示通信失败。
产生NACK信号的情况有如下几种:
引用连接,这里讲的很好,将I2C协议的所以细节都讲到了:
I2C的时钟永远由I2C Master 主机来控制产生。
- I2C主机 Master-Transmit 的时候,主机控制I2C总线的SCL时钟,主机发送8个数据位之后,主机SDA释放,主机发送第九个时钟,从机拉低SDA总线表示ACK(或者从机不拉低SDA表示NACK)
- I2C主机是Master-Receiver的时候,主机控制I2C总线的SCL时钟,从机在主机的SCL时钟控制下从机发送8个数据位,发送8个数据位之后从机释放SDA总线,主机发出第九个时钟并且主机拉低SDA表示ACK信号回复给从机,或者主机不拉低SDA表示NACK信号回复给从机。
1-无:主机发送了I2C从机的地址,从机地址不存在,在第9个时钟信号时没有从机拉低SDA电平,表示发送了NACK信号。
2-错:主机发送了8位数据之后,从机没有正确处理或者有错误,在第9个时钟信号时没有从机拉低SDA电平,表示发送了NACK信号。
3-停:在主机 Master-Receive模式,主机在接收完最有个DATA数据后发送 NACK 信号从机数据已经接收结束。
4-忙:Slave忙碌,无法开始数据传输
1.5 I2C写时序
主机通过I2C总线与从机之间进行通信不外乎两个操作:写和读,I2C总线单字节写时序如下图所示:
- Start起始位
- 从机地址(7bit, MSB先发送,了LSB后发送),方向位(1bit ,读1, 写0)
- 主机发送8bit数据为之后,从机回复ACK
- 主机重发送Start起始位,repeated-start
- 主机发送8位寄存器地址
- 从机回复ACK
- 主机发送8位DATA数据
- 从机回复ACK
- 主机发送STOP停止位
图 26.1.1.5 就是 I2C 写时序,我们来看一下写时序的具体步骤:
1)、开始信号。
2)、发送 I2C 设备地址,每个 I2C 器件都有一个设备地址,通过发送具体的设备地址来决定访问哪个 I2C 器件。这是一个 8 位的数据,其中高 7 位是设备地址,最后 1 位是读写位,为1 的话表示这是一个读操作,为 0 的话表示这是一个写操作。
3)、 I2C 器件地址后面跟着一个读写位,为 0 表示写操作,为 1 表示读操作。
4)、从机发送的 ACK 应答信号。
5)、重新发送开始信号。
6)、发送要写写入数据的寄存器地址。
7)、从机发送的 ACK 应答信号。
8)、发送要写入寄存器的数据。
9)、从机发送的 ACK 应答信号。
10)、停止信号。
1.6 I2C读时序
I2C总线的单字节读时序如下图所示:
I2C的单字节读时序要比写时序复杂一些,不时序分为4大步:
- 第一步是发送设备地址
- 第二步是发送要读取的寄存器地址
- 第三部是重新发送设备地址
- 最后一步就是从I2C从器件输出要读取的寄存器值。
读取的寄存器值,我们具体来看一下这几步
- 主机发送起始信号Start
- 主机发送知己要读取的I2C从机地址
- 读写控制位,因为事项I2C从机发送数据,因此是写信号。
- 从机发送ACK应答信号
- 重新发送Start起始信号
- 主机发送要读取的寄存器地址
- 从机发送ACK应答信号
- 重新发送START信号
- 重新要发送要读取的I2C从机地址
- 读写控制位,这里是读信号,表示接下来是从I2C 从设备里读取数据
- 从设备发送ACK应答信号
- 从I2C器件里读取数据
- 主机发出 NO ACK信号,表示读取完成,不需要从机再发送ACK信号了。
- 主机发出STOP信号,停止I2C通信。
2. I2C 多字节读写时序
有时候我们需要读写多个字节,多字节读写时序和单字节的基本一致,只是在读写数据的时候可以连续发送多个自己的数据,其它的控制时序都是和单字节是一样的。
3. I.MX6U I2C
3.1 I.MX6U I2C 简介
I.MX6U提供了4个I2C外设,通过这4个I2C外设即可以完成与I2C从器件进行通信,I.MX6U的I2C外设特性如下:
- 与标准I2C总线兼容
- 多主机运行
- 软件可以编程的64种不同的串行时钟序列
- 软件可选择的应答位
- 开始/结束信号生成和检测
- 重复开始信号生成
- 确认位生成
- 总线忙检测
I.MX6U的I2C支持两种工作模式:标准模式和快速模式,标准模式下I2C数据传输速率最高100Kbps,在快速模式下数据传输速率最高为400Kbps。
3.2 I.MX6U I2C 寄存器
我们接下来看一下I2C的几个重要寄存器。
3.2.1 I2Cx_IADR
首先看一下 I2Cx_IADR (x=1~4)寄存器,这是I2C的地址寄存器,此寄存器结构如下图:
I2Cx_IADR 中存放7bit的I2C从机地址,当I2C器件工作在Slave从机模式下时,从机收到主机发送的Slave地址就做出回应(ACK)。本实验我们作为I2C主机不需要设置I2Cx_IAR。
寄存器 I2Cx_IADR 只有 ADR(bit7:1)位有效,用来保存 I2C 从设备地址数据。
当我们(I2C主机)要访问某个 I2C 从设备的时候就需要将其设备地址写入到 I2Cx_ADR 里面。
3.2.2 I2Cx_IFDR
接下来看一下寄存器I2Cx_IFDR,这个是 I2C 的分频寄存器,寄存器结构如图 26.1.2.2 所示:
寄存器 I2Cx_IFDR 也只有 IC(bit5:0)这个位,用来设置 I2C 的波特率, I2C 的时钟源可以选择 IPG_CLK_ROOT=66MHz,通过设置 IC 位既可以得到想要的 I2C 波特率。 IC 位可选的设置如图 26.1.2.3 所示:
不像其他外设的分频设置一样可以随意设置,图 26.1.2.3 中列出了 IC 的所有可选值。比如现在I2C的时钟源为66MHz,我们要设置I2C的波特率为100KHz,那么IC就可以设置为0X15,也就是 640 分频。 66000000/640=103.125KHz≈100KHz。
3.2.3 I2Cx_ICR
寄存器 I2Cx_ICR 的各位定义如下:
位 | 描述 |
IEN bit[7] | I2C使能位,0的时候关闭I2C,1的时候使能I2C,必须在其它I2C控制位设置之前先使能该位。 该位也控制着I2c的软件复位 |
IIEN bit[6] | I2C中断使能位, 0, I2C中断关闭,但是I2Cx_I2SR[IIF]寄存器的IIF标志还是会在中断条件满足的时候置1,用户需要清除I2Cx_I2SR[IIF]位。 1, I2C中断使能,当I2C中断发生的时候 I2C_I2SR[IIF]位也会被置1。 |
MSTA bit[5] | Master/Slave mode,主机/从机模式 Note: MSTA标记被软件清除用来产生一个STOP停止位,它也可能会被硬件清除当硬件检测到仲裁丢失的时候。 0: Slave 从机模式 1: Master 主机模式 |
MTX bit[4] | Transmit/Receive mode select 发送/接收模式选择 0: Receive 当一个从机被寻址到后,软件应该根据从机的I2C_I2SR[SRW]寄存器里的 read/write bit 位来设置MTX 1: Tansmit 在主机模式,MTX应该根据读写类型来设置,所以说对于address cycle 寻址周期,MTX总是1. |
TXAK bit[3] | Transmit acknowledge enable ,发送应答使能。控制驱动到 I2Cx_SDA 总线上应答类型,对于主机和从机都一样。 注意: 只有当I2C工作在Receiver模式下时才能写 TXAK 0: ACK 信号发送,在接收完数据后第9个时钟周期的时候 1: NACK 信号发送 |
RSTA bit[2] | Repeated Restart,重开始 总是读为0,在没有丢失总线控制权的情况下重发送一个 start (repeated start) |
未使用 bit[0] | 保留未使用 |
3.2.4 I2Cx_I2SR
I2Cx_I2SR寄存器里指示传输方向和传输状态。
位 | 描述 |
保留 bit[15:8] | 保留未使用 |
ICF bit[7] | 数据传输指示位,当数据中的任一个字节传输时清零此位 0 数据正在传输 1 数据传输完成, 在最后一个字节传输万完成的第9个时钟的下降沿设置此位。 |
IAAS bit[6] | I2C设备被作为从机寻址成功 0: 没有被寻址 1: 寻址成功,当I2C自己的I2Cx_IADR寄存其的值和呼叫寻址匹配的时候设置 |
IBB bit[5] | I2C bus busy,I2C总线忙位 注意:当I2C启用之后,它会不停的轮询SDA和SCL总线信号好探测Start起始位和Stop停止位。 0: 总线空闲 idel , if Stop信号被探测到 ibb位被清零 1: 总线忙 busy,if start信号被探测到 ibb 位被设置 |
IAL bit[4] | 仲裁丢失,被硬件设置(IAL 必须被软件清除通过对此位写0 在中断服务函数中) I2Cn_SDA 输入采样到低,当主机master驱动一个高电平在寻址或者数据传输周期。 I2Cn_SDA输入采样到低,当主句驱动高电平在主句ACK应答周期。 0: 无仲裁丢失 1: 仲裁丢失 |
保留 bit[3] | |
SRW bit[2] | |
IIF bit[1] | I2C中断,必须被软件清零通过写0 0:没有中断被pending 1:有争端被pending |
3.2.5 I2C_I2DR
最后一个寄存器就是 I2Cx_I2DR,这是 I2C 的数据寄存器,此寄存器只有低 8 位有效,当要发送数据的时候将要发送的数据写入到此寄存器,如果要接收数据的话直接读取此寄存器即可得到接收到的数据。
In Master Receive mode, reading the data register allows a read to occur and initiates the next byte to be received. In Slave mode, the same function is available after it isaddressed.
在主机接收模式,读取数据寄存器允许read发生并且指示下一个自己可以别接收。所以读取之前需要“假读”。
4. 硬件原理
根据正点原子I.MX6U APLHA 开发板的电路原理图,I2C1 使用的引脚如下
正点原子 I.MX6ULL 引脚复用:
引脚 | 复用IO | 复用ALT |
I2C1_SCL | UART4_TXD | |
I2C1_SDA | UART4_RXD |
4.1. I2C IO 复用寄存器
正点原子 I.MX6ULL ALPHA开发板使用 I2C1 时使用 UART4_TX_DATA 作为 I2C1_SCL , UART4_RX_DATA 作为 I2C1_SDA 。
对应的寄存器如下
在I.MX6ULL 参考手册里说明,使用I2C需要将IO引脚配置为开漏模式,并且配置IO引脚的 SION 为打开。
5 AP3216C 红外/接近/环境光传感器
AP3216C 简介
I.MX6U-ALPHA 开发板上通过 I2C1 连接了一个三合一环境传感器: AP3216C, AP3216C是由敦南科技推出的一款传感器,其支持环境光强度(ALS)、接近距离(PS)和红外线强度(IR)这三个环境参数检测。该芯片可以通过 IIC 接口与主控制相连,并且支持中断, AP3216C 的特点如下:
①、 I2C 接口,快速模式下波特率可以到 400Kbit/S
②、多种工作模式选择: ALS、 PS+IR、 ALS+PS+IR、 PD 等等。
③、内建温度补偿电路。
④、宽工作温度范围(-30° C ~ +80° C)。
⑤、超小封装, 4.1mm x 2.4mm x 1.35mm
⑥、环境光传感器具有 16 位分辨率。
⑦、接近传感器和红外传感器具有 10 位分辨率。
AP3216C 常被用于手机、平板、导航设备等,其内置的接近传感器可以用于检测是否有物
体接近,比如手机上用来检测耳朵是否接触听筒,如果检测到的话就表示正在打电话,手机就会关闭手机屏幕以省电。也可以使用环境光传感器检测光照强度,可以实现自动背光亮度调节。
AP3216C 结构如图 26.1.3.1 所示:
AP3216 的设备地址为 0X1E,同几乎所有的 I2C 从器件一样, AP3216C 内部也有一些寄存器,通过这些寄存器我们可以配置 AP3216C 的工作模式,并且读取相应的数据。 AP3216C 我们用的寄存器如表 26.1.3.1 所示:
敦南科技AP3216C 红外/环境光/接近传感器的 I2C 写时序1:
敦南科技AP3216C 红外/环境光/接近传感器的 I2C 写时序2:
敦南科技AP3216C 红外/环境光/接近传感器的 I2C 读时序1:
敦南科技AP3216C 红外/环境光/接近传感器的 I2C 读时序2:
AP3216C传感器的重要寄存器
6. 结束
本文至此结束