这是我想的BMP180程序,串口输出测量值。检测到的温度总是错误的,气压也没有问题。海拔高度的计算是从网上挑选出来的。让我们一起交流,集思广益。
#include
#include
#include
#define uchar unsigned char
#define uint unsigned int
sbit SDA=P1^0;
sbit SCL=P1^1;
uchar code Comd0[]="temp:";
uint tempre[6];
#define OSS 1 // 过采样设置,(OSS0,1,2,3)
long temperature=0; //温度值
long pressure=0; //压力值
float height=0; //相对海拔高度值
short ac1;
short ac2;
short ac3;
short ac4;
short ac5;
short ac6;
short b1;
short b2;
short mb;
short mc;
short md;
void Some_Nop()
{
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
}
void Delay_ms(uchar i)
{
uint j;
for(;i>0;i--)
for(j=0;j<124;j );
}
void Delay_s() //延时1s
{
uchar i;
for(i=0;i<20;i )
{
TH0=0x4c;
TL0=0x00;
TR0=1;
while(TF0==0);TF0=0;
TR0=0;
}
}
/*************** I2C *******************/
/*****************************************************/
void I2C_init() //I2C初始化
{
SDA=1;
SCL=1;
}
void I2C_Start() //I2C开始
{
SDA=1;
Some_Nop();
SCL=1;
Some_Nop();
SDA=0;
Some_Nop();
SCL=0;
_nop_();
}
void I2C_Stop() //I2C结束
{
SDA=0;
Some_Nop();
SCL=1;
Some_Nop();
SDA=1;
Some_Nop();
}
void I2C_ACK(bit a)
{
if(a==1) SDA=0; /*在此发出响应或非响应信号,ack=1,发送数据正常;ack=0表示被控器没有回应或损坏。 */
else SDA=1;
_nop_();
_nop_();
SCL=1;
Some_Nop(); //保持数据时间 , 即SCL时间大于4.7μs
SCL=0; //清时钟线,钳住I2C继续接收总线
_nop_();
_nop_();
}
void I2C_WriteByte(uint date) //I2C主机写从机地址,命令
{
uint i;
SCL=0;
Some_Nop();
for(i=0;i<8;i )
{
if(date&0x80) SDA=1; /*判断发送位*/
elseSDA=0;
_nop_();
SCL=1; /*时钟线高,通知被控器接收数据位*/
date<<=1;
Some_Nop();
SCL=0;
}
SDA=1; //释放SDA,接收应答
_nop_();
_nop_();
}
unsigned int I2C_ReadByte() //I2C读从机发送的数据
{
uchar i;
uint k=0;
SDA=1;
for(i=0;i<8;i )
{
SCL=0;
Some_Nop();
SCL=1;
if(SDA==1) k |=0x01; /*读取数据位,将接收到的数据位放入k中 */
k = k << 1;
}
SCL=0;
return k;
}
/* 读出BMP180内部数据,MSB、LSB */
/*********************************************************/
int Multiple_read0(uchar ST_Address)
{
//uchar st_Address;
long _data0;
long MSB=0;
long LSB=0;
<>I2C_Start(); //起始信号I2C_WriteByte(0xee); //发送设备地址,写信号
I2C_ACK(1); //应答
I2C_WriteByte(ST_Address); //发送存储单元地址
I2C_ACK(1); //应答
I2C_Start(); //重新起始信号
I2C_WriteByte(0xef); //发送设备地址+读信号
I2C_ACK(1); //应答
MSB = I2C_ReadByte();
I2C_ACK(1); //应答
LSB = I2C_ReadByte();
I2C_ACK(0);
I2C_Stop();
_data0 = (MSB << 8)|(LSB);
return _data0;
}
void Init_BMP180() //BMP180初始化
{
ac1 = Multiple_read0(0xAA);
ac2 = Multiple_read0(0xAC);
ac3 = Multiple_read0(0xAE);
ac4 = Multiple_read0(0xB0);
ac5 = Multiple_read0(0xB2);
ac6 = Multiple_read0(0xB4);
b1 = Multiple_read0(0xB6);
b2 = Multiple_read0(0xB8);
mb = Multiple_read0(0xBA);
mc = Multiple_read0(0xBC);
md = Multiple_read0(0xBE);
}
//**********************读温度**********************
int bmp180ReadTemp(void)
{
int Tempreture = 0;
I2C_Start(); //起始信号
I2C_WriteByte(0xee); //发送设备地址,写信号
I2C_ACK(1);
I2C_WriteByte(0xF4); // 存储单元地址
I2C_ACK(1);
I2C_WriteByte(0x2E); // 向存储单元写入0x2e
I2C_ACK(0);
I2C_Stop(); //发送停止信号
Delay_ms(4); //等待4.5ms
Tempreture = Multiple_read0(0xF6);
//Tempreture = 0x00001111;
return Tempreture;
}
//**********************读气压****************************
long bmp180ReadPressure(void)
{
long Pressure = 0;
long msb=0;
int lsb=0;
int XLSB=0;
I2C_Start(); //起始信号
I2C_WriteByte(0xee); //发送设备地址,写信号
I2C_ACK(1);
I2C_WriteByte(0xF4); // 存储单元地址
I2C_ACK(1);
I2C_WriteByte(0x34+(OSS<<6)); // 向存储单元写入0x34+(OSS<<6)
I2C_ACK(0);
I2C_Stop(); //发送停止信号
Delay_ms(2+2*OSS); //等待
I2C_Start(); //起始信号
I2C_WriteByte(0xee); //发送设备地址,写信号
I2C_ACK(1);
I2C_WriteByte(0xF6);
I2C_ACK(1);
I2C_Start(); //重新起始信号
I2C_WriteByte(0xef); //发送设备地址,读信号
I2C_ACK(1);
msb = I2C_ReadByte();
I2C_ACK(1);
lsb = I2C_ReadByte();
I2C_ACK(1);
XLSB = I2C_ReadByte();
I2C_ACK(0);
I2C_Stop(); //发送停止信号
Pressure = (msb<<16 | lsb<<8 | XLSB)>>(8-OSS);
return Pressure;
}
//**************************************************
void bmp180_Calculate()
{
long x1, x2, x3, b3, b5, b6, b7, p, ut, up;
unsigned long b4;
ut = bmp180ReadTemp(); // 读取温度数据
up = bmp180ReadPressure(); // 读取压强数据
x1 = ((ut - 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)<>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;
}
void serial_init() //串口初始化
{
TMOD=0x21; //T1工作方式2,用于波特率发生器
TH1=0xf3; //12MHz 波特率2400bps
TL1=0xf3;
PCON &=0x7f; //波特率不倍增
SCON=0x50; //允许发送接收
ES=1; //允许串口中断
EA=1; //开总中断
TR1=1; //启动波特率发生
}
void putchar(unsigned char c)
{
SBUF=c;
while(!TI); //等待发送完成
TI=0; //清除TI标志,准备下次发送
}
void Next()
{
putchar(0x0d);
putchar(0x0a);
}
int main(void)
{
uchar i;
uchar j;
I2C_init();
Init_BMP180();
serial_init();
while(1)
{
Delay_s();
for(i=0;i<5;i++)
putchar(Comd0[i]); //发送命令0
bmp180_Calculate();
tempre[0]= 0x30+ temperature / 100;
tempre[1]= 0x30+ temperature / 100%10;
tempre[2]= 0x2e;
tempre[3]= 0x30+ temperature % 10;
tempre[4]= 0x60;
tempre[5]= 0x43;
for(j=0;j<6;j++)
putchar(tempre[j]);
Next();
}
}