OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 17723|回复: 26

STM32F103VCT6驱动气压计芯片BMP180

[复制链接]

2

主题

11

帖子

0

精华

初级会员

Rank: 2

积分
60
金钱
60
注册时间
2015-3-18
在线时间
4 小时
发表于 2015-4-14 17:15:02 | 显示全部楼层 |阅读模式
[mw_shl_code=c,true][/mw_shl_code]
最近驱动了一款气压计传感器BMP180,拿出来和大家分享一下。希望能帮到那些正为此困惑的人。

实际效果如下图。说明一下,本人在江苏昆山,海平面较低,所以显示海拔只有32.4m。我用真空发生器做过实验,压强会减小,海拔会上升。精度还需做更精确的实验区验证。


此程序完全按照数据手册里面的配置说明一步一步配置,然后读取寄存器参数,然后转换结果。数据手册如附件,我已经标明了重点需要看的地方。
程序源码如下:
[mw_shl_code=c,true]#include "iic.h" #include "delay.h" //调用了延时函数 #include "usart.h" #include <math.h> //SCL -> PC1 //SDA -> PC2 #define SCL_H() GPIO_SetBits(GPIOC, GPIO_Pin_1) #define SCL_L() GPIO_ResetBits(GPIOC, GPIO_Pin_1) #define SDA_H() GPIO_SetBits(GPIOC, GPIO_Pin_2) #define SDA_L() GPIO_ResetBits(GPIOC, GPIO_Pin_2) #define SDA GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_2) #define BMP180_SlaveAddr 0xee //BMP180的器件地址 //BMP180校准系数 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; u8 BMP180_ID=0; //BMP180的ID float True_Temp=0; //实际温度,单位:℃ float True_Press=0; //实际气压,单位a float True_Altitude=0; //实际高度,单位:m /*外部芯片IIC引脚初始化 *SCLC1 *SDAC2 */ void IIC_PortInit(void) { GPIO_InitTypeDef GPIO_InitStructure; //定义一个GPIO_InitTypeDef类型的结构体 GPIO_InitStructure.GPIO_Pin = (GPIO_Pin_1|GPIO_Pin_2); //PC1,PC2 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD; //漏极开漏 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOC, &GPIO_InitStructure); GPIO_SetBits(GPIOC, GPIO_Pin_1|GPIO_Pin_2); //拉高 } void IIC_Init(void) { SCL_H(); //SCL = 1; delay_us(5); SDA_H(); //SDA = 1; delay_us(5); } void IIC_Start(void) { SDA_H(); //SDA = 1; delay_us(5); SCL_H(); //SCL = 1; delay_us(5); SDA_L(); //SDA = 0; delay_us(5); } void IIC_Stop(void) { SDA_L(); //SDA = 0; delay_us(5); SCL_H(); //SCL = 1; delay_us(5); SDA_H(); //SDA = 1; delay_us(5); } unsigned char IIC_ReceiveACK(void) { unsigned char ACK; SDA_H(); //SDA=1;//要读低电平需先拉高再读,否则读到的是错误数据,很重要! SCL_H(); //SCL=1; delay_us(5); if (SDA==1) //SDA为高 { ACK = 1; } else ACK = 0; //SDA为低 SCL_L(); //SCL = 0;//SCL为低电平时SDA上的数据才允许变化,为传送下一个字节做准备 delay_us(5); return ACK; } void IIC_SendACK(unsigned char ack) { if (ack == 1)SDA_H(); else if (ack == 0)SDA_L(); //SDA = ack; SCL_H(); //SCL = 1; delay_us(5); SCL_L(); //SCL = 0; delay_us(5); } unsigned char IIC_SendByte(unsigned char dat) { unsigned char i; unsigned char bResult=1; SCL_L(); //SCL = 0;//拉低时钟线 delay_us(5); for( i=0;i<8;i++ ) //一个SCK,把dat一位一位的移送到SDA上 { if( (dat<<i)&0x80 )SDA_H(); //SDA = 1;//先发高位 else SDA_L(); //SDA = 0; delay_us(5); SCL_H(); //SCL = 1; delay_us(5); SCL_L(); //SCL = 0; delay_us(5); } bResult=IIC_ReceiveACK(); //发送完一个字节的数据,等待接受应答信号 return bResult; //返回应答信号 } unsigned char IIC_ReadByte(void) { unsigned char dat; unsigned char i; SCL_H(); //SCL = 1;//始终线拉高为读数据做准备 delay_us(5); for( i=0;i<8;i++ ) { dat <<= 1; dat = dat | (SDA); delay_us(5); SCL_L(); //SCL = 0; delay_us(5); SCL_H(); //SCL = 1; delay_us(5); } return dat; } /*从BMP180中读1个字节的数据*/ u8 BMP180_ReadOneByte(u8 ReadAddr) { u8 temp = 0; u8 IIC_ComFlag = 1; //IIC通信标志,为0标志正常,1表示通信错误 IIC_Start(); //IIC start IIC_ComFlag = IIC_SendByte(BMP180_SlaveAddr); //slave address+W:0 //printf("IIC_ComFlag=%u \r\n",IIC_ComFlag); if (IIC_ComFlag == 0) //返回值为0表示通信正常,可以继续通信。否则不通信了 { IIC_SendByte(ReadAddr); //发送命令代码 IIC_Start(); IIC_SendByte(BMP180_SlaveAddr|0x01); //slave address+R:1 temp = IIC_ReadByte(); //读数据 IIC_SendACK(1); IIC_Stop(); } return (temp); } /*从BMP180中读2个字节的数据*/ short BMP180_ReadTwoByte(u8 ReadAddr) { u8 IIC_ComFlag = 1; //IIC通信标志,为0标志正常,1表示通信错误 u8 MSB,LSB; short temp; IIC_Start(); IIC_ComFlag = IIC_SendByte(BMP180_SlaveAddr); if (IIC_ComFlag == 0) { IIC_SendByte(ReadAddr); IIC_Start(); IIC_SendByte(BMP180_SlaveAddr|0x01); MSB = IIC_ReadByte(); //先读高位 IIC_SendACK(0); //ACK LSB = IIC_ReadByte(); //再读低位 IIC_SendACK(1); //NACK IIC_Stop(); } temp = MSB*256+LSB; return temp; } /*向BMP180的寄存器写一个字节的数据*/ void Write_OneByteToBMP180(u8 RegAdd, u8 Data) { IIC_Start(); //IIC start IIC_SendByte(BMP180_SlaveAddr); //slave address+W:0 IIC_SendByte(RegAdd); IIC_SendByte(Data); IIC_Stop(); } /*读取BMP180的校准系数*/ void Read_CalibrationData(void) { AC1 = BMP180_ReadTwoByte(0xaa); AC2 = BMP180_ReadTwoByte(0xac); AC3 = BMP180_ReadTwoByte(0xae); AC4 = BMP180_ReadTwoByte(0xb0); AC5 = BMP180_ReadTwoByte(0xb2); AC6 = BMP180_ReadTwoByte(0xb4); B1 = BMP180_ReadTwoByte(0xb6); B2 = BMP180_ReadTwoByte(0xb8); MB = BMP180_ReadTwoByte(0xba); MC = BMP180_ReadTwoByte(0xbc); MD = BMP180_ReadTwoByte(0xbe); printf("AC1:%d \r\n",AC1); printf("AC2:%d \r\n",AC2); printf("AC3:%d \r\n",AC3); printf("AC4:%d \r\n",AC4); printf("AC5:%d \r\n",AC5); printf("AC6:%d \r\n",AC6); printf("B1:%d \r\n",B1); printf("B2:%d \r\n",B2); printf("MB:%d \r\n",MB); printf("MC:%d \r\n",MC); printf("MD:%d \r\n",MD); } /*读BMP180没有经过补偿的温度值*/ long Get_BMP180UT(void) { long UT; Write_OneByteToBMP180(0xf4,0x2e); //write 0x2E into reg 0xf4 delay_ms(10); //wait 4.5ms UT = BMP180_ReadTwoByte(0xf6); //read reg 0xF6(MSB),0xF7(LSB) printf("UT:%ld \r\n",UT); return UT; } /*读BMP180没有经过补偿的压力值*/ long Get_BMP180UP(void) { long UP=0; Write_OneByteToBMP180(0xf4,0x34); //write 0x34 into reg 0xf4 delay_ms(10); //wait 4.5ms UP = BMP180_ReadTwoByte(0xf6); UP &= 0x0000FFFF; printf("UP:%ld \r\n",UP); return UP; } /*把未经过补偿的温度和压力值转换为时间的温度和压力值 *True_Temp:实际温度值,单位:℃ *True_Press:时间压力值,单位a *True_Altitude:实际海拔高度,单位:m */ void Convert_UncompensatedToTrue(long UT,long UP) { long X1,X2,X3,B3,B5,B6,B7,T,P; unsigned long B4; X1 = ((UT-AC6)*AC5)>>15; //printf("X1:%ld \r\n",X1); X2 = ((long)MC<<11)/(X1+MD); //printf("X2:%ld \r\n",X2); B5 = X1+X2; //printf("B5:%ld \r\n",B5); T = (B5+8)>>4; //printf("T:%ld \r\n",T); True_Temp = T/10.0; printf("Temperature:%.1f \r\n",True_Temp); B6 = B5-4000; //printf("B6:%ld \r\n",B6); X1 = (B2*B6*B6)>>23; //printf("X1:%ld \r\n",X1); X2 = (AC2*B6)>>11; //printf("X2:%ld \r\n",X2); X3 = X1+X2; //printf("X3:%ld \r\n",X3); B3 = (((long)AC1*4+X3)+2)/4; //printf("B3:%ld \r\n",B3); X1 = (AC3*B6)>>13; //printf("X1:%ld \r\n",X1); X2 = (B1*(B6*B6>>12))>>16; //printf("X2:%ld \r\n",X2); X3 = ((X1+X2)+2)>>2; //printf("X3:%ld \r\n",X3); B4 = AC4*(unsigned long)(X3+32768)>>15; //printf("B4:%lu \r\n",B4); B7 = ((unsigned long)UP-B3)*50000; //printf("B7:%lu \r\n",B7); if (B7 < 0x80000000) { P = (B7*2)/B4; } else P=(B7/B4)*2; //printf("P:%ld \r\n",P); X1 = (P/256.0)*(P/256.0); //printf("X1:%ld \r\n",X1); X1 = (X1*3038)>>16; //printf("X1:%ld \r\n",X1); X2 = (-7357*P)>>16; //printf("X2:%ld \r\n",X2); P = P+((X1+X2+3791)>>4); //printf("P:%ld \r\n",P); True_Press = P; printf("Press:%.1fPa \r\n",True_Press); True_Altitude = 44330*(1-pow((P/101325.0),(1.0/5.255))); printf("Altitude:%.3fm \r\n",True_Altitude); }[/mw_shl_code] [mw_shl_code=c,true]int main() {     long UT,UP;     delay_init();                      //延时函数初始化     NVIC_Configuration();             //设置NVIC中断分组2: 2位抢占优先级,2位响应优先级     uart1_init(38400);         //串口1初始化,和上位机通信          System_Init();                  //io,timer,adc,dac,lcd初始化    Read_CalibrationData();         //读取BMP180的校准系数     while(1)     {           BMP180_ID = BMP180_ReadOneByte(0xd0);    //读取ID地址         printf("BMP180_ID:0x%x \r\n",BMP180_ID);         UT = Get_BMP180UT();         UP = Get_BMP180UP();         Convert_UncompensatedToTrue(UT,UP);         sprintf(LCD_Buff,"ID:0x%x",BMP180_ID); Lcd12864_WriteString(0,0,LCD_Buff);         sprintf(LCD_Buff,"Temp:%.1f'C",True_Temp); Lcd12864_WriteString(1,0,LCD_Buff);         sprintf(LCD_Buff,"Press:%.1fPa",True_Press); Lcd12864_WriteString(2,0,LCD_Buff);         sprintf(LCD_Buff,"Altitude:%.1fm",True_Altitude); Lcd12864_WriteString(3,0,LCD_Buff);         delay_ms(1000);[/mw_shl_code] [mw_shl_code=c,true]}     [/mw_shl_code] [mw_shl_code=c,true][/mw_shl_code]





