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

来源:互联网 发布:eclipse mac 百度网盘 编辑:程序博客网 时间:2024/04/27 23:51

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 buffferstatic 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                  0x60int   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;}
0 1
原创粉丝点击