本文主要是Linux中应用层直接使用I2C驱动的相关笔记,若笔记中有错误或者不合适的地方,欢迎批评指正😃。
点击查看使用工具及版本
Windows windows11 Ubuntu Ubuntu16.04的64位版本 VMware® Workstation 16 Pro 16.2.3 build-19376536 SecureCRT Version 8.7.2 (x64 build 2214) - 正式版-2020年5月14日 Linux开发板 华清远见 底板: FS4412_DEV_V5 核心板: FS4412 V2 u-boot 2013.01
点击查看本文参考资料
点击查看相关文件下载
在linux内核中为我们提供了一个I2C字符设备驱动,我们直接在linux内核中配置使用就可以了。
一、linux配置 1. 设备树 exynos4412平台每个i2c通道的信息是通过设备树提供的,因此需要首先在exynos4412-fs4412.dts中增加5通道(MPU6050就挂载在这个通道上)的节点。关于I2C设备树的书写实例,我们可以参考linux内核源码中的这个文档:
1 Documentation/devicetree/bindings/i2c/i2c-s3c2410.txt
然后我们在linux内核源码的设备树中添加以下内容:
1 2 3 4 5 6 7 8 9 i2c@138B 0000{ #address-cells = <1> ; #size-cells = <0> ; samsung,i2c-sda-delay = <100 >; samsung,i2c-max-bus-freq = <20000 >; pinctrl-0 = <&i2c5_bus>; pinctrl-names = "default" ; status = "okay" ; };
2. 内核配置 另外我们还需要在内核中开启I2C字符设备驱动:
1 2 3 Device Drivers ---> -*- I2C support ---> <*> I2C device interface
3. 编译测试 然后我们就可以重新编译内核和设备树文件,我们在linux内核目录下执行:
1 2 make dtbs # 编译设备树 make uImage # 编译内核
编译完成后,我们将内核和设备树文件拷贝到相应的目录中,然后重启开发板,重启之后我们将会在 /dev/目录下看到i2c开头的设备节点:
1 2 [root@farsight ]# ls /dev/i2c* i2c-0 i2c-5
当我们读写i2c设备的时候就是通过这个设备节点进行的。
二、read和write读写I2C 我们可以直接通过read和write函数读写I2C设备,此处以MPU6050为例。
1. 使用步骤
2. mpu6050.c 2.1 read_data_from_mpu6050() 点击查看函数详情
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 static int read_data_from_mpu6050 (int fd, unsigned char reg, unsigned char *pdata) { int ret = 0 ; unsigned char buf[1 ] = {reg}; ret = write(fd, buf, 1 ); if (ret != 1 ) { printf ("write reg failed,in read_data_from_mpu6050!\n" ); return -1 ; } buf[0 ] = 0 ; ret = read(fd, buf, 1 ); if (ret != 1 ) { printf ("read data failed,in read_data_from_mpu6050!\n" ); return -1 ; } *pdata = buf[0 ]; return 0 ; }
2.2 write_data_to_mpu6050() 点击查看函数详情
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 static int write_data_to_mpu6050 (int fd, unsigned char reg, unsigned char data) { unsigned char buf[2 ] = {reg, data}; int ret = 0 ; ret = write(fd, buf, 2 ); if (ret != 2 ) { printf ("write data failed,in write_data_to_mpu6050\n" ); return -1 ; } return 0 ; }
2.3 init_mpu6050() 点击查看函数详情
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 int init_mpu6050 (int fd) { int ret = 0 ; ret = ioctl(fd, I2C_TENBIT, 0 ); if (ret < 0 ) { printf ("ioctl I2C_TENBIT failed,in init_mpu6050\n" ); return -1 ; } ret = ioctl(fd, I2C_SLAVE, 0x68 ); if (ret < 0 ) { printf ("ioctl I2C_TENBIT failed,in init_mpu6050\n" ); return -1 ; } ret = write_data_to_mpu6050(fd, PWR_MGMT_1, 0x00 ); ret += write_data_to_mpu6050(fd, SMPLRT_DIV, 0x07 ); ret += write_data_to_mpu6050(fd, ACCEL_CONFIG, 0x19 ); ret += write_data_to_mpu6050(fd, GYRO_CONFIG, 0xF8 ); if (ret < 0 ) { printf ("write init data to mpu6050 failed,in init_mpu6050\n" ); return -1 ; } return 0 ; }
2.4 read_accelx() 点击查看函数详情
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 int read_accelx (int fd) { unsigned short val = 0 ; unsigned char d = 0 ; int ret = 0 ; ret = read_data_from_mpu6050(fd, ACCEL_XOUT_L, &d); val = d; ret = read_data_from_mpu6050(fd, ACCEL_XOUT_H, &d); val |= d << 8 ; if (ret < 0 ) { printf ("read accel x value failed,in read_accelx\n" ); return -1 ; } else { return val; } }
2.5 read_accely() 点击查看函数详情
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 int read_accely (int fd) { unsigned short val = 0 ; unsigned char d = 0 ; int ret = 0 ; ret = read_data_from_mpu6050(fd, ACCEL_YOUT_L, &d); val = d; ret = read_data_from_mpu6050(fd, ACCEL_YOUT_H, &d); val |= d << 8 ; if (ret < 0 ) { printf ("read accel y value failed,in read_accely\n" ); return -1 ; } else { return val; } }
2.6 read_accelz() 点击查看函数详情
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 int read_accelz (int fd) { unsigned short val = 0 ; unsigned char d = 0 ; int ret = 0 ; ret = read_data_from_mpu6050(fd, ACCEL_ZOUT_L, &d); val = d; ret = read_data_from_mpu6050(fd, ACCEL_ZOUT_H, &d); val |= d << 8 ; if (ret < 0 ) { printf ("read accel z value failed,in read_accelz\n" ); return -1 ; } else { return val; } }
2.7 read_temp() 点击查看函数详情
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 int read_temp (int fd) { unsigned short val = 0 ; unsigned char d = 0 ; int ret = 0 ; ret = read_data_from_mpu6050(fd, TEMP_OUT_L, &d); val = d; ret = read_data_from_mpu6050(fd, TEMP_OUT_H, &d); val |= d << 8 ; if (ret < 0 ) { printf ("read temp value failed,in read_temp\n" ); return -1 ; } else { return val; } }
2.8 read_gyrox() 点击查看函数详情
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 int read_gyrox (int fd) { unsigned short val = 0 ; unsigned char d = 0 ; int ret = 0 ; ret = read_data_from_mpu6050(fd, GYRO_XOUT_L, &d); val = d; ret = read_data_from_mpu6050(fd, GYRO_XOUT_H, &d); val |= d << 8 ; if (ret < 0 ) { printf ("read gyro x value failed,in read_gyrox\n" ); return -1 ; } else { return val; } }
2.9 read_gyroy() 点击查看函数详情
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 int read_gyroy (int fd) { unsigned short val = 0 ; unsigned char d = 0 ; int ret = 0 ; ret = read_data_from_mpu6050(fd, GYRO_YOUT_L, &d); val = d; ret = read_data_from_mpu6050(fd, GYRO_YOUT_H, &d); val |= d << 8 ; if (ret < 0 ) { printf ("read gyro y value failed,in read_gyroy\n" ); return -1 ; } else { return val; } }
2.10 read_gyroz() 点击查看函数详情
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 int read_gyroz (int fd) { unsigned short val = 0 ; unsigned char d = 0 ; int ret = 0 ; ret = read_data_from_mpu6050(fd, GYRO_ZOUT_L, &d); val = d; ret = read_data_from_mpu6050(fd, GYRO_ZOUT_H, &d); val |= d << 8 ; if (ret < 0 ) { printf ("read gyro z value failed,in read_gyroz\n" ); return -1 ; } else { return val; } }
3. mpu6050.h 点击查看详情
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 #ifndef __MPU6050_H__ #define __MPU6050_H__ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <sys/ioctl.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 0x3E #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 I2C_SLAVE 0x0703 #define I2C_TENBIT 0x0704 #define CLS "\033[0m" #define BLACK "\033[1;30m" #define RED "\033[1;31m" #define GREEN "\033[1;32m" #define YELLOW "\033[1;33m" #define BLUE "\033[1;34m" #define PURPLE "\033[1;35m" #define CYAN "\033[1;36m" #define WHITE "\033[1;37m" #define BOLD "\033[1m" int init_mpu6050 (int fd) ; int read_accelx (int fd) ;int read_accely (int fd) ;int read_accelz (int fd) ;int read_temp (int fd) ;int read_gyrox (int fd) ;int read_gyroy (int fd) ;int read_gyroz (int fd) ;#endif
4. mpu6050_app.c 点击查看详情
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <sys/ioctl.h> #include "mpu6050.h" int main (int argc, char *argv[]) { int fd = -1 ; if (argc < 2 ) { printf ("\nusage:\n" ); printf ("%s /dev/dev_name\n" , argv[0 ]); return -1 ; } if ((fd = open(argv[1 ], O_RDWR)) < 0 ) { printf ("open %s failed!\n" , argv[1 ]); return -1 ; } init_mpu6050(fd); while (1 ) { sleep(2 ); printf ("Accel-X:0x%x\n" , read_accelx(fd)); printf ("Accel-Y:0x%x\n" , read_accely(fd)); printf ("Accel-Z:0x%x\n" , read_accelz(fd)); printf ("Temp:0x%x\n" , read_temp(fd)); printf ("GYRO-X:0x%x\n" , read_gyrox(fd)); printf ("GYRO-Y:0x%x\n" , read_gyroy(fd)); printf ("GYRO-z:0x%x\n" , read_gyroz(fd)); printf ("\n" ); } close(fd); fd = -1 ; return 0 ; }
5. 编译测试 编译的时候注意使用交叉编译工具链,测试的时候,我们使用的设备节点是在系统启动的时候就创建好了的,使用的设备节点是:
三、ioctl读写I2C 我们可以通过ioctl一个函数读写I2C设备,此处以MPU6050为例。
1. 相关结构体和宏 只使用ioctl来读写i2c设备的话,我们需要用到3个宏和两个结构体,不过为了方便,这几个会在mpu6050.h中重新实现。
1.1 三个宏 这里需要用到三个宏定义,它们定义在linux内核源码的这个目录下:
1 include/uapi/linux/i2c-dev.h
我们可以看到这三个宏定义如下:
1 2 3 #define I2C_SLAVE 0x0703 #define I2C_TENBIT 0x0704 #define I2C_RDWR 0x0707
后边为了方便使用,将这三个宏定义定义到 mpu6050.h 文件中去。
1.2 struct i2c_rdwr_ioctl_data 这个结构体定义在linux内核源码的这个目录下:
1 include/uapi/linux/i2c-dev.h
我们打开这个文件,会看到结构体定义如下:
1 2 3 4 5 struct i2c_rdwr_ioctl_data { struct i2c_msg __user *msgs ; __u32 nmsgs; };
【成员说明】
msgs : struct i2c_msg类型指针变量,指向要发送给i2c设备的消息的首地址。
nmsgs : __u32 类型,表示有几个消息需要发送。
1.3 struct i2c_msg 这个结构体定义在linux内核中的这个目录下:
1 include/uapi/linux/i2c.h
我们打开这个文件,该结构体定义如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 struct i2c_msg { __u16 addr; __u16 flags; #define I2C_M_TEN 0x0010 #define I2C_M_RD 0x0001 #define I2C_M_STOP 0x8000 #define I2C_M_NOSTART 0x4000 #define I2C_M_REV_DIR_ADDR 0x2000 #define I2C_M_IGNORE_NAK 0x1000 #define I2C_M_NO_RD_ACK 0x0800 #define I2C_M_RECV_LEN 0x0400 __u16 len; __u8 *buf; };
【成员介绍】
addr :从机的地址
flags : 一个标志,它表示从机设备地址位数,值为0的话表示使用7位从设备地址。
buf :我们要发送或者接收数据的内存空间首地址
len :表示buf中有几个数据需要发送或者接收,一般来说向i2c设备写数据的话,这个值一般会是2,一个表示寄存器地址,一个表示要写入的值,从i2c设备读数据的话,一般会是1。
2. 使用步骤
3. mpu6050.c 3.1 read_data_from_mpu6050() 点击查看函数详情
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 static int read_data_from_mpu6050 (int fd, unsigned char slave, unsigned char reg, unsigned char *pdata) { struct i2c_rdwr_ioctl_data work = {NULL }; struct i2c_msg msgs [2] = {{0 }}; unsigned char buf1[1 ] = {reg}; unsigned char buf2[1 ] = {0 }; int ret = 0 ; work.msgs = msgs; work.nmsgs = 2 ; msgs[0 ].addr = slave; msgs[0 ].flags = 0 ; msgs[0 ].buf = buf1; msgs[0 ].len = 1 ; msgs[1 ].addr = slave; msgs[1 ].flags = I2C_M_RD; msgs[1 ].buf = buf2; msgs[1 ].len = 1 ; ret = ioctl(fd, I2C_RDWR, &work); if (ret < 0 ) { printf ("ioctl I2C_RDWR failed,in read_data_from_mpu6050!\n" ); return -1 ; } else { *pdata = buf2[0 ]; return 0 ; } }
3.2 write_data_to_mpu6050() 点击查看函数详情
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 static int write_data_to_mpu6050 (int fd, unsigned char slave, unsigned char reg, unsigned char data) { struct i2c_rdwr_ioctl_data work = {NULL }; struct i2c_msg msg = {0 }; unsigned char buf[2 ] = {reg, data}; int ret = 0 ; work.msgs = &msg; work.nmsgs = 1 ; msg.addr = slave; msg.flags = 0 ; msg.buf = buf; msg.len = 2 ; ret = ioctl(fd, I2C_RDWR, &work); if (ret < 0 ) { printf ("ioctl I2C_RDWR failed,in write_data_to_mpu6050!\n" ); return -1 ; } else { return 0 ; } }
3.3 init_mpu6050() 点击查看函数详情
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 int init_mpu6050 (int fd) { int ret = 0 ; ret = ioctl(fd, I2C_TENBIT, 0 ); if (ret < 0 ) { printf ("ioctl I2C_TENBIT failed,in init_mpu6050\n" ); return -1 ; } ret = ioctl(fd, I2C_SLAVE, SLAVE_ADDRESS); if (ret < 0 ) { printf ("ioctl I2C_TENBIT failed,in init_mpu6050\n" ); return -1 ; } ret = write_data_to_mpu6050(fd, SLAVE_ADDRESS, PWR_MGMT_1, 0x00 ); ret += write_data_to_mpu6050(fd, SLAVE_ADDRESS, SMPLRT_DIV, 0x07 ); ret += write_data_to_mpu6050(fd, SLAVE_ADDRESS, ACCEL_CONFIG, 0x19 ); ret += write_data_to_mpu6050(fd, SLAVE_ADDRESS, GYRO_CONFIG, 0xF8 ); if (ret < 0 ) { printf ("write init data to mpu6050 failed,in init_mpu6050\n" ); return -1 ; } return 0 ; }
3.4 read_accelx() 点击查看函数详情
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 int read_accelx (int fd) { unsigned short val = 0 ; unsigned char d = 0 ; int ret = 0 ; ret = read_data_from_mpu6050(fd, SLAVE_ADDRESS, ACCEL_XOUT_L, &d); val = d; ret = read_data_from_mpu6050(fd, SLAVE_ADDRESS, ACCEL_XOUT_H, &d); val |= d << 8 ; if (ret < 0 ) { printf ("read accel x value failed,in read_accelx\n" ); return -1 ; } else { return val; } }
3.5 read_accely() 点击查看函数详情
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 int read_accely (int fd) { unsigned short val = 0 ; unsigned char d = 0 ; int ret = 0 ; ret = read_data_from_mpu6050(fd, SLAVE_ADDRESS, ACCEL_YOUT_L, &d); val = d; ret = read_data_from_mpu6050(fd, SLAVE_ADDRESS, ACCEL_YOUT_H, &d); val |= d << 8 ; if (ret < 0 ) { printf ("read accel y value failed,in read_accely\n" ); return -1 ; } else { return val; } }
3.6 read_accelz() 点击查看函数详情
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 int read_accelz (int fd) { unsigned short val = 0 ; unsigned char d = 0 ; int ret = 0 ; ret = read_data_from_mpu6050(fd, SLAVE_ADDRESS, ACCEL_ZOUT_L, &d); val = d; ret = read_data_from_mpu6050(fd, SLAVE_ADDRESS, ACCEL_ZOUT_H, &d); val |= d << 8 ; if (ret < 0 ) { printf ("read accel z value failed,in read_accelz\n" ); return -1 ; } else { return val; } }
3.7 read_temp() 点击查看函数详情
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 int read_temp (int fd) { unsigned short val = 0 ; unsigned char d = 0 ; int ret = 0 ; ret = read_data_from_mpu6050(fd, SLAVE_ADDRESS, TEMP_OUT_L, &d); val = d; ret = read_data_from_mpu6050(fd, SLAVE_ADDRESS, TEMP_OUT_H, &d); val |= d << 8 ; if (ret < 0 ) { printf ("read temp value failed,in read_temp\n" ); return -1 ; } else { return val; } }
3.8 read_gyrox() 点击查看函数详情
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 int read_gyrox (int fd) { unsigned short val = 0 ; unsigned char d = 0 ; int ret = 0 ; ret = read_data_from_mpu6050(fd, SLAVE_ADDRESS, GYRO_XOUT_L, &d); val = d; ret = read_data_from_mpu6050(fd, SLAVE_ADDRESS, GYRO_XOUT_H, &d); val |= d << 8 ; if (ret < 0 ) { printf ("read gyro x value failed,in read_gyrox\n" ); return -1 ; } else { return val; } }
3.9 read_gyroy() 点击查看函数详情
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 int read_gyroy (int fd) { unsigned short val = 0 ; unsigned char d = 0 ; int ret = 0 ; ret = read_data_from_mpu6050(fd, SLAVE_ADDRESS, GYRO_YOUT_L, &d); val = d; ret = read_data_from_mpu6050(fd, SLAVE_ADDRESS, GYRO_YOUT_H, &d); val |= d << 8 ; if (ret < 0 ) { printf ("read gyro y value failed,in read_gyroy\n" ); return -1 ; } else { return val; } }
3.10 read_gyroz() 点击查看函数详情
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 int read_gyroz (int fd) { unsigned short val = 0 ; unsigned char d = 0 ; int ret = 0 ; ret = read_data_from_mpu6050(fd, SLAVE_ADDRESS, GYRO_ZOUT_L, &d); val = d; ret = read_data_from_mpu6050(fd, SLAVE_ADDRESS, GYRO_ZOUT_H, &d); val |= d << 8 ; if (ret < 0 ) { printf ("read gyro z value failed,in read_gyroz\n" ); return -1 ; } else { return val; } }
4. mpu6050.h 点击查看详情
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 #ifndef __MPU6050_H__ #define __MPU6050_H__ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <sys/ioctl.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 0x3E #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 SLAVE_ADDRESS 0x68 #define PWR_MGMT_1 0x6B #define I2C_SLAVE 0x0703 #define I2C_TENBIT 0x0704 #define I2C_RDWR 0x0707 struct i2c_msg { unsigned short addr; unsigned short flags; #define I2C_M_TEN 0x0010 #define I2C_M_RD 0x0001 unsigned short len; unsigned char *buf; }; struct i2c_rdwr_ioctl_data { struct i2c_msg *msgs ; unsigned int nmsgs; }; int init_mpu6050 (int fd) ; int read_accelx (int fd) ;int read_accely (int fd) ;int read_accelz (int fd) ;int read_temp (int fd) ;int read_gyrox (int fd) ;int read_gyroy (int fd) ;int read_gyroz (int fd) ;#endif
5. mpu6050_app.c 点击查看详情
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <sys/ioctl.h> #include "mpu6050.h" int main (int argc, char *argv[]) { int fd = -1 ; if (argc < 2 ) { printf ("\nusage:\n" ); printf ("%s /dev/dev_name\n" , argv[0 ]); return -1 ; } if ((fd = open(argv[1 ], O_RDWR)) < 0 ) { printf ("open %s failed!\n" , argv[1 ]); return -1 ; } init_mpu6050(fd); while (1 ) { sleep(2 ); printf ("Accel-X:0x%x\n" , read_accelx(fd)); printf ("Accel-Y:0x%x\n" , read_accely(fd)); printf ("Accel-Z:0x%x\n" , read_accelz(fd)); printf ("Temp:0x%x\n" , read_temp(fd)); printf ("GYRO-X:0x%x\n" , read_gyrox(fd)); printf ("GYRO-Y:0x%x\n" , read_gyroy(fd)); printf ("GYRO-z:0x%x\n" , read_gyroz(fd)); printf ("\n" ); } close(fd); fd = -1 ; return 0 ; }
6. 编译测试 编译的时候注意使用交叉编译工具链,测试的时候,我们使用的设备节点是在系统启动的时候就创建好了的,使用的设备节点是: