I2C的使用

  • I2C使用

    在飞腾派使用以及飞腾小车的开发过程中我们不需要编写I2C驱动,因此这里不对I2C的时序、发送的数据格式等等做介绍,这里简单介绍一下I2C协议以及如何在Linux下和Python中使用。

    • I2C介绍

      没有了解过硬件相关知识的人可以这么理解I2C,就是所有数据都是根据寄存器地址进行读写的,另外I2C是一个总线协议,因此所有芯片都是连在相同的两根线上,即是共用的;所以每次读的时候,就是给I2C总线发送要读设备地址和寄存器地址;同理,写的时候,就是发送要写的设备地址、寄存器地址和要写的数据。

      在同一个I2C总线上的芯片都会接收到每次发送的请求,芯片会进行设备地址校验,如果不是自己的设备地址,那就不会响应这次请求。

      I2C总线示意图

    • Linux下使用I2C

      Linux下使用I2C有一个工具i2c-tools,飞腾派官方镜像中是自带这个的,如果没有的话可以在终端运行下面命令安装一下。

      sudo apt-get install i2c-tools
      

      这个工具里包含很多命令,下面一个一个来说。

      • i2cdetect扫描I2C总线并列出已连接的设备

        首先在一个开发板或者PC上是可能有多个I2C总线的,因此可以先列出所有的I2C总线。

        i2cdetect -l
        

        返回的内容格式如下:

        i2c-3   i2c         56247000.i2c            I2C adapter
        i2c-2   i2c         56226000.i2c            I2C adapter
        

        其中i2c-2i2c-3就表示可以用的总线号为23。这个是PC端才会有的参数,并不是I2C协议自带定义的,假如使用单片机这种MCU编程控制的话,一般不涉及到总线号这个参数。

        知道可用的总线后,便可以使用如下命令查看一个总线上的所有设备。

        i2cdetect -r -y 2
        

        返回的内容格式如下:

             0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
        00:          -- -- -- -- -- -- -- -- -- -- -- -- -- 
        10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
        20: -- -- -- -- -- -- -- -- -- -- UU -- -- -- -- -- 
        30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
        40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
        50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
        60: UU -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
        70: -- -- -- -- -- -- -- --
        

        以上面这个返回为例子,可以看到在总线2上有两个设备,地址分别为0x2a0x60,在不为--的位置上把行和列加起来就是设备的地址,有时候会显示UU,有时候也会直接显示设备地址。

      • i2cdump显示I2C设备的所有寄存器内容

        知道可用总线及设备后,接下来可以对设备进行读写了,先说一下读取,有两种方式,一种是直接读取设备所有寄存器数据,就是这个i2cdump指令,另一个是i2cget,只读取一个寄存器,这个下面再讲。i2cdump的使用举例如下:

        i2cdump -f -y 2 0x2a
        

        这里就是指定了要读取的总线及设备的地址,返回的结果格式如下:

        No size specified (using byte-data access)
            0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f    0123456789abcdef
        00: da 00 81 00 fb 03 00 00 00 00 00 43 01 03 00 00   ?.?.??.....C??..
        10: 55 55 55 00 00 00 00 00 00 00 00 00 00 00 00 00   UUU.............
        20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
        30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
        40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
        50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
        60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
        70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
        80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
        90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
        a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
        b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
        c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
        d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
        e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
        f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
        

        就是一个类似表格的形式,展示设备中所有寄存器的数据,右边是一个转ASCII字符的展示。这个指令可以方便的查看设备寄存器数据,调试时候比较好用。

      • i2cget从指定寄存器中读取数据

        下面介绍读取指定寄存器数据的指令。i2cget一次可以读出来一个寄存器的数据,使用举例如下:

        sudo i2cget -y 2 0x2a 0x02
        

        这里就是读取总线2上的设备地址为0x2a的芯片上寄存器地址为0x02中的数据。返回内容就是十六进制的一个字节的数据。

        0x81
        
      • i2cset向指定I2C设备的寄存器中写入数据

        下面介绍向寄存器中写入数据,i2cset指令一次只能写入一个寄存器数据,使用距离如下:

        i2cset -f -y 2 0x2a 0x77 0x3f
        

        这里就是向总线2上设备地址为0x2a的芯片上寄存器地址为0x77中写入数据0x3f,这个指令正确执行时候没有返回。如果想验证是否写入成功可以读取寄存器数据进行查看。

    • Python下使用I2C

      因为在开发飞腾派小车时候是飞腾派连接PCA9685,再由PCA9685连接TB6612FNG,所以需要学习Python下使用I2C

      • 安装所需库smbus

        需要安装第三方库smbus,使用pip管理Python库的话,使用如下命令安装。

        pip3 install smbus
        

        如果是使用apt管理Python的库的话,使用如下命令安装smbus

        sudo apt-get update
        sudo apt-get install python3-smbus
        

        有时候apt可能找不到需要的包,因此需要先update更新一下。

      • 声明总线对象

        使用如下代码声明一个总线对象,所需参数为要控制的总线号。

        import smbus
        
        bus = smbus.SMBus(2)
        
      • 向总线上发送写寄存器指令 WRITE

        使用如下函数写寄存器。

        addr  = 0x60
        reg   = 0x00
        value = 0x10
        
        bus.write_byte_data(addr, reg, value)
        

        其中addr就是设备在总线上的地址,这个可以用之前的Linux下的i2c-tools工具查找;reg就是要写的寄存器地址,value就是要写的数据,这三个参数都是一个字节大小,格式也和之前的在Linux下的i2cset差不多。

      • 向总线上发送读寄存器指令 READ

        使用如下函数读寄存器。

        addr  = 0x60
        reg   = 0x00
        
        bus.read_byte_data(addr, reg)
        

        其中addr就是设备在总线上的地址,这个可以用之前的Linux下的i2c-tools工具查找;reg就是要写的寄存器地址,这两个参数都是一个字节大小,和写寄存器的函数一样,格式也和之前的在Linux下的i2cget差不多。

      到这里在Python下使用I2C的基本功能就介绍完了。