找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 5374|回复: 9
收起左侧

51单片机初学实践:用BME280模块获取温度、湿度和气压数据

  [复制链接]
ID:759974 发表于 2020-7-18 23:54 | 显示全部楼层 |阅读模式
我想为电子钟增加环境数据监测功能,主要是气温,湿度和气压这三项,BME280模块可以测量这三项数据,是一个不错的选择。
Annotation 2020-07-18 231237.png



Annotation 2020-07-18 232239.png




今天对照datasheet和之前坛友分享的资料,编写代码实现了气温,湿度和气压这三项数据的读取,并在LCD1602屏幕和UART打印显示,
效果如图所示:

51hei图片_20200718233539.jpg

Annotation 2020-07-18 225015.png


在实践过程中,有以下心得:

1、BME280模块有三种工作模式,其中forced mode适合我的需要

Annotation 2020-07-18 231315.png


Annotation 2020-07-18 231523.png


2、我的需求,可以对照Weather Monitoring方式,文档上有详细说明
我对精度要求并不高,oversampleing选择x1即可,如此设置,功耗也最小。

Annotation 2020-07-18 231716.png

Annotation 2020-07-18 231911.png



Annotation 2020-07-18 232113.png


3、读取的ADC数据,不能直接使用,必须进行补偿计算,64位整数运算精度最高,但对于单片机不太合适,可以使用double类型
计算过程,详见datasheet中的附件代码

Annotation 2020-07-18 232716.png

Annotation 2020-07-18 232401.png





main函数代码:

  1. void main()
  2. {
  3.         uint8 chip_id = 0;
  4.         uint8 pdata pbuf[31] = {0};

  5.         ConfigUART(9600);
  6.         printf(">ConfigUART done.\r\n\r\n");
  7.         Delay500ms();

  8.         BME280_Init();
  9.         printf(">BME280_Init done.\r\n\r\n");
  10.         Delay500ms();

  11.         chip_id        = BME280_Read_Chip_Id();
  12.         printf(">BME280_Chip_Id = 0x%bx\r\n\r\n", (uint8)chip_id);

  13.     LCD1602_Init();        //初始化液晶
  14.         LCD1602_Show_Char(6, 0, 0);        //5x7字符 ℃
  15.         LCD1602_Show_Char(14, 0, '%');//5x7字符 %
  16.         LCD1602_Show_Str(8, 1, "hPa"); // 液晶显示屏更新显示
  17.        
  18.         while(1)
  19.         {
  20.                 Delay500ms();Delay500ms();
  21.                 BME280_Read_ADC(&BME280_adc_P, &BME280_adc_T, &BME280_adc_H);
  22.                 printf(">BME280_adc_T = 0x%08lx \r\n", BME280_adc_T);
  23.                 printf(">BME280_adc_H = 0x%08lx \r\n", BME280_adc_H);
  24.                 printf(">BME280_adc_P = 0x%08lx \r\n", BME280_adc_P);
  25.                 printf("\r\n");

  26.                 BME280_Temperature        = BME280_compensate_T_double(BME280_adc_T);
  27.                 BME280_Humidity                = BME280_compensate_H_double(BME280_adc_H);
  28.                 BME280_Pressure                = BME280_compensate_P_double(BME280_adc_P);
  29.                
  30.                 sprintf(pbuf, "%6.2f", BME280_Temperature);
  31.                 printf(">BME280_Temperature : %s c\r\n", pbuf);
  32.                 LCD1602_Show_Str(0, 0, pbuf); // 液晶显示屏更新显示

  33.                 sprintf(pbuf, "%6.2f", BME280_Humidity);
  34.                 printf(">BME280_Humidity : %s %%\r\n", pbuf);
  35.                 LCD1602_Show_Str(8, 0, pbuf); // 液晶显示屏更新显示
  36.                
  37.                 sprintf(pbuf, "%7.2f", BME280_Pressure/100);
  38.                 printf(">BME280_Pressure : %s hPa\r\n", pbuf);
  39.                 LCD1602_Show_Str(0, 1, pbuf); // 液晶显示屏更新显示

  40.                 printf("--------------------------------\r\n\r\n");
  41.         }
  42. }
复制代码

