STM32:I2C

目录

1.I2C基础概念

2.总线构成

3.I2C协议

3.1 信号操作

3.2 主机发送数据流程

​​​​​​​3.3 主机接收数据流程

4.Linux下IIC驱动架构

4.1 芯片控制器层adapter

4.2 核心层core.c   i2c_bus

4.3 设备驱动层

4.4 重要数据结构

5.MPU6050流程


1.I2C基础概念

       IIC(InterIntegrated Circuit)总线是一种由PHILIPS公司开发的两线式串行总线,用于连接微控制器及其外围设备。IIC总线产生于在80年代,最初为音频和视频设备开发,如今主要在服务器管理中使用,其中包括单个组件状态的通信。例如管理员可对各个组件进行查询,以管理系统的配置或掌握组件的功能状态,如电源和系统风扇。可随时监控内存、硬盘、网络、系统温度等多个参数,增加了系统的安全性,方便了管理。

2.总线构成

        IIC总线是由数据线SDA和时钟SCL构成的串行总线,可发送和接收数据。在CPU与被控IC之间、IC与IC之间进行双向传送,标准传送速率100kbps。各种被控制电路均并联在这条总线上,但就像电话机一样只有拨通各自的号码才能工作,所以每个电路和模块都有唯一的地址。在信息的传输过程中,IIC总线上并接的每一模块电路既是主控器(或被控器),又是发送器(或接收器),这取决于它所要完成的功能。

CPU发出的控制信号分为地址码(寄存器)和控制量(数据)两部分。

 

https://img-blog.csdn.net/20160229155616688?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center

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信号后也退出与主机之间的通信

 

https://img-my.csdn.net/uploads/201210/12/1350020466_3649.PNG

注意:主机通过发送地址码与对应的从机建立了通信关系,而挂接在总线上的其它从机虽然同时也收到了地址码,但因为与其自身的地址不相符合,因此提前退出与主机的通信;主机的一次发送通信,其发送的数据数量不受限制。主机是通过 P 信号通知发送的结束,从机收到 P 信号后退出本次通信;主机的每一次发送后都是通过从机的 ACK 信号了解从机的接收状况,如果应答错误则重发。

​​​​​​​3.3 主机接收数据流程

(1)主机发送启动信号后,接着发送命令字节(其中 R/W=1,从从机读入主机)

(2)对应的从机收到地址字节后,返回一个应答信号并向主机发送数据

(3)主机收到数据后向从机反馈一个应答信号

(4)从机收到应答信号后再向主机发送下一个数据 

(5)当主机完成接收数据后,向从机发送一个“非应答信号(ACK=1)”,从机收到ASK=1 的非应答信号后便停止发送

(6)主机发送非应答信号后,再发送一个停止信号,释放总线结束通信

 

https://img-my.csdn.net/uploads/201210/12/1350020803_8926.PNG

注意:主机所接收数据的数量是由主机自身决定,当发送“非应答信号/A”时从机便结束传送并释放总线(非应答信号的两个作用:前一个数据接收成功,停止从机的再次发送)。

4.LinuxIIC驱动架构

        Linux定义了系统的IIC驱动体系结构,在Linux系统中,IIC驱动由3部分组成,即IIC核心、IIC总线驱动和IIC设备驱动。这3部分相互协作,形成了非常通用、可适应性很强的IIC框架。

https://img-blog.csdn.net/20160317213313496?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center

4.1 芯片控制器层adapter
  • 控制器初始化
  • 控制器底层传输函数(起始,数据,应答,停止)
4.2 核心层core.c   i2c_bus
  • i2c_bus总线初始化
  • client(设备)和i2c_driver(设备驱动)匹配过程
  1. 创建client(设备)时匹配i2c_driver(驱动)过程
  2. 注册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)

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

摸鱼特长生.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值