找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

帖子
查看: 3779|回復: 12
打印 上一主題 下一主題
收起左側

BMP280傳感器氣壓無數據,溫度偏高,是怎么回事

[復制鏈接]
跳轉到指定樓層
樓主
ID:71233 發(fā)表于 2022-2-23 09:29 | 只看該作者 |只看大圖 回帖獎勵 |倒序瀏覽 |閱讀模式
最近玩BMP280,發(fā)現(xiàn)測得的氣溫數值比正常的高,大約要高出2至3度,而氣壓為0。讀取BMP280內部所有寄存器,發(fā)現(xiàn)氣壓寄存器0xF7-0xF9的值均為0,而氣溫寄存器0xFA-0xFC均有氣溫ADC結果。這是為什么?
下面是復位后和設置正常模式下的bmp280內部寄存器數據:




分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復

使用道具 舉報

沙發(fā)
ID:401564 發(fā)表于 2022-2-23 13:28 | 只看該作者
BMP280雖然在溫度測量方面并不是很精確,但誤差一般都是可以在1攝氏度以下的
你這超過2攝氏度了,就要看一下你程序的時序對不對了
讀取數據之前要先讀取ADC標志位,讀取到完成標志位之后,再讀取溫度和壓力,然后再用數據手冊中提供的代碼進行校正,最后再顯示
最好不要用串口顯示,直接是OLED或者數碼管顯示就行
回復

使用道具 舉報

板凳
ID:71233 發(fā)表于 2022-2-23 13:38 | 只看該作者
要說是轉換未完成嘛,0xf3狀態(tài)寄存器讀出的數據是0xc0且溫度寄存器已經有了轉換后的原始數值。
回復

使用道具 舉報

地板
ID:1003226 發(fā)表于 2022-2-23 14:19 | 只看該作者
最好不要用串口顯示
回復

使用道具 舉報

5#
ID:401564 發(fā)表于 2022-2-23 14:48 | 只看該作者
新新科技 發(fā)表于 2022-2-23 13:38
要說是轉換未完成嘛,0xf3狀態(tài)寄存器讀出的數據是0xc0且溫度寄存器已經有了轉換后的原始數值。

我不知道你上面的表格是怎么得來的,是仿真還是串口?
如果能確認你讀寫的程序都是對的話,那么,你所讀取到的0xf3的值是:0x0c,對應的bit3是1,就是"轉換正在運行",只有數據已經復制到映射寄存器之后,bit3才會清除
你可能是看錯了,是0x0c
而不是你認為的0xc0
回復

使用道具 舉報

6#
ID:71233 發(fā)表于 2022-2-23 16:17 | 只看該作者
我讀取bmp280內部寄存器從0xf3開始的10個字節(jié),然后判斷當狀態(tài)寄存器0xF3的bit3為0時,將這10個字節(jié)用串口發(fā)送到電腦,依然是那樣的結果:氣壓寄存器的數值為0,溫度寄存器有數據。
回復

使用道具 舉報

7#
ID:71233 發(fā)表于 2022-2-23 19:33 | 只看該作者
Y_G_G 發(fā)表于 2022-2-23 14:48
我不知道你上面的表格是怎么得來的,是仿真還是串口?
如果能確認你讀寫的程序都是對的話,那么,你所讀取到 ...

不可能一直都沒有氣壓的數據吧。我覺得這東西在正常模式下面,從隱藏寄存器復制氣壓ADC數據到映射寄存器之前(或許正在轉換),映射寄存器應該存儲上一次的數據,這個數據暫時是不會被清零的。
回復

使用道具 舉報

8#
ID:71233 發(fā)表于 2022-2-24 10:52 | 只看該作者
知道是什么原因了,昨晚試了三個模塊,發(fā)現(xiàn)的確是芯片的問題,其他兩個模塊雖然能測量氣壓和溫度,但溫度的誤差也不盡人意,估計這280不是正品的。
回復

使用道具 舉報

9#
ID:401564 發(fā)表于 2022-2-24 14:44 | 只看該作者
新新科技 發(fā)表于 2022-2-24 10:52
知道是什么原因了,昨晚試了三個模塊,發(fā)現(xiàn)的確是芯片的問題,其他兩個模塊雖然能測量氣壓和溫度,但溫度的 ...

