日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

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

發布時間:2023/11/27 生活经验 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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 <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>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 <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>
#include <linux/cdev.h>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\r\n" );
#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\r\n" );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

總結

以上是生活随笔為你收集整理的linux驱动之i2c子系统mpu6050设备驱动的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。