51单片机读取温度和大气压强

51单片机读取温度和大气压强

通过bmp280读取当前的大气压强和温度

c文件

`

#include "BMP280.h"

unsigned char BMP280_ADDRESS=0xEC;//设置传感器地址    //BMP280 I2C地址  (csb,sdo引脚都接高电平) sdo接高电平为0xEE,sdo接低电平为0xEC
unsigned char id;

long xdata t_fine;
unsigned long xdata p;
unsigned short xdata dig_T[1],dig_P[1];

short xdata digt[2],digp[9];

long xdata TEMP,PRESS;
/**
  * @brief  I2C开始
  * @param  无
  * @retval 无
  */
void I2C_Start(void)
{
	I2C_SDA=1;
	I2C_SCL=1;
	I2C_SDA=0;
	I2C_SCL=0;
}

/**
  * @brief  I2C停止
  * @param  无
  * @retval 无
  */
void I2C_Stop(void)
{
	I2C_SDA=0;
	I2C_SCL=1;
	I2C_SDA=1;
}

/**
  * @brief  I2C发送一个字节
  * @param  Byte 要发送的字节
  * @retval 无
  */
void I2C_SendByte(unsigned char Byte)
{
	unsigned char i;
	for(i=0;i<8;i++)
	{
		I2C_SDA=Byte&(0x80>>i);
		I2C_SCL=1;
		I2C_SCL=0;
	}
}

/**
  * @brief  I2C接收一个字节
  * @param  无
  * @retval 接收到的一个字节数据
  */
unsigned char I2C_ReceiveByte(void)
{
	unsigned char i,Byte=0x00;
	I2C_SDA=1;
	for(i=0;i<8;i++)
	{
		I2C_SCL=1;
		if(I2C_SDA){Byte|=(0x80>>i);}
		I2C_SCL=0;
	}
	return Byte;
}

/**
  * @brief  I2C发送应答
  * @param  AckBit 应答位,0为应答,1为非应答
  * @retval 无
  */
void I2C_SendAck(unsigned char AckBit)
{
	I2C_SDA=AckBit;
	I2C_SCL=1;
	I2C_SCL=0;
}

/**
  * @brief  I2C接收应答位
  * @param  无
  * @retval 接收到的应答位,0为应答,1为非应答
  */
unsigned char I2C_ReceiveAck(void)
{
	unsigned char AckBit;
	I2C_SDA=1;
	I2C_SCL=1;
	AckBit=I2C_SDA;
	I2C_SCL=0;
	return AckBit;
}


/**
  * @brief  BMP280写入一个字节
  * @param  WordAddress 要写入字节的地址
  * @param  Data 要写入的数据
  * @retval 无
  */
void BMP280_WriteByte(unsigned char WordAddress,Data)
{
	I2C_Start();
	I2C_SendByte(BMP280_ADDRESS);
	I2C_ReceiveAck();
	I2C_SendByte(WordAddress);
	I2C_ReceiveAck();
	I2C_SendByte(Data);
	I2C_ReceiveAck();
	I2C_Stop();
}

/**
  * @brief  BMP280读取一个字节
  * @param  WordAddress 要读出字节的地址
  * @retval 读出的数据
 */
unsigned char BMP280_ReadByte(unsigned char WordAddress)
{
	unsigned char Data;
	I2C_Start();
	I2C_SendByte(BMP280_ADDRESS);
	I2C_ReceiveAck();
	I2C_SendByte(WordAddress);
	I2C_ReceiveAck();
	I2C_Start();
	I2C_SendByte(BMP280_ADDRESS|0x01);
	I2C_ReceiveAck();
	Data=I2C_ReceiveByte();
	I2C_SendAck(1);
	I2C_Stop();
	return Data;
}
/**
  * @brief  bmp280初始化,读取补偿参数存储在dig_xx一系列变量中
  * @param  操作i2c地址为0xEE的bmp280传感器,操作i2c地址为0xEC的bmp280传感器。
  * @retval 无
  */
void BMP280_INIT(void)
{
	unsigned char add,j;
    
	BMP280_WriteByte(0xF4,0xB7); //设置16倍过采样和一般模式,其他配置详见手册
	BMP280_WriteByte(0xF5,0xB0); //设置待机间隔时间,过滤器,三线spi禁用
	//开始读取补偿数据,注意高低位顺序
	dig_T[0]=BMP280_ReadByte(0x89); //温度校核值
	dig_T[0]<<=8;
	dig_T[0]+=BMP280_ReadByte(0x88);
	
	digt[0]=BMP280_ReadByte(0x8B); 
	digt[0]<<=8;
	digt[0]+=BMP280_ReadByte(0x8A);
	
	digt[1]=BMP280_ReadByte(0x8D);
	digt[1]<<=8;
	digt[1]+=BMP280_ReadByte(0x8C);
	
	
	//气压校核值
	dig_P[0]=(unsigned short)BMP280_ReadByte(0x8F);
	dig_P[0]<<=8;
	dig_P[0]+=(unsigned short)BMP280_ReadByte(0x8E);
	j=1;add=0x90;
	while (j<=8)
		{
			digp[j]=BMP280_ReadByte(add+1);
			digp[j]<<=8;
			digp[j]+=BMP280_ReadByte(add);
			j++;add=add+2;
	  }
	}
/**
  * @brief  BMP280软复位
  * @param  无
  * @retval 无
  */
void BMP280_Reset()
{
    BMP280_WriteByte(0xE0,0xB6);//软复位
	  BMP280_WriteByte(0xF4,0xB7); //设置16倍过采样和一般模式,其他配置详见手册
	  BMP280_WriteByte(0xF5,0x10); //设置待机间隔时间,过滤器,三线spi禁用
}
/**
  * @brief  同一i2c总线上两个BMP280读取原始数据并完成补偿运算
  * @param 
  * @retval 无
  */

void BMP280_ReadADC(void)
{
	unsigned char i;
	unsigned long xdata temp_xlsb,temp_lsb,temp_msb,press_xlsb,press_lsb,press_msb;
	long xdata var1, var2, T;
	long xdata adc_T,adc_P;
	i=0;

		
		id=BMP280_ReadByte(0xD0);
		if (id!=0x58){BMP280_Reset();}//故障软复位,好像没卵用
		I2C_Start();
		I2C_SendByte(BMP280_ADDRESS);
		I2C_ReceiveAck();
		I2C_SendByte(0xF7);
		I2C_ReceiveAck();
		I2C_Start();
		I2C_SendByte(BMP280_ADDRESS|0x01);
		I2C_ReceiveAck();
		press_msb=I2C_ReceiveByte();
		I2C_SendAck(0);
		press_lsb=I2C_ReceiveByte();
		I2C_SendAck(0);
		press_xlsb=I2C_ReceiveByte();
		I2C_SendAck(0);
		temp_msb=I2C_ReceiveByte();
		I2C_SendAck(0);
		temp_lsb=I2C_ReceiveByte();
		I2C_SendAck(0);
		temp_xlsb=I2C_ReceiveByte();
		I2C_SendAck(1);
		I2C_Stop();   	//突发读取所有原始数据  
	
		adc_T=0;
		adc_T=(temp_msb<<12)|(temp_lsb<<4)|(temp_xlsb>>4); //20位温度原始数据存储到adc_T中
  
		adc_P=0;
	
		adc_P=(press_msb<<12)|(press_lsb<<4)|(press_xlsb>>4); //20位温度原始数据存储到adc_P中

	  
//校准语句,引用自bmp280官方手册简化版运算------------------------------------------------------------------------
// Returns temperature in DegC, resolution is 0.01 DegC. Output value of “5123” equals 51.23 DegC. 
// t_fine carries fine temperature as global value
	var1=((((adc_T>>3)-((long)dig_T[0]<<1)))*((long)digt[0]))>>11;
	var2=(((((adc_T>>4)-((long)dig_T[0]))*((adc_T>>4)-((long)dig_T[0])))>>12)*((long)digt[1]))>>14;
	t_fine = var1 + var2;
	T = (t_fine * 5 + 128) >> 8;
	TEMP=T;   //将温度值输出到TEMP

// Returns pressure in Pa as unsigned 32 bit integer. Output value of “96386” equals 96386 Pa = 963.86 hPa
	var1=(((long)t_fine)>>1)-(long)64000;
	var2=(((var1>>2)*(var1>>2))>>11 )*((long)digp[7]);
	var2=var2+((var1*((long)digp[4]))<<1);
	var2=(var2>>2)+(((long)digp[2])<<16);
	var1=(((digp[1]*(((var1>>2)*(var1>>2))>>13))>>3)+((((long)digp[0])*var1)>>1))>>18;
	var1=((((32768+var1))*((long)dig_P[0]))>>15);
	if (var1 == 0)
	{
		TEMP=0; // avoid exception caused by division by zero
	}
	p = (((unsigned long)(((long)1048576)-adc_P)-(var2>>12)))*3125;
	if (p<0x80000000) 
	{
		p = (p<<1)/((unsigned long)var1);
	} 
	else
	{
		p=(p/(unsigned long)var1)*2;
	}
	var1=(((long)digp[7])*((long)(((p>>3)*(p>>3))>>13)))>>12;
	var2=(((long)(p>>2))*((long)digp[6]))>>13;
	p=(unsigned long)((long)p+((var1 + var2 + digp[5])>>4));
	PRESS= p ;      //将转换所得压力值复制到PRESS变量
//校准结束--------------------------------------------------------------------------------------------------------

}

`

h文件

#ifndef __BMP280_H__
#define __BMP280_H__

#include "define.h" 

void BMP280_WriteByte(unsigned char WordAddress,Data);
unsigned char BMP280_ReadByte(unsigned char WordAddress);
void BMP280_INIT(void);
void BMP280_ReadADC(void);
extern long xdata TEMP,PRESS;

#endif

  • 10
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值