在95%的情況下,是代碼的問題,跟BMP280是不是正品是沒有關系的
在第一個表格中,復位后的值是和280數據手冊上是一樣的
0xf3的數據是0xC0,就說明轉換沒有完成,這一點很重要,只要是轉換沒有完成的,讀取的數據就有可能是任何數據,去分析太多是沒有意義的
一定要轉換完成之后,馬上讀取6個溫度的壓力數據,期間不要有太長時間的延時,如果你連續(xù)轉換模式,ADC轉換和數據改變是同時進行的,也就是說ADC邊進行,邊改變溫度和壓力寄存器的值,這個在數據手冊中是有說明的
還有,最好不要用串口,先用數碼管或者OLED進行驗證
如果還不行,就把代碼上傳
回復

使用道具 舉報

10#
ID:71233 發(fā)表于 2022-2-25 09:16 | 只看該作者
//關鍵源碼如下:

#define        BMP280_Address     0xec       //器件地址
#define        BMP280_TEMP_ADDR    0xfa   //溫度寄存器
#define        BMP280_PRESS_ADDR   0xf7  //氣壓寄存器

//校正參數
unsigned short dig_T1;
short dig_T2;
short dig_T3;
unsigned short dig_P1;
short dig_P2;
short dig_P3;
short dig_P4;
short dig_P5;
short dig_P6;
short dig_P7;
short dig_P8;
short dig_P9;

long bmp280_MultipleReadThree(unsigned char addr) //讀取三個字節(jié)
{
    unsigned char msb, lsb, xlsb;
    long temp = 0;
    msb = BMP280_Read(addr);
    lsb = BMP280_Read(addr + 1);
    xlsb = BMP280_Read(addr + 2);
    temp = (long)(((unsigned long)msb << 12)|((unsigned long)lsb << 4)|((unsigned long)xlsb >> 4));
    return temp;
}

short bmp280_MultipleReadTwo(unsigned char addr) //讀取兩個字節(jié)
{
    unsigned char msb, lsb;
    short temp = 0;
    lsb = BMP280_Read(addr);
    msb = BMP280_Read(addr + 1);

    temp = (short)msb << 8;
    temp |= (short)lsb;

    return temp;
}

bit BMP280_Init()//BMP280初始化
{
    unsigned char temp = 0;
    BMP280_Write(0xe0, 0xb6);
    temp = BMP280_Read(0xd0);
    if(temp != 0x58)return 1;//
BMP280_Write(0xf4, 0xff);
BMP280_Write(0xf5, 0x00);

    dig_T1 = bmp280_MultipleReadTwo(0x88);
    dig_T2 = bmp280_MultipleReadTwo(0x8A);
    dig_T3 = bmp280_MultipleReadTwo(0x8C);
    dig_P1 = bmp280_MultipleReadTwo(0x8E);
    dig_P2 = bmp280_MultipleReadTwo(0x90);
    dig_P3 = bmp280_MultipleReadTwo(0x92);
    dig_P4 = bmp280_MultipleReadTwo(0x94);
    dig_P5 = bmp280_MultipleReadTwo(0x96);
    dig_P6 = bmp280_MultipleReadTwo(0x98);
    dig_P7 = bmp280_MultipleReadTwo(0x9A);
    dig_P8 = bmp280_MultipleReadTwo(0x9C);
    dig_P9 = bmp280_MultipleReadTwo(0x9E);
    delay_ms(200);
    return 0;
}


long BMP280_GetValue(uchar i)//獲取氣壓和溫度
{
    long adc_T;
    long adc_P;
    long var1, var2, T, p;
        unsigned long  t_fine;
    adc_T = bmp280_MultipleReadThree(BMP280_TEMP_ADDR);
    adc_P = bmp280_MultipleReadThree(BMP280_PRESS_ADDR);

    if(adc_P == 0)
    {
                return 0;
    }

    //Temperature
    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 = (unsigned long)(var1+var2);

    T = (var1+var2)/51.20;

    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);
    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;

    if(i)return p;
    else return T;
}
回復

使用道具 舉報

