单片机控制气压海拔模块BMP180之模块化编程(持续更新中)

来源:互联网 发布:ubuntu切换输入法 编辑:程序博客网 时间:2024/04/28 17:13

这里将我写的STC12C5A60S2单片机控制气压海拔测量模块BMP180的程序共享一下,是为了让前辈给予斧正。

更新:

2015/05/05  08:30  完善了温度值的类型及其运算(没有进行实物验证)

2014/04/17 10:22

(也可以用官网封装好的函数BMP180_API  :http://www.general-files.org/download/gs64624bfeh32i0/bmp180_api.zip.html)

(补充:只需要修改bmp180.h文件中含有 “选择” 字样的部分,就可以达到复用的效果,只需注意中文注释部分)

对于lcd2004部分,请参考《单片机控制2004A液晶屏之模块化编程点击进入

模块:


检测到BMP180的存在:



未检测到BMP180的存在:


测试程序:

#include <reg52.h>#include <string.h>#include "lcd2004.h"#include "bmp180.h"UB8 *table0 = "Module     :BMP180" ;UB8 *table1 = "Temperature:" ;UB8 *table2 = "Pressure   :" ;UB8 *table3 = "Altitude   :" ;void display(BMP180_info temp) ;void main(){ BMP180_info temp ;lcd2004Init(); lcd2004WriteCommand(0x0c) ;/*为了显示效果更佳明显,暂时取消光标显示和闪烁,也可以在LCD2004模块内部修改*/lcd2004AddressWriteString(LCD2004_ROW0,0,table0) ;lcd2004AddressWriteString(LCD2004_ROW1,0,table1) ;lcd2004AddressWriteString(LCD2004_ROW2,0,table2) ;lcd2004AddressWriteString(LCD2004_ROW3,0,table3) ;      BMP180Init(&temp);      while(1)                        { if(temp.ExistFlag == BMP180_EXISTENCE) //存在{BMP180Convert(&temp);display(temp) ;}else//不存在{lcd2004CleanAll() ;lcd2004AddressWriteString(LCD2004_ROW0,0,"Error") ;while(1);}}} void display(BMP180_info temp){// 温度lcd2004AddressWriteByte(LCD2004_ROW1,strlen(table1),((UL32)temp.Temperature)%1000/100+'0') ;lcd2004AddressWriteByte(LCD2004_ROW1,strlen(table1)+1,((UL32)temp.Temperature)%100/10+'0') ;lcd2004AddressWriteByte(LCD2004_ROW1,strlen(table1)+2,((UL32)temp.Temperature)%10+'0') ;lcd2004AddressWriteByte(LCD2004_ROW1,strlen(table1)+3,'.') ;lcd2004AddressWriteByte(LCD2004_ROW1,strlen(table1)+4,((UL32)(temp.Temperature*10))%10+'0') ;lcd2004AddressWriteByte(LCD2004_ROW1,strlen(table1)+5,0xdf) ;lcd2004AddressWriteByte(LCD2004_ROW1,strlen(table1)+6,'C') ;//气压lcd2004AddressWriteByte(LCD2004_ROW2,strlen(table2),temp.GasPress%1000000/100000+'0') ;lcd2004AddressWriteByte(LCD2004_ROW2,strlen(table2)+1,temp.GasPress%100000/10000+'0') ;lcd2004AddressWriteByte(LCD2004_ROW2,strlen(table2)+2,temp.GasPress%10000/1000+'0') ;lcd2004AddressWriteByte(LCD2004_ROW2,strlen(table2)+3,'.') ;lcd2004AddressWriteByte(LCD2004_ROW2,strlen(table2)+4,temp.GasPress%1000/100+'0') ;//数据没有全部显示出来lcd2004AddressWriteByte(LCD2004_ROW2,strlen(table2)+5,'K') ;lcd2004AddressWriteByte(LCD2004_ROW2,strlen(table2)+6,'p') ;lcd2004AddressWriteByte(LCD2004_ROW2,strlen(table2)+7,'a') ;//海拔lcd2004AddressWriteByte(LCD2004_ROW3,strlen(table3),(UL32)temp.Altitude%10000/1000+'0') ;lcd2004AddressWriteByte(LCD2004_ROW3,strlen(table3)+1,(UL32)temp.Altitude%1000/100+'0') ;lcd2004AddressWriteByte(LCD2004_ROW3,strlen(table3)+2,(UL32)temp.Altitude%100/10+'0') ;lcd2004AddressWriteByte(LCD2004_ROW3,strlen(table3)+3,(UL32)temp.Altitude%10+'0') ;lcd2004AddressWriteByte(LCD2004_ROW3,strlen(table3)+4,'.') ;lcd2004AddressWriteByte(LCD2004_ROW3,strlen(table3)+5,(UL32)(temp.Altitude*10)%10+'0') ;lcd2004AddressWriteByte(LCD2004_ROW3,strlen(table3)+6,'m') ;}


/*################BMP180.h start################*/

#ifndef __BMP180_H__#define __BMP180_H__#include <reg52.h>#include "common.h"sbit BMP180_sclk_bit = P3^6 ;/*根据硬件连接选择*/sbit BMP180_sda_bit  = P3^7 ;/*根据硬件连接选择*///BMP180校正参数(calibration param)typedef struct {SW16 AC1 ;SW16 AC2 ;SW16 AC3 ;UW16 AC4 ;UW16 AC5 ;UW16 AC6 ;SW16 B1 ;SW16 B2 ;SW16 MB ;SW16 MC ;SW16 MD ;}BMP180_cal_param;typedef struct {UB8  ExistFlag ;  //存在标志BMP180_cal_param  cal_param;//修正系数UB8 Version ;//版本SL32 UnsetTemperature ;//未校正的温度值SL32 UnsetGasPress  ;//未校正的气压值float Temperature ;/*校正后的温度值*/SL32 GasPress ;/*校正后的气压值*/float Altitude ;/*海拔*/}BMP180_info ;#define BMP180_NOT_EXISTENCE 0/*不存在*/#define BMP180_EXISTENCE     1/*存在*/#define OSS  2//范围(0~3)#define BMP180_READ0x01#define BMP180_WRITE(0x01 &(~(0x01<<0)))#defineBMP180_DEVICE_ADDRESS_BASE_VALUE   0xee /*器件地址基值*/                  //#define BMP180_CONTROL_REGISTER_ADDRESS_BASE_VALUE0xf4 /*控制寄存器地址*/#define BMP180_ID_REGISTER_ADDRESS0xd0 /*ID编号寄存器(0x55固定)*/#define BMP180_VERSION_REGISTER_ADDRESS0XD1 /*版本编号*///#define BMP180_SOFT_RESET_REGISTER_BASE_VALUE    0xe0 /*软件复位寄存器,只写,设置0xb6*///control register//#define BMP180_CONTROL_REGISTER_SCO_BIT (0X01<<5)//id register #define BMP180_ID_FIXED_VALUE0x55 /*id固定编号(0x55)*//*****************内部函数******************///初始化extern void BMP180Init(BMP180_info *p);//转换,修正温度、气压,计算海拔extern void BMP180Convert(BMP180_info *temp) ;/*下面两个函数一般不在外部使用,也可以直接声明为BMP180.c的内部函数*///地址写数据extern void BMP180AddressWrite(UB8 addresss,UB8 dataCode) ;//地址读数据extern UB8 BMP180AddressReadByte(UB8 address) ;/**********************************************/#endif /*__BMP180_H__*/



/*################BMP180.h start################*/


/*################BMP180.c start################*/

/***************************************************************************Module:BMP180.cPurpose:Implementation of BMP180 module.Version:0.012014/02/03 12:00(OK)Complier:Keil 8051 C complier V9.01MCU:STC12C5A60S2Author:yangruiQQ:279729201Email:yangrui90s@163.comModification:=================2015/05/05 09:06Reason:1.在BMP180.h中的结构体BMP180_info中修改SL32 Temperature ;//校正后的温度值为float Temperature ;//校正后的温度值因为BMP180内部通过校正得到的温度值为的单位是0.1摄氏度,比如校正后得到280,表示28摄氏度 。 之前的程序是在其他地方修改注意一下,但是这样做不是太好。这里完善一下。2.将函数BMP180Convert(BMP180_info *temp)里面的:temp->Temperature= ((B5 + 8) >> 4;修改为:temp->Temperature= (((B5 + 8) >> 4)*0.1;==================================2014/04/16 23:06Reason:1.在BMP180.h中的结构体BMP180_info中添加了器件存在标志位。2.在初始化函数BMP180Init(...)中添加了器件存在检测功能。==================================2014/04/16 15:39Reason:1.完成=================***************************************************************************/#include <reg52.h>#include <intrins.h> #include <math.h>#include "bmp180.h"/*外部接口函数在BMP180.h中声明*//*****************内部函数******************/static void delay5msForBMP180(void);static void BMP180StartSignal(void) ;static void BMP180StopSignal(void) ;static void BMP180Acknowledge(void) ;static void BMP180WriteByte(UB8 dataCode) ;static UB8  BMP180ReadByte(void) ;static SL32 BMP180AddressRead2Byte(UB8 address) ;static SL32 BMP180ReadUnsetTemperature(void) ;static SL32 BMP180ReadUnsetPressure(void) ;static void BMP180ReadCalibrateParam(BMP180_info *p) ;/**********************************************//******************************************************Function:delay5msForBMP180Input:N/AOutput:N/AReturn:N/ADescription:N/ANote:由STC-ISP V6.67软件针对相应MCU生成,若MCU不同最好也要修改此函数。******************************************************/static void delay5msForBMP180(void)//@11.0592MHZ{unsigned char i, j;_nop_();_nop_();i = 54;j = 198;do{while (--j);} while (--i);}/******************************************************Function:BMP180StartSignalInput:N/AOutput:N/AReturn:N/ADescription:BMP180 start signalNote:N/A******************************************************/static void BMP180StartSignal(void){BMP180_sda_bit = HIGH_LEVEL ;//_nop_() ;BMP180_sclk_bit = HIGH_LEVEL ;//_nop_() ;BMP180_sda_bit = LOW_LEVEL ;//_nop_();    }/******************************************************Function:BMP180StopSignalInput:N/AOutput:N/AReturn:N/ADescription:BMP180  stop signalNote:N/A******************************************************/static void BMP180StopSignal(void){BMP180_sda_bit = LOW_LEVEL ;//_nop_() ;BMP180_sclk_bit = HIGH_LEVEL ;//_nop_() ;BMP180_sda_bit = HIGH_LEVEL ;/*BMP180 self timed write cycle (5ms max)*/delay5msForBMP180();}/******************************************************Function:BMP180AcknowledgeInput:N/AOutput:N/AReturn:N/ADescription:When BMP180 receive a data from mcu , BMP180 write the datato internal address, after completed write ,BMP180 send a zeroto mcu,then mcu can input data into BMP180.(Once the internally timed write cycle has started and the EEPROM inputs are disabled until write finished.)Note:N/A******************************************************/static void BMP180Acknowledge(void){UB8 i=0 ;BMP180_sclk_bit = LOW_LEVEL ;//_nop_() ;BMP180_sclk_bit = HIGH_LEVEL ;//_nop_() ;while((BMP180_sda_bit) && (i<250)){i++;//暂时,具体见调试//经过测试,这里的250足够大了}BMP180_sclk_bit = LOW_LEVEL ;}/******************************************************Function:BMP180WriteByteInput:the data which is ready to write to BMP180Output:N/AReturn:N/ADescription:N/ANote:N/A******************************************************/static void BMP180WriteByte(UB8 dataCode){UB8 i ;UB8 temp = dataCode ;for(i=0 ; i<8 ; i++){BMP180_sclk_bit = LOW_LEVEL ;//_nop_();//方法一BMP180_sda_bit = (bit)(temp & (0x80>>i)) ;//方法二//temp <<= 1 ;//BMP180_sda_bit = CY ;//_nop_();BMP180_sclk_bit = HIGH_LEVEL ;//_nop_();}}/******************************************************Function:BMP180AddressWriteInput:address,dataOutput:N/AReturn:N/ADescription:write 'dataCode' to 'address'Note:N/A******************************************************/void BMP180AddressWrite(UB8 addresss,UB8 dataCode){    BMP180StartSignal();            BMP180WriteByte(BMP180_DEVICE_ADDRESS_BASE_VALUE | BMP180_WRITE);       BMP180Acknowledge() ;        BMP180WriteByte(addresss);       BMP180Acknowledge() ;        BMP180WriteByte(dataCode);           BMP180Acknowledge() ;        BMP180StopSignal();                   }/******************************************************Function:BMP180ReadByteInput:N/AOutput:N/AReturn:the byte-data which read from BMP180Description:N/ANote:N/A******************************************************/static UB8 BMP180ReadByte(void){UB8 i ;UB8 dataCode = 0x00 ;//Ready/*Data on sda pin may change during scl low timer period*/BMP180_sclk_bit = LOW_LEVEL ;//_nop_() ;BMP180_sda_bit = HIGH_LEVEL ;//ready to read//_nop_() ;for(i=0; i<8 ; i++){BMP180_sclk_bit = HIGH_LEVEL ;//_nop_() ;dataCode<<= 1;dataCode |= BMP180_sda_bit ;//_nop_() ;BMP180_sclk_bit = LOW_LEVEL ;//_nop_() ;}return dataCode ;}/******************************************************Function:BMP180AddressReadByteInput:addressOutput:N/AReturn:data which read from bmp180's addressDescription:read byte-data from bmp180's addressNote:不需要应答.******************************************************/UB8 BMP180AddressReadByte(UB8 address){  UB8 dataCode;    BMP180StartSignal();                                  BMP180WriteByte(BMP180_DEVICE_ADDRESS_BASE_VALUE | BMP180_WRITE);       BMP180Acknowledge() ;        BMP180WriteByte(address);               BMP180Acknowledge() ;        BMP180StartSignal();                                  BMP180WriteByte(BMP180_DEVICE_ADDRESS_BASE_VALUE | BMP180_READ);      BMP180Acknowledge() ;        dataCode=BMP180ReadByte();               BMP180StopSignal();      return dataCode; }/******************************************************Function:BMP180AddressRead2ByteInput:addressOutput:N/AReturn:long dataDescription:从连续地址读取数据,并"组装"为long型数据Note:N/A******************************************************/static SL32 BMP180AddressRead2Byte(UB8 address){UB8 msb , lsb ;msb = BMP180AddressReadByte(address)   ;lsb = BMP180AddressReadByte(address+1) ;return ( ((SL32)msb) << 8 | lsb) ;}/******************************************************Function:BMP180ReadUnsetTemperatureInput:addressOutput:N/AReturn:shour int byte-dataDescription:读取未校正的温度值Note:接收后面的一字节数据,主机不需要应答******************************************************/static SL32 BMP180ReadUnsetTemperature(void){BMP180AddressWrite(0xf4,0x2e) ;return (BMP180AddressRead2Byte(0xf6));}/******************************************************Function:BMP180ReadUnsetPressureInput:N/AOutput:N/AReturn:未校正气压值Description:读取未校正的气压值Note:N/A******************************************************/static SL32 BMP180ReadUnsetPressure(void){SL32 pressure = 0;BMP180AddressWrite(0xf4,0x34 + (OSS<<6)) ;delay5msForBMP180();delay5msForBMP180();pressure = BMP180AddressRead2Byte(0xf6) ;pressure = (((SL32)pressure <<8) + BMP180AddressReadByte(0xf8)) >>(8-OSS) ;return pressure;}/******************************************************Function:BMP180ReadCalibrateParamInput:BMP180_info type pointOutput:AC1,AC3,AC3,AC4,AC5,AC6,B1,B2,MB,MC,MDReturn:N/ADescription:读取校正参数Note:N/A******************************************************/static void BMP180ReadCalibrateParam(BMP180_info *p){p->cal_param.AC1= BMP180AddressRead2Byte(0xAA);p->cal_param.AC2= BMP180AddressRead2Byte(0xAC);p->cal_param.AC3= BMP180AddressRead2Byte(0xAE);p->cal_param.AC4= BMP180AddressRead2Byte(0xB0);p->cal_param.AC5= BMP180AddressRead2Byte(0xB2);p->cal_param.AC6= BMP180AddressRead2Byte(0xB4);p->cal_param.B1=  BMP180AddressRead2Byte(0xB6);p->cal_param.B2=  BMP180AddressRead2Byte(0xB8);p->cal_param.MB=  BMP180AddressRead2Byte(0xBA);p->cal_param.MC=  BMP180AddressRead2Byte(0xBC);p->cal_param.MD=  BMP180AddressRead2Byte(0xBE);}/******************************************************Function:Init_BMP180Input:BMP180_info type pointOutput:p->ExistFlag  存在标志位 p->Version    版本号Return:N/ADescription:初始化Note:N/A******************************************************/void BMP180Init(BMP180_info *p){if(BMP180AddressReadByte(BMP180_ID_REGISTER_ADDRESS)== BMP180_ID_FIXED_VALUE){//存在p->ExistFlag = BMP180_EXISTENCE ;BMP180ReadCalibrateParam(p);p->Version = BMP180AddressReadByte(BMP180_VERSION_REGISTER_ADDRESS);}else{//不存在p->ExistFlag = BMP180_NOT_EXISTENCE ;}}/******************************************************Function:BMP180ConvertInput:BMP180_info type pointOutput:temp->UnsetTemperature 未经过校正的温度值 temp->UnsetGasPress    未经过校正的气压值 temp->Temperature      校正后的温度值 temp->GasPress         校正后的气压值 temp->Altitude         海拔计算值Return:N/ADescription:温度值、气压值的校正和海拔的计算Note:N/A******************************************************/void BMP180Convert(BMP180_info *temp){SL32 x1, x2, B5, B6, x3, B3, p;unsigned long b4, b7;//未校正的温度值temp->UnsetTemperature = BMP180ReadUnsetTemperature();//未校正的气压值temp->UnsetGasPress = BMP180ReadUnsetPressure();//温度校正x1 = ((temp->UnsetTemperature) - temp->cal_param.AC6) * (temp->cal_param.AC5) >> 15;x2 = ((SL32)(temp->cal_param.MC) << 11) / (x1 + temp->cal_param.MD);B5 = x1 + x2;temp->Temperature= ((B5 + 8) >> 4)*0.1;//气压校正B6 = B5- 4000;x1 = ((SL32)(temp->cal_param.B2) * (B6 * B6 >> 12)) >> 11;x2 = ((SL32)temp->cal_param.AC2) * B6 >> 11;x3 = x1 + x2;B3 = ((((SL32)(temp->cal_param.AC1) * 4 + x3)<<OSS) + 2)/4;x1 = ((SL32)temp->cal_param.AC3) * B6 >> 13;x2 = ((SL32)(temp->cal_param.B1) * (B6 * B6 >> 12)) >> 16;x3 = ((x1 + x2) + 2) >> 2;b4 = ((SL32)(temp->cal_param.AC4) * (unsigned long) (x3 + 32768)) >> 15;b7 = ((unsigned long)(temp->UnsetGasPress) - B3) * (50000 >> OSS);if( b7 < 0x80000000){     p = (b7 * 2) / b4 ;}    else    { p = (b7 / b4) * 2;}x1 = (p >> 8) * (p >> 8);x1 = ((SL32)x1 * 3038) >> 16;x2 = (-7357 * p) >> 16;temp->GasPress= p + ((x1 + x2 + 3791) >> 4);//海拔计算temp->Altitude =(44330.0 * (1.0-pow((float)(temp->GasPress) / 101325.0, 1.0/5.255)) );}




/*################BMP180.c start################*/


补充:common.h

#ifndef __COMMON_H__#define __COMMON_H__typedef unsigned char UB8 ;typedef unsigned short int UW16 ;typedef unsigned long UL32 ;typedef char SB8;typedef short int SW16 ;typedef long SL32 ;#define HIGH_LEVEL 1#define LOW_LEVEL  0#endif/*__COMMON_H__*/


7 0
原创粉丝点击