读取ADC数据代码:

  1. void BME280_Read_ADC(int32 *adc_P, int32 *adc_T, int32 *adc_H)
  2. {
  3.         uint8 press_msb, press_lsb, press_xlsb;
  4.         uint8 temp_msb, temp_lsb, temp_xlsb;
  5.         uint8 hum_msb, hum_lsb;

  6.         BME280_Set_Measure_Mode();
  7.         BME280_Read_Compensation_Parameters();

  8.         i2c_start();
  9.         i2c_write_byte(BME280_SlaveAddr_Write);
  10.         i2c_send_nack();
  11.         i2c_write_byte(BME280_RegAddr_Pressure);
  12.         i2c_send_nack();
  13.         i2c_start();                        
  14.         i2c_write_byte(BME280_SlaveAddr_Read); // burst read from 0xF7 to 0xFE
  15.         i2c_send_nack();

  16.         // read pressure
  17.         press_msb  = BME280_Burst_Read_Byte_Ack(); // 0xF7, burst read begin
  18.         press_lsb  = BME280_Burst_Read_Byte_Ack(); // 0xF8
  19.         press_xlsb = BME280_Burst_Read_Byte_Ack(); // 0xF9

  20.         // read temperature
  21.         temp_msb  = BME280_Burst_Read_Byte_Ack(); // 0xFA
  22.         temp_lsb  = BME280_Burst_Read_Byte_Ack(); // 0xFB
  23.         temp_xlsb = BME280_Burst_Read_Byte_Ack(); // 0xFC

  24.         // read humidity
  25.         hum_msb  = BME280_Burst_Read_Byte_Ack(); // 0xFD
  26.         hum_lsb  = BME280_Burst_Read_Byte_NAck(); // 0xFE, burst read end

  27.         *adc_P        = (int32)(((uint32)press_msb << 12)|((uint32)press_lsb << 4)|((uint32)press_xlsb >> 4));
  28.         *adc_T        = (int32)(((uint32)temp_msb << 12)|((uint32)temp_lsb << 4)|((uint32)temp_xlsb >> 4));
  29.         *adc_H        = (int32)(((uint32)hum_msb<<8)|((uint32)hum_lsb));
  30. }
复制代码

ADC数据的补偿计算代码(double类型):

  1. // Returns temperature in DegC, double precision. Output value of "51.23" equals 51.23 DegC.
  2. // t_fine carries fine temperature as global value
  3. double BME280_compensate_T_double(BME280_s32_t adc_T)
  4. {
  5.         double var1, var2, T;
  6.         var1 = (((double)adc_T) / 16384.0 - ((double)dig_T1) / 1024.0) * ((double)dig_T2);
  7.         var2 = ((((double)adc_T) / 131072.0 - ((double)dig_T1) / 8192.0) * (((double)adc_T) / 131072.0 - ((double)dig_T1) / 8192.0)) * ((double)dig_T3);

  8.         t_fine = (BME280_s32_t)(var1 + var2);
  9.         T = (var1 + var2) / 5120.0;

  10.         return T;
  11. }

  12. // Returns pressure in Pa as unsigned 32 bit integer. Output value of "96386.2" equals 96386 Pa = 963.86 hPa
  13. double BME280_compensate_P_double(BME280_s32_t adc_P)
  14. {
  15.         double var1, var2, p;
  16.         var1 = ((double)t_fine / 2.0) - 64000.0;
  17.         var2 = var1 * var1 * ((double)dig_P6) / 32768.0;
  18.         var2 = var2 + var1 * ((double)dig_P5) * 2.0;
  19.         var2 = (var2 / 4.0) + (((double)dig_P4) * 65536.0);
  20.         var1 = (((double)dig_P3) * var1 * var1 / 524288.0 + ((double)dig_P2) * var1) / 524288.0;
  21.         var1 = (1.0 + var1 / 32768.0) * ((double)dig_P1);
  22.         if(0.0 == var1)
  23.         {
  24.                 return 0; // avoid exception caused by division by zero
  25.         }
  26.         p = 1048576.0 - (double)adc_P;
  27.         p = (p - (var2 / 4096.0)) * 6250.0 / var1;
  28.         var1 = ((double)dig_P9) * p * p / 2147483648.0;
  29.         var2 = p * ((double)dig_P8) / 32768.0;
  30.         p = p + (var1 + var2 + ((double)dig_P7)) / 16.0;
  31.        
  32.         return p;
  33. }

  34. // Returns humidity in %rH as as double. Output value of "46.332" represents 46.332 %rH
  35. double BME280_compensate_H_double(BME280_s32_t adc_H)
  36. {
  37.         double var_H;

  38.         var_H = (((double)t_fine) - 76800.00);
  39.         var_H = (adc_H - (((double)dig_H4) * 64.0 + ((double)dig_H5) / 16384.0 * var_H)) * (((double)dig_H2) / 65536.0 * (1.0 + ((double)dig_H6) / 67108864.0 * var_H * (1.0 + ((double)dig_H3) / 67108864.0 * var_H)));
  40.         var_H = var_H * (1.0 - ((double)dig_H1) * var_H / 524288.0);
  41.        
  42.         if(var_H > 100.0)
  43.         {
  44.                 var_H = 100.0;
  45.         }
  46.         else if(var_H < 0.0)
  47.         {
  48.                 var_H = 0.0;
  49.         }
  50.        
  51.         return var_H;
  52. }
