發布日期:2022-05-11 點擊率:49
一.IIC協議的圖解如下:
問題思考:1.此程序的IIC速度大概達到了多少?離BMP085的IIC上線速度3.4MBit還有多遠?此程序中如何稍微的修改就提高IIC的速度?
2.比特流的高低位存儲到對應的字節位中很重要,在RGB燈調試中也遇到過。
3.這里可以得到不同精度的大氣壓值,如何操作?
4.這里的SCL引腳和SDA引腳在進行實際操作時,要重新配置,通常推挽模式容易引起電平競爭,但在低速式,不影響數據讀出。
1.數據總線和時鐘總線的端口配置:
?
2:以下是開始和結束信號的函數實現
3.主設備選擇是否向從設備發送應答信號
?
4.從設備向主設備發送應答信號
5.主設備向從設備發送8位數據
6.主設備接收從設備發來的8位數據
具體理解程序請參考BMP085技術手冊。
注:以下為同一環境下,不同測量模式的數據對比。
在測量海拔高度時,傳統的做法是通過測量某一高度的大氣壓力,再經過換算才能得到高度數據。為了測量大氣壓力,就得用上氣壓傳感器,下面就來討論一下氣壓傳感器的應用。
氣壓傳感器是壓力傳感器中的一種,它專用于測量氣體的絕對壓強。目前市場上能見到的氣壓傳感器有很多種,下面就以市場上常見的Bosch公司推出的BMP085來進行討論。BMP085不僅可以實時的測量大氣壓力,還能測量實時溫度。同時它還具有IIC總線的接口,便于單片機進行訪問。另外它的使用也很方便,不需要太多的操作就可讀取到氣壓及測量數據。
BMP085采用強大的8腳陶瓷無引線芯片承載(LCC)超薄封裝,它性能卓越,內置有校準補償,絕對精度最低可以達到0.03hPa(0.25米),并且耗電極低,只有3μA。氣壓測量范圍從300hPa到1100hPa,換算成高度為海拔9000米到500米。下圖是其封裝外形和引腳排列。
引腳各功能如下:1腳(GND)接電源地,2腳(EOC)為完成轉換輸出,3腳(VDDA)為正電源,4腳(VDDD)為數字正電源,5腳為空,6腳(SCL)為IIC的時鐘端,7腳(SDA)為IIC的數據端,8腳(XCLR)為主清除信號輸入端,低電平有效,用來復位BMP085和初始化寄存器和控制器,在不用的情況下可以空置。
BMP085的工作電壓為1.8V~3.6V,典型工作電壓為2.5V,其與單片機相連的典型電路如下圖所示。
BMP085是新一代的小封裝氣壓傳感器,主要用于氣壓溫度檢測,在四軸飛行器上可以用作定高檢測,該傳感器屬于IIC總線接口,依然沿用標準IIC驅動程序
使用該傳感器需要注意的是我們不能直接讀出轉換好的二進制溫度數據或者氣壓數據,必須先讀出一整套約176位的矯正數據,然后啟動轉換,將轉換的數據與矯正數據一起進行矯正運算才能正常獲得溫度,溫度精度為0.1,大氣壓有16bit或者19bit的精度,一般選擇16位精度,
所以對于該傳感器設備,驅動模式如下
1.獲取矯正數據-->啟動溫度轉換--->獲取原始溫度數據-->啟動大氣壓轉換-->獲取原始大氣壓數據-->計算實際溫度數據大氣壓數據
另,轉換時的轉換時間也是計算時的重要參數,計算大氣壓時的過程中需要使用冤死溫度
矯正數據如下
矯正數據都是16位有符號的,所以讀出的時候需要連續讀取兩個字節
通過計算得到的大氣壓強可以計算得到當前傳感器相對于海平面的絕對高度
具體驅動代碼如下所示
#ifndef __BMP085_H_
#define __BMP085_H_
#include "ioremap.h"
#include "common.h"
#include "stm32f10x.h"
#include "uart.h"
#include "delay.h"
//BMP SDA PC0
//BMP SCL PC1
#define BMP_ACK_WAIT_TIME 200 //iic通訊時的ack等待時間
#define BMP085_DEBUG 1
#define OSS 0 // 大氣壓的轉換時間,有0-3可選值
//地址均為讀地址
#define BMP085_ADDR 0xEE //定義器件在IIC總線中的寫地址
#define BMP_AC1_ADDR 0xAA //定義校準寄存器的地址
#define BMP_AC2_ADDR 0xAC
#define BMP_AC3_ADDR 0xAE
#define BMP_AC4_ADDR 0xB0
#define BMP_AC5_ADDR 0xB2
#define BMP_AC6_ADDR 0xB4
#define BMP_B1_ADDR 0xB6
#define BMP_B2_ADDR 0xB8
#define BMP_MB_ADDR 0xBA
#define BMP_MC_ADDR 0xBC
#define BMP_MD_ADDR 0xBE
#define CONTROL_REG_ADDR 0xF4 //控制寄存器,在這個寄存器中設置不同的值可以設置不同轉換時間,同時不同的值可以確認轉換大氣壓或者溫度
#define BMP_COVERT_TEMP 0x2E //轉換溫度 4.5MS
#define BMP_COVERT_PRES_0 0x34 //轉換大氣壓 4.5ms
#define BMP_COVERT_PRES_1 0x74 //轉換大氣壓 7.5ms
#define BMP_COVERT_PRES_2 0xB4 //轉換大氣壓 13.5ms
#define BMP_COVERT_PRES_3 0xF4 //轉換大氣壓 25.5ms
#define BMP_TEMP_PRES_DATA_REG 0xF6 //兩個字節溫度數據
//0xf6 0xf7 0xf8 壓強地址
//0xf6 0xf7 溫度地址
typedef struct BMP085PARAM //校準參數表
{
s16 ac1;
s16 ac2;
s16 ac3;
u16 ac4;
u16 ac5;
u16 ac6;
s16 b1;
s16 b2;
s16 mb;
s16 mc;
s16 md;
}BMP085PARAM;
void BmpInit(void); //接口與參數初始化
//讀取溫度數據并校正轉換
long BmpConvertTemp(void);
//讀取壓強數據并校正轉換
long BmpConvertPressure(void);
#endif
#include "bmp085.h"
static struct BMP085PARAM bmp085ParamStruct={0,0,0,0,0,0,0,0,0,0,0};
//IO方向設置
#define BMP_SDA_IN() {GPIOC->CRL&=0xFFFFFFF0;GPIOC->CRL|=8;}
#define BMP_SDA_OUT() {GPIOC->CRL&=0xFFFFFFF0;GPIOC->CRL|=3;}
//IO操作函數
#define BMP_SCL PCout(1) //SCL
#define BMP_SDA PCout(0) //SDA
#define BMP_READ_SDA PCin(0) //輸入SDA
static void BMP085IOInit(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOC, ENABLE );
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_1;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP ; //推挽輸出
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
BMP_SCL=1;
BMP_SDA=1;
}
//發送IIC起始信號
static void ComStart(void)
{
BMP_SDA_OUT(); //sda線輸出
BMP_SDA=1;
BMP_SCL=1;
DelayUs(5);
BMP_SDA=0;//START:when CLK is high,DATA change form high to low
DelayUs(5);
BMP_SCL=0;//鉗住I2C總線,準備發送或接收數據
}
//發送IIC停止信號
static void ComStop(void)
{
BMP_SDA_OUT();//sda線輸出
BMP_SDA=0;//STOP:when CLK is high DATA change form low to high
BMP_SCL=1;
DelayUs(5);
BMP_SDA=1;//發送I2C總線結束信號
DelayUs(5);
}
//等待ACK,為1代表無ACK 為0代表等到了ACK
static u8 ComWaitAck(void)
{
u8 waitTime=0;
BMP_SDA_OUT();//sda線輸出
BMP_SDA=1;
DelayUs(5);
BMP_SDA_IN(); //SDA設置為輸入
BMP_SCL=1;
DelayUs(5);
while(BMP_READ_SDA)
{
waitTime++;
DelayUs(1);
if(waitTime > BMP_ACK_WAIT_TIME)
{
ComStop();
return 1;
}
}
BMP_SCL=0;
return 0;
}
static void ComSendAck(void)
{
BMP_SCL=0;
BMP_SDA_OUT();
BMP_SDA=0;
DelayUs(2);
BMP_SCL=1;
DelayUs(5);
BMP_SCL=0;
DelayUs(5);
}
static void ComSendNoAck(void)
{
BMP_SCL=0;
BMP_SDA_OUT();
BMP_SDA=1;
DelayUs(2);
BMP_SCL=1;
DelayUs(5);
BMP_SCL=0;
DelayUs(5);
}
//返回0 寫入收到ACK 返回1寫入未收到ACK
static u8 ComSendByte(u8 byte)
{
u8 t;
BMP_SDA_OUT();
for(t=0;t
ut=BmpReadTemp(); // 讀取溫度
x1=(((long)ut - (long)bmp085ParamStruct.ac6)*(long)bmp085ParamStruct.ac5) >> 15;
x2=((long) bmp085ParamStruct.mc << 11) / (x1 + bmp085ParamStruct.md);
b5=x1 + x2;
temperature=((b5 + 8) >> 4); //溫度計算,官方公式
#ifdef BMP085_DEBUG
printf("bmp085 temp is %f 'C
",((float)temperature)/10.0);
#endif
return temperature;
}
//讀取壓強數據并校正轉換
long BmpConvertPressure(void)
{
unsigned int ut;
unsigned long up;
long x1, x2, b5, b6, x3, b3, p;
unsigned long b4, b7;
long pressure;
ut=BmpReadTemp(); // 讀取溫度,計算壓強時需要溫度做參數
up=Bmp085ReadPressure(); // 讀取壓強
x1=(((long)ut - (long)bmp085ParamStruct.ac6)*(long)bmp085ParamStruct.ac5) >> 15;
x2=((long)bmp085ParamStruct.mc << 11) / (x1 + bmp085ParamStruct.md);
b5=x1 + x2;
b6=b5 - 4000;
// Calculate B3
x1=(bmp085ParamStruct.b2 * (b6 * b6)>>12)>>11;
x2=(bmp085ParamStruct.ac2 * b6)>>11;
x3=x1 + x2;
b3=(((((long)bmp085ParamStruct.ac1)*4 + x3)<
// Calculate B4
x1=(bmp085ParamStruct.ac3 * b6)>>13;
x2=(bmp085ParamStruct.b1 * ((b6 * b6)>>12))>>16;
x3=((x1 + x2) + 2)>>2;
b4=(bmp085ParamStruct.ac4 * (unsigned long)(x3 + ))>>15;
b7=((unsigned long)(up - b3) * (>>OSS));
if (b7 < 0x)
p=(b7<<1)/b4;
else
p=(b7/b4)<
#ifdef BMP085_DEBUG
printf("bmp085 pressure is %f KPa
",((float)pressure)/1000.0);
#endif
return pressure;
}
首頁科技知識正文
infinite
09-22
已關閉評論
傳感器 樹莓派
樹莓派連接BMP085數字壓力傳感器
內容
廣告
相關
我最近買了一塊基于BMP085數字壓力傳感器的模塊(GY-65),所以應該寫一篇關于如何從樹莓派中讀取BMP085傳感器數據的文章,樹莓派讀取BMP085的數據是通過SMbus總線來完成的。SMBus(System Management Bus)是I2C協議的一個子集。
GY65的價格參考
BMP085氣壓傳感器
GY65與樹莓派的連接可參考下圖
Python代碼
下面是簡單的測試代碼,代碼首先對BMP085氣壓傳感器進行初始化,然后通過不斷地循環來讀取溫度和氣壓數據。下面是具體的Python代碼:
#!/usr/bin/python
import smbus
import time
bus=smbus.SMBus(0) # 如果樹莓派版本是2.0,那么“ bus=smbus.SMBus(1) ”
address=0x77
def read_byte(adr):
return bus.read_byte_data(address, adr)
def read_word(adr):
high=bus.read_byte_data(address, adr)
low=bus.read_byte_data(address, adr+1)
val=(high
下一篇: PLC、DCS、FCS三大控
上一篇: 電氣控制線路圖控制原