11#
ID:71233 發(fā)表于 2022-2-25 12:57 | 只看該作者
本帖最后由 新新科技 于 2022-2-25 13:29 編輯

手冊提供的BMP280器件地址是0x76,而手頭這模塊是0xec,莫非不是BMP280?
回復

使用道具 舉報

12#
ID:401564 發(fā)表于 2022-2-25 15:16 | 只看該作者
新新科技 發(fā)表于 2022-2-25 12:57
手冊提供的BMP280器件地址是0x76,而手頭這模塊是0xec,莫非不是BMP280?

BMP280從機地址就是0xec的呀,沒錯呀
BMP280_Read函數呢?里面有沒有應答?每次讀取完一個字節(jié)的數據之后,都要主機產生一個應答信號的
0xf3的讀取呢?是不是先讀取這個寄存器之后再讀取壓力和溫度數據的?
給你一個我的代碼參考一下,這是我?guī)讉€月剛剛開始學C語言的時候寫的,已經驗證通過的了
/*BMP280.c  BMP280相關操作函數
選擇IIC操作方式,相關的選擇端口要硬件先選擇好
SDO=0,IIC從機地址為:0xec(寫),0xed(讀)
*/

#include "BMP280.h"
#include "IIC.h"
#define BMP280_S32_t long
#define Write_BMP280_slave 0xec
#define Read_BMP280_slave  0xed
#define Read_BMP280_temp_msb 0xfa        //讀取溫度最高位地址,讀取是從最高位讀到最低位的
#define Read_BMP280_press_msb 0xf7        //讀取氣壓最高位地址,讀取是從最高位讀到最低位的
#define Read_BMP280_Status 0xf3                //讀取ADC運行狀態(tài)位
unsigned short dig_T1;                  //BMP280校正值保存的相關地址
short                   dig_T2;
short                   dig_T3;
unsigned short dig_P1;
short                   dig_P2;
short                   dig_P3;
short                   dig_P4;
short                   dig_P5;
short                   dig_P6;
short                   dig_P7;
short                   dig_P8;
short                   dig_P9;


