Linux用户层I2C读取LSM6DSL陀螺仪记录

硬件外设
开发板Lubancat V2/dev/i2c-3
LSM6DSL陀螺仪i2c(7bit地址0x6a)

开发板配置I2C

开发板采用Lubancat-V2,运行Linux内核4.19

使用I2C3外设

因为i2c3外设的设备树默认没有启用,所以在 /boot/uEnv/uEnv.txt 打开,也即取消i2c3-m0注释

随后重启/reboot激活I2C3设备

终端输入

ls  /dev/i2c-*

得到

至此开发板的I2C配置完成

LSM6DSL接口板硬件

此处原理图是LSM6DS3TR-C,其引脚定义和寄存器定义与LSM6DSL一致

完成:供电+SDA连线(到Lubancat I2C3 SDA)+SCL连线(到Lubancat I2C3 SCL)

LSM6DSL特性

LSM6DSL默认上电之后加速度的ODR=0,即不输出加速度数据,所以需要手动配置,此外默认加速度测量范围-2g ~ 2g

 LSM6DSL默认上电之后陀螺仪的ODR=0,即不输出角速度数据,所以需要手动配置,此外默认角速度测量范围0~250dps

代码实现

i2c_lsm6dsl_linux.h 主要作用是声明寄存器地址、函数等


#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>

/************** I2C Address *****************/

#define LSM6DSL_ACC_GYRO_I2C_ADDRESS_LOW 0x6a  // SAD[0] = 0
#define LSM6DSL_ACC_GYRO_I2C_ADDRESS_HIGH 0x6b // SAD[0] = 1

/************** Who am I  *******************/

#define LSM6DSL_ACC_GYRO_WHO_AM_I 0x6A

/************** Device Register  *******************/

#define LSM6DSL_ACC_GYRO_FUNC_CFG_ACCESS 0x01

#define LSM6DSL_ACC_GYRO_SENSOR_SYNC_TIME 0x04
#define LSM6DSL_ACC_GYRO_SENSOR_RES_RATIO 0x05

#define LSM6DSL_ACC_GYRO_FIFO_CTRL1 0x06
#define LSM6DSL_ACC_GYRO_FIFO_CTRL2 0x07
#define LSM6DSL_ACC_GYRO_FIFO_CTRL3 0x08
#define LSM6DSL_ACC_GYRO_FIFO_CTRL4 0x09
#define LSM6DSL_ACC_GYRO_FIFO_CTRL5 0x0A

#define LSM6DSL_ACC_GYRO_DRDY_PULSE_CFG_G 0x0B
#define LSM6DSL_ACC_GYRO_INT1_CTRL 0x0D
#define LSM6DSL_ACC_GYRO_INT2_CTRL 0x0E
#define LSM6DSL_ACC_GYRO_WHO_AM_I_REG 0x0F
#define LSM6DSL_ACC_GYRO_CTRL1_XL 0x10
#define LSM6DSL_ACC_GYRO_CTRL2_G 0x11
#define LSM6DSL_ACC_GYRO_CTRL3_C 0x12
#define LSM6DSL_ACC_GYRO_CTRL4_C 0x13
#define LSM6DSL_ACC_GYRO_CTRL5_C 0x14
#define LSM6DSL_ACC_GYRO_CTRL6_C 0x15
#define LSM6DSL_ACC_GYRO_CTRL7_G 0x16
#define LSM6DSL_ACC_GYRO_CTRL8_XL 0x17
#define LSM6DSL_ACC_GYRO_CTRL9_XL 0x18
#define LSM6DSL_ACC_GYRO_CTRL10_C 0x19

#define LSM6DSL_ACC_GYRO_MASTER_CONFIG 0x1A
#define LSM6DSL_ACC_GYRO_WAKE_UP_SRC 0x1B
#define LSM6DSL_ACC_GYRO_TAP_SRC 0x1C
#define LSM6DSL_ACC_GYRO_D6D_SRC 0x1D
#define LSM6DSL_ACC_GYRO_STATUS_REG 0x1E

