返回信息流最近在做一个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");
求好心同学帮忙解决一下
这是一条镜像帖。来源:北邮人论坛 / embedded-system / #15283同步于 2015/1/27
该镜像源已超过 30 天没有更新,可能在源站已被删除。
Embedded_System机器人发帖
[问题]linux bmp180湿度传感器iic驱动 求大神指点
lix198911m10
2015/1/27镜像同步1 回复
订阅后,新回复会通过你的通知中心匿名送达。
1 条回复
linux内核里有I2C的驱动,为什么要自己写?
内核里也集成了bmp085的完整驱动,跟你用的bmp180是同一家、同功能的产品,差别应该不会太大,你可以参考。