MS5611簡介
MS5611氣壓傳感器是由MEAS(瑞士)推出的一款SPI和I2C總線接口的新一代高分辨率氣壓傳感器,分辨率可達到10cm。該傳感器模塊包括一個高線性度的壓力傳感器和一個超低功耗的24位Σ模數轉換器(工廠校準系數)。MS5611提供了一個精確的24位數字壓力值和溫度值以及不同的操作模式,可以提高轉換速度并優化電流消耗。高分辨率的溫度輸出無須額外傳感器可實現高度計/溫度計功能。可以與幾乎任何微控制器連接。通信協議簡單,無需在設備內部寄存器編程。MS5611壓力傳感器只有5.0毫米×3.0毫米×1.0毫米的小尺寸可以集成在移動設備中。這款傳感器采用領先的MEMS技術并得益于MEAS(瑞士)十余年的成熟設計以及大批量制造經驗,保證產品具有高穩定性以及非常低的壓力信號滯后。
ms5611是同時支持I2C和SPI通信協議的氣壓計芯片。已經很普遍的被用在飛行器控制板上作為高度傳感器。開發過stm32的朋友都知道它的硬件I2C是由bug的,一般使用的都是自己編寫的軟件I2C通信協議。但是其硬件SPI通信卻是沒有問題的。SPI通信一般會比I2C通信快點。下面先從硬件上說明MS5611在選擇SPI的準備。
MS5611要選擇使用SPI通信首先需要做的就是把芯片的PS引腳置低。參考數據手冊如下:
根據其設計的PCB原理圖如下:
應用案例
氣壓傳感器首次在智能手機上使用是在GalaxyNexus上,而之后推出的一些Android旗艦手機里也包含了這一傳感器,像GalaxySIII、GalaxyNote2和小米2手機上也都有,不過大家對于氣壓傳感器仍非常的陌生。跟字面的意思一樣,氣壓傳感器就是用來測量氣壓的,但測量氣壓對于普通的手機用戶來說又有什么作用呢?
海拔高度測量
對于喜歡登山的人來說,都會非常關心自己所處的高度。海拔高度的測量方法,一般常用的有2種方式,一是通過GPS全球定位系統,二是通過測出大氣壓,然后根據氣壓值計算出海拔高度。
由于受到技術和其它方面原因的限制,GPS計算海拔高度一般誤差都會有十米左右,而如果在樹林里或者是在懸崖下面時,有時候甚至接收不到GPS衛星信號。
而氣壓的方式可選擇的范圍會廣些,而且可以把成本可以控制在比較低的水平。另外像GalaxyNexus等手機的氣壓傳感器還包括溫度傳感器,它可以捕捉到溫度來對結果進行修正,以增加測量結果的精度。
所以在手機原有GPS的基礎上再增加氣壓傳感器的功能,可以讓的三維定位更加精準。
導航輔助
現在不少開車人士會用手機來進行導航,不過常常會有人抱怨在高架橋里導航常常會出錯 。比如在高架橋上時,GPS說右轉,而實際上右邊根本沒有右轉出口,這主要是GPS無法判斷你是橋上還是橋下而造成的錯誤導航。一般高架橋上下兩層的高度都會有幾米到十幾米的距離了,而GPS的誤差可能會有幾十米,所以發生上面的事情也就可以理解了。
而如果手機里增加一個氣壓傳感器就不一樣了,他的精度可以做到1米的誤差,這樣就可以很好的輔助GPS來測量出所處的高度,錯誤導航的問題也就容易解決了。室內定位
由于在室內無法很好的接收GPS信號,所以當使用者進入一幢很厚的樓宇時,內置感應器可能會失去衛星的信號,所以無法識別用戶的地理位置,并且無法感知垂直高度。而如果手機加上氣壓傳感器再配合加速計、陀螺儀等技術就可以做到精準的室內定位。這樣以后你在商場購物時,就可以通過手機定位來告訴你你想購買的產品在商場的那個位置,哪一層樓。
另外氣壓傳感器還可以為釣魚愛好者提供相關信息(魚在水中分層及活躍性與大氣壓相關)或天氣預報等功能。不過目前氣壓傳感器還處于一個被忽略的狀態,氣壓傳感器要想被更多人了解和使用還需要一些相關技術的成熟和普及,以及更多的開發者針對這一傳感器推出更多的應用和相關功能。
MS5607系列高度計壓力傳感器采用SPI和I2C數字接口,測量范圍為10~1,200 mbar,溫度補償范圍為40°C~+85°C。該傳感器模塊工作電壓為1.8V~3.6V,包括有高線性度壓力傳感器和具有在制造工廠已校準好系數的低功耗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組數據
unsigned long D1_Pres,D2_Temp; // 存放壓力和溫度
float dT,Temperature,Pressure;
double OFF,SENS;
float TEMP2,Aux,OFF2,SENS2; //溫度校驗值
/*-------------------------SPI_B0-----------------------------*/
void Init_SPI_B0(void)
{
P3SEL |= 0x0E; // P9.1-3 SPI option select
UCB0CTL1 |= UCSWRST; // 復位SPI狀態機
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;
}
評論