Arduino 开源代码——BMP180 程序(三)程序源码

1.项目描述:

使用硬 IIC 口,从 BMP180 中获取温度、气压以及海拔高度值。

2.项目准备

Arduino nano 板、BMP180 模组、Arduino IDE。
Arduino 是我非常喜欢的一款 IDE,C++ 语法特性让我在设计以及使用的时候非常方便。同时在工作中,如果需要快速开发做演示,我也很喜欢使用 Arduino。走量产项目的话,还是不推荐它。

3.数据手册解读

http://read.pudn.com/downloads707/sourcecode/others/2839579/GY68BMP180/相关数据手册/BST-BMP180-DS000-07.pdf

BMP180 寄存器

在上一篇我们讲解了 BMP180 的工作环境和电气性能。我们知晓 BMP180 是通过 IIC 进行操作的,那么这章我们就可以开始介绍 BMP180 的寄存器。
Arduino 开源代码——BMP180 程序(一)器件选型须知
Arduino 开源代码——BMP180 程序(二)寄存器介绍

程序源码

其实根据上一章我们就能自己进行操作了。但是,本源码用浮点数而不是BMP发表的整数。
原手册都是建立在整数的基础上,在使用除法时候很容易被四舍五入导致结果偏差过大。
本源码采取的浮点数不受这个问题和修正的影响,会随输入值的变化而平稳地变化(同样也是不精准的,与整数不精准的原理不同)。也使得方程更简单,更容易实现,减少计算误差。
参考 http://wmrx00.sourceforge.net/Arduino/BMP085-Calcs.pdf (需要自备梯子)

IIC代码

本代码采取了更多的是C++思想,C程序员C++没学过就请多查询资料。

Object_IIC.h

/*!
 * @file Object_IIC.h
 * @n IIC族顶层父类
 *
 *
 * @author [郑振静]([email protected])
 * @version  V1.0
 * @date  2019-04-24
 */
#ifndef ZZJ_OBJECT_IIC_H
#define ZZJ_OBJECT_IIC_H


#include "Wire.h"
#include "Object.h"

namespace ZZJ_LIB
{

	class Object_IIC:public Object
	{

	protected:
		uint8_t m_address;                                          //I2C地址
		uint8_t m_chipid;                                           //芯片id
		bool    m_begin_flag;                                       //初始化成功标志


		virtual bool      config(uint8_t reg_chipid);                                            //读取芯片ID和与预设芯片ID是否相同
		virtual void      write1(uint8_t reg, uint8_t bitNum,uint8_t value);                     //I2C写value到reg寄存器中第bitNum位中
		virtual void   writes(uint8_t reg, uint8_t bitStart, uint8_t length,uint8_t value);   //I2C写value到reg寄存器中第bitStart位开始后length个位
		virtual void      write8(uint8_t reg, uint8_t value);                                    //I2C写8个位的value到reg寄存器中
		virtual uint8_t   read1(uint8_t reg, uint8_t bitNum);                                    //I2C读取reg寄存器的第bitNum位
		virtual uint8_t   reads(uint8_t reg, uint8_t bitStart, uint8_t length);                  //I2C读取reg寄存器的第bitStart位开始后length个位
		virtual uint8_t   read8(uint8_t reg);                                                    //I2C读取reg寄存器的8位
		virtual uint16_t  read16(uint8_t reg);                                                   //I2C读取reg寄存器的16位
		virtual uint32_t  read24(uint8_t reg);                                                   //I2C读取reg寄存器的24位
		virtual int16_t   readS16(uint8_t reg);
		virtual uint16_t  read16_LE(uint8_t reg);                                                //I2C大段模式读取reg寄存器的16位数据返回
		virtual int16_t   readS16_LE(uint8_t reg);

	};
	
}

#endif

Object_IIC.c

