首页 > linux驱动之i2c子系统mpu6050设备驱动

linux驱动之i2c子系统mpu6050设备驱动

以下是mpu6050简单的驱动实现,mpu6050是I2C接口的6轴传感器,可以作为字符设备注册到内核,本代码运行环境是3.4.2内核,4.3.2版本的编译链,12.04版本的Ubuntu,硬件环境是jz2440开发板;

 

按照之前分析的I2C驱动框架,mpu6050驱动主要是实现外设端的驱动,主要是注册外设到I2C总线,而外设端注册到I2C总线包括device及driver两个部分注册到I2C总线,采用分离的设计思想,详情见代码:

 

device注册到I2C总线:

 

#include 
#include 
#include 
#include 
#include 
#include 
#include static const unsigned short addr_list[] = { 0x50,0x68, I2C_CLIENT_END };
static struct i2c_board_info mpu6050_info = {.type = "mpu6050",
};
static struct i2c_client *mpu6050_client;static int mpu6050dev_init ( void )
{struct i2c_adapter *i2c_adap;i2c_adap = i2c_get_adapter ( 0 );mpu6050_client = i2c_new_probed_device ( i2c_adap, &mpu6050_info, addr_list, NULL );i2c_put_adapter ( i2c_adap );if ( mpu6050_client )return 0;elsereturn -ENODEV;
}
static void mpu6050dev_exit ( void )
{i2c_unregister_device ( mpu6050_client );}module_init ( mpu6050dev_init );
module_exit ( mpu6050dev_exit );
MODULE_LICENSE ( "GPL" );

 

注:为实现动态加载驱动模块,使用了 i2c_new_probed_device  函数,该函数的关键作用是在把设备注册到总线之前,会判断该设备的地址是否真实有效,或者也可以说是该设备是否真实存在;另外也可以使用i2c_new_device函数来加载一个设备到总线,但是该函数类似I2C总线总force属性,会强制认为加载的设备地址真实有效,或者是强制认为当前的设备真实存在,  另外在把mpu6050关联到I2C适配器上时,调用了 i2c_get_adapter ( 0 ) 函数,由于S3C2440只有一个I2C适配器,所以该函数的参数直接写0,即第一个适配器;

接下来是设备驱动加载到I2C总线:

 

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include static ssize_t mpu6050_write ( struct file *file, const char __user *buf, size_t, loff_t *offset );
static ssize_t mpu6050_read ( struct file *file, char __user *buf, size_t size, loff_t *offset );
static int mpu6050drv_probe ( struct i2c_client *i2c_client, const struct i2c_device_id *i2c_device_id );
static int mpu6050drv_remove ( struct i2c_client *i2c_client );static struct i2c_device_id mpu6050drv_id =
{.name = "mpu6050",.driver_data = 0x68,};static struct i2c_driver mpu6050drv =
{.driver    = {.name    = "mympu6050",.owner    = THIS_MODULE,},.probe = mpu6050drv_probe,.remove = mpu6050drv_remove,.id_table = &mpu6050drv_id,};/* 字符设备相关 */
int major = 0;
static struct cdev mpu6050_cdev;
static struct file_operations mpu6050ops =
{.owner = THIS_MODULE,.read = mpu6050_read,.write = mpu6050_write,
};static struct class *cls;
static ssize_t mpu6050_read ( struct file *file, char __user *buf, size_t size, loff_t *offset )
{return 0;
}static ssize_t mpu6050_write ( struct file *file, const char __user *buf, size_t size, loff_t *offset )
{return 0;
}
static int mpu6050drv_probe ( struct i2c_client *i2c_client, const struct i2c_device_id *i2c_device_id )
{dev_t dev = 0;printk ( "mpu6050drv_probe
" );
#if 0/* 把mpu6050当做字符设备注册到内核 */major = register_chrdev ( 0, "mpu6050", &mpu6050ops );
#elsealloc_chrdev_region ( &dev, 0, 2, "mpu6050_region" );        // 占用2个次设备号cdev_init ( &mpu6050_cdev, &mpu6050ops );mpu6050_cdev.owner = THIS_MODULE;cdev_add ( &mpu6050_cdev, dev, 2 );                            // 占用2个次设备号#endifcls = class_create ( THIS_MODULE, "mpu6050cls" );major = MAJOR ( dev );device_create ( cls, NULL, MKDEV ( major, 0 ), NULL, "mpu6050" );
//    device_create ( cls, NULL, MKDEV ( major, 1 ), NULL, "mpu6050_2" );return 0;
}
static int mpu6050drv_remove ( struct i2c_client *i2c_client )
{printk ( "mpu6050drv_remove
" );unregister_chrdev_region ( 0, 1 );cdev_del ( &mpu6050_cdev );device_destroy ( cls, MKDEV ( major, 0 ) );
//    device_destroy ( cls, MKDEV ( major, 1 ) );
    class_destroy ( cls );return 0;
}
static int mpu6050_init ( void )
{i2c_add_driver ( &mpu6050drv );return 0;
}static void mpu6050_exit ( void )
{i2c_del_driver ( &mpu6050drv );}module_init ( mpu6050_init );
module_exit ( mpu6050_exit );
MODULE_LICENSE ( "GPL" );

 

当设备加载到I2C总线,外设驱动也加载到总线后,I2Ccore会调用match函数,匹配 mpu6050drv 结构体总 id_table  成员里的name是否和加载的外设名一致,如果一致就会进行绑定,然后调用外设驱动的probe函数,这样I2C驱动就基本上完成了,接下来就是根据外设的具体情况去处理了,比如如果外设是mpu6050、则当做字符设备注册到内核,然后编写读写函数,这些就已经不是I2C驱动框架之内的工作了,而是字符设备驱动的范畴了;

本驱动没有具体去实现mpu6050的读写过程,具体的代码完全可以借用裸机版的代码,本实例仅供I2C驱动框架参考。

转载于:https://www.cnblogs.com/weishengzhong/p/7468397.html

更多相关:

  • jdt可以做语法树分析,并且支持visitor模式对代码进行分析。跟pmd的分析方式一样,我们只要实现 visitor接口即可实现一个插件。 @Service("requestMappingInfoService")public class RequestMappingInfoServiceImpl implements Reques...

  • 1.静态方法 static:通常在一个类中定义一个方法为static,那就是说,无需本类的对象即可调用此方法 声明为static的方法有以下几条限制: (1)它们仅能调用其他的static方法。  (2)它们只能访问static数据。 (3)它们不能以任何方式引用this 或super。 class Simple {static v...

  • 类的静态构造函数也叫类型构造器,静态构造器,他调用的时刻由CLR来控制:CLR会选择如下时间之一来调用静态构造函数:      1,在类型的第一个实例创建之前,或类型的非继承字段或成员第一次访问之前。这里的“之前”,代表前后衔接的意思。这里的时刻是精确的!      2,在非继承的静态字段或成员第一次访问之前的某个时刻,具体时刻不定!...

  • 2019独角兽企业重金招聘Python工程师标准>>> django的settings中包含三个static相关设置项: STATIC_ROOT STATIC_URL STATICFILES_DIRS STATIC_URL 好理解,就是映射到静态文件的url,一般为/static/ STATICFILES...