#define LSM6DSL_ACC_GYRO_OUT_TEMP_L 0x20
#define LSM6DSL_ACC_GYRO_OUT_TEMP_H 0x21
#define LSM6DSL_ACC_GYRO_OUTX_L_G 0x22
#define LSM6DSL_ACC_GYRO_OUTX_H_G 0x23
#define LSM6DSL_ACC_GYRO_OUTY_L_G 0x24
#define LSM6DSL_ACC_GYRO_OUTY_H_G 0x25
#define LSM6DSL_ACC_GYRO_OUTZ_L_G 0x26
#define LSM6DSL_ACC_GYRO_OUTZ_H_G 0x27
#define LSM6DSL_ACC_GYRO_OUTX_L_XL 0x28
#define LSM6DSL_ACC_GYRO_OUTX_H_XL 0x29
#define LSM6DSL_ACC_GYRO_OUTY_L_XL 0x2A
#define LSM6DSL_ACC_GYRO_OUTY_H_XL 0x2B
#define LSM6DSL_ACC_GYRO_OUTZ_L_XL 0x2C
#define LSM6DSL_ACC_GYRO_OUTZ_H_XL 0x2D
#define LSM6DSL_ACC_GYRO_SENSORHUB1_REG 0x2E
#define LSM6DSL_ACC_GYRO_SENSORHUB2_REG 0x2F
#define LSM6DSL_ACC_GYRO_SENSORHUB3_REG 0x30
#define LSM6DSL_ACC_GYRO_SENSORHUB4_REG 0x31
#define LSM6DSL_ACC_GYRO_SENSORHUB5_REG 0x32
#define LSM6DSL_ACC_GYRO_SENSORHUB6_REG 0x33
#define LSM6DSL_ACC_GYRO_SENSORHUB7_REG 0x34
#define LSM6DSL_ACC_GYRO_SENSORHUB8_REG 0x35
#define LSM6DSL_ACC_GYRO_SENSORHUB9_REG 0x36
#define LSM6DSL_ACC_GYRO_SENSORHUB10_REG 0x37
#define LSM6DSL_ACC_GYRO_SENSORHUB11_REG 0x38
#define LSM6DSL_ACC_GYRO_SENSORHUB12_REG 0x39
#define LSM6DSL_ACC_GYRO_FIFO_STATUS1 0x3A
#define LSM6DSL_ACC_GYRO_FIFO_STATUS2 0x3B
#define LSM6DSL_ACC_GYRO_FIFO_STATUS3 0x3C
#define LSM6DSL_ACC_GYRO_FIFO_STATUS4 0x3D
#define LSM6DSL_ACC_GYRO_FIFO_DATA_OUT_L 0x3E
#define LSM6DSL_ACC_GYRO_FIFO_DATA_OUT_H 0x3F
#define LSM6DSL_ACC_GYRO_TIMESTAMP0_REG 0x40
#define LSM6DSL_ACC_GYRO_TIMESTAMP1_REG 0x41
#define LSM6DSL_ACC_GYRO_TIMESTAMP2_REG 0x42

#define LSM6DSL_ACC_GYRO_TIMESTAMP_L 0x49
#define LSM6DSL_ACC_GYRO_TIMESTAMP_H 0x4A

#define LSM6DSL_ACC_GYRO_STEP_COUNTER_L 0x4B
#define LSM6DSL_ACC_GYRO_STEP_COUNTER_H 0x4C

#define LSM6DSL_ACC_GYRO_SENSORHUB13_REG 0x4D
#define LSM6DSL_ACC_GYRO_SENSORHUB14_REG 0x4E
#define LSM6DSL_ACC_GYRO_SENSORHUB15_REG 0x4F
#define LSM6DSL_ACC_GYRO_SENSORHUB16_REG 0x50
#define LSM6DSL_ACC_GYRO_SENSORHUB17_REG 0x51
#define LSM6DSL_ACC_GYRO_SENSORHUB18_REG 0x52