BST-BMP180-DS000-07.pdf

1.9 MB, 下载次数: 3700

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

88

主题

7377

帖子

5

精华

资深版主

Rank: 8Rank: 8

积分
14980
金钱
14980
注册时间
2013-11-13
在线时间
1823 小时
发表于 2015-4-14 22:25:26 | 显示全部楼层
开往春天的手扶拖拉机
回复 支持 反对

使用道具 举报

5

主题

91

帖子

0

精华

初级会员

Rank: 2

积分
183
金钱
183
注册时间
2014-10-28
在线时间
14 小时
发表于 2015-4-14 23:30:40 | 显示全部楼层
不错,我用ms5611 按手册精度更高
话说对高度有进行处理或者融合么?不然这个高度不是很准的吧
ps:貌似应该不是这个版区吧
成功必然有成功的原因,
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165508
金钱
165508
注册时间
2010-12-1
在线时间
2115 小时
发表于 2015-4-14 23:38:11 | 显示全部楼层
谢谢分享......
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

2

主题

16

帖子

0

精华

初级会员

Rank: 2

积分
61
金钱
61
注册时间
2015-4-18
在线时间
3 小时
发表于 2015-4-20 17:26:24 | 显示全部楼层
能不能给个bmp180 中文数据手册
回复 支持 反对

