linux_module_learn/i2c/mpu6050.c

246 lines
6.9 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/cdev.h>
#include <linux/fs.h>
#include <linux/wait.h>
#include <linux/errno.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
#include <linux/device.h>
#include <linux/io.h>
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/of_address.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 WHO_AM_I 0x75
#define SlaveAddress 0xD0
#define Address 0x68 //MPU6050地址
#define I2C_RETRIES 0x0701
#define I2C_TIMEOUT 0x0702
#define I2C_SLAVE 0x0703 //IIC从器件的地址设置
#define I2C_BUS_MODE 0x0780
static struct mpu6050_dev{
struct cdev c_dev;
dev_t devno;
struct class *class;
struct device *device;
struct i2c_client *client;
};
static int i2c_write_mpu6050(struct i2c_client *mpu6050_client, u8 address, u8 data)
{
int error = 0;
u8 write_data[2];
struct i2c_msg send_msg; //要发送的数据结构体
/*设置要发送的数据*/
write_data[0] = address;
write_data[1] = data;
/*发送 iic要写入的地址 reg*/
send_msg.addr = mpu6050_client->addr; //mpu6050在 iic 总线上的地址
send_msg.flags = 0; //标记为发送数据
send_msg.buf = write_data; //写入的首地址
send_msg.len = 2; //reg长度
/*执行发送*/
error = i2c_transfer(mpu6050_client->adapter, &send_msg, 1);
if (error != 1)
{
pr_err("\n i2c_transfer error \n");
return -1;
}
return 0;
}
static int i2c_read_mpu6050(struct i2c_client *mpu6050_client, u8 address, void *data, u32 length)
{
return 0;
}
static int mpu6050_init(struct i2c_client *mpu6050_client)
{
int error = 0;
/*配置mpu6050*/
error += i2c_write_mpu6050(mpu6050_client, PWR_MGMT_1, 0X00);
error += i2c_write_mpu6050(mpu6050_client, SMPLRT_DIV, 0X07);
error += i2c_write_mpu6050(mpu6050_client, CONFIG, 0X06);
error += i2c_write_mpu6050(mpu6050_client, ACCEL_CONFIG, 0X01);
if (error < 0)
{
/*初始化错误*/
pr_err("\n mpu6050_init error \n");
return -1;
}
return 0;
}
/*字符设备操作函数集open函数实现*/
static int mpu6050_open(struct inode *inode, struct file *filp)
{
struct mpu6050_dev *mpu = NULL;
mpu = container_of(inode->i_cdev, struct mpu6050_dev, c_dev);
filp->private_data = mpu;
return mpu6050_init(mpu);
}
/*字符设备操作函数集,.read函数实现*/
static ssize_t mpu6050_read(struct file *filp, char __user *buf, size_t cnt, loff_t *off)
{
return 0;
}
/*字符设备操作函数集,.release函数实现*/
static int mpu6050_release(struct inode *inode, struct file *filp)
{
return 0;
}
/*字符设备操作函数集*/
static struct file_operations mpu6050_chr_dev_fops =
{
.owner = THIS_MODULE,
.open = mpu6050_open,
.read = mpu6050_read,
.release = mpu6050_release,
};
static struct mpu6050_dev mpu6050dev;
/*i2c总线设备函数集*/
static int mpu6050_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
int ret = 0;
ret = alloc_chrdev_region(&(mpu6050dev.devno),0,1,"mpu6050");
if(ret < 0){
pr_err("chrdev alloc region failed\n");
return ret;
}
pr_info("devno is %u(major:%u,minor:%u)\n",mpu6050dev.devno,MAJOR(mpu6050dev.devno), MINOR(mpu6050dev.devno));
cdev_init(&mpu6050dev.c_dev, &mpu6050_chr_dev_fops);
mpu6050dev.c_dev.owner = THIS_MODULE;
ret = cdev_add(&mpu6050dev.c_dev, mpu6050dev.devno, 1);
if(ret < 0){
pr_err("chrdev add failed\n");
goto cdev_add_err;
}
ret = class_create(THIS_MODULE, "mpu_class");
if(IS_ERR(ret))
{
pr_err("create class faild!/n");
goto class_create_err;
}
mpu6050dev.class = ret;
ret = device_create(mpu6050dev.class,NULL,devno,NULL,"mpu6050");
if(IS_ERR(ret))
{
pr_err("device_create failed\n");
goto device_create_err;
}
mpu6050dev.device = ret;
mpu6050dev.client = client;
return 0;
device_create_err:
class_destroy(mpu6050dev.class);
class_create_err:
cdev_del(&mpu6050dev.c_dev);
cdev_add_err:
unregister_chrdev_region(mpu6050dev.devno, 1);
return ret;
}
static int mpu6050_remove(struct i2c_client *client)
{
device_destroy(mpu6050dev.class, mpu6050dev.device);
class_destroy(mpu6050dev.class);
cdev_del(&mpu6050dev.c_dev);
unregister_chrdev_region(mpu6050dev.devno, 1);
return 0;
}
/*定义ID 匹配表*/
static const struct i2c_device_id gtp_device_id[] = {
{"fire,i2c_mpu6050", 0},
{}};
/*定义设备树匹配表*/
static const struct of_device_id mpu6050_of_match_table[] = {
{.compatible = "fire,i2c_mpu6050"},
{/* sentinel */}};
/*定义i2c总线设备结构体*/
struct i2c_driver mpu6050_driver = {
.probe = mpu6050_probe,
.remove = mpu6050_remove,
.id_table = gtp_device_id,
.driver = {
.name = "fire,i2c_mpu6050",
.owner = THIS_MODULE,
.of_match_table = mpu6050_of_match_table,
},
};
/*
* 驱动初始化函数
*/
static int __init mpu6050_driver_init(void)
{
int ret;
pr_info("mpu6050_driver_init\n");
ret = i2c_add_driver(&mpu6050_driver);
return 0;
}
/*
* 驱动注销函数
*/
static void __exit mpu6050_driver_exit(void)
{
pr_info("mpu6050_driver_exit\n");
i2c_del_driver(&mpu6050_driver);
}
module_init(mpu6050_driver_init);
module_exit(mpu6050_driver_exit);
MODULE_LICENSE("GPL");