复制代码

详细代码请参见附件


Annotation 2020-07-18 230907.png


以上代码使用C51开发板调试,接线简单,具体端口可参看config.h

初学单片机,难免有错漏之处,还请各位坛友不吝赐教。


BME280_UART_LCD1602_STC89C52RC.7z (1.33 MB, 下载次数: 152)

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

ID:810398 发表于 2020-8-1 20:14 | 显示全部楼层
学习一下,有AVR单片机驱动BME280的程序吗?
回复

使用道具 举报

ID:601357 发表于 2021-1-22 21:09 | 显示全部楼层
谢谢分享我再找找为什么获取温度压力都可以但是湿度怎么都是0的原因
回复

使用道具 举报

ID:810398 发表于 2021-2-13 18:50 | 显示全部楼层
以上代码转换为AVR单片机的程序,多谢分享!

#define   int8     signed   char
#define   int16    signed   int
#define   int32    signed long int
#define   uint8    unsigned char
#define   uint16   unsigned int       
#define   uint32   unsigned long int  
#define BME280_s32_t signed long int
#define BME280_u32_t unsigned long int

#define BME280_SCL_INPUT    (DDRD &= ~(1 << PD7))  //SCL设置为输入口
#define BME280_SCL_OUTPUT   (DDRD |= (1 << PD7))  //SCL设置为输出口
#define BME280_SCL_LOW      (PORTD &= ~(1 << PD7))   //SCL设置为输出低电平
#define BME280_SCL_HIGH     (PORTD |= (1 << PD7))   //SCL设置为输出高电平
#define BME280_SCL_INDATA   (PIND & (1 << PD7))   //读取SCL的端口状态

#define BME280_SDA_INPUT    (DDRB &= ~(1 << PB7))  //SDA设置为输入口
#define BME280_SDA_OUTPUT   (DDRB |= (1 << PB7))  //SDA设置为输出口
#define BME280_SDA_LOW      (PORTB &= ~(1 << PB7))   //SDA设置为输出低电平
#define BME280_SDA_HIGH     (PORTB |= (1 << PB7))   //SDA设置为输出高电平
#define BME280_SDA_INDATA   (PINB & (1 << PB7))   //读取SDA的端口状态

#define        BME280_SlaveAddr_Write        0xEC
#define        BME280_SlaveAddr_Read        0xEC+1
#define        BME280_RegAddr_Pressure        0xF7

uint16         dig_T1;
int16         dig_T2;
int16         dig_T3;
uint16         dig_P1;
int16         dig_P2;
int16         dig_P3;
int16         dig_P4;
int16         dig_P5;
int16         dig_P6;
int16         dig_P7;
int16         dig_P8;
int16         dig_P9;
uint8         dig_H1;
int16         dig_H2;
uint8         dig_H3;
int16         dig_H4;
int16         dig_H5;
int16         dig_H6;

int32  BME280_adc_T;
int32  BME280_adc_P;
int32  BME280_adc_H;

double  BME280_Temperature;
double  BME280_Pressure;
double  BME280_Humidity;

BME280_s32_t  t_fine;


void BME280_delay_us(unsigned int delay_counter)//延时1us
{   
   do
   {
      delay_counter--;       
          WDR();             //喂狗程序  
   }while(delay_counter>1);
}
void BME280_Delay_ms(unsigned int delay_counter)
{
while(delay_counter!=0)
   {
          BME280_delay_us(1000);
      delay_counter--;
          WDR();             //喂狗程序
   }
}

