模拟IIC协议驱动气压传感器bmp085

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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值