这里将我写的STC12C5A60S2单片机控制气压海拔测量模块BMP180的程序共享一下,是为了让前辈给予斧正。
更新:2014/04/17 10:22
(也可以用官网封装好的函数BMP180_API :http://www.general-files.org/download/gs64624bfeh32i0/bmp180_api.zip.html)
(补充:只需要修改bmp180.h文件中含有 “选择” 字样的部分,就可以达到复用的效果,只需注意中文注释部分)
(提示:因为其中的宏较多,建议source insight查看代码)
对于LCD2004模块,请参考我的另一篇文章《单片机控制2004A液晶屏之模块化编程》http://blog.csdn.net/yagnruinihao/article/details/19999551
模块:
检测到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) { //温度,这里要注意温度部分是表示有多少个0.1摄氏度,所有有10倍的关系 lcd2004AddressWriteByte(LCD2004_ROW1,strlen(table1),temp.Temperature%10000/1000+‘0‘) ; lcd2004AddressWriteByte(LCD2004_ROW1,strlen(table1)+1,temp.Temperature%1000/100+‘0‘) ; lcd2004AddressWriteByte(LCD2004_ROW1,strlen(table1)+2,temp.Temperature%100/10+‘0‘) ; lcd2004AddressWriteByte(LCD2004_ROW1,strlen(table1)+3,‘.‘) ; lcd2004AddressWriteByte(LCD2004_ROW1,strlen(table1)+4,temp.Temperature%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 ; //未校正的气压值 SL32 Temperature ; /*校正后的温度值*/ SL32 GasPress ; /*校正后的气压值*/ float Altitude ; /*海拔*/ }BMP180_info ; #define BMP180_NOT_EXISTENCE 0 /*不存在*/ #define BMP180_EXISTENCE 1 /*存在*/ #define OSS 2 //范围(0~3) #define BMP180_READ 0x01 #define BMP180_WRITE (0x01 &(~(0x01<<0))) #define BMP180_DEVICE_ADDRESS_BASE_VALUE 0xee /*器件地址基值*/ //#define BMP180_CONTROL_REGISTER_ADDRESS_BASE_VALUE 0xf4 /*控制寄存器地址*/ #define BMP180_ID_REGISTER_ADDRESS 0xd0 /*ID编号寄存器(0x55固定)*/ #define BMP180_VERSION_REGISTER_ADDRESS 0XD1 /*版本编号*/ //#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_VALUE 0x55 /*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.c Purpose :Implementation of BMP180 module. Version :0.01 2014/02/03 12:00(OK) Complier:Keil 8051 C complier V9.01 MCU :STC12C5A60S2 Author :yangrui QQ :279729201 Email :yangrui90s@163.com Modification: ================= 2014/04/16 23:06 Reason: 1.在BMP180.h中的结构体BMP180_info中添加了器件存在标志位。 2.在初始化函数BMP180Init(...)中添加了器件存在检测功能。 ================= ================= 2014/04/16 15:39 Reason: 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 :delay5msForBMP180 Input :N/A Output :N/A Return :N/A Description :N/A Note :由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 :BMP180StartSignal Input :N/A Output :N/A Return :N/A Description :BMP180 start signal Note :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 :BMP180StopSignal Input :N/A Output :N/A Return :N/A Description :BMP180 stop signal Note :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 :BMP180Acknowledge Input :N/A Output :N/A Return :N/A Description :When BMP180 receive a data from mcu , BMP180 write the data to internal address, after completed write ,BMP180 send a zero to 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 :BMP180WriteByte Input :the data which is ready to write to BMP180 Output :N/A Return :N/A Description :N/A Note :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 :BMP180AddressWrite Input :address,data Output :N/A Return :N/A Description :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 :BMP180ReadByte Input :N/A Output :N/A Return :the byte-data which read from BMP180 Description :N/A Note :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 :BMP180AddressReadByte Input :address Output :N/A Return :data which read from bmp180‘s address Description :read byte-data from bmp180‘s address Note :不需要应答. ******************************************************/ 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 :BMP180AddressRead2Byte Input :address Output :N/A Return :long data Description :从连续地址读取数据,并"组装"为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 :BMP180ReadUnsetTemperature Input :address Output :N/A Return :shour int byte-data Description :读取未校正的温度值 Note :接收后面的一字节数据,主机不需要应答 ******************************************************/ static SL32 BMP180ReadUnsetTemperature(void) { BMP180AddressWrite(0xf4,0x2e) ; return (BMP180AddressRead2Byte(0xf6)); } /****************************************************** Function :BMP180ReadUnsetPressure Input :N/A Output :N/A Return :未校正气压值 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 :BMP180ReadCalibrateParam Input :BMP180_info type point Output :AC1,AC3,AC3,AC4,AC5,AC6,B1,B2,MB,MC,MD Return :N/A Description :读取校正参数 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_BMP180 Input :AC1,AC2,AC3,AC4,AC5,AC6,B1,B2,MB,MC,MD Output :AC1,AC2,AC3,AC4,AC5,AC6,B1,B2,MB,MC,MD Return :N/A Description :初始化 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 ; } } 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; //气压校正 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__*/