/* 产生I2C总线INPUT;                              //SDA设置为输入口
   BME280_dela起始信号 */
void i2c_start()
{
   /* I2C_SDA = 1; //首先确保SDA、SCL都是高电平
    I2C_SCL = 1;
    i2c_delay();
    I2C_SDA = 0; //先拉低SDA
    i2c_delay();
    I2C_SCL = 0; //再拉低SCL
        */
// BME280_delay_us(10);
  BME280_SDA_INPUT;//SDA=1;
  //BME280_delay_us(10);
  BME280_SCL_INPUT;//SCL=1;
  BME280_delay_us(10);
  BME280_SDA_OUTPUT;//SDA=0;
  BME280_delay_us(10);
  BME280_SCL_OUTPUT;//SCL=0;
  //BME280_delay_us(10);
  //return 1;
}

/* 产生I2C总线停止信号 */
void i2c_stop()
{
    /*
        I2C_SCL = 0; //首先确保SDA、SCL都是低电平
    I2C_SDA = 0;
    i2c_delay();
    I2C_SCL = 1; //先拉高SCL
    i2c_delay();
    I2C_SDA = 1; //再拉高SDA
    i2c_delay();
        */
        //BME280_delay_us(10);
        BME280_SCL_OUTPUT;//SCL=0;
        BME280_SDA_OUTPUT; //SDA=0;
        BME280_delay_us(10);
        BME280_SCL_INPUT;//SCL=1;
        BME280_delay_us(10);
        BME280_SDA_INPUT;//SDA=1;
        BME280_delay_us(10);       
}

/* I2C总线发送ACK信号 */
void i2c_send_ack()
{
    /*
        I2C_SDA = 0;   //8位数据发送完后,拉低SDA,发送ACK应答信号
    i2c_delay();
    I2C_SCL = 1;   //拉高SCL
    i2c_delay();
    I2C_SCL = 0;   //再拉低SCL完成应答位,并保持住总线       
        */
        BME280_SDA_OUTPUT; //SDA=0;
        BME280_delay_us(10);
        BME280_SCL_INPUT;//SCL=1;
        BME280_delay_us(10);       
        BME280_SCL_OUTPUT;//SCL=0;
}

/* I2C总线发送NACK信号 */
void i2c_send_nack()
{
    /*
        I2C_SDA = 1;   //8位数据发送完后,拉高SDA,发送NACK非应答信号
    i2c_delay();
    I2C_SCL = 1;   //拉高SCL
    i2c_delay();
    I2C_SCL = 0;   //再拉低SCL完成应答位,并保持住总线       
        */
        BME280_SDA_INPUT;//SDA=1;
        BME280_delay_us(10);
        BME280_SCL_INPUT;//SCL=1;
        BME280_delay_us(10);       
        BME280_SCL_OUTPUT;//SCL=0;
}

/* I2C总线写操作,dat-待写入字节,返回值-从机应答位的值 */
void i2c_write_byte(uint8 dat)
{
    uint8 mask;  //用于探测字节内某一位值的掩码变量

    for (mask=0x80; mask!=0; mask>>=1) //从高位到低位依次进行
    {
        if ((mask&dat) == 0)  //该位的值输出到SDA上
            BME280_SDA_OUTPUT; //SDA=0;//I2C_SDA = 0;
        else
            BME280_SDA_INPUT;//SDA=1;//I2C_SDA = 1;
        BME280_delay_us(10);        //i2c_delay();
        BME280_SCL_INPUT;//SCL=1;//I2C_SCL = 1;          //拉高SCL
        BME280_delay_us(10);        //i2c_delay();
        BME280_SCL_OUTPUT;//SCL=0;//I2C_SCL = 0;          //再拉低SCL,完成一个位周期
    }
}


/* I2C总线读操作,返回值-读到的字节 */
uint8 i2c_read_byte()
{
    uint8 mask;
    uint8 dat;

    BME280_SDA_INPUT;//SDA=1;I2C_SDA = 1;  //首先确保主机释放SDA
    for (mask=0x80; mask!=0; mask>>=1) //从高位到低位依次进行
    {
        BME280_delay_us(10);        //i2c_delay();
        BME280_SCL_INPUT;//SCL=1;I2C_SCL = 1;      //拉高SCL
        if(BME280_SDA_INDATA)//if(I2C_SDA == 0)  //读取SDA的值
            dat |= mask;  //为1时,dat中对应位置1
        else            
                        dat &= ~mask; //为0时,dat中对应位清零
        BME280_delay_us(10);        //i2c_delay();
        BME280_SCL_OUTPUT;//SCL=0;I2C_SCL = 0;      //再拉低SCL,以使从机发送出下一位
    }

    return dat;
}