使用道具 举报

2

主题

11

帖子

0

精华

初级会员

Rank: 2

积分
60
金钱
60
注册时间
2015-3-18
在线时间
4 小时
 楼主| 发表于 2015-4-21 08:34:00 | 显示全部楼层
回复【3楼】simplelifeNick:
---------------------------------
这个高度是根据温度和气压值综合计算出来,实验了一下,精度不是很高。这个东西只是没事拿来玩玩,研究一下。
仁兄是湖北哪里的?我也来自湖北。
回复 支持 反对

使用道具 举报

2

主题

11

帖子

0

精华

初级会员

Rank: 2

积分
60
金钱
60
注册时间
2015-3-18
在线时间
4 小时
 楼主| 发表于 2015-4-21 08:36:37 | 显示全部楼层
回复【5楼】zhangjun62:
---------------------------------
sorry,这个我也是看英文手册弄的,没有找到中文手册。
其实也还好吧,只需要看一些关键的地方就可以了,没必要全文阅读。附件中的手册我已经把重点要看的圈出来了。希望对你有点帮助。
回复 支持 反对

使用道具 举报

头像被屏蔽

65

主题

277

帖子

0

精华

高级会员

Rank: 4

积分
674
金钱
674
注册时间
2013-8-11
在线时间
29 小时
发表于 2015-4-21 09:08:45 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
回复 支持 反对