#define LSM6DSL_ACC_GYRO_FUNC_SRC 0x53
#define LSM6DSL_ACC_GYRO_TAP_CFG1 0x58
#define LSM6DSL_ACC_GYRO_TAP_THS_6D 0x59
#define LSM6DSL_ACC_GYRO_INT_DUR2 0x5A
#define LSM6DSL_ACC_GYRO_WAKE_UP_THS 0x5B
#define LSM6DSL_ACC_GYRO_WAKE_UP_DUR 0x5C
#define LSM6DSL_ACC_GYRO_FREE_FALL 0x5D
#define LSM6DSL_ACC_GYRO_MD1_CFG 0x5E
#define LSM6DSL_ACC_GYRO_MD2_CFG 0x5F

#define LSM6DSL_ACC_GYRO_OUT_MAG_RAW_X_L 0x66
#define LSM6DSL_ACC_GYRO_OUT_MAG_RAW_X_H 0x67
#define LSM6DSL_ACC_GYRO_OUT_MAG_RAW_Y_L 0x68
#define LSM6DSL_ACC_GYRO_OUT_MAG_RAW_Y_H 0x69
#define LSM6DSL_ACC_GYRO_OUT_MAG_RAW_Z_L 0x6A
#define LSM6DSL_ACC_GYRO_OUT_MAG_RAW_Z_H 0x6B

#define LSM6DSL_ACC_GYRO_X_OFS_USR 0x73
#define LSM6DSL_ACC_GYRO_Y_OFS_USR 0x74
#define LSM6DSL_ACC_GYRO_Z_OFS_USR 0x75

/************** Embedded functions register mapping  *******************/
#define LSM6DSL_ACC_GYRO_SLV0_ADD 0x02
#define LSM6DSL_ACC_GYRO_SLV0_SUBADD 0x03
#define LSM6DSL_ACC_GYRO_SLAVE0_CONFIG 0x04
#define LSM6DSL_ACC_GYRO_SLV1_ADD 0x05
#define LSM6DSL_ACC_GYRO_SLV1_SUBADD 0x06
#define LSM6DSL_ACC_GYRO_SLAVE1_CONFIG 0x07
#define LSM6DSL_ACC_GYRO_SLV2_ADD 0x08
#define LSM6DSL_ACC_GYRO_SLV2_SUBADD 0x09
#define LSM6DSL_ACC_GYRO_SLAVE2_CONFIG 0x0A
#define LSM6DSL_ACC_GYRO_SLV3_ADD 0x0B
#define LSM6DSL_ACC_GYRO_SLV3_SUBADD 0x0C
#define LSM6DSL_ACC_GYRO_SLAVE3_CONFIG 0x0D
#define LSM6DSL_ACC_GYRO_DATAWRITE_SRC_MODE_SUB_SLV0 0x0E
#define LSM6DSL_ACC_GYRO_CONFIG_PEDO_THS_MIN 0x0F

#define LSM6DSL_ACC_GYRO_SM_STEP_THS 0x13
#define LSM6DSL_ACC_GYRO_PEDO_DEB_REG 0x14
#define LSM6DSL_ACC_GYRO_STEP_COUNT_DELTA 0x15

#define LSM6DSL_ACC_GYRO_MAG_SI_XX 0x24
#define LSM6DSL_ACC_GYRO_MAG_SI_XY 0x25
#define LSM6DSL_ACC_GYRO_MAG_SI_XZ 0x26
#define LSM6DSL_ACC_GYRO_MAG_SI_YX 0x27
#define LSM6DSL_ACC_GYRO_MAG_SI_YY 0x28
#define LSM6DSL_ACC_GYRO_MAG_SI_YZ 0x29
#define LSM6DSL_ACC_GYRO_MAG_SI_ZX 0x2A
#define LSM6DSL_ACC_GYRO_MAG_SI_ZY 0x2B
#define LSM6DSL_ACC_GYRO_MAG_SI_ZZ 0x2C
#define LSM6DSL_ACC_GYRO_MAG_OFFX_L 0x2D
#define LSM6DSL_ACC_GYRO_MAG_OFFX_H 0x2E
#define LSM6DSL_ACC_GYRO_MAG_OFFY_L 0x2F
#define LSM6DSL_ACC_GYRO_MAG_OFFY_H 0x30
#define LSM6DSL_ACC_GYRO_MAG_OFFZ_L 0x31
#define LSM6DSL_ACC_GYRO_MAG_OFFZ_H 0x32