uint8 BME280_Read_Byte(uint8 read_addr)
{
        uint8 dat;

        i2c_start();         
        i2c_write_byte(BME280_SlaveAddr_Write);
        i2c_send_nack();
        i2c_write_byte(read_addr);
        i2c_send_nack();

        i2c_start();
        i2c_write_byte(BME280_SlaveAddr_Read);
        i2c_send_nack();

        dat = i2c_read_byte();
        i2c_send_nack();

        return dat;
}

void BME280_Write_Byte(uint8 write_addr, uint8 dat)
{
        i2c_start();                       
        i2c_write_byte(BME280_SlaveAddr_Write);
        i2c_send_nack();
        i2c_write_byte(write_addr);
        i2c_send_nack();
        i2c_write_byte(dat);
        i2c_send_nack();
        i2c_stop();                  
}

int16 BME280_Read_Word(uint8 read_addr)
{   
        uint8 msb, lsb;
        int16 dat;

        i2c_start();
        i2c_write_byte(BME280_SlaveAddr_Write);
        i2c_send_nack();
        i2c_write_byte(read_addr);
        i2c_send_nack();
        i2c_start();
        i2c_write_byte(BME280_SlaveAddr_Read); // burst read two bytes
        i2c_send_nack();
    lsb = i2c_read_byte();
        i2c_send_ack();
    msb = i2c_read_byte();
        i2c_send_nack();

        dat = msb << 8;
        dat |= lsb;        

        return dat;
}

void BME280_Reset()
{
    BME280_Write_Byte(0xE0, 0xB6);
}

uint8 BME280_Read_Chip_Id()
{
        uint8 cid = 0;
        cid = BME280_Read_Byte(0xD0);
        // ASSERT(cid == 0X60)
       
        return cid;
}

void BME280_Set_Measure_Mode()
{
        // Humidity oversampling x1
        BME280_Write_Byte(0xF2, 0x01);
        // Pressure oversampling x1
        // Temperature oversampling x1
        // Set sensor forced mode
        BME280_Write_Byte(0xF4, 0x26);
}


uint8 BME280_Burst_Read_Byte_Ack()
{
        uint8 dat;

    dat = i2c_read_byte();
        i2c_send_ack();
       
        return dat;
}

uint8 BME280_Burst_Read_Byte_NAck()
{
        uint8 dat;

    dat = i2c_read_byte();
        i2c_send_nack();
       
        return dat;
}


uint16 BME280_Burst_Read_Word_Ack()
{
        uint8 msb, lsb;
        uint16 dat;

    lsb = i2c_read_byte();
        i2c_send_ack();
    msb = i2c_read_byte();
        i2c_send_ack();
        dat = msb << 8;
        dat |= lsb;
       
        return dat;
}

