STM32F1与STM32CubeIDE编程实例-BMP180气压温度传感器驱动

BMP180气压温度传感器驱动

1、BMP180介绍

BMP180 是用于测量气压和温度的最佳低成本传感解决方案。 传感器焊接在带有 3.3V 稳压器、I2C 电平转换器和 I2C 引脚上的上拉电阻的 PCB 上。 BMP180 取代了 BMP085。

BMP180有如下特点:

  • 压力感应范围:300-1100 hPa(海拔9000m至-500m)
  • 分辨率高达 0.03hPa / 0.25m
  • -40 至 +85°C 工作范围,±2°C 温度精度

在前面的文章中,对BMP180做了介绍,请参考:

2、BMP180配置

关于STM32CubeIDE工程创建、配置请参考前面文章:

本次BMP180的配置如下:

在这里插入图片描述

保存配置并生成代码。

3、BMP180驱动实现

本次驱动使用到DWT延时,请参考前面文章:

*

1)BMP180驱动基本定义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#ifndef \_\_BMP180\_H\_\_
#define \_\_BMP180\_H\_\_

#include "stm32f1xx\_hal.h"
#include <stdint.h>

// BMP180采样模式
typedef enum {
ultra_low_power, // 超低功耗模式
standart, // 标准模式
high_resolution, // 高分辨率模式
ultra_high_resolution // 超高分辨率模式
} _bmp180_oversampling_settings;


typedef struct {

I2C_HandleTypeDef \*hi2cx; // I2C句柄

// 传感器数据
float temperature; // 温度
int32\_t pressure; // 气压
float altitude; // 海拨
int32\_t sea_pressure; // 海平面气压

// Settings
enum \_bmp180\_oversampling\_settings oversampling_setting; // 采样模式
uint8\_t oss; // 采样模式值

// 校准数据
int16\_t AC1;
int16\_t AC2;
int16\_t AC3;
uint16\_t AC4;
uint16\_t AC5;
uint16\_t AC6;
int16\_t B1;
int16\_t B2;
int32\_t B3;
uint32\_t B4;
int32\_t B5;
int32\_t B6;
uint32\_t B7;
int16\_t MB;
int16\_t MC;
int16\_t MD;
} bmp180\_t;
//初始化
uint8\_t bmp180\_init(I2C_HandleTypeDef \*hi2cx, bmp180\_t \*bmp180);
// 读取所有数据
void bmp180\_get\_all(bmp180\_t \*bmp180);
// 读取温度值
void bmp180\_get\_temperature(bmp180\_t \*bmp180);
// 读取气压值
void bmp180\_get\_pressure(bmp180\_t \*bmp180);
// 根据气压计算高度
void bmp180\_get\_altitude(bmp180\_t \*bmp180);
// 设置海平面气压
void bmp180\_set\_sea\_pressure(bmp180\_t \*bmp180, int32\_t sea_pressure);
#endif //\_\_BMP180\_H\_\_

2)驱动辅助函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include "bmp180\_internals.h"
#include <math.h>

static void bmp180\_read(bmp180\_t \*bmp180, uint8\_t reg, uint8\_t \*buffer, uint8\_t size)
{
HAL\_I2C\_Mem\_Read(bmp180->hi2cx, BMP180_ADDRESS, reg, 1, buffer, size, HAL_MAX_DELAY);
}

static void bmp180\_write(bmp180\_t \*bmp180, uint8\_t reg, uint8\_t \*buffer, uint8\_t size)
{
HAL\_I2C\_Mem\_Write(bmp180->hi2cx, BMP180_ADDRESS, reg, 1, buffer, size, HAL_MAX_DELAY);
}

static int bmp180\_is\_ready(bmp180\_t \*bmp180)
{
return HAL\_I2C\_IsDeviceReady(bmp180->hi2cx, BMP180_ADDRESS, 1, HAL_MAX_DELAY);
}