#include "Object_IIC.h"
namespace ZZJ_LIB
{
	/***********************************************

			 检测是否连接和设置是否正确
		  读取芯片ID和与预设芯片ID是否相同
				相同返回true否则false

	***********************************************/
	bool Object_IIC::config(uint8_t reg_chipid)           
	{
		bool ret = false;
   Serial.println(read8(reg_chipid));
		if (read8(reg_chipid) == m_chipid) {
			ret = true;
		}
		return ret;
	}

	/***********************************************

				给寄存器写数据和读数据

	***********************************************/
	void Object_IIC::write1(uint8_t reg, uint8_t bitNum,uint8_t value)
	{
		uint8_t temp;
		temp = read8(reg);
		temp = (value != 0) ? (temp | (1 << bitNum)) : (temp & ~(1 << bitNum));
		write8(reg,temp);
	}
	
	void Object_IIC::writes(uint8_t reg, uint8_t bitStart, uint8_t length,uint8_t value)
	{
		uint8_t temp;
		uint8_t data;
		data = read8(reg);
		temp = ((1 << length) - 1) << (bitStart - length + 1);
		temp = ~(temp);
		data &= temp;
		data += value << (bitStart - length + 1);
		write8(reg,data);
	}
	
	void Object_IIC::write8(uint8_t reg, uint8_t value)
	{
		Wire.beginTransmission((uint8_t)m_address);
		Wire.write((uint8_t)reg);
		Wire.write((uint8_t)value);
		Wire.endTransmission();
	}


    uint8_t Object_IIC::read1(uint8_t reg, uint8_t bitNum)
	{
		uint8_t value;
		uint8_t ret;
		
		value = read8(reg);
		ret = value & (1 << bitNum);
		return ret;
	}
	
	uint8_t Object_IIC::reads(uint8_t reg, uint8_t bitStart, uint8_t length)
	{
		uint8_t value;
		uint8_t ret;
		
		value = read8(reg);
		ret = value & ((1 << length) - 1) << (bitStart - length + 1);
		ret >>= (bitStart - length + 1); 
		return ret;
	}
	
	uint8_t Object_IIC::read8(uint8_t reg)
	{
		uint8_t value;

		Wire.beginTransmission((uint8_t)m_address);
		Wire.write((uint8_t)reg);
		Wire.endTransmission();
		Wire.requestFrom((uint8_t)m_address, (byte)1);
		value = Wire.read();

		return value;
	}

	uint16_t Object_IIC::read16(uint8_t reg)
	{
		uint16_t value;

		Wire.beginTransmission((uint8_t)m_address);
		Wire.write((uint8_t)reg);
		Wire.endTransmission();
		Wire.requestFrom((uint8_t)m_address, (byte)2);
		value = (Wire.read() << 8) | Wire.read();

		return value;
	}

	uint16_t Object_IIC::read16_LE(uint8_t reg) {
		uint16_t temp = read16(reg);
		return (temp >> 8) | (temp << 8);
	}

	int16_t Object_IIC::readS16(uint8_t reg)
	{
		return (int16_t)read16(reg);
	}

	int16_t Object_IIC::readS16_LE(uint8_t reg)
	{
		return (int16_t)read16_LE(reg);
	}

	uint32_t Object_IIC::read24(uint8_t reg)
	{
		uint32_t value;

		Wire.beginTransmission((uint8_t)m_address);
		Wire.write((uint8_t)reg);
		Wire.endTransmission();
		Wire.requestFrom((uint8_t)m_address, (byte)3);

		value = Wire.read();
		value <<= 8;
		value |= Wire.read();
		value <<= 8;
		value |= Wire.read();

		return value;
	}

}

BMP180代码

BMP180_IIC.h

/*!
   @file BMP180_IIC.h
   @n BMP180_IIC获取温度,气压


   @author [郑振静]([email protected])
   @version  V1.0
   @date  2019-04-24
*/
#ifndef ZZJ_BMP180_IIC_H
#define ZZJ_BMP180_IIC_H

#include "Object_IIC.h"


#define BMP180_ADDR                      0X77
#define BMP180_CHIPID                    0X55

