在msp430上使用BMP085
属于msp430的软件实现IIC的应用。记得当初调试的时候,对着示波器看了好久的时钟。在不同单片机上使用时一定要注意时钟大小,注意SDK与SDA是否按手册上给出的波形变化。
使用器件型号:msp430F169/msp430F149,BMP085@BOSCH
典型应用电路:
bmp.c
#include <msp430x16x.h>
#include "BMP.h"
#include <math.h>
//大气压强传感器
//参数定义
long pressure,temperature;
float altitude;
short ac1;
short ac2;
short ac3;
unsigned short ac4;
unsigned short ac5;
unsigned short ac6;
short b1;
short b2;
short mb;
short mc;
short md;
void Delay_ms(unsigned long nValue)
{
unsigned long nCount=106;
int i;
unsigned long j;
for(i = nValue;i > 0;i--)
{
for(j = nCount;j > 0;j--);
}
}
/**************************************
起始信号
**************************************/
void Start()
{
pSCL_OUT;
pSDA_OUT;
pSCL_H;
pSDA_H;
Delay_ms(4);
pSDA_L;
Delay_ms(4);
pSCL_L;
}
//
//void Start()
//{
// SCL_OUT;
// SDA_OUT;
//
// SCL_H;
// Delay_ms(2);
// SDA_H;
// Delay_ms(2);
// SDA_L;
// Delay_ms(2);
// SCL_L;
// Delay_ms(2);
//}
/**************************************
停止信号
**************************************/
void Stop()
{
pSDA_OUT;
pSCL_H;
// SCL_L;
pSDA_L;
Delay_ms(4);
pSCL_H;
pSDA_H;
Delay_ms(4);
}
/**************************************
发送应答信号
**************************************/
void SendACK(void)
{
pSCL_L;
pSDA_OUT;
pSDA_L;
Delay_ms(2);
pSCL_H;
Delay_ms(2);
pSDA_L;
}
void SendNoACK(void)
{
pSCL_L;
pSDA_OUT;
pSDA_H;
Delay_ms(2);
pSCL_H;
Delay_ms(2);
pSCL_L;
}
/**************************************
接收应答信号
**************************************/
uint8_t RecvACK()
{
char ucErrTime=0;
pSCL_L;Delay_ms(2);/////////////////////
pSDA_IN;
pSCL_H;Delay_ms(2);
while(pSDA_RIN)
{
ucErrTime++;
if(ucErrTime>250)
{
Stop();
return 1;
}
}
pSCL_L;
Delay_ms(2);
return 0;
// SDA_IN;
// Delay_ms(2);
// _NOP();
// _NOP();
// _NOP();
// _NOP();
// t=SDA_RIN;
// Delay_ms(2);
// _NOP();
// _NOP();
// _NOP();
// _NOP();
// SCL_L;
// Delay_ms(2);
}
/**************************************
向IIC总线发送一个字节数据
**************************************/
//void SendByte(uint8_t dat)
//{
// uint8_t i;
//
// SDA_OUT;
//
// for (i=0; i<8; i++) //8位计数器
// {
// if((dat& 0x80)>>7)
// SDA_H;
// else
// SDA_L;
// dat<<=1;
// Delay_ms(2);
// SCL_H;
// Delay_ms(2);
// SCL_L;
// Delay_ms(2);
// }
// RecvACK();
//
//}
void SendByte(uint8_t dat)
{
uint8_t i;
pSDA_OUT;
for (i=0; i<8; i++) //8位计数器
{
pSCL_L;
Delay_ms(2);
if((dat& 0x80)>>7)
pSDA_H;
else
pSDA_L;
dat<<=1;
Delay_ms(2);
pSCL_H;
Delay_ms(2);
}
pSCL_L;
Delay_ms(2);
pSDA_H;
Delay_ms(2);
RecvACK();
}
uint8_t RecvByte()
{
uint8_t i,dat=0;
pSDA_IN;
Delay_ms(2);
for(i=0;i<8;i++)
{
pSCL_L;
Delay_ms(2);
pSCL_H;
dat<<=1;
if(pSDA_RIN)dat++;
Delay_ms(1);
}
pSDA_OUT;
return dat;
}
short Multiple_read(uint8_t ST_Address)
{
uint8_t msb, lsb;
short _data;
Start(); //起始信号
SendByte(0xEE); //发送设备地址+写信号
SendByte(ST_Address); //发送存储单元地址
Start(); //起始信号
SendByte(0xEF); //发送设备地址+读信号
msb = RecvByte(); //BUF[0]存储
SendACK(); //回应ACK
lsb = RecvByte();
SendNoACK(); //最后一个数据需要回NOACK
Stop(); //停止信号
Delay_ms(5);
_data = ((short)msb) << 8;
_data |= lsb;
return _data;
}
long bmp085ReadTemp(void)
{
Start(); //起始信号
SendByte(0xEE); //发送设备地址+写信号
SendByte(0xF4); // write register address
SendByte(0x2E); // write register data for temp
Stop(); //发送停止信号
Delay_ms(5);
// max time is 4.5ms
return (long) Multiple_read(0xF6);
}
long bmp085ReadPressure(void)
{
long pressure = 0;
Start(); //起始信号
SendByte(0xEE); //发送设备地址+写信号
SendByte(0xF4); // write register address
SendByte(0x34); // write register data for pressure
Stop(); //发送停止信号
Delay_ms(5); // max time is 4.5ms
pressure = (long) Multiple_read(0xF6);
pressure &= 0x0000FFFF;
return pressure;
}
void Init_BMP085(void)
{
ac1 = Multiple_read(0xAA);
ac2 = Multiple_read(0xAC);
ac3 = Multiple_read(0xAE);
ac4 = Multiple_read(0xB0);
ac5 = Multiple_read(0xB2);
ac6 = Multiple_read(0xB4);
b1 = Multiple_read(0xB6);
b2 = Multiple_read(0xB8);
mb = Multiple_read(0xBA);
mc = Multiple_read(0xBC);
md = Multiple_read(0xBE);
}
//long bmp085_calc_pressure
void bmp085Convert()
{
unsigned int ut;
unsigned long up;
long x1, x2, b5, b6, x3, b3, p;
unsigned long b4, b7;
ut = bmp085ReadTemp();
ut = bmp085ReadTemp(); // 读取温度
up = bmp085ReadPressure(); // 读取压强
x1 = (((long)ut - (long)ac6)*(long)ac5) >> 15;
x2 = ((long) mc << 11) / (x1 + md);
b5 = x1 + x2;
temperature = ((b5 + 8) >> 4);
b6 = b5 - 4000;
// Calculate B3
x1 = (b2 * (b6 * b6)>>12)>>11;
x2 = (ac2 * b6)>>11;
x3 = x1 + x2;
b3 = (((((long)ac1)*4 + x3)<<OSS) + 2)>>2;
// Calculate B4
x1 = (ac3 * b6)>>13;
x2 = (b1 * ((b6 * b6)>>12))>>16;
x3 = ((x1 + x2) + 2)>>2;
b4 = (ac4 * (unsigned long)(x3 + 32768))>>15;
b7 = ((unsigned long)(up - b3) * (50000>>OSS));
if (b7 < 0x80000000)
p = (b7<<1)/b4;
else
p = (b7/b4)<<1;
x1 = (p>>8) * (p>>8);
x1 = (x1 * 3038)>>16;
x2 = (-7357 * p)>>16;
pressure = p+((x1 + x2 + 3791)>>4);
altitude=44330 * (1-pow((p/ 101325.0),(1.0/5.255)));
}
void uint_uart(void)
{
P5SEL = 0x00;
//P5SEL |=BIT2;
// P5SEL &=~ BIT1;
// P5DIR &=~BIT1;
P5DIR |= BIT1+BIT2;
BCSCTL1=(XT2OFF+RSEL2);
DCOCTL=DCO2;
pSCL_OUT;
pSDA_OUT;
pSCL_H;
pSDA_H;
}
/***FUNC+*********************************************************************/
/* Name : Init_CLK */
/* Descrp : Set PLL Clock. */
/* Input : None. */
/* Output : None. */
/* Return : None. */
/***FUNC-*********************************************************************/
void Init_CLK(void)
{
unsigned int iq0;
//BCSCTL1&=~0X00; //打开XT2振荡器
BCSCTL1 &= ~XT2OFF; //打开XT振荡器
do
{
IFG1 &= ~OFIFG; // 清除振荡器失效标志
for (iq0 = 0xFF; iq0 > 0; iq0--); // 延时,等待XT2起振
}
while ((IFG1 & OFIFG) != 0); // 判断XT2是否起振
//BCSCTL2 =SELM_2+SELS; //选择MCLK、SMCLK为XT2
BCSCTL2 |= SELM1+SELS; //MCLK为8MHZ,SMCLK为8MHZ
}
int main()
{
// Stop watchdog timer to prevent time out reset
WDTCTL = WDTPW + WDTHOLD;
Init_CLK();//时钟初始化
P5SEL = 0;
// 将P1.4 P1.5 P1.6 P1.7设置为输出方向
pSDA_OUT;
pSCL_OUT;
Init_BMP085();
while(1){
bmp085Convert();
//Delay_ms(5000);
}
}
bmp.h
#ifndef _BMP_H_
#define _BMP_H_
/******************************** BMP085 **********************************************/
#define BMP085_ADDRESS 0xEE //发送模块地址+W(表示写操作)
#define BMP085_PROM_START__ADDR 0xAA
#define BMP085_CTRL_MEAS_REG 0xF4 //发送命令控制方式:发送寄存器地址 向固定的寄存器(0xF4)写特定值
#define BMP085_T_MEASURE 0x2E // temperature measurent
#define BMP085_P_MEASURE 0x34 // pressure measurement
#define BMP085_ADC_OUT_MSB_REG 0xF6 //读取数据方式:送寄存器地址 从特定的寄存器(Tab4.2的寄存器地址)读返回值
#define OSS 0 // 大气压的转换时间,有0-3可选值
//类比温湿度传感器宏定义及其封装
#define pSDA_OUT P5DIR |= BIT1
#define pSCL_OUT P5DIR |= BIT0
#define pSDA_IN P5DIR &=~BIT1
#define pSDA_RIN (P5IN & BIT1)
#define pSDA_H P5OUT |= BIT1 //DATA <---> P2.2
#define pSDA_L P5OUT &=~ BIT1
#define pSCL_H P5OUT |= BIT0 //SCL <---> P2.1
#define pSCL_L P5OUT &=~ BIT0
typedef unsigned long uint32_t;
typedef unsigned short uint16_t;
typedef unsigned char uint8_t;
//----------------------------------------------------------------
//Functions Declare
void Init_CLK(void);
/******************************** End of BMP085 **********************************************/
#endif