基於STM32F103移植BME280官方驅動庫


一、 寫這個移植手冊的目的

9月份接手了一個新的項目,需要用到溫度、濕度、和壓力三個參數,並且參數值的要求比較嚴苛,經過一番查詢發現BOSCH有一顆BME280傳感器,性價比相當高,經過與供應商核對以及網絡查詢后最終決定使用這顆料,於是原理圖、PCB圖、PCB板一氣呵成,但是最終在使用STM32F103驅動BME280的時候出現了問題(根本原因在於懶惰),本來覺的可以在網上找一個現成的驅動修修補補就可以用了,哪知尋遍整個網絡也沒有看到有人放出STM32F103直接驅動BME280的文章(相當失望,嘿嘿),最終所能查到的就只有BOSCH公司放出的官方驅動SDK(個人認為這是最好的驅動),接口需要自己根據具體的處理器實現,所以只能自力更生,潛心手寫。
閑話不多說,開始寫吧!
二、 IIC總線接口
BME280傳感器支持IIC總線和SPI總線,由於BME280傳感器的工作頻率為25HZ,頻率比較低,並且IIC總線相對於SPI可以節約1個處理器的IO口,所以最終確定使用IIC總線,總線時序使用模擬的方式,便於將來移植到不同的處理器上面。
硬件配置需要注意:BME280的SDO引腳直接接地,CSB引腳直接接到3.3V電源,中間不用使用任何電阻直接連接保證電平穩定性。

 

以前公司內部也有比較成熟的IIC總線的驅動,但是沒有仔細嚴格分析過時序的正確性,正好利用這個機會將IIC總線的時序從頭到尾捋捋。

開始:

要掌握IIC的通信協議,需要掌握以下6個通信信號: 
1.起始信號 
2.終止信號 
3.寫數據 
4.讀數據 
5.應答信號 
6.非應答信號

IIC總線寫時序

IIC總線讀時序

 

• 起始和終止信號
SCL線為高電平期間,SDA線由高電平向低電平的變化表示起始信號;SCL線為高電平期間,SDA線由低電平向高電平的變化表示終止信號。
• 應答信號
發送器每發送一個字節,就在時鍾脈沖9期間釋放數據線,由接收器反饋一個應答信號。 應答信號為低電平時,規定為有效應答位(ACK簡稱應答位),表示接收器已經成功地接收了該字節;應答信號為高電平時,規定為非應答位(NACK)
• 數據讀寫

一目了然吧!?參考代碼如下:

/*******************************************************************************
I2C_START

*******************************************************************************/
void BMP280_I2C_START(void)
{
  BMP280_I2C_SCL(1);
  BMP280_I2C_SDA(1);
  BMP280_I2C_DELAY(2);
  BMP280_I2C_SDA(0);
  BMP280_I2C_DELAY(2);
  BMP280_I2C_SCL(0); 
}

/*******************************************************************************
I2C_STOP

*******************************************************************************/
void BMP280_I2C_STOP(void)
{
  BMP280_I2C_SCL(1);
  BMP280_I2C_SDA(0);
  BMP280_I2C_DELAY(2);
  BMP280_I2C_SDA(1);
  BMP280_I2C_DELAY(2);
}

/*******************************************************************************
I2C_WAIT_ACK
*******************************************************************************/
uint8_t BMP280_I2C_WAIT_ACK(void)
{
  uint8_t Wait_cnt;

  BMP280_I2C_SCL(0);
  BMP280_I2C_SDA(1); 
  BMP280_I2C_SDA_IN();
  BMP280_I2C_DELAY(2);
  BMP280_I2C_SCL(1);

  Wait_cnt = 255;

  while(BMP280_RD_I2C_SDA != 0)
  {
    Wait_cnt--;
    if(Wait_cnt == 0)
    {
      break;
    }
  }

  BMP280_I2C_SCL(0);
  BMP280_I2C_SDA_OUT();

  if(Wait_cnt == 0) 
  {
    BMP280_I2C_STOP();
  }

  return Wait_cnt;
}

/*******************************************************************************
I2C_ACK
*******************************************************************************/
void BMP280_I2C_ACK(void)
{
  BMP280_I2C_SDA(0);
  BMP280_I2C_SCL(0);
  BMP280_I2C_DELAY(2);
  BMP280_I2C_SCL(1); 
  BMP280_I2C_DELAY(2);
  BMP280_I2C_SCL(0);
}