/***********************************************
                寄存器向量表
***********************************************/
#define BMP180_R_REG_XLSB                0XF8              //用于读写16位数据
#define BMP180_R_REG_LSB                 0XF7              
#define BMP180_R_REG_MSB                 0XF6              

#define	BMP180_RW_REG_MEAS               0XF4              //用于设置模式,检测工作,测量控制
#define	BMP180_RW_REG_RESULT             0XE0              //用于复位
#define BMP180_R_REG_CHIPID              0XD0              //读取芯片ID寄存器

#define BMP180_R_REG_AC1_S               0XAA              //校准系数......
#define BMP180_R_REG_AC1_E               0XAB
#define BMP180_R_REG_AC2_S               0XAC
#define BMP180_R_REG_AC2_E               0XAD
#define BMP180_R_REG_AC3_S               0XAE
#define BMP180_R_REG_AC3_E               0XAF
#define BMP180_R_REG_AC4_S               0XB0
#define BMP180_R_REG_AC4_E               0XB1
#define BMP180_R_REG_AC5_S               0XB2
#define BMP180_R_REG_AC5_E               0XB3
#define BMP180_R_REG_AC6_S               0XB4
#define BMP180_R_REG_AC6_E               0XB5
#define BMP180_R_REG_B1_S                0XB6
#define BMP180_R_REG_B1_E                0XB7
#define BMP180_R_REG_B2_S                0XB8
#define BMP180_R_REG_B2_E                0XB9
#define BMP180_R_REG_MB_S                0XBA
#define BMP180_R_REG_MB_E                0XBB
#define BMP180_R_REG_MC_S                0XBC
#define BMP180_R_REG_MC_E                0XBD
#define BMP180_R_REG_MD_S                0XBE
#define BMP180_R_REG_MD_E                0XBF

/***********************************************
         设置模式常量值
         BMP180_RW_REG_MEAS
***********************************************/
#define BMP180_MODE_BIT                  07             
#define BMP180_MODE_LENGTH               02
#define BMP180_ULTRA_LOW_POWER           0              //超低功耗模式
#define BMP180_STANDARD                  1              //标准模式
#define BMP180_HIGH_RESOLUTION           2              //高分辨率模式
#define BMP180_ULTRA_HIGH_RESOLUTION     3              //超高分辨率模式

#define BMP180_CONVERSION_TIME_BIT       04
#define BMP180_CONVERSION_TIME_LENGTH    05
#define BMP180_COMMAND_TEMPERATURE       46             //温度时等待时长
#define BMP180_COMMAND_PRESSURE0         52             //超低功耗模式,气压等待时长
#define BMP180_COMMAND_PRESSURE1         116            //标准模式,气压等待时长
#define BMP180_COMMAND_PRESSURE2         180            //高分辨率模式,气压等待时长
#define BMP180_COMMAND_PRESSURE3         244            //超高分辨率模式,气压等待时长

namespace ZZJ_LIB
{
struct bmp180_data_s
{
  double bmp180_c5;
  double bmp180_c6;
  double bmp180_mc;
  double bmp180_md;
  double bmp180_x0;
  double bmp180_x1;
  double bmp180_x2;
  double bmp180_y0;
  double bmp180_y1;
  double bmp180_y2;
  double bmp180_p0;
  double bmp180_p1;
  double bmp180_p2;

  double bmp180_UT;
  double bmp180_UP;
};

struct bmp180_open_data_s
{
  double bmp180_T;
  double bmp180_P;
};

class BMP180_IIC : public Object_IIC
{

  private:

    bool m_getTemp_flag;
    uint8_t m_mode;
    double init_pressure;
    bmp180_data_s m_bmp180_data;
    bmp180_open_data_s m_bmp180_open_data;                                                        //暂时为共有成员方便调试。

    bool initMode(uint8_t mode);                                                          //初始化模式                                                 //尝试是否初始化成功

    void getCalParam();                                                                   //获取校准系数
    void getUT();                                                                         //获取温度系数
    void getUP();                                                                         //获取气压系数
  public:

    BMP180_IIC();
    bool  begin(uint8_t addr = BMP180_ADDR, uint8_t chipid = BMP180_CHIPID, uint8_t mode = BMP180_STANDARD);         //初始化BMP280,初始化成功返回true
    
    float   getTemperature(void);                                                     //获取温度值
    float   getPressure(void);                                                        //获取气压值
    float   getAltitude(float seaLevelhPa = 1013.25);                                 //获取海拔值
    float   getHeight();                                                              //获取高度
    uint8_t getMode();                                                                //获取当前模式
};


}
#endif

BMP180_IIC.c

#include "BMP180_IIC.h"
#include 
namespace ZZJ_LIB
{

BMP180_IIC::BMP180_IIC()
{
  m_begin_flag = false;                  //设置初始化标志信息,防止重复初始化
}

bool  BMP180_IIC::begin(uint8_t addr, uint8_t chipid, uint8_t mode)
{
  bool ret = false;
  m_chipid = chipid;
  m_address = addr;
  m_mode = mode;

  Wire.begin();

  if (!m_begin_flag)
  {
    delay(1000);
    ret = config(BMP180_R_REG_CHIPID);//获取初始化是否成功
    
    m_begin_flag = true;
  }
  if (ret)
    ret = (initMode(m_mode) ? 1 : 0);
  if (ret)
    getCalParam();
  init_pressure = getPressure();
  return ret;
}

bool  BMP180_IIC::initMode(uint8_t mode)
{
  bool ret = false;
  uint8_t meas = read8(BMP180_RW_REG_MEAS);
  meas &= ~(3 << 6);
  write8(BMP180_RW_REG_MEAS, mode << 6 | (meas));
  ret = true;
  return ret;
}

uint8_t  BMP180_IIC::getMode()
{
  uint8_t ret;
  uint8_t meas = read8(BMP180_RW_REG_MEAS);
  ret = meas >> 6;
  return ret;
}

void  BMP180_IIC::getCalParam()
{
  int16_t bmp180_AC1 = read16(BMP180_R_REG_AC1_S);
  int16_t bmp180_AC2 = read16(BMP180_R_REG_AC2_S);
  int16_t bmp180_AC3 = read16(BMP180_R_REG_AC3_S);
  uint16_t bmp180_AC4 = read16(BMP180_R_REG_AC4_S);
  uint16_t bmp180_AC5 = read16(BMP180_R_REG_AC5_S);
  uint16_t bmp180_AC6 = read16(BMP180_R_REG_AC6_S);
  int16_t bmp180_B1  = read16(BMP180_R_REG_B1_S);
  int16_t bmp180_B2  = read16(BMP180_R_REG_B2_S);
  int16_t bmp180_MB  = read16(BMP180_R_REG_MB_S);
  int16_t bmp180_MC  = read16(BMP180_R_REG_MC_S);
  int16_t bmp180_MD  = read16(BMP180_R_REG_MD_S);
  double c3 = 160.0 * pow(2, -15) * bmp180_AC3;
  double c4 = pow(10, -3) * pow(2, -15) * bmp180_AC4;
  double b1 = pow(160, 2) * pow(2, -30) * bmp180_B1;
  m_bmp180_data.bmp180_c5 = (pow(2, -15) / 160) * bmp180_AC5;
  m_bmp180_data.bmp180_c6 = bmp180_AC6;
  m_bmp180_data.bmp180_mc = (pow(2, 11) / pow(160, 2)) * bmp180_MC;
  m_bmp180_data.bmp180_md = bmp180_MD / 160.0;
  m_bmp180_data.bmp180_x0 = bmp180_AC1;
  m_bmp180_data.bmp180_x1 = 160.0 * pow(2, -13) * bmp180_AC2;
  m_bmp180_data.bmp180_x2 = pow(160, 2) * pow(2, -25) * bmp180_B2;
  m_bmp180_data.bmp180_y0 = c4 * pow(2, 15);
  m_bmp180_data.bmp180_y1 = c4 * c3;
  m_bmp180_data.bmp180_y2 = c4 * b1;
  m_bmp180_data.bmp180_p0 = (3791.0 - 8.0) / 1600.0;
  m_bmp180_data.bmp180_p1 = 1.0 - 7357.0 * pow(2, -20);
  m_bmp180_data.bmp180_p2 = 3038.0 * 100.0 * pow(2, -36);

}
void BMP180_IIC::getUT()
{
  uint8_t meas = BMP180_COMMAND_TEMPERATURE;
  meas &= ~(3 << 6);
  meas = m_mode << 6 | (meas);
  write8(BMP180_RW_REG_MEAS, meas);
  delay(5);
  uint32_t T_MSB = read8(BMP180_R_REG_MSB);
  uint32_t T_LSB = read8(BMP180_R_REG_LSB);
  m_bmp180_data.bmp180_UT = (T_MSB << 8) + T_LSB;
}
void BMP180_IIC::getUP()
{
  switch (m_mode)
  {
    case 0: write8(BMP180_RW_REG_MEAS, BMP180_COMMAND_PRESSURE0 ); delay(5); break;
    case 1: write8(BMP180_RW_REG_MEAS, BMP180_COMMAND_PRESSURE1 ); delay(8); break;
    case 2: write8(BMP180_RW_REG_MEAS, BMP180_COMMAND_PRESSURE2 ); delay(14); break;
    case 3: write8(BMP180_RW_REG_MEAS, BMP180_COMMAND_PRESSURE3 ); delay(26); break;
  }
  uint32_t P_MSB = read8(BMP180_R_REG_MSB);
  uint32_t P_LSB = read8(BMP180_R_REG_LSB);
  uint32_t P_XLSB = read8(BMP180_R_REG_XLSB);
  m_bmp180_data.bmp180_UP = ( (P_MSB << 8) + P_LSB  + (P_XLSB  >> 8));
}
float BMP180_IIC::getTemperature(void)
{
  float ret = -404;
  getUT();
  double temp_a = m_bmp180_data.bmp180_c5 * (m_bmp180_data.bmp180_UT - m_bmp180_data.bmp180_c6);
  ret = temp_a + (m_bmp180_data.bmp180_mc / (temp_a + m_bmp180_data.bmp180_md));
  m_getTemp_flag = 1;
  m_bmp180_open_data.bmp180_T = ret;
  return ret;
}
float BMP180_IIC::getPressure(void)
{
  float ret = -404;
  if (!m_getTemp_flag)
    getTemperature();
  getUP();
  double s = m_bmp180_open_data.bmp180_T - 25.0;
  double x = (m_bmp180_data.bmp180_x2 * pow(s, 2)) + (m_bmp180_data.bmp180_x1 * s) + m_bmp180_data.bmp180_x0;
  double y = (m_bmp180_data.bmp180_y2 * pow(s, 2)) + (m_bmp180_data.bmp180_y1 * s) + m_bmp180_data.bmp180_y0;
  double z = (m_bmp180_data.bmp180_UP - x) / y;
  ret = (m_bmp180_data.bmp180_p2 * pow(z, 2)) + (m_bmp180_data.bmp180_p1 * z) + m_bmp180_data.bmp180_p0;
  m_getTemp_flag = 0;
  m_bmp180_open_data.bmp180_P = ret;
  return ret;
}
float BMP180_IIC::getAltitude(float seaLevelhPa)
{
  float ret = -404;
  ret = 44330 * (1 - pow(((m_bmp180_open_data.bmp180_P) / seaLevelhPa), (1.0 / 5.255)));
  return ret;
}
float BMP180_IIC::getHeight()
{

  return getAltitude(init_pressure);
}
}

代码我也提供一份到我的百度云盘,有需要者可以自行拿去。同时提供了一份例子。
链接:https://pan.baidu.com/s/16OWhSTGLE_EfkgQpCaIRiA
提取码:sc53

你可能感兴趣的:(Arduino)