目录
1.I2C基础概念
IIC(Inter-Integrated Circuit)总线是一种由PHILIPS公司开发的两线式串行总线,用于连接微控制器及其外围设备。IIC总线产生于在80年代,最初为音频和视频设备开发,如今主要在服务器管理中使用,其中包括单个组件状态的通信。例如管理员可对各个组件进行查询,以管理系统的配置或掌握组件的功能状态,如电源和系统风扇。可随时监控内存、硬盘、网络、系统温度等多个参数,增加了系统的安全性,方便了管理。
2.总线构成
IIC总线是由数据线SDA和时钟SCL构成的串行总线,可发送和接收数据。在CPU与被控IC之间、IC与IC之间进行双向传送,标准传送速率100kbps。各种被控制电路均并联在这条总线上,但就像电话机一样只有拨通各自的号码才能工作,所以每个电路和模块都有唯一的地址。在信息的传输过程中,IIC总线上并接的每一模块电路既是主控器(或被控器),又是发送器(或接收器),这取决于它所要完成的功能。
CPU发出的控制信号分为地址码(寄存器)和控制量(数据)两部分。
3.I2C协议
- 2条双向串行线,一条数据线SDA,一条时钟线SCL。
- SDA传输数据是大端传输,每次传输8bit,即一字节。
- 支持多主控(multimastering),任何时间点只能有一个主控。
- 总线上每个设备都有自己的一个addr,共7个bit,广播地址全0。
3.1 信号操作
- 开始信号:SCL为高电平时,SDA由高电平向低电平跳变,开始传送数据;
- 结束信号:SCL为高电平时,SDA由低电平向高电平跳变,结束传送数据;
- 数据传输信号:在开始条件以后,时钟信号SCL的高电平周期期间,当数据线稳定时,数据线SDA的状态表示数据有效,即数据可以被读走,开始进行读操作。在时钟信号SCL的低电平周期期间,数据线上数据才允许改变。每位数据需要一个时钟脉冲。
- 应答信号:接收数据的IC在接收到8bit数据后,向发送数据的IC发出特定的低电平脉冲,表示已收到数据。CPU向受控单元发出一个信号后,等待受控单元发出一个应答信号,CPU接收到应答信号后,根据实际情况作出是否继续传递信号的判断。若未收到应答信号,由判断为受控单元出现故障。
- 非应答信号:当第9个SCL时钟周期时,SDA保持高电平,表示非应答信号。
3.2 主机发送数据流程
(1)主机在检测到总线为“空闲状态”(即 SDA、SCL 线均为高电平)时,发送一个启动信号“S”,开始一次通信的开始
(2)主机接着发送一个命令字节。该字节由 7 位的外围器件地址和 1 位读写控制位 R/W组成(此时 R/W=0,从主机写入从机)
(3)相对应的从机收到命令字节后向主机回馈应答信号 ACK(ACK=0)
(4)主机收到从机的应答信号后开始发送第一个字节的数据
(5)从机收到数据后返回一个应答信号 ACK
(6)主机收到应答信号后再发送下一个数据字节
(7)当主机发送最后一个数据字节并收到从机的 ACK 后,通过向从机发送一个停止信号P结束本次通信并释放总线。从机收到P信号后也退出与主机之间的通信
注意:①主机通过发送地址码与对应的从机建立了通信关系,而挂接在总线上的其它从机虽然同时也收到了地址码,但因为与其自身的地址不相符合,因此提前退出与主机的通信;②主机的一次发送通信,其发送的数据数量不受限制。主机是通过 P 信号通知发送的结束,从机收到 P 信号后退出本次通信;③主机的每一次发送后都是通过从机的 ACK 信号了解从机的接收状况,如果应答错误则重发。
3.3 主机接收数据流程
(1)主机发送启动信号后,接着发送命令字节(其中 R/W=1,从从机读入主机)
(2)对应的从机收到地址字节后,返回一个应答信号并向主机发送数据
(3)主机收到数据后向从机反馈一个应答信号
(4)从机收到应答信号后再向主机发送下一个数据
(5)当主机完成接收数据后,向从机发送一个“非应答信号(ACK=1)”,从机收到ASK=1 的非应答信号后便停止发送
(6)主机发送非应答信号后,再发送一个停止信号,释放总线结束通信
注意:主机所接收数据的数量是由主机自身决定,当发送“非应答信号/A”时从机便结束传送并释放总线(非应答信号的两个作用:前一个数据接收成功,停止从机的再次发送)。
4.Linux下IIC驱动架构
Linux定义了系统的IIC驱动体系结构,在Linux系统中,IIC驱动由3部分组成,即IIC核心、IIC总线驱动和IIC设备驱动。这3部分相互协作,形成了非常通用、可适应性很强的IIC框架。
4.1 芯片控制器层adapter
- 控制器初始化
- 控制器底层传输函数(起始,数据,应答,停止)
4.2 核心层core.c i2c_bus
- i2c_bus总线初始化
- client(设备)和i2c_driver(设备驱动)匹配过程
- 创建client(设备)时匹配i2c_driver(驱动)过程
- 注册i2c_driver(驱动)时匹配client(设备)过程
- 总线探测probe
4.3 设备驱动层
- 设备驱动注册
- 设备驱动探测probe,并初始化i2c器件
- 数据传输
4.4 重要数据结构
i2c_client 表示一个IIC设备,由系统根据设备树生成
struct i2c_client
{
unsigned short flags; //标志位
unsigned short addr; //设备的地址, 7位为读写位,[6:0]地址
char name[I2C_NAME_SIZE]; //设备的名称,最大为20个字节
struct i2c_adapter *adapter; //依附的适配器i2c_adapter,适配器指明所属的总线
struct i2c_driver *driver; //指向设备对应的驱动程序
struct device dev; //设备结构体
int irq; //设备申请的中断号
struct list_head list; //连接到总线上的所有设备
struct list_head detected; //已经被发现的设备链表
struct completion released; //是否已经释放的完成量
};
i2c_msg 一个i2c_msg 代表着Slave(i2c client)和Host(i2c controller)之间的一次单向数据传输。
struct i2c_msg {
__u16 addr; /* 从机地址 */
__u16 flags; /* 标志位,指定进行的操作 */
#define I2C_M_TEN 0x0010 /* this is a ten bit chip address */
#define I2C_M_RD 0x0001 /* read data, from slave to master */
#define I2C_M_STOP 0x8000 /* if I2C_FUNC_PROTOCOL_MANGLING */
#define I2C_M_NOSTART 0x4000 /* if I2C_FUNC_NOSTART */
#define I2C_M_REV_DIR_ADDR 0x2000 /* if I2C_FUNC_PROTOCOL_MANGLING */
#define I2C_M_IGNORE_NAK 0x1000 /* if I2C_FUNC_PROTOCOL_MANGLING */
#define I2C_M_NO_RD_ACK 0x0800 /* if I2C_FUNC_PROTOCOL_MANGLING */
#define I2C_M_RECV_LEN 0x0400 /* length will be first received byte */
__u16 len; /* msg length(单位为字节,需要注意) */
__u8 *buf; /* pointer to msg data */
};
写:从host---》slave: 设置寄存器,设置寄存器数据
char txbuf[2] = {reg, val};
struct i2c_msg msg[1] = {
{client->addr, 0, 2, txbuf}, //设置寄存器、设置值
};
i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg));
读:从host---》slave: 设置寄存器
从slave---》host: 返回读取数据
char txbuf[1] = { reg };
char rxbuf[1];
struct i2c_msg msg[2] = {
{client->addr, 0, 1, txbuf}, //设置寄存器
{client->addr, I2C_M_RD, 1, rxbuf} //返回读取数据
};
ret = i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg));
5.MPU6050流程
1)初始化 IIC 接口
MPU6050 采用 IIC 与 fs4412 通信,需要先初始化与 MPU6050 连接的 SDA和 SCL 数据线。这部分内核完成,可以不用考虑。
2)复位 MPU6050
MPU6050 内部所有寄存器恢复默认值,通过对电源管理寄存器 1(0X6B)的bit7 写 1 实现。 复位后, 电源管理寄存器 1 恢复默认值(0X40),然后必须设置该寄存器为0X00,以唤醒 MPU6050,进入正常工作状态。
3)设置角速度传感器(陀螺仪)和加速度传感器的满量程范围
设置两个传感器的满量程范围(FSR),分别通过陀螺仪配置寄存器(0X1B)和加速度传感器配置寄存器(0X1C)设置。一般设置陀螺仪的满量程范围为±2000dps,加速度传感器的满量程范围为±2g。
4)其他参数设置
需要配置的参数有:设置陀螺仪采样率和设置数字低通滤波器(DLPF)等。
5)配置系统时钟源并使能角速度传感器和加速度传感器
系统时钟源同样是通过电源管理寄存器 1(0X1B)来设置,该寄存器的最低三位用于设置系统时钟源选择,默认值是 0(内部 8M RC 震荡)。也可以设置为 1,选择 x 轴陀螺 PLL 作为时钟源,以获得更高精度的时钟;同时,使能角速度传感器和加速度传感器,这两个操作通过电源管理寄存器 2(0X6C)来设置,设置对应位为 0 即可开启。
6)读取角速度传感器和加速度传感器
通过读取相关寄存器,得到加速度传感器、角速度传感器和温度传感器的数据。(59-72)