|
基于mega 16 做的。不知道为什么?读出来的温度值、气压值以及转换的海拔值都不对!
从EEPROM中读出的校准值全部一样!
下面是程序:
#ifndef Header_H_
#define Header_H_
#include <avr/io.h>
#include "display.h"
//#include "delay.h"
#include "math.h"
#include <avr/signal.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <string.h>
#include <stdio.h>
#include <avr/pgmspace.h>
#include <avr/eeprom.h>
#include "hbj.h"
//======定义从器件地址和读写方式============//
#define RD_DEVICE_ADD 0XEF //即11101111,1110111是BMP085器件的固定地址,最后的1表示对从器件进行读操作
#define WR_DEVICE_ADD 0XEE //即11101110,1110111是BMP085器件的固定地址,最后的0表示对从器件进行写操作
//======TWI状态定义================//
#define START 0X08
#define RE_START 0X10
#define MT_SLA_ACK 0x18
#define MT_SLA_NOACK 0X20
#define MT_DATA_ACK 0X28
#define MT_DATA_NOACK 0X30
#define MR_SLA_ACK 0X40
#define MR_SLA_NOACK 0X48
#define MR_DATA_ACK 0X50
#define MR_DATA_NOACK 0X58
//=======常用TWI操作定义=========//
#define Start() (TWCR=(1<<TWINT)|(1<<TWSTA)|(1<<TWEN))
#define Stop() (TWCR=(1<<TWINT)|(1<<TWSTO)|(1<<TWEN))
#define Wait() {while(!(TWCR&(1<<TWINT)));}
#define TestACK() (TWSR&0XF8)
#define SetACK() (TWCR|=(1<<TWEA))
#define SetNOACK() (TWCR&=~(1<<TWEA))
#define Twi() (TWCR=(1<<TWINT)|(1<<TWEN))
#define Write8Bit(x) {TWDR=(x);TWCR=(1<<TWINT)|(1<<TWEN);}
/*
//=======引脚电平宏定义=========//
#define LCM_RS_1 PORTB_Bit0=1 //RS脚输出高电平
#define LCM_RS_0 PORTB_Bit0=0 //RS脚输出低电平
#define LCM_RW_1 PORTB_Bit1=1
#define LCM_RW_O PORTB_Bit1=0
#define LCM_EN_1 PORTB_Bit2=1
#define LCM_EN_0 PORTB_Bit2=0
#define DataPort PORTA
#define Busy 0X80
*/
#endif /* Header_H_ */
#include "Header.h"
//========定义全局变量=======//
//volatile unsigned char ge,shi,bai,qian,wan.shiwan;//显示变量
volatile unsigned char ucReadTemp[2]; //接收到的温度数据缓冲区
volatile unsigned char ucReadPressure[2]; //接收到的气压数据缓冲区
volatile int ac1;
volatile int ac2;
volatile int ac3;
volatile unsigned int ac4;
volatile unsigned int ac5;
volatile unsigned int ac6;
volatile int b1;
volatile int b2;
volatile int mb;
volatile int mc;
volatile int md;
volatile long watch1,watch2,watch3;
//======工作指示灯=======//
#define LED_RED_OUT PORTB //输出寄存器
#define LED_RED_DDR DDRB //方向寄存器
#define LED_RED_IO_ID 1 //IO口号
#define LED_RED_INIT {LED_RED_OUT|=(1<<LED_RED_IO_ID);LED_RED_DDR|=(1<<LED_RED_IO_ID);}//设置为输出高电平
#define LED_RED_ON LED_RED_OUT&=~(1<<LED_RED_IO_ID) //点亮LED
#define LED_RED_OFF LED_RED_OUT|=(1<<LED_RED_IO_ID) //熄灭LED
//=======函数的声明============//
unsigned char IIC_Write(unsigned char ucRomAddress,unsigned char *ucBuff,unsigned char len);
unsigned char IIC_Read(unsigned char ucRomAddress,unsigned char *ucBuff,unsigned char len);
void BMP085ReadTemp(void);
void BMP085ReadPressure(void);
void INIT_BMP085(void);
void BMP085Convert();
void main(void)
{
//_delay_ms(400); //延时400ms等待电源稳定
//=====IO口设置======//
DDRA=0XFF;
PORTA=0X00;
DDRB=0XFF;
PORTB=0X00;
DDRC=0XFF;
PORTC=0XFF;
DDRD=0XFF;
PORTD=0X00;
LED_RED_INIT;
INIT_BMP085();
while(1)
{
LED_RED_ON;
BMP085Convert();
LED_RED_OFF;
_delay_ms(1000);
}
}
//======IIC总线写n个字节(成功返回0,失败返回1)========//
unsigned char IIC_Write(unsigned char ucRomAddress,unsigned char *ucBuff,unsigned char len)
{
unsigned char i;
Start(); //启动IIC总线
Wait(); //等待回应
if(TestACK()!=START)
return 1; //若回应不是启动信号,则失败返回1
Write8Bit(WR_DEVICE_ADD); //写IIC从器件地址、写方向
Wait(); //等待回应
if (TestACK()!=MT_SLA_ACK)
{
return 1; //若回应不是ACK信号,则失败返回1
}
Write8Bit(ucRomAddress); //写BMP085的ROM地址
Wait(); //等待回应
if (TestACK()!=MT_DATA_ACK)
{
return 1; //若回应不是ACK信号,则失败返回1
}
for (i=0;i<len;i++)
{
Write8Bit(ucBuff[i]); //写数据到BMP085的ROM中
Wait(); //等待回应
if (TestACK()!=MT_DATA_ACK)
{
return 1; //若回应的不是ACK信号,则失败返回1
}
_delay_ms(10);
}
Stop(); //停止IIC总线
_delay_ms(10); //延时等待BMP085写完
return 0; //写入成功,返回0
}
//===========IIC总线读n个字节(成功返回0,失败返回1)==============//
unsigned char IIC_Read(unsigned char ucRomAddress,unsigned char *ucBuff,unsigned char len)
{
unsigned char i;
Start(); //启动IIC总线
Wait(); //等待回应
if(TestACK()!=START)
return 1; //若回应不是启动信号,则失败返回1
Write8Bit(WR_DEVICE_ADD); //写IIC从器件地址、写方向
Wait(); //等待回应
if (TestACK()!=MT_SLA_ACK)
{
return 1; //若回应不是ACK信号,则失败返回1
}
Write8Bit(ucRomAddress); //写BMP085的ROM地址
Wait(); //等待回应
if (TestACK()!=MT_DATA_ACK)
{
return 1; //若回应不是ACK信号,则失败返回1
}
Start(); //重新启动IIC总线
Wait(); //等待回应
if(TestACK()!=RE_START)
return 1; //若回应不是重新启动信号,则失败返回1
Write8Bit(WR_DEVICE_ADD); //写IIC从器件地址、写方向
Wait(); //等待回应
if (TestACK()!=MR_SLA_ACK)
{
return 1; //若回应不是ACK信号,则失败返回1
}
Write8Bit(ucRomAddress); //写BMP085的ROM地址
Wait(); //等待回应
if (TestACK()!=MT_DATA_ACK)
{
return 1; //若回应不是ACK信号,则失败返回1
}
for (i=0;i<len;i++)
{
Twi(); //启动IIC的读写方式
SetACK(); //设置接收自动应答
_delay_ms(10);
Wait(); //等待回应
_delay_ms(10);
*(ucBuff+i)=TWDR; //连续读取的len个字节数据依次存入对应的数组中
}
SetNOACK(); //读数据的最后一位后紧跟着的是无应答
_delay_ms(10);
Stop(); //停止IIC总线
return 0; //成功,返回0
}
//==========BMP085读温度========================//
void BMP085ReadTemp(void)
{
unsigned char t=0X2E;
IIC_Write(0XF4,&t,1); //向地址0XF4写0X2E,进行温度转换
_delay_ms(5); //延时大于4.5ms
IIC_Read(0XF6,ucReadTemp,2);//从地址0XF6开始读出温度数据并存到数组ucReadTemp中
}
//=========BMP085读气压=========================//
void BMP085ReadPressure(void)
{
unsigned char t=0X34;
IIC_Write(0XF4,&t,1); //向地址0XF4写0X2E,进行第一次气压转换
_delay_ms(5); //延时大于4.5ms
IIC_Read(0XF6,ucReadPressure,2);//从地址0XF6开始读出气压数据并存到数组ucReadPressure中
}
//=======初始化BMP085=========================//
void INIT_BMP085(void)
{
unsigned char temp[2];
// IIC_Read(0XAA,temp,2);
// ac1=(temp[0]<<8)|temp[1];
IIC_Read(0XAA,temp,1);
ac1=(temp[0]<<8);
IIC_Read(0XAB,temp,1);
ac1=ac1+temp;
IIC_Read(0XAC,temp,2);
ac2=(temp[0]<<8)|temp[1];
IIC_Read(0XAE,temp,2);
ac3=(temp[0]<<8)|temp[1];
IIC_Read(0XB0,temp,2);
ac4=(temp[0]<<8)|temp[1];
IIC_Read(0XB2,temp,2);
ac5=(temp[0]<<8)|temp[1];
IIC_Read(0XB4,temp,2);
ac6=(temp[0]<<8)|temp[1];
IIC_Read(0XB6,temp,2);
b1=(temp[0]<<8)|temp[1];
IIC_Read(0XB8,temp,2);
b2=(temp[0]<<8)|temp[1];
IIC_Read(0XBA,temp,2);
mb=(temp[0]<<8)|temp[1];
IIC_Read(0XBC,temp,2);
mc=(temp[0]<<8)|temp[1];
IIC_Read(0XBE,temp,2);
md=(temp[0]<<8)|temp[1]; //连续读取EEPROM中的校准数据,并存放到相应的变量中,供后面补偿使用
}
//===========转换子函数==========//
void BMP085Convert()
{
long ut,up,Temperature,Pressure,Altitude;//定义长整型变量
long x1,x2,b5,b6,x3,b3,p;
unsigned long b4,b7; //定义无符号长整型变量
BMP085ReadTemp(); //读取温度
ut=ucReadTemp[0]<<8|ucReadTemp[1];//合成温度数据
watch1=ut;
x1=((long)ut-ac6)*ac5>>15; //根据EEPROM中的值对获取的温度数据进行补偿换算
x2=((long)mc<<11/(x1+md));
b5=x1+x2;
Temperature=(b5+8)>>4;
BMP085ReadPressure(); //读取气压
up=ucReadPressure[0]<<8|ucReadPressure[1];//合成气压数据
watch2=up;
up&=0X0000FFFF;
b6=b5-4000; //根据EEPROM中的值对获取的气压数据进行补偿换算
x1=(b2*(b6*b6>>12))>>11;
x2=ac2*b6>>11;
x3=x1+x2;
b3=(((long)ac1*4+x3)+2)/4;
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>>0);
if (b7<0X80000000)
{
p=(b7*2)/b4;
}
else
{
p=(b7/b4)*2;
}
x1=(p>>8)*(p>>8);
x1=(x1*3038)>>16;
x2=(-7357*p)>>16;
Pressure=p+((x1+x2+3791)>>4);
//====转换为海拔=====//
Altitude =(44330.0 * (1.0-pow((float)(up) / 101325.0, 1.0/5.255)) );
watch3=Altitude;
} |
阿莫论坛20周年了!感谢大家的支持与爱护!!
你熬了10碗粥,别人一桶水倒进去,淘走90碗,剩下10碗给你,你看似没亏,其实你那10碗已经没有之前的裹腹了,人家的一桶水换90碗,继续卖。说白了,通货膨胀就是,你的钱是挣来的,他的钱是印来的,掺和在一起,你的钱就贬值了。
|