3)驱动定义实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
uint8\_t bmp180\_init(I2C_HandleTypeDef \*hi2cx, bmp180\_t \*bmp180)
{
bmp180->hi2cx = hi2cx;

// 检查设备是否准备好
if (bmp180\_is\_ready(bmp180))
return 1;

uint8\_t buffer[22];

// 重置传感器
buffer[0] = 0xB6;
bmp180\_write(bmp180, SOFT, &buffer[0], 1);
HAL\_Delay(10);

// 读取传感设备ID,判断是否为BMP180
bmp180\_read(bmp180, ID, &buffer[0], 1);
if (buffer[0] != 0x55) {
return 2;
}

// 校准传感器参数
bmp180\_read(bmp180, CALIB, buffer, 22);

// 判断是否校准成功
for (uint8\_t i = 0; i < 22; i += 2) {
uint16\_t combined_calibration_data = convert8bitto16bit(buffer[i], buffer[i + 1]);
if (combined_calibration_data == 0x00 || combined_calibration_data == 0XFF) {
return 2;
}
}

// 设置硬件采样
switch (bmp180->oversampling_setting) {
case ultra_low_power:
bmp180->oss = 0;
break;
case standart:
bmp180->oss = 1;
break;
case high_resolution:
bmp180->oss = 2;
break;
case ultra_high_resolution:
bmp180->oss = 3;
break;
default:
bmp180->oversampling_setting = standart;
bmp180->oss = 1;
break;
}

// 储存校准参数
bmp180->AC1 = convert8bitto16bit(buffer[0], buffer[1]);
bmp180->AC2 = convert8bitto16bit(buffer[2], buffer[3]);
bmp180->AC3 = convert8bitto16bit(buffer[4], buffer[5]);
bmp180->AC4 = convert8bitto16bit(buffer[6], buffer[7]);
bmp180->AC5 = convert8bitto16bit(buffer[8], buffer[9]);
bmp180->AC6 = convert8bitto16bit(buffer[10], buffer[11]);
bmp180->B1 = convert8bitto16bit(buffer[12], buffer[13]);
bmp180->B2 = convert8bitto16bit(buffer[14], buffer[15]);
bmp180->B3 = 0;
bmp180->B4 = 0;
bmp180->B5 = 0;
bmp180->B6 = 0;
bmp180->B7 = 0;
bmp180->MB = convert8bitto16bit(buffer[16], buffer[17]);
bmp180->MC = convert8bitto16bit(buffer[18], buffer[19]);
bmp180->MD = convert8bitto16bit(buffer[20], buffer[21]);
bmp180->sea_pressure = 101325;

return 0;
}


void bmp180\_get\_all(bmp180\_t \*bmp180)
{
bmp180\_get\_temperature(bmp180);
bmp180\_get\_pressure(bmp180);
bmp180\_get\_altitude(bmp180);
}

// 读取温度值原始数据
static int16\_t \_bmp180\_read\_ut(bmp180\_t \*bmp180)
{
uint8\_t write_data = 0x2E, ut_data[2];

bmp180\_write(bmp180, CTRL_MEAS, &write_data, 1);
HAL\_Delay(5);
bmp180\_read(bmp180, OUT_MSB, ut_data, 2);

return (convert8bitto16bit(ut_data[0], ut_data[1]));
}

// 读取气压值原始数据
static int32\_t \_bmp180\_read\_up(bmp180\_t \*bmp180)
{
uint8\_t write_data = 0x34 + (bmp180->oss << 6), up_data[3];
bmp180\_write(bmp180, CTRL_MEAS, &write_data, 1);
uint8\_t wait = 0;
switch (bmp180->oversampling_setting) {
case ultra_low_power:
wait = 5;
break;
case standart:
wait = 8;
break;
case high_resolution:
wait = 14;
break;
case ultra_high_resolution:
wait = 26;
break;
default:
wait = 5;
break;
}
HAL\_Delay(wait);
bmp180\_read(bmp180, OUT_MSB, up_data, 3);

return ((up_data[0] << 16) + (up_data[1] << 8) + up_data[2]) >> (8 - bmp180->oss);
}


void bmp180\_get\_temperature(bmp180\_t \*bmp180)
{
int16\_t ut = \_bmp180\_read\_ut(bmp180);
int32\_t X1, X2;

X1 = (ut - bmp180->AC6) \* bmp180->AC5 / powerof2(15);
X2 = bmp180->MC \* powerof2(11) / (X1 + bmp180->MD);
bmp180->B5 = X1 + X2;
bmp180->temperature = ((bmp180->B5 + 8) / powerof2(4)) / 10.0;
}


