1.测试描述:
使用模拟IIC,从BMP180中获取ID号、温度值、气压值以及计算海拔高度。
2.测试准备:
硬件平台:原子战舰V3开发板
测试工具:逻辑分析仪、串口调试工具
3.数据手册解读:
(1) 首先是多个字节的读取时序图,从这里也可以看出BMP180芯片的地址+写信号是0xEE,地址+读信号为0xEF,当然手册前面也有提到过,有兴趣的可以自己去查看一下手册。
(2) 然后本人测试时默认使用的是下图画横线部分的部分,也就是气压这块使用的是低功耗模式。OSS的值要注意,因为后期的计算需要这个,并且读取UT值时也要做对应的处理。
(3) 下图就是手册里给出的利用BMP180里的参数计算气压和温度的流程图。特别注意流程里的OSS,由于本测试使用的OSS = 0,所以在实际代码中省去了这一部分。
4.测试代码:
由于本工程是直接使用原子战舰的标准例程-库函数版本\实验23 IIC实验源码改过来的,所以模拟IIC部分使用的原子这块的代码。BMP180部分由本人编写。
(1) 首先是BMP180.C的代码片
#include "bmp180.h"
#include "delay.h"
#include "math.h"
//存储BMP180数据的结构
_bmp180 bmp180
//BMP180初始化
//对使用的IIC端口进行初始化
void BMP_Init(void)
{
IIC_Init()
}
//写一个数据到BMP180
void BMP_WriteOneByte(uint8_t WriteAddr,uint8_t DataToWrite)
{
IIC_Start()
IIC_Send_Byte(0xEE)
IIC_Wait_Ack()
IIC_Send_Byte(WriteAddr)
IIC_Wait_Ack()
IIC_Send_Byte(DataToWrite)
IIC_Wait_Ack()
IIC_Stop()
}
//从BMP180读一个字节数据
uint8_t BMP_ReadOneByte(uint8_t ReadAddr)
{
uint8_t data = 0
IIC_Start()
IIC_Send_Byte(0xEE)
IIC_Wait_Ack()
IIC_Send_Byte(ReadAddr)
IIC_Wait_Ack()
IIC_Start()
IIC_Send_Byte(0xEF)
IIC_Wait_Ack()
data = IIC_Read_Byte(1)
IIC_Stop()
return data
}
//从BMP180读一个16位的数据
short BMP_ReadTwoByte(uint8_t ReadAddr)
{
short data
uint8_t msb,lsb
IIC_Start()
IIC_Send_Byte(0xEE)
IIC_Wait_Ack()
IIC_Send_Byte(ReadAddr)
IIC_Wait_Ack()
IIC_Start()
IIC_Send_Byte(0xEF)
IIC_Wait_Ack()
msb = IIC_Read_Byte(1)
lsb = IIC_Read_Byte(0)
IIC_Stop()
data = msb*256 + lsb
return data
}
//从BMP180的获取计算参数
void BMP_ReadCalibrationData(void)
{
bmp180.AC1 = BMP_ReadTwoByte(0xAA)
bmp180.AC2 = BMP_ReadTwoByte(0xAC)
bmp180.AC3 = BMP_ReadTwoByte(0xAE)
bmp180.AC4 = BMP_ReadTwoByte(0xB0)
bmp180.AC5 = BMP_ReadTwoByte(0xB2)
bmp180.AC6 = BMP_ReadTwoByte(0xB4)
bmp180.B1 = BMP_ReadTwoByte(0xB6)
bmp180.B2 = BMP_ReadTwoByte(0xB8)
bmp180.MB = BMP_ReadTwoByte(0xBA)
bmp180.MC = BMP_ReadTwoByte(0xBC)
bmp180.MD = BMP_ReadTwoByte(0xBE)
}
//从BMP180读取未修正的温度
long BMP_Read_UT(void)
{
long temp = 0
BMP_WriteOneByte(0xF4,0x2E)
delay_ms(5)
temp = (long)BMP_ReadTwoByte(0xF6)
return temp
}
//从BMP180读取未修正的大气压
long BMP_Read_UP(void)
{
long pressure = 0
BMP_WriteOneByte(0xF4,0x34)
delay_ms(5)
pressure = (long)BMP_ReadTwoByte(0xF6)
//pressure = pressure + BMP_ReadOneByte(0xf8)
pressure &= 0x0000FFFF
return pressure
}
//用获取的参数对温度和大气压进行修正,并计算海拔
void BMP_UncompemstatedToTrue(void)
{
bmp180.UT = BMP_Read_UT()
bmp180.UT = BMP_Read_UT()
bmp180.UP = BMP_Read_UP()
bmp180.X1 = ((bmp180.UT - bmp180.AC6) * bmp180.AC5) >> 15
bmp180.X2 = (((long)bmp180.MC) << 11) / (bmp180.X1 + bmp180.MD)
bmp180.B5 = bmp180.X1 + bmp180.X2
bmp180.Temp = (bmp180.B5 + 8) >> 4
bmp180.B6 = bmp180.B5 - 4000
bmp180.X1 = ((long)bmp180.B2 * (bmp180.B6 * bmp180.B6 >> 12)) >> 11
bmp180.X2 = ((long)bmp180.AC2) * bmp180.B6 >> 11
bmp180.X3 = bmp180.X1 + bmp180.X2
bmp180.B3 = ((((long)bmp180.AC1) * 4 + bmp180.X3) + 2) /4
bmp180.X1 = ((long)bmp180.AC3) * bmp180.B6 >> 13
bmp180.X2 = (((long)bmp180.B1) *(bmp180.B6*bmp180.B6 >> 12)) >>16
bmp180.X3 = ((bmp180.X1 + bmp180.X2) + 2) >> 2
bmp180.B4 = ((long)bmp180.AC4) * (unsigned long)(bmp180.X3 + 32768) >> 15
bmp180.B7 = ((unsigned long)bmp180.UP - bmp180.B3) * 50000
if(bmp180.B7 < 0x80000000)
{
bmp180.p = (bmp180.B7 * 2) / bmp180.B4
}
else
{
bmp180.p = (bmp180.B7 / bmp180.B4) * 2
}
bmp180.X1 = (bmp180.p >> 8) * (bmp180.p >>8)
bmp180.X1 = (((long)bmp180.X1) * 3038) >> 16
bmp180.X2 = (-7357 * bmp180.p) >> 16
bmp180.p = bmp180.p + ((bmp180.X1 + bmp180.X2 + 3791) >> 4)
bmp180.altitude = 44330 * (1-pow(((bmp180.p) / 101325.0),(1.0/5.255)))
}
(2) 然后是BMP180.H部分
#ifndef _BMP180_H_
#define _BMP180_H_
#include "myiic.h"
typedef struct __BMP180
{
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;
long UT;
long UP;
long X1;
long X2;
long X3;
long B3;
unsigned long B4;
long B5;
long B6;
long B7;
long p;
long Temp;
float altitude;
}_bmp180;
extern _bmp180 bmp180;
void BMP_Init(void);
uint8_t BMP_ReadOneByte(uint8_t ReadAddr);
void BMP_WriteOneByte(uint8_t WriteAddr,uint8_t DataToWrite);
short BMP_ReadTwoByte(uint8_t ReadAddr);
void BMP_ReadCalibrationData(void);
long BMP_Read_UT(void);
long BMP_Read_UP(void);
void BMP_UncompemstatedToTrue(void);
#endif
由于是测试,所以将所有的参数都建了一个结构体,方便DEBUG时通过WATCH窗口查看,实际使用当中可以将一些非必要的参数做成临时变量。
5.测试时遇到的问题:
在BMP_UncompemstatedToTrue函数中,开头时首先读取UT和UP的值。开始时两者都只是读取一次,测算时发现UT值并未正确读出,为0,从而导致算出来的实际温度值在-71度左右,海拔在2500多米。通过逻辑分析仪监测,发现在第一次读取数据时,模拟IIC部分发出的数据是错误的。如下图画线处所示:
但是从图中可以看出,后面部分是正常的。针对这个现象我对延时、底层驱动模块都做了改变和测试,没有任何的改观。所以后面将UT值读取两次,就是为了消除这个错误,这也是一个折中的办法。经修改后实测读取正常。
6.测试结果:
本人在上海,平均海拔在4m的样子,温度值基本一致。由于海拔、温度、气压三者之间的联系,所以该气压也大致可以认定为测算出的实际大气压。
7.测试源码:
链接:https://pan.baidu.com/s/1qYmD2VU
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)