linux_module_learn/i2c/mpu6050.c

246 lines
6.9 KiB
C
Raw Permalink Normal View History

2023-07-22 13:42:32 +08:00
#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");