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配置页面中文注释
...
随机推荐
- robotframework常见问题解决汇总
1.select window 失效 当关闭弹出框后,回到原页面,或者关闭弹出框后,又弹出新的对话框,导致select window 失效,报错 window not found 在select wi ...
- XListview刷新和加载
//继承IXListViewListenerpublic class MainActivity extends Activity implements OnItemClickListener,IXLi ...
- TweenMax说明
TweenMax 采用了与它的兄弟相似的易于学习的语法结构.实事上,因为它扩展自它们,TweenMax 可以做任何 TweenLite 和/或者 TweenFilterLite 能做的事,还加上了更多 ...
- Python里如何实现C中switch...case的功能
python没有switch case 不过可以通过建立字典实现类似的功能 例子:根据输入的年月日,判断是该年中的第几天 y = int(input('请输入年:')) m = int(input(' ...
- UVA 10200 Prime Time (打表)
题目链接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem ...
- 困扰你的private static final long serialVersionUID
很多时候一个新手在写代码的时候,往往你的IDE就会告诉你一个警告 然后你点击处理这个警告之后,它就会默认给你的类生成一个 private static final long serialVersion ...
- 参数修饰符ref,out ,params的区别
参数修饰符ref,out ,params的区别 C#中有三个关键字-ref,out ,params,可是这三个之间的区别你都明白了吗? 那么我们就来认识一下参数修饰符ref,out ,params吧, ...
- java打jar包
一.打包jar文件 1 如果是class文件 jar cvf myjar.jar Foo.class Bar.class 如果是包 jar cvf myjar.jar pac ...
- 关于jsp页面 title中文乱码问题的解决方法
我知道了 我jsp饮用了html 是我2个页面都写了Title 然后冲突了 就乱码了 分享给大家
- 使用FusionCharts出柱状图和饼状图
在最近的项目中,需要使用出图,能够查看柱状图,饼状图等效果,刚开始我们用JS写的效果,发现效果不理想,找了一个JS插件发现效果还是不理想,客户也不满意,客户希望要很炫的效果,最后我们使用了Fusion ...