使用道具 举报

5

主题

91

帖子

0

精华

初级会员

Rank: 2

积分
183
金钱
183
注册时间
2014-10-28
在线时间
14 小时
发表于 2015-4-21 09:29:28 | 显示全部楼层
回复【6楼】hbsyzscc:
---------------------------------
嗯  也是湖北的,我用ms5611来测高度,做定高控制
ms5611的手册说精度10cm  
气压计都会用温补的,气压变化到不大,不过算出来高度漂移蛮大的,关键有个缓变的波动 都快1m了
所以还是要用超声波 加速度计 gps什么的来融合了
成功必然有成功的原因,
回复 支持 反对

使用道具 举报

2

主题

16

帖子

0

精华

初级会员

Rank: 2

积分
61
金钱
61
注册时间
2015-4-18
在线时间
3 小时
发表于 2015-4-22 22:38:32 | 显示全部楼层
回复【7楼】hbsyzscc:
---------------------------------
嗯,谢谢
回复 支持 反对

使用道具 举报

2

主题

16

帖子

0

精华

初级会员

Rank: 2

积分
61
金钱
61
注册时间
2015-4-18
在线时间
3 小时
发表于 2015-5-20 20:13:21 | 显示全部楼层
能把源码贴出来吗
回复 支持 反对

使用道具 举报

0

主题

1

帖子

0

精华

新手入门

积分
21
金钱
21
注册时间
2015-6-2
在线时间
0 小时
发表于 2015-6-2 15:36:17 | 显示全部楼层
您好 您用的LCD12864是哪一款呢 您能给我看一下完整的程序吗?
谢谢
回复 支持 反对

使用道具 举报

3

主题

36

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1348
金钱
1348
注册时间
2013-1-11
在线时间
135 小时
发表于 2015-10-21 17:06:57 | 显示全部楼层
楼主的传感器最大能测多大的真空压力?
回复 支持 反对

使用道具 举报

2

主题

11

帖子

0

精华

初级会员

Rank: 2

积分
60
金钱
60
注册时间
2015-3-18
在线时间
4 小时
 楼主| 发表于 2015-10-25 09:33:09 | 显示全部楼层
我用的LCD12864是带ST7920控制器的那款。
底层驱动代码如附件,希望可以帮到你。

LCD12864底层驱动.zip

2.24 KB, 下载次数: 1211

回复 支持 反对

使用道具 举报

2

主题

11

帖子

0

精华

初级会员

Rank: 2

积分
60
金钱
60
注册时间
2015-3-18
在线时间
4 小时
 楼主| 发表于 2015-10-25 09:37:28 | 显示全部楼层
回复【13楼】LSM32:
---------------------------------
这个我没实际测定哦,我们的标准大气压为100Kpa,我用真空发生器对准BMP180上的那个小圆孔,气压明显下降,低于我们的标准大气压了。
我也是只验证了这种现象,具体线性度什么的由于手头条件不够也没有去验证。
回复 支持 反对