//=================================================================================================
void BMP280_init()                        //BMP280初始化函數
{
        Delay_ms(100);
        IIC_start();

        Write_byte(Write_BMP280_slave); //從機地址

        Write_byte(0xf4);          //寄存器設置設備的數據采集選項(0xf4)
        Write_byte(0xf0);          //先進入休眠模式,完成0xf5的設置之后再進入正常模式

        Write_byte(0xf5);          //存器設置設備的速率、過濾器和接口選項
        Write_byte(0x00);          // IIR濾波關閉,0.5mS測量一次

        Write_byte(0xf4);          //寄存器設置設備的數據采集選項(0xf4)
        Write_byte(0xff);          //溫度和壓力都是20位模式,采樣模式為正常模式

        IIC_stop();

        dig_T1=Read_BMP280_2Byte(0x88);         //讀取幾個校驗值
        dig_T2=Read_BMP280_2Byte(0x8a);
        dig_T3=Read_BMP280_2Byte(0x8c);
        dig_P1=Read_BMP280_2Byte(0x8e);
        dig_P2=Read_BMP280_2Byte(0x90);
        dig_P3=Read_BMP280_2Byte(0x92);
        dig_P4=Read_BMP280_2Byte(0x94);
        dig_P5=Read_BMP280_2Byte(0x96);
        dig_P6=Read_BMP280_2Byte(0x98);
        dig_P7=Read_BMP280_2Byte(0x9a);
        dig_P8=Read_BMP280_2Byte(0x9c);
        dig_P9=Read_BMP280_2Byte(0x9e);

}
//=================================================================================================
short Read_BMP280_2Byte(unsigned char BMP280_addr)                          //讀取校正值,所有校正值是用兩個地址存放的,所以就讀取兩個字節(jié)
{
   short temp;
   unsigned char Data_LSB,Data_MSB;
        IIC_start();
        Write_byte(Write_BMP280_slave); //從機地址
        Write_byte(BMP280_addr);
        IIC_start();
        Write_byte(Read_BMP280_slave); //從機地址
        Data_LSB=read_byte();
        IIC_Ask();
        Data_MSB=read_byte();
        IIC_Nask();
        IIC_stop();
        temp=(Data_MSB<<8)|Data_LSB;
        return temp;
}
//=================================================================================================
long Read_BMP280_3Byte(unsigned char BMP280_addr)                          //讀取測量值,所有測量值是用三地址存放的,所以就讀取三個字節(jié)
{
   long temp;
   unsigned char Data_XLSB,Data_LSB,Data_MSB;
        IIC_start();
        Write_byte(Write_BMP280_slave); //從機地址
        Write_byte(BMP280_addr);
        IIC_start();
        Write_byte(Read_BMP280_slave); //從機地址
        Data_MSB=read_byte();
        IIC_Ask();
        Data_LSB=read_byte();
        IIC_Ask();
        Data_XLSB=read_byte();
        IIC_Nask();
        IIC_stop();
        temp=(long)(((unsigned long)Data_MSB<<12)|((unsigned long)Data_LSB<<4)|((unsigned long)Data_XLSB>>4));
        return temp;
}
//=================================================================================================
double Read_BMP280_adc(unsigned char Reg_addr)                                                                //讀取傳感器adc數據
{                                                                                                                                                        //
         double Data;                                                                                                                        //返回值就是加入校正計算好的溫度或者壓力值
           long adc_data,adc_data_add;                                                                                        //轉換結果保存
         unsigned char f,measuring;                                                                                                 //
                                                                                                                                                          //
          if(Reg_addr==Read_BMP280_temp_msb)                                                                           //根據輸入選擇溫度或者氣壓ADC
          {                                                                                                                                                //
                 for(f=0;f<32;f++)                                                                                                        //
                        {                                                                                                                                //
                                do{measuring=Read_status();}                                                                //讀取ADC狀態(tài)位
                                  while(measuring==0x08);                                                                                //
                                adc_data=Read_BMP280_3Byte(Read_BMP280_temp_msb);                        //讀取溫度ADC結果
                                adc_data_add=adc_data_add+adc_data;                                                           //adc結果相加
                         }                                                                                                                                //
                                adc_data_add=adc_data_add/32;                                                                   //進行多次ADC,然后取平均值
                                 Data=bmp280_compensate_T_double(adc_data);                                        //進行校正處理
          }                                                                                                                                                //
                           else                                                                                                                         //
                                   {                                                                                                                        //
                                        for(f=0;f<128;f++)                                                                                //
                                        {                                                                                                                //
                                                do{measuring=Read_status();}                                                //讀取ADC狀態(tài)位
                                                  while(measuring==0x08);                                                                //
                                                adc_data=Read_BMP280_3Byte(Read_BMP280_press_msb);        //讀取氣壓ADC結果
                                                adc_data_add=adc_data_add+adc_data;                                          //adc結果相加
                                         }                                                                                                                //
                                                adc_data_add=adc_data_add/128;                                                //進行多次ADC,然后取平均值
                                                 Data=bmp280_compensate_P_double(adc_data);                        //進行校正處理
                                   }
         return Data;
}
//=================================================================================================
double bmp280_compensate_T_double(long adc_T)                           //數據手冊復制過來的,溫度和校正值的計算
{
double var1, var2, T,t_fine;
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 = (long)(var1 + var2);
T = (var1 + var2) / 5120.0;
return T;
}
//=================================================================================================
double bmp280_compensate_P_double(long adc_P)                                          //數據手冊復制過來的氣壓和校正值的計算
{
double var1, var2, p,t_fine;
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 (var1 == 0.0)
{
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;
}
//=================================================================================================
unsigned char Read_status()                                                                //讀取狀態(tài)位,檢測ADC是否完成
{
        unsigned char temp;
        IIC_start();
        Write_byte(Write_BMP280_slave); //從機地址
        Write_byte(Read_BMP280_Status);        //讀取ADC運行狀態(tài)位
        IIC_start();
        Write_byte(Read_BMP280_slave); //從機地址
        temp=read_byte();
        IIC_Nask();
        IIC_stop();
        return temp;
}
//=================================================================================================
回復

使用道具 舉報

13#
ID:1099969 發(fā)表于 2024-10-21 11:49 | 只看該作者
問一下溫度偏高解決了沒有
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表