標題:
單片機+bmp180高度計輸出壓強,溫度都有波動,高度算出來更是變化很多,怎么濾波
[打印本頁]
作者:
zhouzhouzhouh
時間:
2019-4-26 16:35
標題:
單片機+bmp180高度計輸出壓強,溫度都有波動,高度算出來更是變化很多,怎么濾波
網(wǎng)上查看有卡爾曼濾波,怎么跟程序結(jié)合起來,keil中為什么寫入pow函數(shù)就會出錯
#include <REG51.H>
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <INTRINS.H> //包含_nop_()函數(shù)定義的頭文件
#define uchar unsigned char
#define uint unsigned int
#define BMP180_SlaveAddress 0xee //定義器件在IIC總線中的從地址
#define OSS 0 // 過采樣設(shè)置(注意:代碼沒有設(shè)置為使用其他oss值)
#define DataPort P0 //LCD1602數(shù)據(jù)端口
sbit LCM_RS=P3^5; //LCD1602命令端口寄存器選擇位,輸入
sbit LCM_RW=P3^6; //LCD1602命令端口讀寫
sbit LCM_EN=P3^4; //LCD1602命令端口使能
sbit SCL=P2^1; //IIC時鐘引腳定義
sbit SDA=P2^0; //IIC數(shù)據(jù)引腳定義
int dis_data; //變量
typedef unsigned char BYTE;
typedef unsigned short WORD;
long temperature;//溫度值
long pressure;//壓力值
long height;//相對海拔高度值
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;
/***************延時函數(shù)**********************/
void delay(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
/**************寫命令到lcm子函數(shù)*****************/
void write_com(uchar com)
{
LCM_RS=0;
LCM_RW=0;
LCM_EN=0;
P0=com;
delay(5);
LCM_EN=1;
delay(5);
LCM_EN=0;
}
/***************寫數(shù)據(jù)到lcm子函數(shù)****************/
void write_data(uchar date)
{LCM_RS=1;
P0=date;
delay(5);
LCM_EN=1;
delay(5);
LCM_EN=0;
}
/**************初始化LCD1602*********************/
void InitLcd()
{
write_com(0x38); //設(shè)置16X2顯示,5X7點陣,8位數(shù)據(jù)接口
write_com(0x0c);//設(shè)置開顯示,不顯示光標
write_com(0x06);//寫一個字符后地址指針加1
write_com(0x01);//顯示清0,數(shù)據(jù)指針清0
}
/****************顯示指定坐標的一個字符*******************/
void DisplayOneChar(uchar X,uchar Y,uchar WData)
{
Y&=1;
X&=15;
if(Y)X|=0x40;
X|=0x80;
write_com(X);
write_data(WData);
}
/*************************************延時5微秒函數(shù)**************************************/
void Delay5us()
{
_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();
}
/************************************延時5毫秒函數(shù)*************************************/
void Delay5ms()
{
WORD n = 560;
while (n--);
}
//獲取BMP180設(shè)備ID默認值為0x55
/*uchar GetBMP180DevicelD()
{
uchar DevicelD=0;
BMP180_Start(); //起始信號
BMP180_SendByte(BMP180_SlaveAddress);; //發(fā)送設(shè)備地址+寫信號
BMP180_SendByte(0xD0); //發(fā)送存儲單元地址OD為ID存儲寄存器
BMP180_Start(); //起始信號
BMP180_SendByte(BMP180_SlaveAddress); //發(fā)送設(shè)備地址+讀信號
DevicelD =BMP180_SendByte(0xee);
BMP180_Stop();
return DevicelD;
}*/
/**************************************開始信號(bmp180啟動)**************************************/
void BMP180_Start()
{
SDA = 1; //拉高數(shù)據(jù)線
SCL = 1; //拉高時鐘線
Delay5us(); //延時
SDA = 0; //產(chǎn)生下降沿
Delay5us(); //延時
SCL = 0; //拉低時鐘線
}
/**************************************停止信號(停止)**************************************/
void BMP180_Stop()
{
SDA = 0; //拉低數(shù)據(jù)線
SCL = 1; //拉高時鐘線
Delay5us(); //延時
SDA = 1; //產(chǎn)生上升沿
Delay5us(); //延時
}
/**************************************發(fā)送應(yīng)答信號**************************************/
void BMP180_SendACK(bit ack)
{
SDA = ack; //寫應(yīng)答信號
SCL = 1; //拉高時鐘線
Delay5us(); //延時
SCL = 0; //拉低時鐘線
Delay5us(); //延時
}
/**************************************接收應(yīng)答信號**************************************/
bit BMP180_RecvACK()
{
SCL = 1; //拉高時鐘線
Delay5us(); //延時
CY = SDA; //讀應(yīng)答信號
SCL = 0; //拉低時鐘線
Delay5us(); //延時
return CY;
}
/**************************************向IIC總線發(fā)送一個字節(jié)數(shù)據(jù)**************************************/
void BMP180_SendByte(BYTE dat)
{
BYTE i;
for (i=0; i<8; i++) //8位計數(shù)器
{
dat <<= 1; //移出數(shù)據(jù)的最高位
SDA = CY; //送數(shù)據(jù)口
SCL = 1; //拉高時鐘線
Delay5us(); //延時
SCL = 0; //拉低時鐘線
Delay5us(); //延時
}
BMP180_RecvACK();
}
/**************************************從IIC總線接收一個字節(jié)數(shù)據(jù)**************************************/
BYTE BMP180_RecvByte()
{
BYTE i;
BYTE dat = 0;
SDA = 1; //使能內(nèi)部上拉,準備讀取數(shù)據(jù),
for (i=0; i<8; i++) //8位計數(shù)器
{
dat <<= 1;
SCL = 1; //拉高時鐘線
Delay5us(); //延時
dat |= SDA; //讀數(shù)據(jù)
SCL = 0; //拉低時鐘線
Delay5us(); //延時
}
return dat;
}
/*******************從BMP180中讀取兩字節(jié)數(shù)據(jù)******************************/
short Multiple_read(uchar ST_Address)
{
uchar msb, lsb;
short _data;
BMP180_Start(); //起始信號
BMP180_SendByte(BMP180_SlaveAddress); //發(fā)送設(shè)備地址+寫信號
BMP180_SendByte(ST_Address); //發(fā)送存儲單元地址
BMP180_Start(); //起始信號
BMP180_SendByte(BMP180_SlaveAddress+1); //發(fā)送設(shè)備地址+讀信號
msb = BMP180_RecvByte(); //BUF[0]存儲
BMP180_SendACK(0); //主機發(fā)送應(yīng)答信號,回應(yīng)ACK
lsb = BMP180_RecvByte();
BMP180_SendACK(1); //最后一個數(shù)據(jù)需要回非ACK
BMP180_Stop(); //停止信號
Delay5ms();
_data = msb << 8;
_data |= lsb;
return _data;
}
/******************************溫度讀取**************************************/
long bmp180ReadTemp(void)
{
BMP180_Start(); //起始信號
BMP180_SendByte(BMP180_SlaveAddress); //發(fā)送設(shè)備地址+寫信號
BMP180_SendByte(0xF4); // write register address
BMP180_SendByte(0x2E); // write register data for temp
BMP180_Stop(); //發(fā)送停止信號
delay(10);// max time is 4.5ms
return (long) Multiple_read(0xF6); //返回溫度,0.1℃
}
/************************壓強讀取*************************************/
long bmp180ReadPressure(void)
{
long pressure = 0;
BMP180_Start(); //起始信號
BMP180_SendByte(BMP180_SlaveAddress); //發(fā)送設(shè)備地址+寫信號
BMP180_SendByte(0xF4); // write register address
BMP180_SendByte(0x34); // write register data for pressure
BMP180_Stop(); //發(fā)送停止信號
delay(10); // max time is 4.5ms
pressure = Multiple_read(0xF6);
pressure &= 0x0000FFFF;
return pressure; //返回氣壓值,pa
}
/****************初始化BMP180,讀出內(nèi)部標定參數(shù)**************/
void Init_BMP180()
{
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);
}
double pow(double a,double b)
{
double result=1;
for(;b>0;b--)
{
result*=a;
}
return result;
}
/*************************獲取氣壓、溫度并顯示******************************/
void bmp180Convert()
{
unsigned int ut;
unsigned long up;
long x1, x2, b5, b6, x3, b3, p;
unsigned long b4, b7;
long temp,y;
ut = bmp180ReadTemp(); // 讀取溫度
up = bmp180ReadPressure(); // 讀取壓強
//根據(jù)芯片手冊提供的公式計算補償后的溫度
x1 = (((long)ut - (long)ac6)*(long)ac5) >> 15;//x1=((ut-ac6)*ac5)/(2^15)
x2 = ((long) mc << 11) / (x1 + md); //x2=(mc*2^11)/(x1+md)
b5 = x1 + x2; //b5=x1+x2
temperature = (b5 + 8) >> 4; //t=(b5+8)/(2^4)
// 根據(jù)芯片手冊提供的公式計算補償后的氣壓
b6 = b5 - 4000;
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);
delay(50);
temp=1.0563;
y=0.1987;
pow(temp,y);
/*temp=pressure/101325;
y=1/5.255;
temp=pow(temp,y);
//height=(44330*(1-temp));*/
//height= 44330*(1-pow((pressure/101325.0),(1.0/5.255)));
height=(101325-pressure)*843/1000;
if(height<0)
{
height=(-height);
//height=(-123);
DisplayOneChar(0,0,'T');//溫度部分
DisplayOneChar(1,0,':');
DisplayOneChar(2,0,temperature%1000/100+0x30);
DisplayOneChar(3,0,temperature%100/10+0x30);
DisplayOneChar(4,0,'.');
DisplayOneChar(5,0,temperature%10+0x30);
DisplayOneChar(6,0,0XDF);
DisplayOneChar(7,0,'C');
DisplayOneChar(8,0,'H');//海拔部分
DisplayOneChar(9,0,'-');
DisplayOneChar(10,0,height%10000/1000+0x30);
DisplayOneChar(11,0,height%1000/100+0x30);
DisplayOneChar(12,0,height%100/10+0x30);
DisplayOneChar(13,0,height%10+0x30);
DisplayOneChar(14,0,'.');
DisplayOneChar(15,0,height*10%10+0x30);
//DisplayOneChar(15,0,'m');
DisplayOneChar(0,1,'P');//氣壓部分
DisplayOneChar(1,1,':');
DisplayOneChar(2,1,pressure%1000000/100000+48);
DisplayOneChar(3,1,pressure%100000/10000+48);
DisplayOneChar(4,1,pressure%10000/1000+48);
DisplayOneChar(5,1,'.');
DisplayOneChar(6,1,pressure%1000/100+48);
DisplayOneChar(7,1,pressure%100/10+48);
//DisplayOneChar(8,1,pressure%10/1+48);
DisplayOneChar(8,1,'K');
DisplayOneChar(9,1,'p');
DisplayOneChar(10,1,'a');
}
else
{
DisplayOneChar(0,0,'T');//溫度部分
DisplayOneChar(1,0,':');
DisplayOneChar(2,0,temperature%1000/100+0x30);
DisplayOneChar(3,0,temperature%100/10+0x30);
DisplayOneChar(4,0,'.');
DisplayOneChar(5,0,temperature%10+0x30);
DisplayOneChar(6,0,0XDF);
DisplayOneChar(7,0,'C');
DisplayOneChar(8,0,' ');
DisplayOneChar(9,0,'H');//海拔部分
DisplayOneChar(10,0,height%10000/1000+0x30);
DisplayOneChar(11,0,height%1000/100+0x30);
DisplayOneChar(12,0,height%100/10+0x30);
DisplayOneChar(13,0,height%10+0x30);
DisplayOneChar(14,0,'.');
DisplayOneChar(15,0,height*10%10+0x30);
//DisplayOneChar(15,0,'m');
DisplayOneChar(0,1,'P');//氣壓部分
DisplayOneChar(1,1,':');
DisplayOneChar(2,1,pressure%1000000/100000+48);
DisplayOneChar(3,1,pressure%100000/10000+48);
DisplayOneChar(4,1,pressure%10000/1000+48);
DisplayOneChar(5,1,'.');
DisplayOneChar(6,1,pressure%1000/100+48);
DisplayOneChar(7,1,pressure%100/10+48);
//DisplayOneChar(8,1,pressure%10/1+48);
DisplayOneChar(8,1,'K');
DisplayOneChar(9,1,'p');
DisplayOneChar(10,1,'a');
}
}
/**********************主程序***************************/
void main()
{ long icid;
delay(50); //上電延時
InitLcd(); //液晶初始化
Init_BMP180(); //初始化BMP180
/*icid = Multiple_read(0xD0);
if (icid==0xee)
DisplayOneChar(8,1,'y');
else DisplayOneChar(9,1,'n');
while(1);*/
while(1) //循環(huán)
{
bmp180Convert();
delay(100);
}
}
復(fù)制代碼
歡迎光臨 (http://www.torrancerestoration.com/bbs/)
Powered by Discuz! X3.1