使用道具 举报

1

主题

57

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
317
金钱
317
注册时间
2015-11-4
在线时间
72 小时
发表于 2015-12-31 14:46:14 | 显示全部楼层
楼主,能贴出源代码吗
回复 支持 反对

使用道具 举报

34

主题

127

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1067
金钱
1067
注册时间
2012-1-7
在线时间
157 小时
发表于 2016-1-11 16:21:53 | 显示全部楼层
BMP085和BMP180一样吗?
回复 支持 反对

使用道具 举报

1

主题

15

帖子

0

精华

初级会员

Rank: 2

积分
88
金钱
88
注册时间
2011-7-22
在线时间
11 小时
发表于 2016-2-25 15:27:36 | 显示全部楼层
运行一会就飘了啊,不知道怎么回事
人外人天外天,学习无止境!
回复 支持 反对

使用道具 举报

0

主题

4

帖子

0

精华

新手入门

积分
11
金钱
11
注册时间
2016-10-21
在线时间
0 小时
发表于 2016-10-21 09:36:34 | 显示全部楼层
BMP085停产时间太久了,市面上应该没有原装货了。 BMP180 目前也是处于停产缺货,我手上有大批库存,价格合理,保证原厂原装货,有需要跟我联系。 13560762444 李小姐 QQ 2355640870
回复 支持 反对

使用道具 举报

2

主题

46

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
208
金钱
208
注册时间
2016-1-26
在线时间
40 小时
发表于 2016-10-21 11:18:12 | 显示全部楼层
simplelifeNick 发表于 2015-4-21 09:29
回复【6楼】hbsyzscc:
---------------------------------
嗯&nbsp;&nbsp;也是湖北的,我用ms5611来测高度 ...

友情提示MS5611不准确请检查电源纹波
回复 支持 反对

使用道具 举报

13

主题

101

帖子

0

精华

高级会员

Rank: 4

积分
509
金钱
509
注册时间
2016-1-4
在线时间
87 小时
发表于 2016-10-30 10:47:10 | 显示全部楼层
simplelifeNick 发表于 2015-4-21 09:29
回复【6楼】hbsyzscc:
---------------------------------
嗯&nbsp;&nbsp;也是湖北的,我用ms5611来测高度 ...

请问一下你是不是用气压计与一些模块融合测量一个相应的高度???
回复 支持 反对

使用道具 举报

6

主题

48

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
354
金钱
354
注册时间
2016-4-12
在线时间
97 小时
发表于 2016-12-5 14:30:11 | 显示全部楼层
楼主  你们用的12864都是5v供电的么  32直接驱动可以么
回复 支持 反对

使用道具 举报

33

主题

310

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
495
金钱
495
注册时间
2016-12-31
在线时间
63 小时
发表于 2017-3-15 16:56:12 | 显示全部楼层
你好,可不可以给一下参考例程呀
回复 支持 反对

使用道具 举报

33

主题

310

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
495
金钱
495
注册时间
2016-12-31
在线时间
63 小时
发表于 2017-3-15 16:57:06 | 显示全部楼层
zhangjun62 发表于 2015-5-20 20:13
能把源码贴出来吗

同求源码
回复 支持 反对

使用道具 举报

33

主题

310

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
495
金钱
495
注册时间
2016-12-31
在线时间
63 小时
发表于 2017-3-15 17:03:39 | 显示全部楼层
楼主能不能分享一下源码呀
回复 支持 反对

使用道具 举报

3

主题

15

帖子

0

精华

初级会员

Rank: 2

积分
76
金钱
76
注册时间
2016-9-19
在线时间
8 小时
发表于 2017-6-15 13:35:03 | 显示全部楼层
这种标了重点的文档真是赶时间的好东西。
回复 支持 反对

使用道具 举报

0

主题

2

帖子

0

精华

新手上路

积分
46
金钱
46
注册时间
2015-8-5
在线时间
8 小时
发表于 2017-9-8 11:35:47 | 显示全部楼层
本帖最后由 小朋哥123 于 2017-9-12 11:04 编辑

我自己实践了一下你的程序,感觉有点问题,用你的程序读数总是忽高忽低的,程序里面求UT和UP的语句,用的是BMP180_ReadTwoByte,我换成了BMP180_ReadOneByte就可以了,读数就正常了。。。感觉读两位数据那个函数有点问题,可能我的不对,请大家也可以试一试。。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-5-18 11:08

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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