bmp085的驱动文件如下
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/input.h>
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/serio.h>
#include <linux/delay.h>
#include <linux/clk.h>
#include <linux/wait.h>
#include <linux/sched.h>
#include <linux/cdev.h>
#include <linux/miscdevice.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/uaccess.h>
#include <mach/gpio.h>
#define DEVICE_NAME "bmp085"
#define BMP085_SlaveAddress 0xee //定义器件在IIC总线中的从地址
#define SDA S5PV210_GPH3(1)
#define SCL S5PV210_GPH3(0)
#define ONE 1
#define ZERO 0
#define OSS 0
#define GET_PARAMETE 0x10
#define GET_TEMP 0x20
#define GET_PRESSURE 0x30
#define BMP085_FINAL_TEMP 0x40
#define BMP085_FINAL_PRESSURE 0x50
#define GET_FINAL_START 0x60
#define UDELAY {udelay(5);}
#define MDELAY {mdelay(5);}
//bmp085器件参数
static long temperature=0;
static long pressure=0xff;
static char buf[6]; //data bufffer
static int read_falg;
static struct BMP085_PARAMETER{
short ac1;
short ac2;
short ac3;
unsigned short ac4;
unsigned short ac5;
unsigned short ac6;
short b1;
short b2;
short mb;
short mc;
short md;
};
struct BMP085_PARAMETER bmp085_parameter;
//起始信号
void bmp085_start(void) //SCL为高电平时,SDA由高电平向低电平跳变,开始传送数据。
{
gpio_set_value(SDA, 1); //拉高数据线
gpio_set_value(SCL, 1); //拉高时钟线
UDELAY; //延时
gpio_set_value(SDA, 0); //产生下降沿
UDELAY; //延时
gpio_set_value(SCL, 0); //拉低时钟线
}
//停止信号
void bmp085_stop (void) //SCL为高电平时,SDA由低电平向高电平跳变,结束传送数据。
{
gpio_set_value(SDA, 0); //拉低数据线
gpio_set_value(SCL, 1); //拉高时钟线
UDELAY; //延时
gpio_set_value(SDA, 1); //产生上升沿
UDELAY; //延时
}
//发送应答信号 入口参数:ack (0x0:ACK 0x01:NAK)
void bmp085_sendack(unsigned char ack)
{
if(ack) //写应答信号
gpio_set_value(SDA, 1);
else
gpio_set_value(SDA, 0);
gpio_set_value(SCL, 1); //拉高时钟线
UDELAY; //延时
gpio_set_value(SCL, 0); //拉低时钟线
UDELAY; //延时
}
//接收应答信号
unsigned char bmp085_recvack(void)
{
unsigned char cy;
gpio_set_value(SCL, 1); //拉高时钟线
gpio_direction_input(SDA);
UDELAY; //延时
cy=gpio_get_value(SDA); //读应答信号
gpio_set_value(SCL, 0); //拉低时钟线
UDELAY; //延时
gpio_direction_output(SDA,1);
UDELAY; //延时
return cy;
}
//向IIC总线发送一个字节数据
void bmp085_sendbyte(unsigned char dat)
{
unsigned char i;
unsigned char cy[8];
unsigned char data;
for (i=0; i<8; i++) //获取字节的每一位
{
data=dat&0x80;
if(data)
cy[i]=ONE;
else
cy[i]=ZERO;
dat<<=1;
}
for (i=0; i<8; i++) //8位计数器
{
gpio_set_value(SDA,cy[i]); //送数据口
gpio_set_value(SCL, 1); //拉高时钟线
UDELAY; //延时
gpio_set_value(SCL, 0); //拉低时钟线
UDELAY; //延时
}
bmp085_recvack();
}
//从IIC总线接收一个字节数据
unsigned char bmp085_recvbyte(void)
{
unsigned char i;
unsigned char dat = 0;
gpio_set_value(SDA,1); //使能内部上拉,准备读取数据
gpio_direction_input(SDA);
UDELAY; //延时
for (i=0; i<8; i++) //8位计数器
{
dat <<= 1;
gpio_set_value(SCL, 1); //拉高时钟线
UDELAY; //延时
dat |= gpio_get_value(SDA); //读数据
gpio_set_value(SCL, 0); //拉低时钟线
UDELAY; //延时
}
gpio_direction_output(SDA,1);
return dat;
}
short multiple_read(unsigned char ST_Address)
{
unsigned char msb, lsb;
short data;
bmp085_start(); //起始信号
bmp085_sendbyte(BMP085_SlaveAddress); //发送设备地址+写信号
bmp085_sendbyte(ST_Address); //发送存储单元地址
bmp085_start(); //起始信号
bmp085_sendbyte(BMP085_SlaveAddress+1); //发送设备地址+读信号
msb = bmp085_recvbyte(); //BUF[0]存储
bmp085_sendack(0x0); //回应ACK
lsb = bmp085_recvbyte();
bmp085_sendack(0x01); //最后一个数据需要回NOACK
bmp085_stop(); //停止信号
MDELAY; //延时
data = msb << 8;
data |= lsb;
return data;
}
void init_bmp085(void)
{
bmp085_parameter.ac1= multiple_read(0xAA);
bmp085_parameter.ac2= multiple_read(0xAC);
bmp085_parameter.ac3= multiple_read(0xAE);
bmp085_parameter.ac4= multiple_read(0xB0);
bmp085_parameter.ac5= multiple_read(0xB2);
bmp085_parameter.ac6= multiple_read(0xB4);
bmp085_parameter.b1 = multiple_read(0xB6);
bmp085_parameter.b2 = multiple_read(0xB8);
bmp085_parameter.mb = multiple_read(0xBA);
bmp085_parameter.mc = multiple_read(0xBC);
bmp085_parameter.md = multiple_read(0xBE);
printk("the parameter ac1=%d\n",bmp085_parameter.ac1);
printk("the parameter ac2=%d\n",bmp085_parameter.ac2);
printk("the parameter ac3=%d\n",bmp085_parameter.ac3);
printk("the parameter ac4=%d\n",bmp085_parameter.ac4);
printk("the parameter ac5=%d\n",bmp085_parameter.ac5);
printk("the parameter ac6=%d\n",bmp085_parameter.ac6);
printk("the parameter b1=%d\n",bmp085_parameter.b1);
printk("the parameter b2=%d\n",bmp085_parameter.b2);
printk("the parameter mb=%d\n",bmp085_parameter.mb);
printk("the parameter mc=%d\n",bmp085_parameter.mc);
printk("the parameter md=%d\n",bmp085_parameter.md);
}
long bmp085_read_temp(void)
{
bmp085_start(); //起始信号
bmp085_sendbyte(BMP085_SlaveAddress); //发送设备地址+写信号
bmp085_sendbyte(0xF4); // write register address
bmp085_sendbyte(0x2E); // write register data for temp
bmp085_stop(); //发送停止信号
MDELAY; // max time is 4.5ms
return (long) multiple_read(0xF6);
}
long bmp085_read_pressure(void)
{
long pressure = 0;
bmp085_start(); //起始信号
bmp085_sendbyte(BMP085_SlaveAddress); //发送设备地址+写信号
bmp085_sendbyte(0xF4); // write register address
bmp085_sendbyte(0x34); // write register data for pressure
bmp085_stop(); //发送停止信号
MDELAY; // max time is 4.5ms
pressure = multiple_read(0xF6);
pressure &= 0x0000FFFF;
return pressure; //return (long) bmp085ReadShort(0xF6);
}
void bmp085_get_data(void)
{
temperature = bmp085_read_temp();
temperature = bmp085_read_temp(); // 读取温度
pressure = bmp085_read_pressure();
pressure = bmp085_read_pressure(); // 读取压强
}
void bmp085_data_calculate(void)
{
long x1, x2, b5, b6, x3, b3, p;
unsigned long b4, b7;
x1 = ((long)temperature - bmp085_parameter.ac6) * bmp085_parameter.ac5 >> 15;
x2 = ((long) bmp085_parameter.mc << 11) / (x1 +bmp085_parameter.md);
b5 = x1 + x2;
temperature = (b5 + 8) >> 4;
b6 = b5 - 4000;
x1 = (bmp085_parameter.b2 * (b6 * b6 >> 12)) >> 11;
x2 = bmp085_parameter.ac2 * b6 >> 11;
x3 = x1 + x2;
b3 = (((long)bmp085_parameter.ac1 * 4 + x3) + 2)/4;
x1 = bmp085_parameter.ac3 * b6 >> 13;
x2 = (bmp085_parameter.b1 * (b6 * b6 >> 12)) >> 16;
x3 = ((x1 + x2) + 2) >> 2;
b4 = (bmp085_parameter.ac4 * (unsigned long) (x3 + 32768)) >> 15;
b7 = ((unsigned long)pressure - b3) * (50000 >> OSS);
if( b7 < 0x80000000)
p = (b7 * 2) / b4 ;
else
p = (b7 / b4) * 2;
x1 = (p >> 8) * (p >> 8);
x1 = (x1 * 3038) >> 16;
x2 = (-7357 * p) >> 16;
pressure = p + ((x1 + x2 + 3791) >> 4);
}
void conversion(long temp_data)
{
buf[0]=temp_data/100000 ;
temp_data=temp_data%100000; //取余运算
buf[1]=temp_data/10000;
temp_data=temp_data%10000; //取余运算
buf[2]=temp_data/1000;
temp_data=temp_data%1000; //取余运算
buf[3]=temp_data/100;
temp_data=temp_data%100; //取余运算
buf[4]=temp_data/10;
temp_data=temp_data%10; //取余运算
buf[5]=temp_data;
}
static long bmp085_ioctl(struct file *filp, unsigned int cmd,unsigned long arg)
{
switch(cmd)
{
case GET_PARAMETE:
init_bmp085();
break;
case GET_TEMP:
temperature=bmp085_read_temp();
conversion(temperature);
break;
case GET_PRESSURE:
pressure=bmp085_read_pressure();
conversion(pressure);
break;
case GET_FINAL_START:
bmp085_get_data();
bmp085_data_calculate();
break;
case BMP085_FINAL_TEMP:
conversion(temperature);
read_falg=0x22;
break;
case BMP085_FINAL_PRESSURE:
conversion(pressure);
read_falg=0x88;
break;
default:
printk("iotcl cmd no found!\n");
return -EINVAL;
}
return 0;
}
static ssize_t bmp085_read(struct file *file, char __user *buffer, size_t size, loff_t *pos)
{
int ret=0;
long data;
if(read_falg==0x22)
data=temperature;
if(read_falg==0x88)
data=pressure;
ret=copy_to_user(buffer,&data,sizeof(data));
if(ret<0){
printk("copy to user err!\n");
return -EFAULT;
}
return 0;
}
static int bmp085_open(struct inode *inode, struct file *file)
{
printk("open in kernel\n");
return 0;
}
static int bmp085_release(struct inode *inode, struct file *file)
{
printk("bmp085_release\n");
return 0;
}
static struct file_operations bmp085_dev_fops={
.owner = THIS_MODULE,
.open = bmp085_open,
.read = bmp085_read,
.unlocked_ioctl = bmp085_ioctl,
.release = bmp085_release,
};
static struct miscdevice bmp085_dev = {
.minor = MISC_DYNAMIC_MINOR,
.name = DEVICE_NAME,
.fops = &bmp085_dev_fops,
};
static int __init bmp085_dev_init(void) {
int ret;
ret = gpio_request(SDA, "BMP085_SDA");
if (ret){
printk("%s: request GPIO %d for bmp085 failed, ret = %d\n", DEVICE_NAME,SDA, ret);
return ret;
}
ret = gpio_request(SCL, "BMP085_SCL");
if (ret){
printk("%s: request GPIO %d for bmp085 failed, ret = %d\n", DEVICE_NAME,SCL, ret);
return ret;
}
gpio_direction_output(SDA, 1);
gpio_direction_output(SCL, 1);
ret = misc_register(&bmp085_dev);
printk(DEVICE_NAME"\tinitialized\n");
return ret;
}
static void __exit bmp085_dev_exit(void)
{
gpio_free(SDA);
gpio_free(SCL);
misc_deregister(&bmp085_dev);
}
module_init(bmp085_dev_init);
module_exit(bmp085_dev_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("www");
应用层的测试app如下
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <strings.h>
#define GET_PARAMETE 0x10
#define GET_TEMP 0x20
#define GET_PRESSURE 0x30
#define BMP085_FINAL_TEMP 0x40
#define BMP085_FINAL_PRESSURE 0x50
#define GET_FINAL_START 0x60
int bmpfd;//bmp085文件描述符
long data_covertion(char *buf)
{
long data;
data+=buf[0]*100000;
data+=buf[1]*10000;
data+=buf[2]*1000;
data+=buf[3]*100;
data+=buf[4]*10;
data+=buf[5];
return data;
}
int main(int argc,char **argv)
{
int ret;
char buf[6];
long pressure;
long temperature;
int i;
bmpfd=open("/dev/bmp085",O_RDWR);
if(bmpfd<0)
{
printf("open bmp085 err!\n");
printf("please cheek!\n");
exit(-1);
}
printf("open bmp085 ok!\n");
ioctl(bmpfd,GET_PARAMETE,0);
while(1)
{
ioctl(bmpfd,GET_FINAL_START,0);
ioctl(bmpfd,BMP085_FINAL_PRESSURE,0);
if(read(bmpfd,&pressure,sizeof(pressure))<0)
printf("read bmp085 err!\n");
printf("the bmp085 pressure=%d\n",pressure);
ioctl(bmpfd,BMP085_FINAL_TEMP ,0);
if(read(bmpfd,&temperature,sizeof(temperature))<0)
printf("read bmp085 err!\n");
printf("the bmp085 temperature=%d\n", temperature);
sleep(2);
}
close(bmpfd);
return 0;
}