/* Accelero Full_ScaleSelection */
#define LSM6DSL_ACC_FULLSCALE_2G ((uint8_t)0x00)  /*!< �2 g */
#define LSM6DSL_ACC_FULLSCALE_4G ((uint8_t)0x08)  /*!< �4 g */
#define LSM6DSL_ACC_FULLSCALE_8G ((uint8_t)0x0C)  /*!< �8 g */
#define LSM6DSL_ACC_FULLSCALE_16G ((uint8_t)0x04) /*!< �16 g */

/* Accelero Full Scale Sensitivity */
#define LSM6DSL_ACC_SENSITIVITY_2G ((float)0.061f)  /*!< accelerometer sensitivity with 2 g full scale  [mgauss/LSB] */
#define LSM6DSL_ACC_SENSITIVITY_4G ((float)0.122f)  /*!< accelerometer sensitivity with 4 g full scale  [mgauss/LSB] */
#define LSM6DSL_ACC_SENSITIVITY_8G ((float)0.244f)  /*!< accelerometer sensitivity with 8 g full scale  [mgauss/LSB] */
#define LSM6DSL_ACC_SENSITIVITY_16G ((float)0.488f) /*!< accelerometer sensitivity with 12 g full scale [mgauss/LSB] */

/* Accelero Power Mode selection */
#define LSM6DSL_ACC_GYRO_LP_XL_DISABLED ((uint8_t)0x00) /* LP disabled*/
#define LSM6DSL_ACC_GYRO_LP_XL_ENABLED ((uint8_t)0x10)  /* LP enabled*/

/* Output Data Rate */
#define LSM6DSL_ODR_BITPOSITION ((uint8_t)0xF0) /*!< Output Data Rate bit position */
#define LSM6DSL_ODR_POWER_DOWN ((uint8_t)0x00)  /* Power Down mode       */
#define LSM6DSL_ODR_13Hz ((uint8_t)0x10)        /* Low Power mode        */
#define LSM6DSL_ODR_26Hz ((uint8_t)0x20)        /* Low Power mode        */
#define LSM6DSL_ODR_52Hz ((uint8_t)0x30)        /* Low Power mode        */
#define LSM6DSL_ODR_104Hz ((uint8_t)0x40)       /* Normal mode           */
#define LSM6DSL_ODR_208Hz ((uint8_t)0x50)       /* Normal mode           */
#define LSM6DSL_ODR_416Hz ((uint8_t)0x60)       /* High Performance mode */
#define LSM6DSL_ODR_833Hz ((uint8_t)0x70)       /* High Performance mode */
#define LSM6DSL_ODR_1660Hz ((uint8_t)0x80)      /* High Performance mode */
#define LSM6DSL_ODR_3330Hz ((uint8_t)0x90)      /* High Performance mode */
#define LSM6DSL_ODR_6660Hz ((uint8_t)0xA0)      /* High Performance mode */

/* Gyro Full Scale Selection */
#define LSM6DSL_GYRO_FS_245 ((uint8_t)0x00)
#define LSM6DSL_GYRO_FS_500 ((uint8_t)0x04)
#define LSM6DSL_GYRO_FS_1000 ((uint8_t)0x08)
#define LSM6DSL_GYRO_FS_2000 ((uint8_t)0x0C)

/* Gyro Full Scale Sensitivity */
#define LSM6DSL_GYRO_SENSITIVITY_245DPS ((float)8.750f)  /**< Sensitivity value for 245 dps full scale  [mdps/LSB] */
#define LSM6DSL_GYRO_SENSITIVITY_500DPS ((float)17.50f)  /**< Sensitivity value for 500 dps full scale  [mdps/LSB] */
#define LSM6DSL_GYRO_SENSITIVITY_1000DPS ((float)35.00f) /**< Sensitivity value for 1000 dps full scale [mdps/LSB] */
#define LSM6DSL_GYRO_SENSITIVITY_2000DPS ((float)70.00f) /**< Sensitivity value for 2000 dps full scale [mdps/LSB] */

