这里将我写的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_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:
- =================
- 2015/05/05 09:06
- Reason:
- 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: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 :BMP180_info type point
- Output :p->ExistFlag 存在标志位
- p->Version 版本号
- 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 ;
- }
- }
- /******************************************************
- Function :BMP180Convert
- Input :BMP180_info type point
- Output :temp->UnsetTemperature 未经过校正的温度值
- temp->UnsetGasPress 未经过校正的气压值
- temp->Temperature 校正后的温度值
- temp->GasPress 校正后的气压值
- temp->Altitude 海拔计算值
- Return :N/A
- Description :温度值、气压值的校正和海拔的计算
- 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__*/
转自:http://blog.csdn.net/yagnruinihao/article/details/23914675