网站建设与规划策划书软件开发工具介绍
- 作者: 五速梦信息网
- 时间: 2026年04月20日 07:41
当前位置: 首页 > news >正文
网站建设与规划策划书,软件开发工具介绍,东莞饭堂承包东莞网站建设,网站建设基础功能目录 六、I2C总线二级外设驱动开发方法 七、I2C总线二级外设驱动开发之名称匹配
- i2c_register_board_info
- i2c_new_device#xff1a;明确二级外设地址的情况下可用
- i2c_new_probed_device 八、I2C总线二级外设驱动开发之设备树匹配 六、I2C总线二级外设驱动开…目录 六、I2C总线二级外设驱动开发方法 七、I2C总线二级外设驱动开发之名称匹配
- i2c_register_board_info
- i2c_new_device明确二级外设地址的情况下可用
- i2c_new_probed_device
八、I2C总线二级外设驱动开发之设备树匹配 六、I2C总线二级外设驱动开发方法 1. 查阅原理图以便得知二级外设挂在哪条I2C总线上、二级外设的身份标识二级外设自身的地址 2. 参照platform样式搭建二级外设驱动框架 3. 查询二级外设芯片手册以便得知驱动需要用到的寄存器地址 注意 1 此处寄存器是指二级外设内部的寄存器每个寄存器在芯片手册里有个对应编号也被称为地址但不是内存地址特别提醒此寄存器不是SOC芯片内部参与内存统一编址的寄存器更不是ARM核-CPU的寄存器 2通过调用i2c_tranfer函数完成与相应寄存器的数据交互 4. 参照字符驱动完成其余代码编写 5. 创建对应的i2c_client对象 linux-3.14\Documentation\i2c\instantiating-devices 匹配方式 1. 名称匹配id和name差不多 2. 设备树匹配 3. ACPI匹配 Advanced Configuration and Power Management Interface 高级配置和电源管理接口 PC机平台采用的一种硬件配置接口 咱们是arm平台这种方式用不了 i2c二级外设驱动框架 c//其它struct file_operations函数实现原理同硬编驱动static int mpu6050_probe(struct i2c_client *pclt,const struct i2c_device_id *pid){//做硬编驱动模块入口函数的活}static int mpu6050_remove(struct i2c_client *pclt){//做硬编驱动模块出口函数的活}/名称匹配时定义struct i2c_device_id数组/static struct i2c_device_id mpu6050_ids {{mpu6050,0},//…..{}};/设备树匹配时定义struct of_device_id数组/static struct of_device_id mpu6050_dts {{.compatible invensense,mpu6050},//….{}};/通过定义struct i2c_driver类型的全局变量来创建i2c_driver对象同时对其主要成员进行初始化/struct i2c_driver mpu6050_driver {.driver {.name mpu6050,.owner THIS_MODULE,.of_match_table mpu6050_dts,},.probe mpu6050_probe,.remove mpu6050_remove,.id_table mpu6050_ids,};/以下其实是个宏展开后相当于实现了模块入口函数和模块出口函数/module_i2c_driver(mpu6050_driver);MODULE_LICENSE(GPL); 七、I2C总线二级外设驱动开发之名称匹配
这种匹配方式需要自己创建i2c_client对象
创建i2c_client对象有三种方式 1. i2c_register_board_info 1.当开发板上电内核跑起来的时候肯定是架构相关的程序首先运行也就是mach-xxx.c 2. mach-xxx.c文件里首先会定义i2c_board_info的结构体数组在mach-xxx.c的初始化函数里调用i2c_register_board_info函数把i2c_board_inifo链接进内核的i2c_board_list链表当中去 3.在驱动i2c目录下和开发板板对应的驱动文件i2c-xxx.c里创建i2c_adapter对象 4.这种方式严重依赖平台缺乏灵活性基本会被遗弃 2. i2c_new_device明确二级外设地址的情况下可用 i2c二级外设client框架 c#include linux/kernel.h#include linux/module.h#include linux/i2c.hstatic struct i2c_board_info mpu6050_info {I2C_BOARD_INFO(mpu6050,二级外设地址) };static struct i2c_client *mpu6050_client;static int __init mpu6050_dev_init(void){struct i2c_adapter *padp NULL;padp i2c_get_adapter(i2c通道编号);mpu6050_client i2c_new_device(padp,mpu6050_info);i2c_put_adapter(padp);return 0;}module_init(mpu6050_dev_init);static void __exit mpu6050_dev_exit(void){i2c_unregister_device(mpu6050_client);}module_exit(mpu6050_dev_exit);MODULE_LICENSE(GPL); 3. i2c_new_probed_device i2c二级外设client框架不明确二级外设地址但是知道是可能几个值之一的情况下可用 c#include linux/kernel.h#include linux/module.h#include linux/i2c.hstatic const unsigned short addr_list[] {0x68,//…..I2C_CLIENT_END};static struct i2c_client *mpu6050_client;static int __init mpu6050_dev_init(void){struct i2c_adapter *padp NULL;struct i2c_board_info mpu6050_info {};strcpy(mpu6050_info.type,mpu6050);padp i2c_get_adapter(i2c通道编号);mpu6050_client i2c_new_probed_device(padp,mpu6050_info,addr_list,NULL);i2c_put_adapter(padp);if(mpu6050_client ! NULL){return 0;}else{return -ENODEV;}}module_init(mpu6050_dev_init);static void __exit mpu6050_dev_exit(void){i2c_unregister_device(mpu6050_client);}module_exit(mpu6050_dev_exit);MODULE_LICENSE(GPL); mpu6050_client.c
#include linux/kernel.h
#include linux/module.h
#include linux/i2c.hstatic struct i2c_board_info mpu6050_info
{I2C_BOARD_INFO(mpu6050,0x68) };static struct i2c_client *gpmpu6050_client NULL;static int __init mpu6050_client_init(void) {struct i2c_adapter *padp NULL;padp i2c_get_adapter(5);gpmpu6050_client i2c_new_device(padp,mpu6050_info);i2c_put_adapter(padp);return 0; }static void mpu6050_client_exit(void) {i2c_unregister_device(gpmpu6050_client); }module_init(mpu6050_client_init); module_exit(mpu6050_client_exit); MODULE_LICENSE(GPL);mpu6050_drv.c #include linux/module.h #include linux/kernel.h #include linux/fs.h #include linux/i2c.h #include linux/cdev.h #include linux/wait.h #include linux/sched.h #include linux/poll.h #include linux/slab.h #include linux/mm.h #include linux/io.h #include asm/uaccess.h #include asm/atomic.h#include mpu6050.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 0x6Bint major 11; int minor 0; int mpu6050_num 1;struct mpu6050_dev {struct cdev mydev;struct i2c_client *pclt;};struct mpu6050_dev *pgmydev NULL;int mpu6050_read_byte(struct i2c_client *pclt,unsigned char reg) {int ret 0;char txbuf[1] {reg};char rxbuf[1] {0};struct i2c_msg msg[2] {{pclt-addr,0,1,txbuf},{pclt-addr,I2C_M_RD,1,rxbuf}};ret i2c_transfer(pclt-adapter,msg,ARRAY_SIZE(msg));if(ret 0){printk(ret %d,in mpu6050_read_byte\n,ret);return ret;}return rxbuf[0]; }int mpu6050_write_byte(struct i2c_client *pclt,unsigned char reg,unsigned char val) {int ret 0;char txbuf[2] {reg,val};struct i2c_msg msg[1] {{pclt-addr,0,2,txbuf},};ret i2c_transfer(pclt-adapter,msg,ARRAY_SIZE(msg));if(ret 0){printk(ret %d,in mpu6050_write_byte\n,ret);return ret;}return 0; }int mpu6050_open(struct inode *pnode,struct file *pfile) {pfile-private_data (void *) (container_of(pnode-i_cdev,struct mpu6050_dev,mydev));return 0; }int mpu6050_close(struct inode *pnode,struct file *pfile) {return 0; }long mpu6050_ioctl(struct file *pfile,unsigned int cmd,unsigned long arg) {struct mpu6050_dev *pmydev (struct mpu6050_dev *)pfile-private_data;union mpu6050_data data;switch(cmd){case GET_ACCEL:data.accel.x mpu6050_read_byte(pmydev-pclt,ACCEL_XOUT_L);data.accel.x | mpu6050_read_byte(pmydev-pclt,ACCEL_XOUT_H) 8;data.accel.y mpu6050_read_byte(pmydev-pclt,ACCEL_YOUT_L);data.accel.y | mpu6050_read_byte(pmydev-pclt,ACCEL_YOUT_H) 8;data.accel.z mpu6050_read_byte(pmydev-pclt,ACCEL_ZOUT_L);data.accel.z | mpu6050_read_byte(pmydev-pclt,ACCEL_ZOUT_H) 8;break;case GET_GYRO:data.gyro.x mpu6050_read_byte(pmydev-pclt,GYRO_XOUT_L);data.gyro.x | mpu6050_read_byte(pmydev-pclt,GYRO_XOUT_H) 8;data.gyro.y mpu6050_read_byte(pmydev-pclt,GYRO_YOUT_L);data.gyro.y | mpu6050_read_byte(pmydev-pclt,GYRO_YOUT_H) 8;data.gyro.z mpu6050_read_byte(pmydev-pclt,GYRO_ZOUT_L);data.gyro.z | mpu6050_read_byte(pmydev-pclt,GYRO_ZOUT_H) 8;break;case GET_TEMP:data.temp mpu6050_read_byte(pmydev-pclt,TEMP_OUT_L);data.temp | mpu6050_read_byte(pmydev-pclt,TEMP_OUT_H) 8;break;default:return -EINVAL;}if(copy_to_user((void *)arg,data,sizeof(data))){return -EFAULT;}return sizeof(data); }void init_mpu6050(struct i2c_client *pclt) {mpu6050_write_byte(pclt,PWR_MGMT_1,0x00);mpu6050_write_byte(pclt,SMPLRT_DIV,0x07);mpu6050_write_byte(pclt,CONFIG,0x06);mpu6050_write_byte(pclt,GYRO_CONFIG,0xF8);mpu6050_write_byte(pclt,ACCEL_CONFIG,0x19); }struct file_operations myops {.owner THIS_MODULE,.open mpu6050_open,.release mpu6050_close,.unlocked_ioctl mpu6050_ioctl, };static int mpu6050_probe(struct i2c_client *pclt,const struct i2c_device_id *pid) {int ret 0;dev_t devno MKDEV(major,minor);/申请设备号/ret register_chrdev_region(devno,mpu6050_num,mpu6050);if(ret){ret alloc_chrdev_region(devno,minor,mpu6050_num,mpu6050);if(ret){printk(get devno failed\n);return -1;}major MAJOR(devno);//容易遗漏注意}pgmydev (struct mpu6050_dev *)kmalloc(sizeof(struct mpu6050_dev),GFP_KERNEL);if(NULL pgmydev){unregister_chrdev_region(devno,mpu6050_num);printk(kmalloc failed\n);return -1;}memset(pgmydev,0,sizeof(struct mpu6050_dev));pgmydev-pclt pclt;/给struct cdev对象指定操作函数集/ cdev_init(pgmydev-mydev,myops);/将struct cdev对象添加到内核对应的数据结构里/pgmydev-mydev.owner THIS_MODULE;cdev_add(pgmydev-mydev,devno,mpu6050_num);init_mpu6050(pgmydev-pclt);return 0; }static int mpu6050_remove(struct i2c_client *pclt) {dev_t devno MKDEV(major,minor);cdev_del(pgmydev-mydev);unregister_chrdev_region(devno,mpu6050_num);kfree(pgmydev);pgmydev NULL;return 0; }struct i2c_device_id mpu6050_ids[]
{{mpu6050,0},{} };struct i2c_driver mpu6050_driver
{.driver {.name mpu6050,.owner THIS_MODULE,},.probe mpu6050_probe,.remove mpu6050_remove,.id_table mpu6050_ids, };#if 0 int __init mpu6050_driver_init(void) {i2c_add_driver(mpu6050_driver); }void __exit mpu6050_driver_exit(void) {i2c_del_driver(mpu6050_driver); } module_init(mpu6050_driver_init); module_exit(mpu6050_driver_exit); #else module_i2c_driver(mpu6050_driver); #endifMODULE_LICENSE(GPL);#ifndef MPU_6050_H #define MPU_6050_Hstruct accel_data {unsigned short x;unsigned short y;unsigned short z; }; struct gyro_data {unsigned short x;unsigned short y;unsigned short z; };union mpu6050_data {struct accel_data accel;struct gyro_data gyro;unsigned short temp; };#define MPU6050_MAGIC K#define GET_ACCEL _IOR(MPU6050_MAGIC,0,union mpu6050_data) #define GET_GYRO _IOR(MPU6050_MAGIC,1,union mpu6050_data) #define GET_TEMP _IOR(MPU6050_MAGIC,2,union mpu6050_data)#endif 使用probed也行 #include linux/kernel.h #include linux/module.h #include linux/i2c.hstatic unsigned short mpu6050_addr_list[]
{0x68,0x69,I2C_CLIENT_END };static struct i2c_client *gpmpu6050_client NULL;static int __init mpu6050_client_init(void) {struct i2c_adapter *padp NULL;struct i2c_board_info mpu6050_info {};strcpy(mpu6050_info.type,mpu6050);padp i2c_get_adapter(5);gpmpu6050_client i2c_new_probed_device(padp,mpu6050_info,mpu6050_addr_list,NULL);i2c_put_adapter(padp);if(gpmpu6050_client ! NULL){return 0;}else{return -ENODEV;} }static void mpu6050_client_exit(void) {i2c_unregister_device(gpmpu6050_client); }module_init(mpu6050_client_init); module_exit(mpu6050_client_exit); MODULE_LICENSE(GPL); 测试用的APP #include sys/types.h #include sys/stat.h #include sys/ioctl.h #include fcntl.h #include unistd.h#include stdio.h#include mpu6050.hint main(int argc,char *argv[]) {int fd -1;union mpu6050_data data;if(argc 2){printf(The argument is too few\n);return 1;}fd open(argv[1],O_RDONLY);if(fd 0){printf(open %s failed \n,argv[1]);return 2;}while(1){sleep(2);ioctl(fd,GET_ACCEL,data);printf(Accel-x0x%x\n,data.accel.x);printf(Accel-y0x%x\n,data.accel.y);printf(Accel-z0x%x\n,data.accel.z);ioctl(fd,GET_GYRO,data);printf(Gyro-x0x%x\n,data.gyro.x);printf(Gyro-y0x%x\n,data.gyro.y);printf(Gyro-z0x%x\n,data.gyro.z);ioctl(fd,GET_TEMP,data);printf(Temp0x%x\n,data.temp);printf(\n);}close(fd);fd -1;return 0; }八、I2C总线二级外设驱动开发之设备树匹配 0x68是从设备号interrupt是中断 IIC的实现和前面LED不太一样那个使用设备树匹配不需要ip IIC需要有一个IP。 #include linux/module.h #include linux/kernel.h #include linux/fs.h #include linux/i2c.h #include linux/cdev.h #include linux/wait.h #include linux/sched.h #include linux/poll.h #include linux/slab.h #include linux/mm.h #include linux/io.h #include asm/uaccess.h #include asm/atomic.h#include mpu6050.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 0x6Bint major 11; int minor 0; int mpu6050_num 1;struct mpu6050_dev {struct cdev mydev;struct i2c_client *pclt;};struct mpu6050_dev *pgmydev NULL;int mpu6050_read_byte(struct i2c_client *pclt,unsigned char reg) {int ret 0;char txbuf[1] {reg};char rxbuf[1] {0};struct i2c_msg msg[2] {{pclt-addr,0,1,txbuf},{pclt-addr,I2C_M_RD,1,rxbuf}};ret i2c_transfer(pclt-adapter,msg,ARRAY_SIZE(msg));if(ret 0){printk(ret %d,in mpu6050_read_byte\n,ret);return ret;}return rxbuf[0]; }int mpu6050_write_byte(struct i2c_client *pclt,unsigned char reg,unsigned char val) {int ret 0;char txbuf[2] {reg,val};struct i2c_msg msg[1] {{pclt-addr,0,2,txbuf},};ret i2c_transfer(pclt-adapter,msg,ARRAY_SIZE(msg));if(ret 0){printk(ret %d,in mpu6050_write_byte\n,ret);return ret;}return 0; }int mpu6050_open(struct inode *pnode,struct file *pfile) {pfile-private_data (void *) (container_of(pnode-i_cdev,struct mpu6050_dev,mydev));return 0; }int mpu6050_close(struct inode *pnode,struct file *pfile) {return 0; }long mpu6050_ioctl(struct file *pfile,unsigned int cmd,unsigned long arg) {struct mpu6050_dev *pmydev (struct mpu6050_dev *)pfile-private_data;union mpu6050_data data;switch(cmd){case GET_ACCEL:data.accel.x mpu6050_read_byte(pmydev-pclt,ACCEL_XOUT_L);data.accel.x | mpu6050_read_byte(pmydev-pclt,ACCEL_XOUT_H) 8;data.accel.y mpu6050_read_byte(pmydev-pclt,ACCEL_YOUT_L);data.accel.y | mpu6050_read_byte(pmydev-pclt,ACCEL_YOUT_H) 8;data.accel.z mpu6050_read_byte(pmydev-pclt,ACCEL_ZOUT_L);data.accel.z | mpu6050_read_byte(pmydev-pclt,ACCEL_ZOUT_H) 8;break;case GET_GYRO:data.gyro.x mpu6050_read_byte(pmydev-pclt,GYRO_XOUT_L);data.gyro.x | mpu6050_read_byte(pmydev-pclt,GYRO_XOUT_H) 8;data.gyro.y mpu6050_read_byte(pmydev-pclt,GYRO_YOUT_L);data.gyro.y | mpu6050_read_byte(pmydev-pclt,GYRO_YOUT_H) 8;data.gyro.z mpu6050_read_byte(pmydev-pclt,GYRO_ZOUT_L);data.gyro.z | mpu6050_read_byte(pmydev-pclt,GYRO_ZOUT_H) 8;break;case GET_TEMP:data.temp mpu6050_read_byte(pmydev-pclt,TEMP_OUT_L);data.temp | mpu6050_read_byte(pmydev-pclt,TEMP_OUT_H) 8;break;default:return -EINVAL;}if(copy_to_user((void *)arg,data,sizeof(data))){return -EFAULT;}return sizeof(data); }void init_mpu6050(struct i2c_client *pclt) {mpu6050_write_byte(pclt,PWR_MGMT_1,0x00);mpu6050_write_byte(pclt,SMPLRT_DIV,0x07);mpu6050_write_byte(pclt,CONFIG,0x06);mpu6050_write_byte(pclt,GYRO_CONFIG,0xF8);mpu6050_write_byte(pclt,ACCEL_CONFIG,0x19); }struct file_operations myops {.owner THIS_MODULE,.open mpu6050_open,.release mpu6050_close,.unlocked_ioctl mpu6050_ioctl, };static int mpu6050_probe(struct i2c_client *pclt,const struct i2c_device_id *pid) {int ret 0;dev_t devno MKDEV(major,minor);/申请设备号/ret register_chrdev_region(devno,mpu6050_num,mpu6050);if(ret){ret alloc_chrdev_region(devno,minor,mpu6050_num,mpu6050);if(ret){printk(get devno failed\n);return -1;}major MAJOR(devno);//容易遗漏注意}pgmydev (struct mpu6050_dev *)kmalloc(sizeof(struct mpu6050_dev),GFP_KERNEL);if(NULL pgmydev){unregister_chrdev_region(devno,mpu6050_num);printk(kmalloc failed\n);return -1;}memset(pgmydev,0,sizeof(struct mpu6050_dev));pgmydev-pclt pclt;/给struct cdev对象指定操作函数集/ cdev_init(pgmydev-mydev,myops);/将struct cdev对象添加到内核对应的数据结构里/pgmydev-mydev.owner THIS_MODULE;cdev_add(pgmydev-mydev,devno,mpu6050_num);init_mpu6050(pgmydev-pclt);return 0; }static int mpu6050_remove(struct i2c_client *pclt) {dev_t devno MKDEV(major,minor);cdev_del(pgmydev-mydev);unregister_chrdev_region(devno,mpu6050_num);kfree(pgmydev);pgmydev NULL;return 0; }struct of_device_id mpu6050_dt[]
{{.compatible invensense,mpu6050},{} };struct i2c_device_id mpu6050_ids[]
{{mpu6050,0},{} };struct i2c_driver mpu6050_driver
{.driver {.name mpu6050,.owner THIS_MODULE,.of_match_table mpu6050_dt,},.probe mpu6050_probe,.remove mpu6050_remove,.id_table mpu6050_ids, };#if 0 int __init mpu6050_driver_init(void) {i2c_add_driver(mpu6050_driver); }void __exit mpu6050_driver_exit(void) {i2c_del_driver(mpu6050_driver); } module_init(mpu6050_driver_init); module_exit(mpu6050_driver_exit); #else module_i2c_driver(mpu6050_driver); #endifMODULE_LICENSE(GPL);测试程序和.h程序和上面一样。
- 上一篇: 网站建设与管理自考试题及答案如何查询网站空间大小
- 下一篇: 网站建设与规划实训报告韩雪冬推荐网站
相关文章
-
网站建设与管理自考试题及答案如何查询网站空间大小
网站建设与管理自考试题及答案如何查询网站空间大小
- 技术栈
- 2026年04月20日
-
网站建设与管理自简历移动互联网开发官网
网站建设与管理自简历移动互联网开发官网
- 技术栈
- 2026年04月20日
-
网站建设与管理专业教学标准泰安房产网签查询系统
网站建设与管理专业教学标准泰安房产网签查询系统
- 技术栈
- 2026年04月20日
-
网站建设与规划实训报告韩雪冬推荐网站
网站建设与规划实训报告韩雪冬推荐网站
- 技术栈
- 2026年04月20日
-
网站建设与规划心得建筑人才网官网网址
网站建设与规划心得建筑人才网官网网址
- 技术栈
- 2026年04月20日
-
网站建设与会展wordpress 关键词链接插件
网站建设与会展wordpress 关键词链接插件
- 技术栈
- 2026年04月20日