/* Gyro Power Mode selection */
#define LSM6DSL_ACC_GYRO_LP_G_DISABLED ((uint8_t)0x00) /* LP disabled*/
#define LSM6DSL_ACC_GYRO_LP_G_ENABLED ((uint8_t)0x80)  /* LP enabled*/

/* Block Data Update */
#define LSM6DSL_BDU_CONTINUOS ((uint8_t)0x00)
#define LSM6DSL_BDU_BLOCK_UPDATE ((uint8_t)0x40)

/* Auto-increment */
#define LSM6DSL_ACC_GYRO_IF_INC_DISABLED ((uint8_t)0x00)
#define LSM6DSL_ACC_GYRO_IF_INC_ENABLED ((uint8_t)0x04)

uint8_t lsm6dsl_readID(int fd);

void lsm6dsl_acc_init(int fd);
void lsm6dsl_acc_read_xyz(int fd, int16_t *pData);

void lsm6dsl_gyro_init(int fd);
void lsm6dsl_gyro_read_xyz(int fd, int16_t *pData);

i2c_lsm6dsl_linux.c 作用是对LSM6DSL加速度初始化函数、陀螺仪初始化函数、数据读取函数定义,并定义main入口函数


#include "i2c_lsm6dsl_linux.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>

#include <linux/i2c.h>
#include <linux/i2c-dev.h>

int main(int argc, char **argv)
{
    if (argc < 2)
    {
        printf("wrong use!!!\n");
        printf("usage: %s [dev]\n", argv[0]);
        return -1;
    }

    int fd = open(argv[1], O_RDWR);
    if (fd < 0)
    {
        printf("can not open %s\n", argv[1]);
        return -2;
    }

    lsm6dsl_acc_init(fd);
    lsm6dsl_gyro_init(fd);

    uint8_t id = lsm6dsl_readID(fd);
    printf("lsm6dsl id = %d\n", id);

    uint16_t acce_raw_data[3];
    uint16_t gyro_raw_data[3];

    for (int i = 0; i < 10; i++)
    {
        lsm6dsl_acc_read_xyz(fd, acce_raw_data);
        printf("raw acce: [x, y, z] = [%d, %d, %d]\n", acce_raw_data[0], acce_raw_data[1], acce_raw_data[2]);

        sleep(1);

        lsm6dsl_gyro_read_xyz(fd, gyro_raw_data);
        printf("raw gyro: [x, y, z] = [%d, %d, %d]\n", gyro_raw_data[0], gyro_raw_data[1], gyro_raw_data[2]);

        sleep(1);
    }

    return 0;
}

static int i2c_read(int fd, uint8_t addr, uint8_t reg_addr, uint8_t *val, uint16_t rd_cnt)
{
    ioctl(fd, I2C_TENBIT, 0); /* 设置7位地址 */

    /* 设置从机地址 */
    if (ioctl(fd, I2C_SLAVE, addr) < 0)
    {
        printf("fail to set i2c slave address!\n");
        close(fd);
        return -1;
    }

    /* 设置收不到ACK的重试次数 */
    ioctl(fd, I2C_RETRIES, 5);

    if (write(fd, &reg_addr, 1) == 1)
    {
        if (read(fd, val, rd_cnt) == rd_cnt)
            return 0;
    }
    else
    {
        return -1;
    }
}

static int i2c_write(int fd, uint8_t addr, uint8_t reg_addr, uint8_t val)
{
    ioctl(fd, I2C_TENBIT, 0); /* 设置7位地址 */

    /* 设置从机地址 */
    if (ioctl(fd, I2C_SLAVE, addr) < 0)
    {
        printf("fail to set i2c slave address!\n");
        close(fd);
        return -1;
    }

    /* 设置收不到ACK的重试次数 */
    ioctl(fd, I2C_RETRIES, 5);

    uint8_t write_arr[2];
    write_arr[0] = reg_addr;
    write_arr[1] = val;
    if (write(fd, write_arr, 2) == 2)
        return 0;
    else
        return -2;
}