void bmp180\_get\_pressure(bmp180\_t \*bmp180)
{
int32\_t X1, X2, X3, up = \_bmp180\_read\_up(bmp180), p;
bmp180->B6 = bmp180->B5 - 4000;
X1 = (bmp180->B2 \* (bmp180->B6 \* bmp180->B6 / powerof2(12))) / powerof2(11);
X2 = bmp180->AC2 \* bmp180->B6 / powerof2(11);
X3 = X1 + X2;
bmp180->B3 = (((bmp180->AC1 \* 4 + X3) << bmp180->oss) + 2) / 4;
X1 = bmp180->AC3 \* bmp180->B6 / powerof2(13);
X2 = (bmp180->B1 \* (bmp180->B6 \* bmp180->B6 / powerof2(12))) / powerof2(16);
X3 = ((X1 + X2) + 2) / powerof2(2);
bmp180->B4 = bmp180->AC4 \* (uint32\_t)(X3 + 32768) / powerof2(15);
bmp180->B7 = ((uint32\_t)up - bmp180->B3) \* (50000 >> bmp180->oss);
if (bmp180->B7 < 0x80000000) {
p = (bmp180->B7 \* 2) / bmp180->B4;
}
else {
p = (bmp180->B7 / bmp180->B4) \* 2;
}
X1 = (p / powerof2(8)) \* (p / powerof2(8));
X1 = (X1 \* 3038) / powerof2(16);
X2 = (-7357 \* p) / powerof2(16);
p = p + (X1 + X2 + 3791) / powerof2(4);
bmp180->pressure = p;
}

void bmp180\_get\_altitude(bmp180\_t \*bmp180)
{
bmp180->altitude = 44330 \* (1 - pow(((float)bmp180->pressure / (float)bmp180->sea_pressure), 1 / 5.255));
}

void bmp180\_set\_sea\_pressure(bmp180\_t \*bmp180, int32\_t sea_pressure)
{
bmp180->sea_pressure = sea_pressure;
}

4、驱动测试

main.c文件中添加如下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
/\* Private includes ----------------------------------------------------------\*/
/\* USER CODE BEGIN Includes \*/
#include <stdio.h>
#include "dwt/dwt\_delay.h"
#include "bmp180/bmp180.h"
/\* USER CODE END Includes \*/

/\* Private variables ---------------------------------------------------------\*/

/\* USER CODE BEGIN PV \*/
bmp180\_t bmp180 = { .oversampling_setting = standart };
/\* USER CODE END PV \*/


int main(void) {
/\* USER CODE BEGIN 1 \*/

/\* USER CODE END 1 \*/

/\* MCU Configuration--------------------------------------------------------\*/

/\* Reset of all peripherals, Initializes the Flash interface and the Systick. \*/
HAL\_Init();

/\* USER CODE BEGIN Init \*/

/\* USER CODE END Init \*/

/\* Configure the system clock \*/
SystemClock\_Config();

/\* USER CODE BEGIN SysInit \*/

/\* USER CODE END SysInit \*/

/\* Initialize all configured peripherals \*/
MX\_GPIO\_Init();
MX\_USART1\_UART\_Init();
MX\_I2C1\_Init();
/\* USER CODE BEGIN 2 \*/
// 初始化DWT计算功能
dwt\_init();
printf("bmp180 demo\r\n");

if(bmp180\_init(&hi2c1, &bmp180) != 0){
printf("bmp180 init failed\r\n");
while(1);
}

// Get all the values

/\* USER CODE END 2 \*/

/\* Infinite loop \*/
/\* USER CODE BEGIN WHILE \*/
while (1) {
/\* USER CODE END WHILE \*/

/\* USER CODE BEGIN 3 \*/

bmp180\_get\_all(&bmp180);
float temperature = bmp180.temperature;
int32\_t pressure = bmp180.pressure;
float altitude = bmp180.altitude;
printf("temp = %.2f \*C,pressure = %d Pa,altitude = %f\r\n",temperature,pressure,altitude);
HAL\_Delay(100);
}
/\* USER CODE END 3 \*/
}

文章来源: https://iotsmart.blog.csdn.net/article/details/125842515