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