修改书《嵌入式Linux系统设计及应用-基于国产龙芯SOCV2.3.0》中IIC的例子,获取MPU6050的数据。
1.连线方式,MPU6050的AD0连接GND,SDA连接P00,SCL连接P01。
2.注册新设备。使用i2c_new _device方法。文件保存为mpu6050_dev.c
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/i2c.h>
#include <linux/err.h>
#include <loongson1.h>
#include <linux/slab.h>
static struct i2c_board_info mpu6050_info = {
I2C_BOARD_INFO("mpu6050",0x68),
};static struct i2c_client *mpu6050_client;
static int mpu6050_dev_init(void)
{
struct i2c_adapter *i2c_adap;
//打开第2复用gpio00,01,必须做
__raw_writel(readl(LS1X_CBUS_SECOND0) | 1 ,LS1X_CBUS_SECOND0);
__raw_writel(readl(LS1X_CBUS_SECOND0) |( 1 << 1 ) ,LS1X_CBUS_SECOND0);
//使用i2c-0设备
i2c_adap = i2c_get_adapter(0);
mpu6050_client = i2c_new_device(i2c_adap, &mpu6050_info);
i2c_put_adapter(i2c_adap);
return 0;
}static void mpu6050_dev_exit(void)
{
i2c_unregister_device(mpu6050_client);
}
module_init(mpu6050_dev_init);
module_exit(mpu6050_dev_exit);
MODULE_LICENSE("GPL");
i2c-*设备通过iic工具查询。
3.注册新驱动。文件保存为mpu6050_drv.c
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/i2c.h>
#include <linux/err.h>
//#include <linux/regmap.h>
#include <linux/slab.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
static int major;
static struct class *class;
static struct i2c_client *mpu6050_client;/* 传入: buf[0] : addr
* 输出: buf[0] : data
*/
static ssize_t mpu6050_read(struct file * file, char __user *buf, size_t count, loff_t *off)
{
unsigned char addr, data;
copy_from_user(&addr, buf, 1);
data = i2c_smbus_read_byte_data(mpu6050_client, addr);
copy_to_user(buf, &data, 1);
return 1;
}/* buf[0] : addr
* buf[1] : data
*/
static ssize_t mpu6050_write(struct file *file, const char __user *buf, size_t count, loff_t *off)
{
unsigned char ker_buf[2];
unsigned char addr, data;copy_from_user(ker_buf, buf, 2);
addr = ker_buf[0];
data = ker_buf[1];printk("addr = 0x%02x, data = 0x%02x\n", addr, data);
if (!i2c_smbus_write_byte_data(mpu6050_client, addr, data))
return 2;
else
return -EIO;
}static struct file_operations mpu6050_fops = {
.owner = THIS_MODULE,
.read = mpu6050_read,
.write = mpu6050_write,
};static int __devinit mpu6050_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
mpu6050_client = client;
//printk("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
major = register_chrdev(0, "mpu6050", &mpu6050_fops);
class = class_create(THIS_MODULE, "mpu6050");
device_create(class, NULL, MKDEV(major, 0), NULL, "mpu6050"); /* /dev/at24cxx */
return 0;
}static int __devexit mpu6050_remove(struct i2c_client *client)
{
//printk("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
device_destroy(class, MKDEV(major, 0));
class_destroy(class);
unregister_chrdev(major, "mpu6050");
return 0;
}static const struct i2c_device_id mpu6050_id_table[] = {
{ "mpu6050", 0 },
{}
};
/* 1. 分配/设置i2c_driver */
static struct i2c_driver mpu6050_driver = {
.driver = {
.name = "mpu6050",
.owner = THIS_MODULE,
},
.probe = mpu6050_probe,
.remove = __devexit_p(mpu6050_remove),
.id_table = mpu6050_id_table,
};static int mpu6050_drv_init(void)
{
/* 2. 注册i2c_driver */
i2c_add_driver(&mpu6050_driver);
return 0;
}static void mpu6050_drv_exit(void)
{
i2c_del_driver(&mpu6050_driver);
}
module_init(mpu6050_drv_init);
module_exit(mpu6050_drv_exit);
MODULE_LICENSE("GPL");
3.makefile文件。分别编译mpu6050_dev.c和mpu6050_drv.c,得到.ko文件。
KERN_DIR = /home/podu/Desktop/linux-3.0.101pwm/linux-3.0.101
all:
make -C $(KERN_DIR) M=`pwd` modules ARCH=mips CROSS_COMPILE=mipsel-linux-clean:
make -C $(KERN_DIR) M=`pwd` modules clean
rm -rf modules.order#obj-m += mpu6050_dev.o
obj-m += mpu6050_drv.o
4.获取mpu6050数据。文件保存为mpu6050.c,编译得到mpu6050。
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>#define MPU_SAMPLE_RATE_REG 0X19 //采样频率分频器
#define MPU_CFG_REG 0X1A //配置寄存器
#define MPU_GYRO_CFG_REG 0X1B //陀螺仪配置寄存器
#define MPU_ACCEL_CFG_REG 0X1C //加速度计配置寄存器
#define MPU_MOTION_DET_REG 0X1F //运动检测阀值设置寄存器
#define MPU_FIFO_EN_REG 0X23 //FIFO使能寄存器#define MPU_INTBP_CFG_REG 0X37 //中断/旁路设置寄存器
#define MPU_INT_EN_REG 0X38 //中断使能寄存器
#define MPU_INT_STA_REG 0X3A //中断状态寄存器#define MPU_ACCEL_XOUTH_REG 0X3B //加速度值,X轴高8位寄存器
#define MPU_ACCEL_XOUTL_REG 0X3C //加速度值,X轴低8位寄存器
#define MPU_ACCEL_YOUTH_REG 0X3D //加速度值,Y轴高8位寄存器
#define MPU_ACCEL_YOUTL_REG 0X3E //加速度值,Y轴低8位寄存器
#define MPU_ACCEL_ZOUTH_REG 0X3F //加速度值,Z轴高8位寄存器
#define MPU_ACCEL_ZOUTL_REG 0X40 //加速度值,Z轴低8位寄存器#define MPU_GYRO_XOUTH_REG 0X43 //陀螺仪值,X轴高8位寄存器
#define MPU_GYRO_XOUTL_REG 0X44 //陀螺仪值,X轴低8位寄存器
#define MPU_GYRO_YOUTH_REG 0X45 //陀螺仪值,Y轴高8位寄存器
#define MPU_GYRO_YOUTL_REG 0X46 //陀螺仪值,Y轴低8位寄存器
#define MPU_GYRO_ZOUTH_REG 0X47 //陀螺仪值,Z轴高8位寄存器
#define MPU_GYRO_ZOUTL_REG 0X48 //陀螺仪值,Z轴低8位寄存器#define MPU_SIGPATH_RST_REG 0X68 //信号通道复位寄存器
#define MPU_MDETECT_CTRL_REG 0X69 //运动检测控制寄存器
#define MPU_USER_CTRL_REG 0X6A //用户控制寄存器
#define MPU_PWR_MGMT1_REG 0X6B //电源管理寄存器1
#define MPU_PWR_MGMT2_REG 0X6C //电源管理寄存器2
#define MPU_FIFO_CNTH_REG 0X72 //FIFO计数寄存器高八位
#define MPU_FIFO_CNTL_REG 0X73 //FIFO计数寄存器低八位
#define MPU_FIFO_RW_REG 0X74 //FIFO读写寄存器
#define MPU_DEVICE_ID_REG 0X75 //器件ID寄存器
//如果AD0脚(9脚)接地,IIC地址为0X68(不包含最低位).
//如果接V3.3,则IIC地址为0X69(不包含最低位).
#define MPU_ADDR 0X68
void transfer(char *val,char *val2){*val = (*val << 8) | (*val2);
}
int main(int argc, char **argv)
{
int rx,ry,rz,ax,ay,az,rxl,ryl,rzl,axl,ayl,azl;
int fd,res1,res2;
int a,b,c;
char x1,x2;
char buf[2],buf2[1],buf3[6];
fd = open("/dev/mpu6050", O_RDWR);
if (fd < 0)
{
printf("can't open /dev/mpu6050\n");
return -1;
}
buf[0]=MPU_PWR_MGMT1_REG;
buf[1]=0x80;
write(fd,buf,2);
sleep(1);buf[0]=MPU_PWR_MGMT1_REG;
buf[1]=0x40;
write(fd,buf,2);
sleep(1);buf[0]=MPU_PWR_MGMT1_REG;
buf[1]=0x00;
write(fd,buf,2);buf[0]=MPU_SAMPLE_RATE_REG;
buf[1]=0x7;
write(fd,buf,2);buf[0]=MPU_CFG_REG;
buf[1]=0x6;
write(fd,buf,2);buf[0]=MPU_GYRO_CFG_REG;
buf[1]=(0X03<<3);
write(fd,buf,2);buf[0]=MPU_ACCEL_CFG_REG;
buf[1]=(0X00<<3);
write(fd,buf,2);buf[0]=MPU_PWR_MGMT1_REG;
buf[1]=0X01;
write(fd,buf,2);
buf[0]=MPU_PWR_MGMT2_REG;
buf[1]=0X00;
write(fd,buf,2);while(1){
buf[0]=MPU_ACCEL_XOUTH_REG;
read(fd,buf,2);
x1=buf[0];
rx=((int)buf[0]<<8) | (int)buf[1];
//transfer(&rx);
printf("rx=%.2f rxh=%d rxl=%d ",rx/16384.0,buf[0],buf[1]);buf[0]=MPU_ACCEL_ZOUTL_REG;
read(fd,buf,1);
x2=buf[0];
printf("xx=%d xx2=%.2f xx3=%d\n",((int)x1<<8) | (int)x2,(((int)x1<<8) | (int)x2)/16364.0,x2);buf[0]=MPU_ACCEL_YOUTH_REG;
read(fd,buf,2);
ry=((int)buf[0]<<8) | (int)buf[1];
printf("ry=%.2f ",ry/16384.0);buf[0]=MPU_ACCEL_ZOUTH_REG;
read(fd,buf,2);
rz=((int)buf[0]<<8) | (int)buf[1];
printf("rz=%.2f\n",rz/16384.0);buf[0]=MPU_GYRO_XOUTH_REG;
read(fd,buf,2);
ax=((int)buf[0]<<8)|buf[1];
//transfer(&rx);
printf("ax=%.2f ",ax/16384.0);buf[0]=MPU_GYRO_YOUTH_REG;
read(fd,buf,2);
ay=((int)buf[0]<<8)|buf[1];
printf("ay=%.2f ",ay/16384.0);buf[0]=MPU_GYRO_ZOUTH_REG;
read(fd,buf,2);
az=((int)buf[0]<<8)|buf[1];
printf("az=%.2f\n",az/16384.0);}
return 0;
}
6.把mpu6050_dev.ko,mpu6050_drv.ko,mpu6050传输到智龙v3开发板上,先加载.ko文件,后运行程序mpu6050。大功告成。
源码:https://download.csdn.net/download/qq_25537607/12341357