MS5611簡介
MS5611氣壓傳感器是由MEAS(瑞士)推出的一款SPI和I2C總線接口的新一代高分辨率氣壓傳感器,分辨率可達(dá)到10cm。該傳感器模塊包括一個高線性度的壓力傳感器和一個超低功耗的24位Σ模數(shù)轉(zhuǎn)換器(工廠校準(zhǔn)系數(shù))。MS5611提供了一個精確的24位數(shù)字壓力值和溫度值以及不同的操作模式,可以提高轉(zhuǎn)換速度并優(yōu)化電流消耗。高分辨率的溫度輸出無須額外傳感器可實(shí)現(xiàn)高度計(jì)/溫度計(jì)功能??梢耘c幾乎任何微控制器連接。通信協(xié)議簡單,無需在設(shè)備內(nèi)部寄存器編程。MS5611壓力傳感器只有5.0毫米×3.0毫米×1.0毫米的小尺寸可以集成在移動設(shè)備中。這款傳感器采用領(lǐng)先的MEMS技術(shù)并得益于MEAS(瑞士)十余年的成熟設(shè)計(jì)以及大批量制造經(jīng)驗(yàn),保證產(chǎn)品具有高穩(wěn)定性以及非常低的壓力信號滯后。
ms5611是同時支持I2C和SPI通信協(xié)議的氣壓計(jì)芯片。已經(jīng)很普遍的被用在飛行器控制板上作為高度傳感器。開發(fā)過stm32的朋友都知道它的硬件I2C是由bug的,一般使用的都是自己編寫的軟件I2C通信協(xié)議。但是其硬件SPI通信卻是沒有問題的。SPI通信一般會比I2C通信快點(diǎn)。下面先從硬件上說明MS5611在選擇SPI的準(zhǔn)備。
MS5611要選擇使用SPI通信首先需要做的就是把芯片的PS引腳置低。參考數(shù)據(jù)手冊如下:
根據(jù)其設(shè)計(jì)的PCB原理圖如下:
應(yīng)用案例
氣壓傳感器首次在智能手機(jī)上使用是在GalaxyNexus上,而之后推出的一些Android旗艦手機(jī)里也包含了這一傳感器,像GalaxySIII、GalaxyNote2和小米2手機(jī)上也都有,不過大家對于氣壓傳感器仍非常的陌生。跟字面的意思一樣,氣壓傳感器就是用來測量氣壓的,但測量氣壓對于普通的手機(jī)用戶來說又有什么作用呢?
海拔高度測量
對于喜歡登山的人來說,都會非常關(guān)心自己所處的高度。海拔高度的測量方法,一般常用的有2種方式,一是通過GPS全球定位系統(tǒng),二是通過測出大氣壓,然后根據(jù)氣壓值計(jì)算出海拔高度。
由于受到技術(shù)和其它方面原因的限制,GPS計(jì)算海拔高度一般誤差都會有十米左右,而如果在樹林里或者是在懸崖下面時,有時候甚至接收不到GPS衛(wèi)星信號。
而氣壓的方式可選擇的范圍會廣些,而且可以把成本可以控制在比較低的水平。另外像GalaxyNexus等手機(jī)的氣壓傳感器還包括溫度傳感器,它可以捕捉到溫度來對結(jié)果進(jìn)行修正,以增加測量結(jié)果的精度。
所以在手機(jī)原有GPS的基礎(chǔ)上再增加氣壓傳感器的功能,可以讓的三維定位更加精準(zhǔn)。
導(dǎo)航輔助
現(xiàn)在不少開車人士會用手機(jī)來進(jìn)行導(dǎo)航,不過常常會有人抱怨在高架橋里導(dǎo)航常常會出錯 。比如在高架橋上時,GPS說右轉(zhuǎn),而實(shí)際上右邊根本沒有右轉(zhuǎn)出口,這主要是GPS無法判斷你是橋上還是橋下而造成的錯誤導(dǎo)航。一般高架橋上下兩層的高度都會有幾米到十幾米的距離了,而GPS的誤差可能會有幾十米,所以發(fā)生上面的事情也就可以理解了。
而如果手機(jī)里增加一個氣壓傳感器就不一樣了,他的精度可以做到1米的誤差,這樣就可以很好的輔助GPS來測量出所處的高度,錯誤導(dǎo)航的問題也就容易解決了。室內(nèi)定位
由于在室內(nèi)無法很好的接收GPS信號,所以當(dāng)使用者進(jìn)入一幢很厚的樓宇時,內(nèi)置感應(yīng)器可能會失去衛(wèi)星的信號,所以無法識別用戶的地理位置,并且無法感知垂直高度。而如果手機(jī)加上氣壓傳感器再配合加速計(jì)、陀螺儀等技術(shù)就可以做到精準(zhǔn)的室內(nèi)定位。這樣以后你在商場購物時,就可以通過手機(jī)定位來告訴你你想購買的產(chǎn)品在商場的那個位置,哪一層樓。
另外氣壓傳感器還可以為釣魚愛好者提供相關(guān)信息(魚在水中分層及活躍性與大氣壓相關(guān))或天氣預(yù)報等功能。不過目前氣壓傳感器還處于一個被忽略的狀態(tài),氣壓傳感器要想被更多人了解和使用還需要一些相關(guān)技術(shù)的成熟和普及,以及更多的開發(fā)者針對這一傳感器推出更多的應(yīng)用和相關(guān)功能。
MS5607系列高度計(jì)壓力傳感器采用SPI和I2C數(shù)字接口,測量范圍為10~1,200 mbar,溫度補(bǔ)償范圍為40°C~+85°C。該傳感器模塊工作電壓為1.8V~3.6V,包括有高線性度壓力傳感器和具有在制造工廠已校準(zhǔn)好系數(shù)的低功耗24位ADC。MS5607-B還包括溫度輸出,尺寸為5 mm x 3 mm x 1 mm,幾乎可以接口到任何微控制器。
氣壓傳感器MS5611使用SPI接口的程序
#include 《msp430x54x.H》
#include 《math.h》 //Keil library
#include 《stdio.h》
#include 《stdlib.h》 //Keil library
#include “MS5611.h”
#include “CC1101.h”
#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long
#define SPI_B0_MO BIT1
#define SPI_B0_MI BIT2
#define MS_B0_CLK BIT3
#define SPI_B0_CS BIT0
#define MS5611_PS BIT7
#define MS5611_SPI P2DIR |= MS5611_PS; P2OUT &= ~MS5611_PS
#define MS5611_Enable P3OUT &= ~SPI_B0_CS
#define MS5611_Disable P3OUT |= SPI_B0_CS
void Init_SPI_B0(void);
void Wait_MS();
unsigned char SPI_B0_Send_byte(unsigned char byte);
unsigned char SPI_B0_Receive_byte(void);
void SPI_B0_Strobe(unsigned char strobe);
unsigned char SPI_B0_Read(unsigned char addr);
unsigned char SPI_B0_Read_16bits(unsigned char addr);
void MS5611_RESET();
void MS5611_Init();
void MS5611_PROM_READ();
unsigned long MS5611_CONVERSION(unsigned char command);
void MS5611_getTemperature(unsigned char OSR_Temp);
void MS5611_getPressure(unsigned char OSR_Pres);
float get_altitude();
#define MS5611_ADC 0x00
#define CMD_MS5611_RESET 0x1E
#define CMD_MS5611_PROM_Setup 0xA0
#define CMD_MS5611_PROM_C1 0xA2
#define CMD_MS5611_PROM_C2 0xA4
#define CMD_MS5611_PROM_C3 0xA6
#define CMD_MS5611_PROM_C4 0xA8
#define CMD_MS5611_PROM_C5 0xAA
#define CMD_MS5611_PROM_C6 0xAC
#define CMD_MS5611_PROM_CRC 0xAE
#define CMD_CONVERT_D1_OSR4096 0x48 // Maximun resolution
#define CMD_CONVERT_D2_OSR4096 0x58 // Maximun resolution
unsigned long setup,C1,C2,C3,C4,C5,C6,CRC; //用于存放PROM中的8組數(shù)據(jù)
unsigned long D1_Pres,D2_Temp; // 存放壓力和溫度
float dT,Temperature,Pressure;
double OFF,SENS;
float TEMP2,Aux,OFF2,SENS2; //溫度校驗(yàn)值
/*-------------------------SPI_B0-----------------------------*/
void Init_SPI_B0(void)
{
P3SEL |= 0x0E; // P9.1-3 SPI option select
UCB0CTL1 |= UCSWRST; // 復(fù)位SPI狀態(tài)機(jī)
UCB0CTL1 |= UCSSEL__SMCLK; // 選擇SCK參考源為SMCLK
UCB0CTL0 |= UCMST+UCSYNC+UCCKPH+UCMSB; // 3-pin, 8-bit SPI master, Clock polarity high, MSB
UCB0CTL0 &= ~UCCKPL;
UCB0BR0 = 0x02;
UCB0BR1 = 0x00;
UCB0CTL1 &= ~UCSWRST;
}
void Wait_MS()
{
while(P3IN&SPI_B0_MI);
}
unsigned char SPI_B0_Send_byte(unsigned char byte)
{
while((UCB0IFG&UCTXIFG)==0);
UCB0TXBUF=byte;
while((UCB0IFG&UCRXIFG)==0);
return(UCB0RXBUF);
}
unsigned char SPI_B0_Receive_byte(void)
{
return SPI_B0_Send_byte(0);
}
unsigned char SPI_B0_Read(unsigned char addr)
{
unsigned char rTemp;
MS5611_Enable; // CS=0 CS enabl
Wait_MS();
SPI_B0_Send_byte(addr); // Send address
rTemp = SPI_B0_Receive_byte();
MS5611_Disable; // CS=1 CS disable
return ( rTemp );
}
unsigned char SPI_B0_Read_16bits(unsigned char addr)
{
unsigned char byteH,byteL;
unsigned int return_value;
MS5611_Enable;
SPI_B0_Send_byte(addr);
byteH = SPI_B0_Receive_byte();
byteL = SPI_B0_Receive_byte();
MS5611_Disable;
return_value = ((unsigned int)byteH《《8) | (byteL);
return(return_value);
}
void SPI_B0_Strobe(unsigned char strobe)
{
MS5611_Enable; //CS=0 CS enable
Wait_MS(); // Wait for CCxxxx ready
SPI_B0_Send_byte(strobe); // Send strobe
MS5611_Disable;
}
/*-------------------------MS5611-----------------------------*/
void MS5611_RESET()
{
SPI_B0_Strobe(CMD_MS5611_RESET);
}
void MS5611_PROM_READ()
{
//MS5611_Enable;
//Wait_MS();
C1 = SPI_B0_Read_16bits(CMD_MS5611_PROM_C1);
C2 = SPI_B0_Read_16bits(CMD_MS5611_PROM_C2);
C3 = SPI_B0_Read_16bits(CMD_MS5611_PROM_C3);
C4 = SPI_B0_Read_16bits(CMD_MS5611_PROM_C4);
C5 = SPI_B0_Read_16bits(CMD_MS5611_PROM_C5);
C6 = SPI_B0_Read_16bits(CMD_MS5611_PROM_C6);
setup = SPI_B0_Read_16bits(CMD_MS5611_RESET);
CRC = SPI_B0_Read_16bits(CMD_MS5611_PROM_CRC);
//MS5611_Disable;
}
void MS5611_Init()
{
Init_SPI_B0();
MS5611_SPI;
P3DIR |= BIT0; P3OUT |= BIT0;
MS5611_RESET();
delay_ms(10);
MS5611_PROM_READ();
delay_ms(10);
}
long MS5611_SPI_read_ADC()
{
unsigned char byteH,byteM,byteL;
long return_value;
MS5611_Enable;
SPI_B0_Send_byte(MS5611_ADC);
byteH = SPI_B0_Receive_byte();
byteM = SPI_B0_Receive_byte();
byteL = SPI_B0_Receive_byte();
MS5611_Disable;
return_value = (((long)byteH)《《16) | (((long)byteM)《《8) | (byteL);
return(return_value);
}
void MS5611_getPressure(unsigned char OSR_Pres)
{
SPI_B0_Strobe(CMD_CONVERT_D1_OSR4096);
D1_Pres=MS5611_SPI_read_ADC();
delay_ms(10);
OFF=(ulong)C2*65536+((ulong)C4*dT)/128;
SENS=(ulong)C1*32768+((ulong)C3*dT)/256;
if(Temperature《2000)
{
// second order temperature compensation when under 20 degrees C
TEMP2 = (dT*dT) / 0x80000000;
Aux = Temperature*Temperature;
OFF2 = 2.5*Aux;
SENS2 = 1.25*Aux;
Temperature = Temperature - TEMP2;
OFF = OFF - OFF2;
SENS = SENS - SENS2;
}
Pressure=(D1_Pres*SENS/2097152-OFF)/32768;
}
void MS5611_getTemperature(unsigned char OSR_Temp)
{
SPI_B0_Strobe(CMD_CONVERT_D2_OSR4096);
D2_Temp=MS5611_SPI_read_ADC();
delay_ms(10);
dT=D2_Temp - (((ulong)C5)《《8);
Temperature=2000+dT*((ulong)C6)/8388608;
}
float get_altitude()
{
float tmp_float,Altitude;
tmp_float = (Pressure / 101325.0);
tmp_float = pow(tmp_float, 0.190295);
Altitude = 44330 * (1.0 - tmp_float);
return (Altitude);
}
void main(void)
{
int i=0;
float altitude[10];
Init_CLK();
//Init_1101();
MS5611_Init();
while(1)
{
MS5611_getTemperature(CMD_CONVERT_D2_OSR4096);
MS5611_getPressure(CMD_CONVERT_D1_OSR4096);
altitude[i++]=get_altitude();
}
_EINT();
LPM4;
}
評論