imx6ul+i2c使用

来源:互联网 发布:js正则表达式空格 编辑:程序博客网 时间:2024/06/08 02:03
Source-lib第三弹:  i2c使用。

因为TQIMX6UL有两个 i2c,一个 i2c1空闲,一个i2c2用于电容屏触摸,rtc,声卡。

原理图如下:


在板子ls /dev/i2c* 发现只有一个i2c1,没有我们板子上这个驱动,查看设备树发现也没有。

自己移植吧.
在设备树中添加代码:
/* add by Sourcelink */
&i2c1 {
    clock_frequency = <100000>;//ckk
    pinctrl-names = "default";
    pinctrl-0 = <&pinctrl_i2c1>;
    status = "okay";
};
/* add by Sourcelink */
        pinctrl_i2c1: i2c1grp {
            fsl,pins = <
                MX6UL_PAD_CSI_MCLK__I2C1_SDA      0x4001b8b0
                MX6UL_PAD_CSI_PIXCLK__I2C1_SCL    0x4001b8b0
            >;
        };
然后重新编译dtb。用命令make dtbs
然后把新的dtb更新到板子上。
再从新看下设备:

移植成功。

用i2c工具查看下:

这个命令表示:查看i2c总线上的设备。 -y表示无视交互过程  -a显示所有 0 表示设备i2c0

发现我们挂载的设备了:0x68是我的mpu6050设备,大功告成。

我用i2c来驱动mpu6050:

int main(int argc, char ** argv)
{
        int dev_fd;
        if ((dev_fd = mpu6050_init()) < 0) {
                ERR("Fail mpu6050_init\n");
                return -1;
        } else {
                INFO("Successful mpu6050_init\n");
        }
        while (1) {
                        if (mpu6050_read_data(dev_fd)) {
                                ERR("mpu6050_read_data fail!!\n");
                        } else {
                                INFO("DIRECTION_X angle: %f\n", accel_to_angle(DIRECTION_X));
                        }               
                        sleep(1);
        }
        return 0;
}
每秒读取一次数据,在转换。

下面是mpu6050初始化函数:
EXPORT int mpu6050_init(void)
{
        int dev_fd;
        if ((dev_fd = open_hardware(I2C1_PATH, O_RDWR)) < 0) {
                ERR("Fail to open I2C device\n");
                return -1;
        }
        if (set_i2c_slave(dev_fd, MPU6050_SLAVE_ADDRESS) < 0) {
                ERR("Fail to set mpu6050 slave address\n");
                close_hardware(dev_fd);
                return -1;
        }
        i2c_write_byte_data(dev_fd, PWR_MGMT_1, 0x00);
        i2c_write_byte_data(dev_fd, SMPLRT_DIV, 0x07);
        i2c_write_byte_data(dev_fd, LRF_CONFIG, 0x06);
        i2c_write_byte_data(dev_fd, GYRO_CONFIG, 0xE8);
        i2c_write_byte_data(dev_fd, ACCEL_CONFIG, 0x01);
        return dev_fd;
}

下面是mpu6050读数据,一次性把所有数据都读出来了:
EXPORT int mpu6050_read_data(int dev_fd)
{
        int ret = 0;
        int i;
        unsigned char temp_buf[20];
        for (i = 0; i < 14; i++) {
                temp_buf[i] = i2c_read_byte_data(dev_fd, ACCEL_XOUT_H + i);
                if (temp_buf[i] == -1)
                        return -1;
        }
        /* 将读出的数据保存到全局结构体变量 */
        /* 加速度角度数据 */
        g_mpu6050.Accel_X = (temp_buf[0] << 8) + temp_buf[1];
        g_mpu6050.Accel_Y = (temp_buf[2] << 8) + temp_buf[3];
        g_mpu6050.Accel_Z = (temp_buf[4] << 8) + temp_buf[5];
        /* 温度 */
        g_mpu6050.Temp = (short)((temp_buf[6] << 8) + temp_buf[7]);
        /* 陀螺仪角速度数据 */
        g_mpu6050.GYRO_X = (temp_buf[8] << 8) + temp_buf[9];
        g_mpu6050.GYRO_Y = (temp_buf[10] << 8) + temp_buf[11];
        g_mpu6050.GYRO_Z = (temp_buf[12] << 8) + temp_buf[13];
        return ret;
}
数据转换:
EXPORT float accel_to_angle(unsigned char direction)
{
        float temp_angle = 0.0;
        switch (direction) {
                case DIRECTION_X:
                        temp_angle = accel_to_angle_x(&g_mpu6050);
                        break;
                case DIRECTION_Y:
                        temp_angle = accel_to_angle_y(&g_mpu6050);
                        break;
                case DIRECTION_Z:
                        temp_angle = accel_to_angle_z(&g_mpu6050);
                        break;
                default : break;
        }
        return temp_angle;
}
效果图:


在使用i2c1时发现了con6会发出数据,查看原理图发现两个冲突了:


解决办法,关闭串口6,既把ttySAC5屏蔽。
修改设备树:
/* modified by Sourcelink
&uart6 {
    pinctrl-names = "default";
    pinctrl-0 = <&pinctrl_uart6>;
    status = "okay";
};
*/