BMP085气压传感器驱动
BMP085是新一代的小封装气压传感器,主要用于气压温度检测,在四轴飞行器上可以用作定高检测,该传感器属于IIC总线接口,依然沿用标准IIC驱动程序
使用该传感器需要注意的是我们不能直接读出转换好的二进制温度数据或者气压数据,必须先读出一整套约176位的矫正数据,然后启动转换,将转换的数据与矫正数据一起进行矫正运算才能正常获得温度,温度精度为0.1,大气压有16bit或者19bit的精度,一般选择16位精度,
所以对于该传感器设备,驱动模式如下
1.获取矫正数据-->启动温度转换--->获取原始温度数据-->启动大气压转换-->获取原始大气压数据-->计算实际温度数据大气压数据
另,转换时的转换时间也是计算时的重要参数,计算大气压时的过程中需要使用冤死温度
矫正数据如下
矫正数据都是16位有符号的,所以读出的时候需要连续读取两个字节
通过计算得到的大气压强可以计算得到当前传感器相对于海平面的绝对高度
具体驱动代码如下所示
#ifndef __BMP085_H_
#define __BMP085_H_
#include "ioremap.h"
#include "common.h"
#include "stm32f10x.h"
#include "uart.h"
#include "delay.h" //BMP SDA PC0
//BMP SCL PC1 #define BMP_ACK_WAIT_TIME 200 //iic通讯时的ack等待时间 #define BMP085_DEBUG 1 #define OSS 0 // 大气压的转换时间,有0-3可选值 //地址均为读地址
#define BMP085_ADDR 0xEE //定义器件在IIC总线中的写地址 #define BMP_AC1_ADDR 0XAA //定义校准寄存器的地址
#define BMP_AC2_ADDR 0XAC
#define BMP_AC3_ADDR 0XAE
#define BMP_AC4_ADDR 0XB0
#define BMP_AC5_ADDR 0XB2
#define BMP_AC6_ADDR 0XB4
#define BMP_B1_ADDR 0XB6
#define BMP_B2_ADDR 0XB8
#define BMP_MB_ADDR 0XBA
#define BMP_MC_ADDR 0XBC
#define BMP_MD_ADDR 0XBE #define CONTROL_REG_ADDR 0XF4 //控制寄存器,在这个寄存器中设置不同的值可以设置不同转换时间,同时不同的值可以确认转换大气压或者温度
#define BMP_COVERT_TEMP 0X2E //转换温度 4.5MS
#define BMP_COVERT_PRES_0 0X34 //转换大气压 4.5ms
#define BMP_COVERT_PRES_1 0X74 //转换大气压 7.5ms
#define BMP_COVERT_PRES_2 0XB4 //转换大气压 13.5ms
#define BMP_COVERT_PRES_3 0XF4 //转换大气压 25.5ms #define BMP_TEMP_PRES_DATA_REG 0XF6 //两个字节温度数据 //0xf6 0xf7 0xf8 压强地址
//0xf6 0xf7 温度地址 typedef struct BMP085PARAM //校准参数表
{
s16 ac1;
s16 ac2;
s16 ac3;
u16 ac4;
u16 ac5;
u16 ac6;
s16 b1;
s16 b2;
s16 mb;
s16 mc;
s16 md;
}BMP085PARAM; void BmpInit(void); //接口与参数初始化 //读取温度数据并校正转换
long BmpConvertTemp(void); //读取压强数据并校正转换
long BmpConvertPressure(void); #endif
#include "bmp085.h" static struct BMP085PARAM bmp085ParamStruct = {0,0,0,0,0,0,0,0,0,0,0}; //IO方向设置
#define BMP_SDA_IN() {GPIOC->CRL&=0XFFFFFFF0;GPIOC->CRL|=8;}
#define BMP_SDA_OUT() {GPIOC->CRL&=0XFFFFFFF0;GPIOC->CRL|=3;} //IO操作函数
#define BMP_SCL PCout(1) //SCL
#define BMP_SDA PCout(0) //SDA
#define BMP_READ_SDA PCin(0) //输入SDA /**************************BMP5883 IIC驱动函数*********************************/ static void BMP085IOInit(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOC, ENABLE ); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure); BMP_SCL = 1;
BMP_SDA = 1;
} //发送IIC起始信号
static void ComStart(void)
{
BMP_SDA_OUT(); //sda线输出
BMP_SDA=1;
BMP_SCL=1;
DelayUs(5);
BMP_SDA=0;//START:when CLK is high,DATA change form high to low
DelayUs(5);
BMP_SCL=0;//钳住I2C总线,准备发送或接收数据
}
//发送IIC停止信号
static void ComStop(void)
{
BMP_SDA_OUT();//sda线输出
BMP_SDA=0;//STOP:when CLK is high DATA change form low to high
BMP_SCL=1;
DelayUs(5);
BMP_SDA=1;//发送I2C总线结束信号
DelayUs(5);
}
//等待ACK,为1代表无ACK 为0代表等到了ACK
static u8 ComWaitAck(void)
{
u8 waitTime = 0;
BMP_SDA_OUT();//sda线输出
BMP_SDA = 1;
DelayUs(5);
BMP_SDA_IN(); //SDA设置为输入
BMP_SCL=1;
DelayUs(5);
while(BMP_READ_SDA)
{
waitTime++;
DelayUs(1);
if(waitTime > BMP_ACK_WAIT_TIME)
{
ComStop();
return 1;
}
}
BMP_SCL = 0;
return 0; } static void ComSendAck(void)
{
BMP_SCL = 0;
BMP_SDA_OUT();
BMP_SDA = 0;
DelayUs(2);
BMP_SCL = 1;
DelayUs(5);
BMP_SCL = 0;
DelayUs(5);
} static void ComSendNoAck(void)
{
BMP_SCL = 0;
BMP_SDA_OUT();
BMP_SDA = 1;
DelayUs(2);
BMP_SCL = 1;
DelayUs(5);
BMP_SCL = 0;
DelayUs(5);
}
//返回0 写入收到ACK 返回1写入未收到ACK
static u8 ComSendByte(u8 byte)
{
u8 t;
BMP_SDA_OUT();
for(t=0;t<8;t++)
{
BMP_SDA=(byte&0x80)>>7;
byte<<=1;
BMP_SCL=1;
DelayUs(5);
BMP_SCL=0;
DelayUs(5);
}
return ComWaitAck();
} static void ComReadByte(u8* byte)
{
u8 i,receive=0;
BMP_SDA_IN();//SDA设置为输入
for(i=0;i<8;i++ )
{
receive <<= 1;
BMP_SCL=1;
DelayUs(5);
if(BMP_READ_SDA)receive++;
BMP_SCL=0;
DelayUs(5);
}
*byte = receive;
} /**************************BMP5883 IIC驱动函数*********************************/ //**************************************
//向I2C设备写入一个字节数据
//**************************************
u8 BmpWriteByte(u8 addr,u8 dataValue)
{
u8 res = 0;
ComStart(); //起始信号
res = ComSendByte(BMP085_ADDR); //发送设备地址+写信号
if(res)
{
#ifdef BMP085_DEBUG
printf("file=%s,func=%s,line=%d\r\n",__FILE__,__FUNCTION__,__LINE__);
#endif
return res;
}
res = ComSendByte(addr); //内部寄存器地址,
if(res)
{
#ifdef BMP085_DEBUG
printf("file=%s,func=%s,line=%d\r\n",__FILE__,__FUNCTION__,__LINE__);
#endif
return res;
}
res = ComSendByte(dataValue); //内部寄存器数据,
if(res)
{
#ifdef BMP085_DEBUG
printf("file=%s,func=%s,line=%d\r\n",__FILE__,__FUNCTION__,__LINE__);
#endif
return res;
}
ComStop(); //发送停止信号
return 0;
} //**************************************
//从I2C设备读取一个字节数据
//**************************************
u8 BmpReadByte(u8 addr,u8* data) //读取一个字节
{
u8 REG_data,res = 0;
ComStart(); //起始信号
res = ComSendByte(BMP085_ADDR); //发送设备地址+写信号
if(res)
{
#ifdef BMP085_DEBUG
printf("file=%s,func=%s,line=%d\r\n",__FILE__,__FUNCTION__,__LINE__);
#endif
return res;
}
res = ComSendByte(addr); //发送存储单元地址,从0开始
if(res)
{
#ifdef BMP085_DEBUG
printf("file=%s,func=%s,line=%d\r\n",__FILE__,__FUNCTION__,__LINE__);
#endif
return res;
}
ComStart(); //起始信号
res = ComSendByte(BMP085_ADDR+1); //发送设备地址+读信号
if(res)
{
#ifdef BMP085_DEBUG
printf("file=%s,func=%s,line=%d\r\n",__FILE__,__FUNCTION__,__LINE__);
#endif
return res;
}
ComReadByte(®_data); //读出寄存器数据
ComSendNoAck(); //接收应答信号
ComStop(); //停止信号
*data = REG_data;
return 0;
} s16 BmpReadTwoByte(u8 addr) //读出BMP085内部数据,连续两个
{
u8 msb, lsb;
short dataValue;
BmpReadByte(addr,&msb);
BmpReadByte(addr + 1,&lsb);
dataValue = ((short)msb)<<8;
dataValue |= lsb;
return dataValue;
} //获取校正参数,读出十一个字的校准系数**************
void BmpGetParam(BMP085PARAM* bmpParam)
{
bmpParam->ac1 = BmpReadTwoByte(BMP_AC1_ADDR);
bmpParam->ac2 = BmpReadTwoByte(BMP_AC2_ADDR);
bmpParam->ac3 = BmpReadTwoByte(BMP_AC3_ADDR);
bmpParam->ac4 = BmpReadTwoByte(BMP_AC4_ADDR);
bmpParam->ac5 = BmpReadTwoByte(BMP_AC5_ADDR);
bmpParam->ac6 = BmpReadTwoByte(BMP_AC6_ADDR);
bmpParam->b1 = BmpReadTwoByte(BMP_B1_ADDR);
bmpParam->b2 = BmpReadTwoByte(BMP_B2_ADDR);
bmpParam->mb = BmpReadTwoByte(BMP_MB_ADDR);
bmpParam->mc = BmpReadTwoByte(BMP_MC_ADDR);
bmpParam->md = BmpReadTwoByte(BMP_MD_ADDR);
} void BmpInit(void) //接口与参数初始化
{
BMP085IOInit();
BmpGetParam(&bmp085ParamStruct);
} //读取温度数据(未经过校正的)
s32 BmpReadTemp(void)
{
BmpWriteByte(CONTROL_REG_ADDR,BMP_COVERT_TEMP); //启动温度转换
DelayMs(5); //等待转换完成,最大转换4.5MS
return (s32)BmpReadTwoByte(BMP_TEMP_PRES_DATA_REG); //返回温度数据
} //读取压强数据未校正
s32 Bmp085ReadPressure(void)
{
s32 pressure = 0;
BmpWriteByte(CONTROL_REG_ADDR,BMP_COVERT_PRES_0); //启动温度转换
DelayMs(10); //等待转换完成,最大转换4.5MS,所以换算的时候要用OSS=0
pressure = (s32)BmpReadTwoByte(BMP_TEMP_PRES_DATA_REG); //返回压力数据,默认使用16字节压力数据
pressure &= 0x0000FFFF;
return pressure;
} //读取温度数据并校正转换
long BmpConvertTemp(void)
{
u32 ut;
long x1, x2, b5;
long temperature; ut = BmpReadTemp(); // 读取温度
x1 = (((long)ut - (long)bmp085ParamStruct.ac6)*(long)bmp085ParamStruct.ac5) >> 15;
x2 = ((long) bmp085ParamStruct.mc << 11) / (x1 + bmp085ParamStruct.md);
b5 = x1 + x2;
temperature = ((b5 + 8) >> 4); //温度计算,官方公式
#ifdef BMP085_DEBUG
printf("bmp085 temp is %f 'C\r\n",((float)temperature)/10.0);
#endif
return temperature;
} //读取压强数据并校正转换
long BmpConvertPressure(void)
{
unsigned int ut;
unsigned long up;
long x1, x2, b5, b6, x3, b3, p;
unsigned long b4, b7;
long pressure; ut = BmpReadTemp(); // 读取温度,计算压强时需要温度做参数
up = Bmp085ReadPressure(); // 读取压强 x1 = (((long)ut - (long)bmp085ParamStruct.ac6)*(long)bmp085ParamStruct.ac5) >> 15;
x2 = ((long)bmp085ParamStruct.mc << 11) / (x1 + bmp085ParamStruct.md);
b5 = x1 + x2; b6 = b5 - 4000;
// Calculate B3
x1 = (bmp085ParamStruct.b2 * (b6 * b6)>>12)>>11;
x2 = (bmp085ParamStruct.ac2 * b6)>>11;
x3 = x1 + x2;
b3 = (((((long)bmp085ParamStruct.ac1)*4 + x3)<<OSS) + 2)>>2; // Calculate B4
x1 = (bmp085ParamStruct.ac3 * b6)>>13;
x2 = (bmp085ParamStruct.b1 * ((b6 * b6)>>12))>>16;
x3 = ((x1 + x2) + 2)>>2;
b4 = (bmp085ParamStruct.ac4 * (unsigned long)(x3 + 32768))>>15; b7 = ((unsigned long)(up - b3) * (50000>>OSS));
if (b7 < 0x80000000)
p = (b7<<1)/b4;
else
p = (b7/b4)<<1; x1 = (p>>8) * (p>>8);
x1 = (x1 * 3038)>>16;
x2 = (-7357 * p)>>16;
pressure = p+((x1 + x2 + 3791)>>4); #ifdef BMP085_DEBUG
printf("bmp085 pressure is %f KPa\r\n",((float)pressure)/1000.0);
#endif
return pressure;
}
BMP085气压传感器驱动的更多相关文章
- Hadoop - 国内各站点最高温度、气压和风速统计
版权说明: 本文章版权归本人及博客园共同所有,转载请标明原文出处(http://www.cnblogs.com/mikevictor07/),以下内容为个人理解,仅供参考. 一.简介 该实例统计国内 ...
- 基于ARM-LINUX的温度传感器驱动-DS18B20
转载:http://blog.csdn.net/ayangke/article/details/6883244 作者:冯建,华清远见嵌入式学院讲师. DS18B20数字温度传感器接线方便,封装成后可应 ...
- Linux下18b20温度传感器驱动代码及测试实例
驱动代码: #include <linux/module.h> #include <linux/fs.h> #include <linux/kernel.h> #i ...
- 基于ARM-LINUX的温度传感器驱动(DS18B20) .
DS18B20数字温度传感器接线方便,封装成后可应用于多种场合,如管道式,螺纹式,磁铁吸附式,不锈钢封装式,型号多种多样,有LTM8877,LTM8874等等.主要根据应用场合的不同而改变其外观.封装 ...
- HCSR04超声波传感器驱动
HC_SR04是一款使用较为广泛的超声波测距模块,模块图如下 该模块具有四个引脚,分别为VCC GND TRIG ECHO,其中VCC GND为供电脚 TRIG为测距触发引脚,ECHO为测距输入引脚 ...
- HMC5883L地磁传感器驱动
霍尼韦尔 HMC5883L 是一种表面贴装的高集成模块,并带有数字接口的弱磁传感器芯片,应用于低成本罗盘和磁场检测领域.HMC5883L 包括最先进的高分辨率 HMC118X 系列磁阻传感器,并附带霍 ...
- ADXL345加速度传感器驱动
ADXL345 是 ADI 公司的一款 3 轴.数字输出的加速度传感器.ADXL345 是 ADI 公司推 出的基于 iMEMS 技术的 3 轴.数字输出加速度传感器.该加速度传感器的特点有: ...
- Linux嵌入式学习-烟雾传感器驱动-字符设备驱动-按键驱动
MQ-2烟雾气敏传感器模块在X210v3开发板上的驱动. 现在需要一个MQ-2烟雾气敏传感器模块的驱动.其检测烟雾超过一定的标准后,会返回一个不同的电平,和按键驱动差不多. 但是在编写驱动的时候,需要 ...
- multiwii 2.4配置页面中文注释
...
随机推荐
- 小师妹问 easyUI mergeCells 行合并后表头和内容对不齐
公司来了一个做easyUI的妹子,恰好那妹子是和我一个学校的,有一天下班妹子在超时买东西正好巧遇,然后妹子就问了问题,随便说手机卡需要我帮忙刷机,然后就问手机买了多久, 多少钱,刚买的时候好用不,然后 ...
- Android中图片占用内存的计算
Android中图片占用内存的计算 原文链接 http://blog.sina.com.cn/s/blog_4e60b09d01016133.html 在Android开发中,我现在发现很多人还不 ...
- js滚动条
/*滚动条在Y轴上的滚动距离*/function ScrollTop(){ var scrollTop = 0, bodyScrollTop = 0, documentScrollTop = 0; i ...
- springMVC拦截器简单配置
<!-- 拦截器 --> <mvc:interceptors> <mvc:interceptor> <!-- 拦截所 ...
- java设计原则:16种原则
一 类的设计原则 1 依赖倒置原则-Dependency Inversion Principle (DIP) 2 里氏替换原则-Liskov Substitution Principle (L ...
- HTNL5新增标签
我们来看一下HTML 5提供的一些新的标签用法以及和HTML 4的区别. <article>标签定义外部的内容.比如来自一个外部的新闻提供者的一篇新的文章,或者来自 blog 的文本,或者 ...
- EtherChannel Cisco 端口聚合详解
冗余连接及其实现 无论什么设备都无法保障运行的绝对稳定性,即使再优秀的产品也无法保证24×7不间断的工作.除去设备或模块损坏.传输线路中断等硬件故障原因以外,还可能由于网络流量过载.任务负荷过大而导致 ...
- 老问题:Android子线程中更新UI的3种方法
在Android项目中经常有碰到这样的问题,在子线程中完成耗时操作之后要更新UI,下面就自己经历的一些项目总结一下更新的方法: 方法一:用Handler 1.主线程中定义Handler: Handle ...
- vim的复制粘贴小结(转)
原文地址:http://lsong17.spaces.live.com/blog/cns!556C21919D77FB59!603.entry 内容: 用vim这么久 了,始终也不知道怎么在vim中使 ...
- FZU 2147 A-B Game(数学)
我们只需要知道这个取完模最大是 a / 2 + 1就可以了,不过超时了几次,换了visual C++才过,oj还真是傲娇啊. #include<iostream> #include< ...