陀螺仪_I2C
mpu6500_i2c_drv.mod.c
1 #include <linux/init.h> 2 #include <linux/module.h> 3 #include <linux/fs.h> 4 #include <linux/device.h> 5 #include <linux/slab.h> 6 #include <linux/gpio.h> 7 #include <linux/i2c.h> 8 #include <linux/mod_devicetable.h> 9 10 #include <asm/io.h> 11 #include <asm/uaccess.h> 12 13 #include <linux/kobject.h> 14 #include <linux/kdev_t.h> 15 #include <linux/list.h> 16 17 #include <linux/cdev.h> 18 #include <linux/interrupt.h> 19 #include <linux/input.h> 20 #include <linux/sched.h> 21 22 #include <asm/string.h> 23 #include <asm-generic/ioctl.h> 24 25 26 #define MPU6500_MAGIC 'K' 27 28 union mpu6500_data 29 { 30 struct { 31 short x; 32 short y; 33 short z; 34 }accel; 35 struct { 36 short x; 37 short y; 38 short z; 39 }gyro; 40 unsigned short temp; 41 }; 42 43 44 45 #define GET_ACCEL _IOR(MPU6500_MAGIC, 0, union mpu6500_data) 46 #define GET_GYRO _IOR(MPU6500_MAGIC, 1, union mpu6500_data) 47 #define GET_TEMP _IOR(MPU6500_MAGIC, 2, union mpu6500_data) 48 49 50 51 #define SMPLRT_DIV 0x19 //陀螺仪采样率,典型值:0x07(125Hz) 52 #define CONFIG 0x1A //低通滤波频率,典型值:0x06(5Hz) 53 #define GYRO_CONFIG 0x1B //陀螺仪自检及测量范围,典型值:0x18(不自检,2000deg/s) 54 #define ACCEL_CONFIG 0x1C //加速计自检、测量范围及高通滤波,典型值:0x18(不自检,2G,5Hz) 55 56 57 58 // 注册59到64 -加速度计测量值 59 #define ACCEL_XOUT_H 0x3B //加速度计x轴数据的高字节 60 #define ACCEL_XOUT_L 0x3C //加速度计x轴数据的低字节 61 #define ACCEL_YOUT_H 0x3D //加速度计y轴数据的高字节 62 #define ACCEL_YOUT_L 0x3E //加速度计y轴数据的低字节 63 #define ACCEL_ZOUT_H 0x3F //加速度计z轴数据的高字节 64 #define ACCEL_ZOUT_L 0x40 //加速度计z轴数据的低字节 65 66 67 // 寄存器65和66 -温度测量 68 #define TEMP_OUT_H 0x41 //温度传感器输出的高字节 69 #define TEMP_OUT_L 0x42 //温度传感器输出的低字节 70 71 72 // 注册67至72 -陀螺仪测量 73 #define GYRO_XOUT_H 0x43 //高字节的x轴陀螺仪输出 74 #define GYRO_XOUT_L 0x44 //低字节的x轴陀螺仪输出 75 #define GYRO_YOUT_H 0x45 //高字节的y轴陀螺仪输出 76 #define GYRO_YOUT_L 0x46 //低字节的y轴陀螺仪输出 77 #define GYRO_ZOUT_H 0x47 //高字节的z轴陀螺仪输出 78 #define GYRO_ZOUT_L 0x48 //低字节的z轴陀螺仪输出 79 80 81 #define PWR_MGMT_1 0x6B //电源管理,典型值:0x00(正常启用) 82 #define WHO_AM_I 0x75 //IIC地址寄存器(默认数值0x68,只读) 83 #define SlaveAddress 0x68 //MPU6050-I2C地址寄存器 84 85 86 87 88 #define W_FLG 0 89 #define R_FLG 1 90 91 92 #define DEV_CNT 1 93 #define DEV_MI 0 94 #define DEV_MAME "mpu6500" 95 96 97 struct class *cls; 98 dev_t dev_no ; 99 100 static struct i2c_client *i2c_test_client = NULL; 101 102 struct mpu6500_pri { 103 struct cdev dev; 104 struct i2c_client *client; 105 }; 106 107 struct mpu6500_pri dev; 108 109 110 111 static void mpu6500_write_byte(struct i2c_client *client,const unsigned char reg,const unsigned char val) 112 { 113 char txbuf[2] = {reg,val}; 114 struct i2c_msg msg[2] = { 115 [0] = { 116 .addr = client->addr, 117 .flags= W_FLG, 118 .len = sizeof(txbuf), 119 .buf = txbuf, 120 }, 121 }; 122 i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg)); 123 } 124 125 126 static char mpu6500_read_byte(struct i2c_client *client,const unsigned char reg) 127 { 128 char txbuf[1] = {reg}; 129 char rxbuf[1] = {0}; 130 struct i2c_msg msg[2] = { 131 [0] = { 132 .addr = client->addr, 133 .flags = W_FLG, 134 .len = sizeof(txbuf), 135 .buf = txbuf, 136 }, 137 [1] = { 138 .addr = client->addr, 139 .flags = R_FLG, 140 .len = sizeof(rxbuf), 141 .buf = rxbuf, 142 }, 143 }; 144 145 i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg)); 146 return rxbuf[0]; 147 } 148 149 150 static int dev_open(struct inode *ip, struct file *fp) 151 { 152 printk("kernel open success ! "); 153 154 return 0; 155 } 156 157 158 159 static long dev_ioctl(struct file *fp, unsigned int cmd, unsigned long arg) 160 { 161 162 printk("kernel ioctl success ! "); 163 164 int res = 0; 165 union mpu6500_data data = {{0}}; 166 switch(cmd){ 167 case GET_ACCEL: 168 data.accel.x = mpu6500_read_byte(dev.client,ACCEL_XOUT_L); 169 data.accel.x|= mpu6500_read_byte(dev.client,ACCEL_XOUT_H)<<8; 170 data.accel.y = mpu6500_read_byte(dev.client,ACCEL_YOUT_L); 171 data.accel.y|= mpu6500_read_byte(dev.client,ACCEL_YOUT_H)<<8; 172 data.accel.z = mpu6500_read_byte(dev.client,ACCEL_ZOUT_L); 173 data.accel.z|= mpu6500_read_byte(dev.client,ACCEL_ZOUT_H)<<8; 174 break; 175 case GET_GYRO: 176 data.gyro.x = mpu6500_read_byte(dev.client,GYRO_XOUT_L); 177 data.gyro.x|= mpu6500_read_byte(dev.client,GYRO_XOUT_H)<<8; 178 data.gyro.y = mpu6500_read_byte(dev.client,GYRO_YOUT_L); 179 data.gyro.y|= mpu6500_read_byte(dev.client,GYRO_YOUT_H)<<8; 180 data.gyro.z = mpu6500_read_byte(dev.client,GYRO_ZOUT_L); 181 data.gyro.z|= mpu6500_read_byte(dev.client,GYRO_ZOUT_H)<<8; 182 printk("gyro:x %d, y:%d, z:%d ",data.gyro.x,data.gyro.y,data.gyro.z); 183 break; 184 case GET_TEMP: 185 data.temp = mpu6500_read_byte(dev.client,TEMP_OUT_L); 186 data.temp|= mpu6500_read_byte(dev.client,TEMP_OUT_H)<<8; 187 printk("temp: %d ",data.temp); 188 break; 189 default: 190 printk(KERN_INFO "invalid cmd"); 191 break; 192 } 193 printk("acc:x %d, y:%d, z:%d ",data.accel.x,data.accel.y,data.accel.z); 194 res = copy_to_user((void *)arg,&data,sizeof(data)); 195 return sizeof(data); 196 } 197 198 199 200 static int dev_release(struct inode *ip, struct file *fp) 201 { 202 203 printk("kernel close success ! "); 204 205 return 0; 206 } 207 208 209 210 struct file_operations fops = { 211 .open = dev_open, 212 .release = dev_release, 213 .unlocked_ioctl = dev_ioctl, 214 }; 215 216 217 218 219 static void mpu6500_init(struct i2c_client *client) 220 { 221 222 printk("kernel mpu6500_init success ! "); 223 224 mpu6500_write_byte(client, PWR_MGMT_1, 0x00); //电源管理,解除休眠 225 mpu6500_write_byte(client, SMPLRT_DIV, 0x07); //设置陀螺仪采样率 226 mpu6500_write_byte(client, CONFIG, 0x06); //设置低通滤波频率 227 mpu6500_write_byte(client, GYRO_CONFIG, 0x18); //设置陀螺仪自检 228 mpu6500_write_byte(client, ACCEL_CONFIG, 0x0); //设置加速计自检 229 230 } 231 232 233 234 235 static int mpu6500_probe(struct i2c_client * client, const struct i2c_device_id * id) 236 { 237 238 printk("kernel mpu6500_probe success ! "); 239 240 dev.client = client; // 保存当前的client信息 241 242 printk(KERN_INFO "mpu6500 match ok "); 243 244 cdev_init(&dev.dev,&fops); 245 246 alloc_chrdev_region(&dev_no,DEV_MI,DEV_CNT,DEV_MAME); 247 248 cdev_add(&dev.dev,dev_no,DEV_CNT); 249 250 mpu6500_init(client); 251 252 /*自动创建设备文件*/ 253 cls = class_create(THIS_MODULE,DEV_MAME); 254 device_create(cls,NULL,dev_no,NULL,"%s%d",DEV_MAME,DEV_MI); 255 256 257 return 0; 258 } 259 260 261 262 static int mpu6500_remove(struct i2c_client * client) 263 { 264 265 printk("kernel mpu6500_remove success ! "); 266 267 device_destroy(cls,dev_no); 268 class_destroy(cls); 269 unregister_chrdev_region(dev_no,DEV_CNT); 270 return 0; 271 } 272 273 274 275 struct i2c_device_id mpu6500_dev_match[] = { 276 {"mpu6500", 0x1111}, 277 {}, 278 }; 279 280 281 struct i2c_driver mpu6500_drv = { 282 .probe = mpu6500_probe, 283 .remove = mpu6500_remove, 284 .driver = { 285 .owner = THIS_MODULE, 286 .name = "mpu6500", 287 }, 288 .id_table = mpu6500_dev_match, 289 }; 290 291 292 static struct i2c_board_info i2c_test_info = { 293 I2C_BOARD_INFO("mpu6500", 0x68), 294 }; 295 296 297 static int __init mpu6500_drv_init(void) 298 { 299 300 printk("kernel mpu6500_drv_init success ! "); 301 302 303 //实例化 i2c_client 304 static struct i2c_adapter * i2c_adap = NULL; 305 i2c_adap = i2c_get_adapter(1); 306 i2c_test_client = i2c_new_device(i2c_adap, &i2c_test_info); 307 i2c_put_adapter(i2c_adap); 308 309 310 //注册一个i2c_driver 311 return i2c_add_driver(&mpu6500_drv); 312 } 313 314 315 static void __exit mpu6500_drv_exit(void) 316 { 317 318 printk("kernel mpu6500_drv_exit success ! "); 319 320 i2c_del_driver(&mpu6500_drv); 321 } 322 323 324 325 // 声明认证 326 module_init(mpu6500_drv_init); 327 module_exit(mpu6500_drv_exit); 328 MODULE_LICENSE("GPL");
mpu6500_i2c_app.cpp (交叉编译)
1 #include <stdio.h> 2 #include <string.h> 3 #include <stdlib.h> 4 #include <unistd.h> 5 #include <sys/types.h> 6 #include <sys/stat.h> 7 #include <sys/ioctl.h> 8 #include <fcntl.h> 9 10 11 #define MPU6500_MAGIC 'K' 12 13 #define GET_ACCEL _IOR(MPU6500_MAGIC, 0, union mpu6500_data) 14 #define GET_GYRO _IOR(MPU6500_MAGIC, 1, union mpu6500_data) 15 #define GET_TEMP _IOR(MPU6500_MAGIC, 2, union mpu6500_data) 16 17 18 19 union mpu6500_data 20 { 21 struct { 22 short x; 23 short y; 24 short z; 25 }accel; 26 struct { 27 short x; 28 short y; 29 short z; 30 }gyro; 31 unsigned short temp; 32 }; 33 34 35 int main(void) 36 { 37 int fd = open("/dev/mpu65000",O_RDWR); 38 if(-1== fd){ 39 perror("open"); 40 return -1; 41 } 42 43 union mpu6500_data data = {{0}}; 44 45 while(1){ 46 ioctl(fd,GET_ACCEL,&data); 47 printf("acc:x %d, y:%d, z:%d ",data.accel.x,data.accel.y,data.accel.z); 48 ioctl(fd,GET_GYRO,&data); 49 printf("gyro:x %d, y:%d, z:%d ",data.gyro.x,data.gyro.y,data.gyro.z); 50 ioctl(fd,GET_TEMP,&data); 51 printf("temp: %d ",data.temp); 52 sleep(1); 53 } 54 return 0; 55 }
Android.mk
1 # Copyright 2012 The Android Open Source Project 2 3 LOCAL_PATH:= $(call my-dir) 4 include $(CLEAR_VARS) 5 6 LOCAL_SRC_FILES:= mpu6500_app.cpp 7 8 LOCAL_C_INCLUDES += external/zlib 9 10 LOCAL_MODULE:= mpu6500_app 11 12 LOCAL_MODULE_TAGS:= optional 13 14 LOCAL_SHARED_LIBRARIES := 15 libbinder 16 libcutils 17 libutils 18 libz 19 20 include $(BUILD_EXECUTABLE)
测试:
success !