void BME280_Read_Compensation_Parameters()
{
        uint8 i, j, k;

        i2c_start();
        i2c_write_byte(BME280_SlaveAddr_Write);
        i2c_send_nack();
        i2c_write_byte(0x88);
        i2c_send_nack();

        i2c_start();
        i2c_write_byte(BME280_SlaveAddr_Read);
        i2c_send_nack();
       
        /* 0x88 - 0x89 */
        dig_T1 = (uint16)BME280_Burst_Read_Word_Ack();
        /* 0x8a - 0x8b */
        dig_T2 = (int16)BME280_Burst_Read_Word_Ack();
        /* 0x8c - 0x8d */
        dig_T3 = (int16)BME280_Burst_Read_Word_Ack();

        /* 0x8E - 0x8F */
        dig_P1 = (uint16)BME280_Burst_Read_Word_Ack();
        /* 0x90 - 0x91 */
        dig_P2 = (int16)BME280_Burst_Read_Word_Ack();
        /* 0x92 - 0x93 */
        dig_P3 = (int16)BME280_Burst_Read_Word_Ack();
        /* 0x94 - 0x95 */
        dig_P4 = (int16)BME280_Burst_Read_Word_Ack();
        /* 0x96 - 0x97 */
        dig_P5 = (int16)BME280_Burst_Read_Word_Ack();
        /* 0x98 - 0x99 */
        dig_P6 = (int16)BME280_Burst_Read_Word_Ack();
        /* 0x9A - 0x9B */
        dig_P7 = (int16)BME280_Burst_Read_Word_Ack();
        /* 0x9C - 0x9D */
        dig_P8 = (int16)BME280_Burst_Read_Word_Ack();
        /* 0x9E - 0x9F */
        dig_P9 = (int16)BME280_Burst_Read_Word_Ack();

        /* 0xA0 skip */
        BME280_Burst_Read_Byte_Ack();

        /* 0xA1 */
        dig_H1 = (uint8)BME280_Burst_Read_Byte_NAck();

        i2c_start();
        i2c_write_byte(BME280_SlaveAddr_Write);
        i2c_send_nack();
        i2c_write_byte(0xE1);
        i2c_send_nack();

        i2c_start();
        i2c_write_byte(BME280_SlaveAddr_Read);
        i2c_send_nack();

        /* 0xE1 - 0xE2 */
        dig_H2 = (int16)BME280_Burst_Read_Word_Ack();
        /* 0xE3 */
        dig_H3 = (uint8)BME280_Burst_Read_Byte_Ack();

        /* 0xE4 - 0xE6 */
        i = (uint8)BME280_Burst_Read_Byte_Ack();
        j = (uint8)BME280_Burst_Read_Byte_Ack();
        k = (uint8)BME280_Burst_Read_Byte_Ack();

        dig_H4 = (int16)((i << 4) | (j & 0x0F));
        dig_H5 = (int16)((k << 4) | (j >> 4));

        /* 0xE7 */
        dig_H6 = (int16)BME280_Burst_Read_Byte_NAck();
}

void BME280_Init(void)
{

        BME280_Reset();
        BME280_Write_Byte(0xF5, 0x00);
}

void BME280_Read_ADC(int32 *adc_P, int32 *adc_T, int32 *adc_H)
{
        uint8 press_msb, press_lsb, press_xlsb;
        uint8 temp_msb, temp_lsb, temp_xlsb;
        uint8 hum_msb, hum_lsb;

        BME280_Set_Measure_Mode();
        BME280_Read_Compensation_Parameters();

        i2c_start();
        i2c_write_byte(BME280_SlaveAddr_Write);
        i2c_send_nack();
        i2c_write_byte(BME280_RegAddr_Pressure);
        i2c_send_nack();
        i2c_start();                        
        i2c_write_byte(BME280_SlaveAddr_Read); // burst read from 0xF7 to 0xFE
        i2c_send_nack();

        // read pressure
        press_msb  = BME280_Burst_Read_Byte_Ack(); // 0xF7, burst read begin
        press_lsb  = BME280_Burst_Read_Byte_Ack(); // 0xF8
        press_xlsb = BME280_Burst_Read_Byte_Ack(); // 0xF9

        // read temperature
        temp_msb  = BME280_Burst_Read_Byte_Ack(); // 0xFA
        temp_lsb  = BME280_Burst_Read_Byte_Ack(); // 0xFB
        temp_xlsb = BME280_Burst_Read_Byte_Ack(); // 0xFC

        // read humidity
        hum_msb  = BME280_Burst_Read_Byte_Ack(); // 0xFD
        hum_lsb  = BME280_Burst_Read_Byte_NAck(); // 0xFE, burst read end

        *adc_P        = (int32)(((uint32)press_msb << 12)|((uint32)press_lsb << 4)|((uint32)press_xlsb >> 4));
        *adc_T        = (int32)(((uint32)temp_msb << 12)|((uint32)temp_lsb << 4)|((uint32)temp_xlsb >> 4));
        *adc_H        = (int32)(((uint32)hum_msb<<8)|((uint32)hum_lsb));
}


// Returns temperature in DegC, double precision. Output value of "51.23" equals 51.23 DegC.
// t_fine carries fine temperature as global value
double BME280_compensate_T_double(BME280_s32_t adc_T)
{
        double var1, var2, T;
        var1 = (((double)adc_T) / 16384.0 - ((double)dig_T1) / 1024.0) * ((double)dig_T2);
        var2 = ((((double)adc_T) / 131072.0 - ((double)dig_T1) / 8192.0) * (((double)adc_T) / 131072.0 - ((double)dig_T1) / 8192.0)) * ((double)dig_T3);

        t_fine = (BME280_s32_t)(var1 + var2);
        T = (var1 + var2) / 5120.0;

        return T;
}

