BBYR Achieve
返回信息流
这是一条镜像帖。来源:北邮人论坛 / embedded-system / #15283同步于 2015/1/27
该镜像源已超过 30 天没有更新,可能在源站已被删除。
Embedded_System机器人发帖

[问题]linux bmp180湿度传感器iic驱动 求大神指点

lix198911m10
2015/1/27镜像同步1 回复
最近在做一个linux iic的开发 驱动基本写好了(不知道对不对) 能够挂载到系统中 但是每次读/写寄存器的时间要消耗5秒钟 好蛋疼 bmp180设备要读取多个寄存器很费时间 我把我的代码贴在下面 求大神耐心点帮忙看看 哭瞎了。。。 linux板级信息已经注册了:在/arch/arm/mach-mini2440.c中 static struct i2c_board_info __initdata BMP180_board_info[] = { { .type = "BMP180", .addr = (0xEE>>1), }, }; i2c_register_board_info(0,BMP180_board_info,ARRAY_SIZE(BMP180_board_info)); 上程序: //********************************** // BMP180 气压传感器驱动程序 // linux平台 // by lixin // 2015年1月22 //********************************** #include <linux/kernel.h> #include <linux/init.h> #include <linux/module.h> #include <linux/slab.h> #include <linux/jiffies.h> #include <linux/i2c.h> #include <linux/mutex.h> #include <linux/fs.h> #include <asm/uaccess.h> #include <linux/miscdevice.h> #include <linux/delay.h> #include <asm/irq.h> #include <mach/regs-gpio.h> #include <mach/hardware.h> #include <linux/mm.h> #include <linux/fs.h> #include <linux/types.h> #include <linux/delay.h> #include <linux/moduleparam.h> #include <linux/errno.h> #include <linux/ioctl.h> #include <linux/cdev.h> #include <linux/string.h> #include <linux/list.h> #include <linux/pci.h> #include <asm/atomic.h> #include <asm/unistd.h> #include <linux/device.h> #include <linux/delay.h> #define DEBUG 1 #ifdef DEBUG #define dbg(x...) printk(x) #else #define dbg(x...) (void)(0) #endif struct i2c_client *BMP180_client;// 定义一个客户端结构体 static int major; //主设备号 static struct class *cls;//设备类 #define BMP180_SLAVE_ADDRESS (0xEE>>1) //device address void *R_GPECON; void *R_GPEUP; static int __devexit BMP180_remove(struct i2c_client *client); static int __devinit BMP180_probe(struct i2c_client *client, const struct i2c_device_id *dev_id); static const struct i2c_device_id BMP180_id[] = { {"BMP180",0x77}, {} }; MODULE_DEVICE_TABLE(i2c, BMP180_id); static struct i2c_driver BMP180_driver = { //设备驱动结构体 .driver = { .name = "BMP180", .owner = THIS_MODULE, }, .id_table = BMP180_id, .probe = BMP180_probe, .remove = __devexit_p(BMP180_remove), }; static ssize_t BMP180_write(struct file *file, const char __user *buf, size_t size, loff_t *offset) { return -EIO; } static ssize_t BMP180_read(struct file *file, char __user *buf, size_t size, loff_t * offset) { unsigned char oss = 0x03;//严格模式 在测量气压时有用 unsigned char reg_all = 0xF4; unsigned char call_t = 0x2E; unsigned char lsb_t = 0xF7;//温度的低8位 unsigned char msb_t = 0xF6;//温度的高8位 unsigned char call_p = 0x34+(oss<<6); unsigned char lsb_p = 0xF7; unsigned char msb_p = 0xF6; unsigned char xlsb_p = 0xF8; unsigned char data_t[2]; unsigned char address_t[2]; unsigned char data_p[3];//转换前的数据 unsigned char address_p[3]; unsigned char write_data[2]; long int test_kernel[2];//转换后的数据 struct i2c_msg msg[2]; printk("read---start"); //发出测量温度信号 /* 向设备中写数据 配置第一个信号 */ write_data[0] = reg_all; write_data[1] = call_t; msg[0].addr = BMP180_client->addr; /* 设备地址*/ msg[0].buf = write_data; /* 设备寄存器地址+数据*/ msg[0].len = 2; /* 地址+数据=2 byte */ msg[0].flags = 0; /* 写*/ i2c_transfer(BMP180_client->adapter, msg, 1); mdelay(5); //测量结束 发出读温度操作 //第一个发送要读取的寄存器地址 写操作 //第二个要发送数据读取后存放的位置 读操作 address_t[0] = msb_t; address_t[1] = lsb_t; msg[0].buf = address_t; msg[0].len = 2; msg[1].addr = BMP180_client->addr; /* 设备地址 */ msg[1].buf = data_t; /* 数据存放的地方*/ msg[1].len = 2; /* 读取两个数=1 byte */ msg[1].flags = I2C_M_RD; /* 读*/ i2c_transfer(BMP180_client->adapter, msg, 2); mdelay(1); /* msg[0].buf = &lsb_t; msg[1].buf = &data[0]; msg[1].flags = I2C_M_RD; i2c_transfer(BMP180_client->adapter, msg, 2); mdelay(1); msg[0].buf = &msb_t; msg[1].buf = &data[1]; i2c_transfer(BMP180_client->adapter, msg, 2); mdelay(1); */ //处理温度数据 test_kernel[0] = (long int)((data_t[0]<<8)|data_t[1]); //对传感器发送测量气压的命令 write_data[1] = call_p; msg[0].buf = write_data; msg[0].len = 2; msg[0].flags = 0;//转换为写模式 i2c_transfer(BMP180_client->adapter, msg, 1); mdelay(26);//延时26毫秒 //开始读取气压的数值 address_p[0] = msb_p; address_p[1] = lsb_p; address_p[2] = xlsb_p; msg[0].buf = address_p; msg[0].len = 3; msg[1].buf = data_p; msg[1].len = 3; i2c_transfer(BMP180_client->adapter, msg, 2); mdelay(1); test_kernel[1] = (long int)(((data_p[0]<<16)|(data_p[1]<<8)|data_p[2])>>(8-oss)); //到此为止测量结束 printk("read---end\n"); printk("%d,%d,%d,%d,%d\n",data_t[0],data_t[1],data_p[0],data_p[1],data_p[2]); printk("test_kernel[0] = %ld test_kernel = %ld",test_kernel[0],test_kernel[1]); copy_to_user(buf, test_kernel, 8);//将数据返回用户空间 return 0; } //open函数用来打开设备并且读取设备中的默认寄存器看看设备是否正常。 static int BMP180_open(struct inode *inode, struct file *file) { //设备打开失败返回1 打开成功返回0 unsigned long temp; short int temp_up; int err=0; int i = 0; unsigned char address[22];//22个寄存器的第一个寄存器的地址 unsigned char data[22];//8位数 struct i2c_msg msg[2]; temp = __raw_readl(R_GPECON); temp = (temp&0x0FFFFFFF)|0xA0000000; __raw_writel(temp,R_GPECON); temp_up = __raw_readl(R_GPEUP); printk("open---start"); address[0] = 0xAA; for(i=0;i<22;i++){ address[i]= address[0]+i; //先告诉系统要读那个寄存器 msg[0].addr = BMP180_client->addr; /* 设备地址*/ msg[0].buf = &address[i]; /* 设备寄存器地址*/ msg[0].len = 1; /* 地址=1 byte */ msg[0].flags = BMP180_client->flags & ( I2C_CLIENT_PEC);; /* 写*/ /* 配置第二个信号将寄存器里面的数据读出来*/ msg[1].addr = BMP180_client->addr; /* 设备地址 */ msg[1].buf = &data[i]; /* ?? */ msg[1].len = 1; /* 信号长度=1 byte */ msg[1].flags = BMP180_client->flags & ( I2C_CLIENT_PEC);; /* 读模式*/ msg[1].flags |= I2C_M_RD; i2c_transfer(BMP180_client->adapter, msg, 2); printk("read---end time"); mdelay(1); printk("time-end"); } for(i=0;i<22;i++){ // if(data[i]==0x00||data==0xFF){err=1;break;}//设备有问题或者读取有问题 printk(" %d ",data[i]); } return err; } static struct file_operations BMP180_fops = { .owner = THIS_MODULE, .read = BMP180_read, .write = BMP180_write, .open = BMP180_open, }; static int __devinit BMP180_probe(struct i2c_client *client, const struct i2c_device_id *dev_id)//用来构建一个client的结构体 { struct device *dev; if(dev_id) { printk("BMP180_DEVICE, dev_id.name (%s) /r/n",dev_id->name); } dbg("probe:name = %s,flag =%d,addr = %d,adapter = %d,driver = %s\n",client->name, client->flags,client->addr,client->adapter->nr,client->driver->driver.name ); R_GPECON = ioremap(0x56000040,0x4);//地址重映射 R_GPEUP = ioremap(0x56000048,0x2);//上拉控制寄存器重映射 BMP180_client = client; major = register_chrdev(0, "BMP180", &BMP180_fops);//向系统获得一个主设备号并且加载对文件操作的结构体。 cls = class_create(THIS_MODULE, "BMP180");//生成模块的class dev = device_create(cls,&client->dev, MKDEV(major, 0), NULL, "BMP180"); /* /dev/at24cxx *///创建文件夹 if (IS_ERR(dev)) { dbg("device create error\n"); } return 0; } static int __devexit BMP180_remove(struct i2c_client *client) { printk("BMP180_detach\n"); device_destroy(cls, MKDEV(major, 0));//撤销class 类 class_destroy(cls);//消除类 unregister_chrdev(major, "BMP180");//撤销主设备注册 // i2c_detach_client(client);//将客户端的client与adapter关联撤销 // kfree(i2c_get_clientdata(client));//释放client对应的内存 return 0; } static int __init BMP180_init(void) { i2c_add_driver(&BMP180_driver);//会调用attach函数进行相关的注册初始化 return 0; } static void __exit BMP180_exit(void) { i2c_del_driver(&BMP180_driver);//会调用BMP180_DETACH函数进行相关清理 } module_init(BMP180_init); module_exit(BMP180_exit); MODULE_LICENSE("GPL"); 求好心同学帮忙解决一下
订阅后,新回复会通过你的通知中心匿名送达。
1 条回复
afeionline机器人#1 · 2015/2/3
linux内核里有I2C的驱动,为什么要自己写? 内核里也集成了bmp085的完整驱动,跟你用的bmp180是同一家、同功能的产品,差别应该不会太大,你可以参考。