uint8_t lsm6dsl_readID(int fd)
{
    uint8_t lsm6dsl_id = 0;
    i2c_read(fd, LSM6DSL_ACC_GYRO_I2C_ADDRESS_LOW, LSM6DSL_ACC_GYRO_WHO_AM_I_REG, &lsm6dsl_id, 1);

    return lsm6dsl_id;
}

void lsm6dsl_acc_init(int fd)
{
    /* 因为LSM6DSL默认上电之后加速度不输出(ODR=0),需要在 LSM6DSL_ACC_GYRO_CTRL1_XL 寄存器进行配置
        在此寄存器顺便将加速度的测量范围配置为 -16g ~ +16g
     */
    uint8_t tmp = LSM6DSL_ODR_833Hz | LSM6DSL_ACC_FULLSCALE_16G;
    i2c_write(fd, LSM6DSL_ACC_GYRO_I2C_ADDRESS_LOW, LSM6DSL_ACC_GYRO_CTRL1_XL, tmp);

    i2c_read(fd, LSM6DSL_ACC_GYRO_I2C_ADDRESS_LOW, LSM6DSL_ACC_GYRO_CTRL3_C, &tmp, 1);
    tmp |= LSM6DSL_BDU_CONTINUOS;
    tmp |= LSM6DSL_ACC_GYRO_IF_INC_ENABLED;
    i2c_write(fd, LSM6DSL_ACC_GYRO_I2C_ADDRESS_LOW, LSM6DSL_ACC_GYRO_CTRL3_C, tmp);
}

void lsm6dsl_acc_read_xyz(int fd, int16_t *pData)
{
    uint8_t acce_rd_buf[6];
    i2c_read(fd, LSM6DSL_ACC_GYRO_I2C_ADDRESS_LOW, LSM6DSL_ACC_GYRO_OUTX_L_XL, acce_rd_buf, 6);

    for (int i = 0; i < 3; i++)
    {
        pData[i] = (acce_rd_buf[2 * i + 1] << 8) | acce_rd_buf[2 * i];
    }
}

void lsm6dsl_gyro_init(int fd)
{
    /* 因为LSM6DSL默认上电之后陀螺仪不输出(ODR=0),需要在 LSM6DSL_ACC_GYRO_CTRL2_G 寄存器进行配置
        在此寄存器顺便将加速度的测量范围配置为 -16g ~ +16g
    */
    uint8_t tmp = 0;
    i2c_read(fd, LSM6DSL_ACC_GYRO_I2C_ADDRESS_LOW, LSM6DSL_ACC_GYRO_CTRL2_G, &tmp, 1);

    tmp |= LSM6DSL_ODR_833Hz;
    tmp |= LSM6DSL_GYRO_FS_1000;
    i2c_write(fd, LSM6DSL_ACC_GYRO_I2C_ADDRESS_LOW, LSM6DSL_ACC_GYRO_CTRL2_G, tmp);

    i2c_read(fd, LSM6DSL_ACC_GYRO_I2C_ADDRESS_LOW, LSM6DSL_ACC_GYRO_CTRL3_C, &tmp, 1);
    tmp |= LSM6DSL_BDU_CONTINUOS;
    tmp |= LSM6DSL_ACC_GYRO_IF_INC_ENABLED;
    i2c_write(fd, LSM6DSL_ACC_GYRO_I2C_ADDRESS_LOW, LSM6DSL_ACC_GYRO_CTRL3_C, tmp);
}

void lsm6dsl_gyro_read_xyz(int fd, int16_t *pData)
{
    uint8_t acce_rd_buf[6];
    i2c_read(fd, LSM6DSL_ACC_GYRO_I2C_ADDRESS_LOW, LSM6DSL_ACC_GYRO_OUTX_L_G, acce_rd_buf, 6);

    for (int i = 0; i < 3; i++)
    {
        pData[i] = (acce_rd_buf[2 * i + 1] << 8) | acce_rd_buf[2 * i];
    }
}

需要注意的是在API函数read  和 write 函数中LSM6DSL地址是7bit地址(最高位是0)

终端输入使用gcc编译:

gcc ./i2c_lsm6dsl_linux.c -o lsm6dsl

运行测试实例:

访问 /dev/i2c-3 需要root权限

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值