搜索
bottom↓
回复: 3

BOSCH的BMP 180 气压芯片自制海拔计!遇到一些问题!求助!

[复制链接]

出0入0汤圆

发表于 2014-8-26 16:50:46 | 显示全部楼层 |阅读模式
基于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碗,继续卖。说白了,通货膨胀就是,你的钱是挣来的,他的钱是印来的,掺和在一起,你的钱就贬值了。

出0入0汤圆

 楼主| 发表于 2014-8-26 17:13:01 | 显示全部楼层
renpeng009 发表于 2014-8-26 16:56
要么时序不对,要么数据类型不对,要么连接不可靠(虚焊?接触不良?)

如果时序不对的话,应该不能成功读出数据吧!

出400入0汤圆

发表于 2014-8-26 19:21:00 | 显示全部楼层
检查是不是数据转换那块有问题

出0入0汤圆

 楼主| 发表于 2014-8-28 08:00:49 | 显示全部楼层
读出来的数据如下,watch1是温度值;watch2是气压值;watch3是海拔值!感觉不对啊!求指导!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-10-3 09:18

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表