BMP180.C文件
#include "N76E003.h"
#include "Common.h"
#include "Delay.h"
#include "SFR_Macro.h"
#include "Function_define.h"
#include "bmp180.h"
#include <math.h> //Keil library
#include <stdlib.h> //Keil library
#include <stdio.h> //Keil library
#include <INTRINS.H> //Keil library
#define uchar unsigned char
#define uint unsigned int
#define BMP085_SlaveAddress 0xee //定义器件在IIC总线中的从地址
#define OSS 0 // Oversampling Setting (note: code is not set up to use other OSS values)
long temperature;//温度值
long pressure; //压力值
long height; //相对海拔高度值
int dis_data;
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;
void Delay5us() //5us延时(不怎么准)
{
nop;
nop; nop; nop; nop; nop; nop; nop; nop;
nop;
nop; nop; nop; nop; nop; nop; nop; nop;
nop;
nop; nop; nop; nop; nop; nop; nop; nop;
nop;
nop; nop; nop; nop; nop; nop; nop; nop;
nop;
nop; nop; nop; nop; nop; nop; nop; nop;
}
/**************************************
起始信号
**************************************/
void BMP085_Start()
{
SDA = 1; //拉高数据线
SCL = 1; //拉高时钟线
Delay5us(); //延时
SDA = 0; //产生下降沿
Delay5us(); //延时
SCL = 0; //拉低时钟线
}
///**************************************
//停止信号
//**************************************/
void BMP085_Stop()
{
SDA = 0; //拉低数据线
SCL = 1; //拉高时钟线
Delay5us(); //延时
SDA = 1; //产生上升沿
Delay5us(); //延时
}
///**************************************
//发送应答信号
//入口参数:ack (0:ACK 1:NAK)
//**************************************/
void BMP085_SendACK(bit ack)
{
SDA = ack; //写应答信号
SCL = 1; //拉高时钟线
Delay5us(); //延时
SCL = 0; //拉低时钟线
Delay5us(); //延时
}
///**************************************
//接收应答信号
//**************************************/
bit BMP085_RecvACK()
{
SCL = 1; //拉高时钟线
Delay5us(); //延时
CY = SDA; //读应答信号
SCL = 0; //拉低时钟线
Delay5us(); //延时
return CY;
}
///**************************************
//向IIC总线发送一个字节数据
//**************************************/
void BMP085_SendByte(unsigned char dat)
{
unsigned char i;
for (i=0; i<8; i++) //8位计数器
{
dat <<= 1; //移出数据的最高位
SDA = CY; //送数据口
SCL = 1; //拉高时钟线
Delay5us(); //延时
SCL = 0; //拉低时钟线
Delay5us(); //延时
}
BMP085_RecvACK();
}
///**************************************
//从IIC总线接收一个字节数据
//**************************************/
unsigned char BMP085_RecvByte()
{
unsigned char i;
unsigned char dat = 0;
SDA = 1; //使能内部上拉,准备读取数据,
for (i=0; i<8; i++) //8位计数器
{
dat <<= 1;
SCL = 1; //拉高时钟线
Delay5us(); //延时
dat |= SDA; //读数据
SCL = 0; //拉低时钟线
Delay5us(); //延时
}
return dat;
}
////*********************************************************
////读出BMP085内部数据,连续两个
////*********************************************************
short Multiple_read(uchar ST_Address)
{
uchar 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(0); //回应ACK
lsb = BMP085_RecvByte();
BMP085_SendACK(1); //最后一个数据需要回NOACK
BMP085_Stop(); //停止信号
Timer0_Delay1ms(5);
_data = msb << 8;
_data |= lsb;
return _data;
}
////********************************************************************
//读函数数据
//**********************************************************************
long bmp085ReadTemp(void)
{
BMP085_Start(); //起始信号
BMP085_SendByte(BMP085_SlaveAddress); //发送设备地址+写信号
BMP085_SendByte(0xF4); // write register address
BMP085_SendByte(0x2E); // write register data for temp
BMP085_Stop(); //发送停止信号
Timer0_Delay1ms(10); // max time is 4.5ms
return (long) Multiple_read(0xF6);
}
////*************************************************************
//读气压数据
//**************************************************************
long bmp085ReadPressure(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(); //发送停止信号
Timer0_Delay1ms(10); // max time is 4.5ms
pressure = Multiple_read(0xF6);
pressure &= 0x0000FFFF;
return pressure;
}
////**************************************************************
////初始化BMP180,根据需要请参考pdf进行修改**************
void Init_BMP085()
{
ac1 = Multiple_read(0xAA);
ac2 = Multiple_read(0xAC);
ac3 = Multiple_read(0xAE);
ac4 = Multiple_read(0xB0);
ac5 = Multiple_read(0xB2);
ac6 = Multiple_read(0xB4);
b1 = Multiple_read(0xB6);
b2 = Multiple_read(0xB8);
mb = Multiple_read(0xBA);
mc = Multiple_read(0xBC);
md = Multiple_read(0xBE);
}
////*****************************************************
//数据转换函数
//*******************************************************
void bmp085Convert()
{
unsigned int ut;
unsigned long up,b4, b7;
long x1, x2,x3;
long b5,b6,b3;
long p;
ut = bmp085ReadTemp(); // 读取温度
up = bmp085ReadPressure(); // 读取压强
x1 = (((long)ut - (long)ac6)*(long)ac5) >> 15;
x2 = ((long) mc << 11) / (x1 + md);
b5 = x1 + x2;
temperature = ((b5 + 8) >> 4);
b6 = b5 - 4000;
// Calculate B3
x1 = (b2 * (b6 * b6)>>12)>>11;
x2 = (ac2 * b6)>>11;
x3 = x1 + x2;
b3 = (((((long)ac1)*4 + x3)<<OSS) + 2)>>2;
// Calculate B4
x1 = (ac3 * b6)>>13;
x2 = (b1 * ((b6 * b6)>>12))>>16;
x3 = ((x1 + x2) + 2)>>2;
b4 = (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);
height=(101325-pressure)*9;//转化得到绝对高度
}
以下是BMP180的头文件
#ifndef _bmp180_h_
#define _bmp180_h_
extern long temperature;
extern long pressure;
extern long height;
void Init_BMP085();//初始化BMP180
void bmp085Convert();//数据转换
#endif
主程序——通过串口0发送温度与气压数据
(PS:定时器1不要再BMP180中使用,会造成串口1无法使用)
#include "N76E003.h"
#include "Common.h"
#include "Delay.h"
#include "SFR_Macro.h"
#include "Function_define.h"
#include "BMP180.h"
#define uint unsigned int
#define uchar unsigned char
uchar abc[14];
void main (void)
{
int i;
Set_All_GPIO_Quasi_Mode;
LED=1;
set_P06;//初始化串口1管脚
set_P07;
//----------串口1、串口0配置----------------
InitialUART0_Timer1(9600);
EA = 1; //开启总中断
while(1)
{
Init_BMP085();//初始化BMP180
bmp085Convert();//数据转换
abc[3]=0x54;//字符“T”
abc[4]=temperature/100+48;
abc[5]=temperature%100/10+48;
abc[6]=0x2e;//字符“.”
abc[7]=temperature%10+48;
abc[8]=0x50;//P
abc[9]=pressure/10000+48;
abc[10]=pressure%10000/1000+48;
abc[11]=pressure%1000/100+48;
for(i=3;i<12;i++)
{
Send_Data_To_UART0(abc[i]);//发送温度与气压
}
}
}
因为我的程序是进入低功耗模式,每小时自动唤醒一次,进行测量,所以前面还有湿度数据,请自动忽略。(经测量温度数据与DHT11接近,气压数据小米3自带的气压计接近)
PS:keil编译器记得将内存模式调到Large,否则在数据转换时的long型数据可能会报错。