zoukankan      html  css  js  c++  java
  • 【linux】i2c使用分析&源码实战


    前言

    • 目前不涉及驱动源码
    • 原文

    1. 设备检查命令

    1.1 查看I2C驱动

    • 命令:ls /sys/bus/i2c/devices 用于查看系统上存在的 I2C 总线

    1.2 i2c-tools

    • i2c-tools,安装 i2c-tools 方便调试 i2c设备

    1.2.1 I2C-detect安装

    • 使用命令:sudo apt install i2c-tools -y 安装 i2c-tools
    • 安装后可以使用命令:i2cdetect、i2cdump、i2cseti2cget

    1.2.2 i2cdetect 命令

    • i2cdetect
      • 用于扫描 I2C 总线上的设备
    • 语法
      • i2cdetect [-y] [-a] [-q|-r] i2cbus [first last]
      • 参数
        • y:关闭交互模式,使用该参数时,不会提示警告信息。
        • a:扫描总线上的所有设备
        • q:使用SMBus的“quick write”命令进行检测,不建议使用该参数
        • r:使用SMBus的“receive byte”命令进行检测,不建议使用该参数
        • i2cbus:指定i2c总线的编号
        • first、last:扫描的地址范围
      • 返回值
        • '-':表示该地址被检测,但是没有芯片应答
        • 'UU':表示该地址当前由内核驱动程序使用
        • '**':** 表示以16进制表示的设备地址编号,如“68”
    • 例子:
      • i2cdetect -a 0
        • i2cdetect:i2cdetect命令
        • -a:总线上所有设备
        • 0:标号为 0 的 I2C,即是 I2C 1。
      • 上图中扫描出存在设备地址为 0x1e0x68 的设备。
      • i2cdetect -F i2cbus:查询 i2c 总线的功能,参数 i2cbus 表示 i2c 总线(看上
      • i2cdetect -V:打印软件的版本号
      • i2cdetect -l:检测当前系统有几组 i2c 总线

    1.2.3 i2cget 命令

    • i2cget
      • 用于读取 I2C 设备的某个寄存器的值
    • 语法
      • i2cget [-f] [-y] i2cbus chip-address [data-address [mode]]
      • 参数
        • f:强制访问
        • y:关闭交互模式,使用该参数时,不会提示警告信息
        • i2cbus:指定 I2C 总线的编号
        • chip-address:I2C 设备地址
        • data-address:I2C 寄存器地址
        • mode:指定读取的大小, 可以是b, w, s或i,分别对应了字节,字,SMBus块, I2C块

    1.2.4 i2cset 命令

    • i2cset
      • 写入指定 I2C 设备的某个寄存器的值
    • 语法
      • i2cset [-f] [-y] [-m mask] [-r] i2cbus chip-address data-address [value] … [mode]
      • 参数
        • f:强制访问
        • y:关闭交互模式,使用该参数时,不会提示警告信息
        • m
        • r:写入后立即回读寄存器值,并将结果与写入的值进行比较
        • i2cbus:指定 I2C 总线的编号
        • chip-address:I2C 设备地址
        • data-address:I2C 寄存器地址
        • value:要写入的值
        • mode:指定读取的大小, 可以是b, w, s或i,分别对应了字节,字,SMBus块, I2C块

    1.2.5 i2cdump 命令

    • i2cdump
      • 读取指定设备的全部寄存器的值
    • 语法
      • i2cdump [-f] [-r first-last] [-y] i2cbus address [mode [bank [bankreg]]]
      • 参数
        • r:指定寄存器范围,只能扫描从 firstlast 区域
        • f:强制访问设备
        • y:关闭人机交互模式
        • i2cbus:指定 I2C 总线的编号
        • address:指定设备地址
        • mode:指定读取的大小, 可以是b, w, s或i,分别对应了字节,字,SMBus块, I2C块
    • 例子
      • i2cdump -V:打印软件的版本号

    2. 源码实战

    • 采用MPU6050设备进行实验
    • 步骤:
      • 先编写基础的 I2C 基础函数
      • 编写 MPU6050 初始化函数和关闭设备文件函数
      • 编写获取 MPU6050 数据函数
      • 编写业务函数

    2.1 编写 bsp_mpu6050.h 文件

    • 编写好 MPU6050 需要的宏
    • extern 外部函数
    /** @file         bsp_mpu6050.h
     *  @brief        简要说明
     *  @details      详细说明
     *  @author       lzm
     *  @date         2020-11-28 19:22:20
     *  @version      v1.0
     *  @copyright    Copyright By lizhuming, All Rights Reserved
     *
     **********************************************************
     *  @LOG 修改日志:
     **********************************************************
    */
    #ifndef _BSP_MPU6050_H_ 
    #define _BSP_MPU6050_H_
    /* 宏 */
    #define SMPLRT_DIV                                  0x19
    #define CONFIG                                      0x1A
    #define GYRO_CONFIG                                 0x1B
    #define ACCEL_CONFIG                                0x1C
    #define ACCEL_XOUT_H                                0x3B
    #define ACCEL_XOUT_L                                0x3C
    #define ACCEL_YOUT_H                                0x3D
    #define ACCEL_YOUT_L                                0x3f
    #define ACCEL_ZOUT_H                                0x3F
    #define ACCEL_ZOUT_L                                0x40
    #define TEMP_OUT_H                                  0x41
    #define TEMP_OUT_L                                  0x42
    #define GYRO_XOUT_H                                 0x43
    #define GYRO_XOUT_L                                 0x44
    #define GYRO_YOUT_H                                 0x45
    #define GYRO_YOUT_L                                 0x46
    #define GYRO_ZOUT_H                                 0x47
    #define GYRO_ZOUT_L                                 0x48
    #define PWR_MGMT_1                                  0x6B
    #define WHO_AM_I                                    0x75
    #define SlaveAddress                                0xD0
    #define Address                                     0x68                  //MPU6050地址
    #define I2C_RETRIES                                 0x0701
    #define I2C_TIMEOUT                                 0x0702
    #define I2C_SLAVE                                   0x0703       //IIC从器件的地址设置
    #define I2C_BUS_MODE                                0x0780
    /* 类型转换 */
    typedef unsigned char uint8_t;
    /* 函数 */
    uint8_t mpu6050_init(char * i2cDev);
    void    mpu6050_close(void);
    short   getData(unsigned char regAddr);
    #endif /* #define _BSP_MPU6050_H_ */
    

    2.2 编写 bsp_mpu6050.c 文件

    • bsp_mpu6050.c
    • 编写 I2C 读写函数
    • 编写 MPU6050 设备初始化函数及关闭文件函数
    • 编写获取 MPU6050 设备寄存器数据函数
    
    /** @file         bsp_mpu6050.c
     *  @brief        简要说明
     *  @details      详细说明
     *  @author       lzm
     *  @date         2020-11-28 19:20:20
     *  @version      v1.0
     *  @copyright    Copyright By lizhuming, All Rights Reserved
     *
     **********************************************************
     *  @LOG 修改日志:
     **********************************************************
    */
    /* 头文件 */
    #include<stdio.h>
    #include<stdlib.h>
    #include<unistd.h>
    #include<sys/ioctl.h>
    #include<sys/types.h>
    #include<sys/stat.h>
    #include<fcntl.h>
    #include<sys/select.h>
    #include<sys/time.h>
    #include "bsp_mpu6050.h"
    /* 设备句柄 */
    int i2cFd; // i2c设备句柄
    /**
      * @brief  i2c 写
      * @param  fd:i2c设备句柄
      * @param  regAddr:寄存器地址
      * @param  val:需要写入的值
      * @retval 0:写入成功
      * @retval -1:写入失败
      * @author lzm
      */
    static uint8_t i2c_write(int fd, uint8_t regAddr, uint8_t val)
    {
        int cnt; // 写入失败后,重复写入的次数
        uint8_t data[2]; // data[0]为寄存器地址,data[1]为需要写入的值
        data[0] = regAddr;
        data[1] = val;
        for(cnt=5; cnt>0; cnt--)
        {
            if(write(fd, data, 2) == 2)
                return 0; // 写入成功
        }
        return -1; // 写入失败
    }
    /**
      * @brief  i2c 读
      * @param  fd:i2c设备句柄
      * @param  regAddr:寄存器地址
      * @param  val:读取到数据保存的地方
      * @retval 0:读取成功
      * @retval -1:读取失败
      * @author lzm
      */
    static uint8_t i2c_read(int fd, uint8_t regAddr, uint8_t * val)
    {
        int cnt; // 读取失败后,重新读取的次数
        for(cnt=5; cnt>0; cnt--)
        {
            if(write(fd, &regAddr, 1) == 1)
            {
                if(read(fd, val, 1) == 1)
                    return 0;
            }
        }
        return -1;
    }
    /**
      * @brief  mpu6050初始化
      * @param  i2cDev
      * @retval 1:初始化成功
      * @retval 0:初始化失败
      * @author lzm
      */
    uint8_t mpu6050_init(char * i2cDev)
    {
        i2cFd = open(i2cDev, O_RDWR); // 打开i2c设备文件
        if(i2cFd < 0)
        {
            printf("Can't open %s!
    ", i2cDev);
            exit(1);
        }
        printf("Open %s success!", i2cDev);
        if(ioctl(i2cFd, I2C_SLAVE, Address) < 0)
        {
            printf("fail to set i2c device slave address!");
            close(i2cFd); // 关闭i2c设备文件
            return -1;
        }
        printf("set slave address to 0x%x success!", Address);
        i2c_write(i2cFd, PWR_MGMT_1, 0X00);
        i2c_write(i2cFd, SMPLRT_DIV, 0X07);
        i2c_write(i2cFd, CONFIG, 0X06);
        i2c_write(i2cFd, ACCEL_CONFIG, 0X01);
        return 1;
    }
    /**
      * @brief  关闭设备文件
      * @param  
      * @retval 
      * @author lzm
      */
    void mpu6050_close(void)
    {
        close(i2cFd);
    }
    /**
      * @brief  获取数据
      * @param  regAddr:寄存器地址
      * @retval 获取到的数据
      * @author lzm
      */
    short getData(unsigned char regAddr)
    {
        char chH; // 高字节
        char chL; // 低字节
        i2c_read(i2cFd, regAddr, &chH);
        usleep(1000);
        i2c_read(i2cFd, regAddr, &chL);
        return ((chH << 8) + chL);
    }
    

    2.3 编写 main.c 文件

    • 编写业务函数
    
    /** @file         main.c
     *  @brief        简要说明
     *  @details      详细说明
     *  @author       lzm
     *  @date         2020-11-28 19:18:20
     *  @version      v1.0
     *  @copyright    Copyright By lizhuming, All Rights Reserved
     *
     **********************************************************
     *  @LOG 修改日志:
     **********************************************************
    */
    #include<stdio.h>
    #include<stdlib.h>
    #include<unistd.h>
    #include<sys/ioctl.h>
    #include<sys/types.h>
    #include<sys/stat.h>
    #include<fcntl.h>
    #include<sys/select.h>
    #include<sys/time.h>
    #include "mpu6050/bsp_mpu6050.h"
    int main(int argc, char * argv[])
    {
        /* 程序开始标语 */
        printf("This is a mpu6050 test!
    ");
        /* 初始化 MCPU6050 */
        mpu6050_init("/dev/i2c-0");
        sleep(1);
        /* mpu6050 应用测试 */
        while(1)
        {
            printf("get mpu6050 data!
    ");
            usleep(1000 * 100);
            printf("ACCE_X:%6d
     ", getData(ACCEL_XOUT_H));
            usleep(1000 * 100);
            printf("ACCE_Y:%6d
     ", getData(ACCEL_YOUT_H));
            usleep(1000 * 100);
            printf("ACCE_Z:%6d
     ", getData(ACCEL_ZOUT_H));
            usleep(1000 * 100);
            printf("GYRO_X:%6d
     ", getData(GYRO_XOUT_H));
            usleep(1000 * 100);
            printf("GYRO_Y:%6d
     ", getData(GYRO_YOUT_H));
            usleep(1000 * 100);
            printf("GYRO_Z:%6d
    
     ", getData(GYRO_ZOUT_H));
            sleep(1);
        }
        /* 退出 mpu6050 */
        mpu6050_close();
    }
    

    相关链接

  • 相关阅读:
    xml方式将dataset导出excel
    linux安装Navicat,界面出现乱码解决方法 (转发)
    ERROR 29 (HY000): File '/var/lib/mysql/txtdata/yz2014_1.txt' not found (Errcode: 13 "Permission denied")
    centos7中yum安装ntfs3g(转载)
    MariaDB中my.cnf文件误删除
    Mysql操作命令出现错误时消除/mysql数据导入txt
    Linux查找yum安装软件在系统中路径
    Centos7安装MariaDB安装数据库yum安装数据库远程登录数据库存储路径更改
    Zookeeper常用命令
    Hbase学习连接-数据导入
  • 原文地址:https://www.cnblogs.com/lizhuming/p/14063151.html
Copyright © 2011-2022 走看看