// Returns pressure in Pa as unsigned 32 bit integer. Output value of "96386.2" equals 96386 Pa = 963.86 hPa
double BME280_compensate_P_double(BME280_s32_t adc_P)
{
        double var1, var2, p;
        var1 = ((double)t_fine / 2.0) - 64000.0;
        var2 = var1 * var1 * ((double)dig_P6) / 32768.0;
        var2 = var2 + var1 * ((double)dig_P5) * 2.0;
        var2 = (var2 / 4.0) + (((double)dig_P4) * 65536.0);
        var1 = (((double)dig_P3) * var1 * var1 / 524288.0 + ((double)dig_P2) * var1) / 524288.0;
        var1 = (1.0 + var1 / 32768.0) * ((double)dig_P1);
        if(0.0 == var1)
        {
                return 0; // avoid exception caused by division by zero
        }
        p = 1048576.0 - (double)adc_P;
        p = (p - (var2 / 4096.0)) * 6250.0 / var1;
        var1 = ((double)dig_P9) * p * p / 2147483648.0;
        var2 = p * ((double)dig_P8) / 32768.0;
        p = p + (var1 + var2 + ((double)dig_P7)) / 16.0;
       
        return p;
}

// Returns humidity in %rH as as double. Output value of "46.332" represents 46.332 %rH
double BME280_compensate_H_double(BME280_s32_t adc_H)
{
        double var_H;

        var_H = (((double)t_fine) - 76800.00);
        var_H = (adc_H - (((double)dig_H4) * 64.0 + ((double)dig_H5) / 16384.0 * var_H)) * (((double)dig_H2) / 65536.0 * (1.0 + ((double)dig_H6) / 67108864.0 * var_H * (1.0 + ((double)dig_H3) / 67108864.0 * var_H)));
        var_H = var_H * (1.0 - ((double)dig_H1) * var_H / 524288.0);
       
        if(var_H > 100.0)
        {
                var_H = 100.0;
        }
        else if(var_H < 0.0)
        {
                var_H = 0.0;
        }
       
        return var_H;
}
回复

使用道具 举报

ID:810398 发表于 2021-2-13 18:52 | 显示全部楼层
谢谢分享!学习了,收获颇多!
回复

使用道具 举报

ID:491278 发表于 2021-4-4 10:30 | 显示全部楼层
3078 发表于 2021-1-22 21:09
谢谢分享我再找找为什么获取温度压力都可以但是湿度怎么都是0的原因

你会不会用的是BMP280
回复

使用道具 举报

ID:99570 发表于 2021-7-17 00:24 | 显示全部楼层
谢谢楼主分享,一句BMP280提醒了我,我说怎么湿度一直是0!
回复

使用道具 举报

ID:1005210 发表于 2022-2-16 12:31 | 显示全部楼层
老师,config.h里,我的配置是这样如下,bme280.c里面的Reset()、BME280_Read_Chip_Id()等函数里面的参数需要修改吗?
sbit I2C_SCL = P2^0;  //I2C总线引脚,BME280 clock
sbit I2C_SDA = P2^1;  //I2C总线引脚,BME280 data

#define LCD1602_DB  P0        //1602液晶数据端口
sbit LCD1602_RS = P2^6; //1602液晶指令/数据选择引脚 EasyBoard主板
sbit LCD1602_RW = P2^5; //1602液晶读写引脚 EasyBoard主板
sbit LCD1602_E  = P2^7; //1602液晶使能引脚 EasyBoard主板
回复

使用道具 举报

ID:375045 发表于 2022-9-3 11:08 | 显示全部楼层
能读到ID,但是温度压力湿度都读不到是什么问题?
>ConfigUART done.

>BME280_Init done.

>BME280_Chip_Id = 0x60

>BME280_adc_T = 0x000fffff
>BME280_adc_H = 0x0000ffff
>BME280_adc_P = 0x000fffff

>BME280_Temperature :   0.00 c
>BME280_Humidity :   2.14 %
>BME280_Pressure :    0.02 hPa
--------------------------------
回复

使用道具 举报

ID:825397 发表于 2023-10-19 16:20 | 显示全部楼层
谢谢楼主分享。网上BMP280驱动较少,楼主程序可以借鉴!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表