當前位置: 首頁 > 工業(yè)電子產(chǎn)品 > 集成電路(ICs) > IC傳感器
發(fā)布日期:2022-05-11 點擊率:51
一.IIC協(xié)議的圖解如下:
問題思考:1.此程序的IIC速度大概達到了多少?離BMP085的IIC上線速度3.4MBit還有多遠?此程序中如何稍微的修改就提高IIC的速度?
2.比特流的高低位存儲到對應(yīng)的字節(jié)位中很重要,在RGB燈調(diào)試中也遇到過。
3.這里可以得到不同精度的大氣壓值,如何操作?
4.這里的SCL引腳和SDA引腳在進行實際操作時,要重新配置,通常推挽模式容易引起電平競爭,但在低速式,不影響數(shù)據(jù)讀出。
1.數(shù)據(jù)總線和時鐘總線的端口配置:
?
2:以下是開始和結(jié)束信號的函數(shù)實現(xiàn)
3.主設(shè)備選擇是否向從設(shè)備發(fā)送應(yīng)答信號
?
4.從設(shè)備向主設(shè)備發(fā)送應(yīng)答信號
5.主設(shè)備向從設(shè)備發(fā)送8位數(shù)據(jù)
6.主設(shè)備接收從設(shè)備發(fā)來的8位數(shù)據(jù)
具體理解程序請參考BMP085技術(shù)手冊。
注:以下為同一環(huán)境下,不同測量模式的數(shù)據(jù)對比。
在測量海拔高度時,傳統(tǒng)的做法是通過測量某一高度的大氣壓力,再經(jīng)過換算才能得到高度數(shù)據(jù)。為了測量大氣壓力,就得用上氣壓傳感器,下面就來討論一下氣壓傳感器的應(yīng)用。
氣壓傳感器是壓力傳感器中的一種,它專用于測量氣體的絕對壓強。目前市場上能見到的氣壓傳感器有很多種,下面就以市場上常見的Bosch公司推出的BMP085來進行討論。BMP085不僅可以實時的測量大氣壓力,還能測量實時溫度。同時它還具有IIC總線的接口,便于單片機進行訪問。另外它的使用也很方便,不需要太多的操作就可讀取到氣壓及測量數(shù)據(jù)。
BMP085采用強大的8腳陶瓷無引線芯片承載(LCC)超薄封裝,它性能卓越,內(nèi)置有校準補償,絕對精度最低可以達到0.03hPa(0.25米),并且耗電極低,只有3μA。氣壓測量范圍從300hPa到1100hPa,換算成高度為海拔9000米到500米。下圖是其封裝外形和引腳排列。
引腳各功能如下:1腳(GND)接電源地,2腳(EOC)為完成轉(zhuǎn)換輸出,3腳(VDDA)為正電源,4腳(VDDD)為數(shù)字正電源,5腳為空,6腳(SCL)為IIC的時鐘端,7腳(SDA)為IIC的數(shù)據(jù)端,8腳(XCLR)為主清除信號輸入端,低電平有效,用來復(fù)位BMP085和初始化寄存器和控制器,在不用的情況下可以空置。
BMP085的工作電壓為1.8V~3.6V,典型工作電壓為2.5V,其與單片機相連的典型電路如下圖所示。
BMP085是新一代的小封裝氣壓傳感器,主要用于氣壓溫度檢測,在四軸飛行器上可以用作定高檢測,該傳感器屬于IIC總線接口,依然沿用標準IIC驅(qū)動程序
使用該傳感器需要注意的是我們不能直接讀出轉(zhuǎn)換好的二進制溫度數(shù)據(jù)或者氣壓數(shù)據(jù),必須先讀出一整套約176位的矯正數(shù)據(jù),然后啟動轉(zhuǎn)換,將轉(zhuǎn)換的數(shù)據(jù)與矯正數(shù)據(jù)一起進行矯正運算才能正常獲得溫度,溫度精度為0.1,大氣壓有16bit或者19bit的精度,一般選擇16位精度,
所以對于該傳感器設(shè)備,驅(qū)動模式如下
1.獲取矯正數(shù)據(jù)-->啟動溫度轉(zhuǎn)換--->獲取原始溫度數(shù)據(jù)-->啟動大氣壓轉(zhuǎn)換-->獲取原始大氣壓數(shù)據(jù)-->計算實際溫度數(shù)據(jù)大氣壓數(shù)據(jù)
另,轉(zhuǎn)換時的轉(zhuǎn)換時間也是計算時的重要參數(shù),計算大氣壓時的過程中需要使用冤死溫度
矯正數(shù)據(jù)如下
矯正數(shù)據(jù)都是16位有符號的,所以讀出的時候需要連續(xù)讀取兩個字節(jié)
通過計算得到的大氣壓強可以計算得到當前傳感器相對于海平面的絕對高度
具體驅(qū)動代碼如下所示
#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 // 大氣壓的轉(zhuǎn)換時間,有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 //控制寄存器,在這個寄存器中設(shè)置不同的值可以設(shè)置不同轉(zhuǎn)換時間,同時不同的值可以確認轉(zhuǎn)換大氣壓或者溫度
#define BMP_COVERT_TEMP 0x2E //轉(zhuǎn)換溫度 4.5MS
#define BMP_COVERT_PRES_0 0x34 //轉(zhuǎn)換大氣壓 4.5ms
#define BMP_COVERT_PRES_1 0x74 //轉(zhuǎn)換大氣壓 7.5ms
#define BMP_COVERT_PRES_2 0xB4 //轉(zhuǎn)換大氣壓 13.5ms
#define BMP_COVERT_PRES_3 0xF4 //轉(zhuǎn)換大氣壓 25.5ms
#define BMP_TEMP_PRES_DATA_REG 0xF6 //兩個字節(jié)溫度數(shù)據(jù)
//0xf6 0xf7 0xf8 壓強地址
//0xf6 0xf7 溫度地址
typedef struct BMP085PARAM //校準參數(shù)表
{
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); //接口與參數(shù)初始化
//讀取溫度數(shù)據(jù)并校正轉(zhuǎn)換
long BmpConvertTemp(void);
//讀取壓強數(shù)據(jù)并校正轉(zhuǎn)換
long BmpConvertPressure(void);
#endif
#include "bmp085.h"
static struct BMP085PARAM bmp085ParamStruct={0,0,0,0,0,0,0,0,0,0,0};
//IO方向設(shè)置
#define BMP_SDA_IN() {GPIOC->CRL&=0xFFFFFFF0;GPIOC->CRL|=8;}
#define BMP_SDA_OUT() {GPIOC->CRL&=0xFFFFFFF0;GPIOC->CRL|=3;}
//IO操作函數(shù)
#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;
}
//發(fā)送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總線,準備發(fā)送或接收數(shù)據(jù)
}
//發(fā)送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;//發(fā)送I2C總線結(jié)束信號
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設(shè)置為輸入
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;
}
//讀取壓強數(shù)據(jù)并校正轉(zhuǎn)換
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(); // 讀取溫度,計算壓強時需要溫度做參數(shù)
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
已關(guān)閉評論
傳感器 樹莓派
樹莓派連接BMP085數(shù)字壓力傳感器
內(nèi)容
廣告
相關(guān)
我最近買了一塊基于BMP085數(shù)字壓力傳感器的模塊(GY-65),所以應(yīng)該寫一篇關(guān)于如何從樹莓派中讀取BMP085傳感器數(shù)據(jù)的文章,樹莓派讀取BMP085的數(shù)據(jù)是通過SMbus總線來完成的。SMBus(System Management Bus)是I2C協(xié)議的一個子集。
GY65的價格參考
BMP085氣壓傳感器
GY65與樹莓派的連接可參考下圖
Python代碼
下面是簡單的測試代碼,代碼首先對BMP085氣壓傳感器進行初始化,然后通過不斷地循環(huán)來讀取溫度和氣壓數(shù)據(jù)。下面是具體的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三大控
上一篇: 電氣控制線路圖控制原