/*******************************************************************************
I2C_NOT_ACK
*******************************************************************************/
void BMP280_I2C_NOT_ACK(void)
{
  BMP280_I2C_SDA(1);
  BMP280_I2C_SCL(0);
  BMP280_I2C_DELAY(2);
  BMP280_I2C_SCL(1);
  BMP280_I2C_DELAY(2);
  BMP280_I2C_SCL(0);
}

/*******************************************************************************
I2C_WRITE_BYTE
*******************************************************************************/
uint8_t BMP280_I2C_WRITE_BYTE(uint8_t dat)
{
  uint8_t i;

  BMP280_I2C_SCL(0); //ÔÚSCLΪµÍÆÚ¼äÉèÖÃSDAΪÊä³ö
  BMP280_I2C_SDA_OUT();
  BMP280_I2C_SDA(0);
  BMP280_I2C_DELAY(1);

  for(i = 0;i < 8;i ++)
  {
    if(dat & 0x80)
    {
      BMP280_I2C_SDA(1);
    }
    else
    {
      BMP280_I2C_SDA(0);
    }
    dat <<= 1;
    BMP280_I2C_DELAY(4);
    BMP280_I2C_SCL(1);
    BMP280_I2C_DELAY(8);
    BMP280_I2C_SCL(0);
  }
  i = BMP280_I2C_WAIT_ACK();
  return i;
}

/*******************************************************************************
I2C_READ_BYTE
*******************************************************************************/
uint8_t BMP280_I2C_READ_BYTE(uint8_t ack)
{
  uint8_t i;
  uint8_t dat=0x00;

  BMP280_I2C_SCL(0);
  BMP280_I2C_SDA(1); 
  BMP280_I2C_SDA_IN();
  BMP280_I2C_DELAY(1);

  for(i = 0;i < 8;i ++)
  {
    dat <<= 1;
    BMP280_I2C_SCL(1);
    BMP280_I2C_DELAY(4);
    if(BMP280_RD_I2C_SDA != 0)
    {
      dat |= 0x01;
    }
    BMP280_I2C_SCL(0);
    BMP280_I2C_DELAY(4);
  }

  BMP280_I2C_SDA_OUT();

  if(ack != 0)
  {
    BMP280_I2C_ACK();
  }
  else
  {
    BMP280_I2C_NOT_ACK();
  }

  return dat;
}

三、 官方代碼移植
官方代碼包含以下幾個文件,將文件添加到工程中

編譯有一處錯誤,將變量的定義移到函數開頭即可,很容易改,這里就不截圖了,大家都懂得。
編譯沒有錯誤后,利用開始寫出的IIC總線時序開始制作接口函數,接口函數有三個如下,直接貼出制作好的接口函數:

int8_t i2c_reg_write(uint8_t i2c_addr, uint8_t reg_addr, uint8_t *reg_data, uint16_t length)
{
  uint8_t res;
  res = BMP280_I2C_Write_Bytes(i2c_addr,reg_addr,reg_data,length);
  if(res==1)
  {
    return 0;
  }
  else
  {
    return 1;
  }
}
int8_t i2c_reg_read(uint8_t i2c_addr, uint8_t reg_addr, uint8_t *reg_data, uint16_t length)
{
  uint16_t res;
  res = BMP280_I2C_Read_Bytes(i2c_addr,reg_addr,reg_data,length);
  if(res==length)
  return 0;
  else
  return 1;
}
void delay_ms(uint32_t period_ms)
{
  Systick_Delay(period_ms);
}

延時函數使用了滴答定時器,延時單位為ms,這個延時很靈活根據自己處理器的使用情況或者是否使用操作系統的情況靈活使用。

至此如果初始化成功,說明移植就已經成功了,接下來就可以參照BOSCH提供的例程進行數據讀取了。

需要注意一點,就是在讀取傳感器參數的時候讀取頻率必須大於25HZ,否則讀數會有問題。

關於BME280的濾波器等參數的設置,請參照BME280官方手冊,至此STM32F103處理器驅動BME280傳感器的程序移植工作完畢,如想交流可以加QQ:184006847。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM