MS5611简介
MS5611气压传感器是由MEAS(瑞士)推出的一款SPI和I²C总线接口的新一代高分辨率气压传感器,分辨率可达到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;
}