一、模块来源
采购链接:
GY-63 MS5611-01BA03 气压传感器 高度传感器模块
资料下载链接:
https://pan.baidu.com/s/1QOrpiggCE6mBpqabJXUufg
提取码:c2pp
二、规格参数
工作电压:1.8~3.6V
工作电流:0.25~23uA
温度精度:0.8℃
温度范围:-40~85℃
气压范围:10~1200 mbar
气压精度:1.5 mbar
输出方式: IIC
管脚数量:3 Pin
以上信息见厂家资料文件
三、移植过程
我们的目标是将例程移植至开发板上【能够测量环境气压】。首先要获取资料,查看数据手册应如何实现读取数据,再移植至我们的工程。
1、查看资料
当PS引脚接高电平时,传感器属于IIC模式;当PS引脚接低电平时,传感器属于SPI模式;在原理图上,PS引脚通过上拉电阻接了高电平,故默认为IIC模式。
器件地址 = 0XEE
CSB的反补码 即CSB引脚接高电平时, 地址为 1110 110+(读写位)
CSB的反补码 即CSB引脚接低电平时, 地址为 1110 111+(读写位)
读取气压与温度的流程:开始-> 读取出厂校准值C1至C6 -> 读取气压D1和温度D2的原始数据 -> 将D2和C1C6带入公式求出dT和TEMP,其中TEMP为温度数据-> 将dT和C1至C6带入公式求出OFF、SENS和P,其中P为气压数据。
2、引脚选择
3、移植至工程
接下来我们配置 SYSCONFIG
- 双击 empty.syscfg 文件,打开它。
- 在 empty.syscfg 文件界面点击 Tools,然后点击 SYSCONFIG 工具。
- 点击 ADD 添加配置
- 添加配置【根据下方图片进行添加】【添加2个GPIO配置】
点击添加GPIO配置:
- 点击保存
WARNING
出现只要出现下面的框就一定要选择:Yes to All
- 然后点击编译(可能会报错,我们不用管!)
- 然后我们所有设定的引脚和功能就会在 ti_msp_dl_config.h 中定义。因为这个文件我们包含进了 board.h 所以我们只需要引用 board.h 即可。【这里的 board.h 就充当了芯片头文件的作用】
移植步骤中的导入.c和.h文件与传感器章节的【DHT11温湿度传感器】相同,只是将.c和.h文件更改为bsp_ms5611.c与bsp_ms5611.h。这里不再过多讲述,移植完成后面修改相关代码。
在文件bsp_ms5611.c中,编写如下代码。
/*
* 立创开发板软硬件资料与相关扩展板软硬件资料官网全部开源
* 开发板官网:www.lckfb.com
* 技术支持常驻论坛,任何技术问题欢迎随时交流学习
* 立创论坛:https://oshwhub.com/forum
* 关注bilibili账号:【立创开发板】,掌握我们的最新动态!
* 不靠卖板赚钱,以培养中国工程师为己任
* Change Logs:
* Date Author Notes
* 2024-05-28 LCKFB-LP first version
*/
#include "bsp_ms5611.h"
#include "stdio.h"
//出厂校准值
//Cal_C1_6[0] = 厂家信息
//Cal_C1_6[1] ~ Cal_C1_6[6] = 校准值
//Cal_C1_6[7] = 校准值的CRC校验
uint16_t Cal_C1_6[8];
/******************************************************************
* 函 数 名 称:IIC_Start
* 函 数 说 明:IIC起始时序
* 函 数 形 参:无
* 函 数 返 回:无
* 作 者:LC
* 备 注:无
******************************************************************/
void IIC_Start(void)
{
SDA_OUT();
SDA(1);
delay_us(5);
SCL(1);
delay_us(5);
SDA(0);
delay_us(5);
SCL(0);
delay_us(5);
}
/******************************************************************
* 函 数 名 称:IIC_Stop
* 函 数 说 明:IIC停止信号
* 函 数 形 参:无
* 函 数 返 回:无
* 作 者:LC
* 备 注:无
******************************************************************/
void IIC_Stop(void)
{
SDA_OUT();
SCL(0);
SDA(0);
SCL(1);
delay_us(5);
SDA(1);
delay_us(5);
}
/******************************************************************
* 函 数 名 称:IIC_Send_Ack
* 函 数 说 明:主机发送应答或者非应答信号
* 函 数 形 参:0发送应答 1发送非应答
* 函 数 返 回:无
* 作 者:LC
* 备 注:无
******************************************************************/
void IIC_Send_Ack(unsigned char ack)
{
SDA_OUT();
SCL(0);
SDA(0);
delay_us(5);
if(!ack) SDA(0);
else SDA(1);
SCL(1);
delay_us(5);
SCL(0);
SDA(1);
}
/******************************************************************
* 函 数 名 称:I2C_WaitAck
* 函 数 说 明:等待从机应答
* 函 数 形 参:无
* 函 数 返 回:0有应答 1超时无应答
* 作 者:LC
* 备 注:无
******************************************************************/
unsigned char I2C_WaitAck(void)
{
char ack = 0;
unsigned char ack_flag = 10;
SCL(0);
SDA(1);
SDA_IN();
delay_us(5);
SCL(1);
delay_us(5);
while( (SDA_GET()==1) && ( ack_flag ) )
{
ack_flag--;
delay_us(5);
}
if( ack_flag <= 0 )
{
IIC_Stop();
return 1;
}
else
{
SCL(0);
SDA_OUT();
}
return ack;
}
/******************************************************************
* 函 数 名 称:Send_Byte
* 函 数 说 明:写入一个字节
* 函 数 形 参:dat要写人的数据
* 函 数 返 回:无
* 作 者:LC
* 备 注:无
******************************************************************/
void Send_Byte(uint8_t dat)
{
int i = 0;
SDA_OUT();
SCL(0);//拉低时钟开始数据传输
for( i = 0; i < 8; i++ )
{
SDA( (dat & 0x80) >> 7 );
delay_us(1);
SCL(1);
delay_us(5);
SCL(0);
delay_us(5);
dat<<=1;
}
}
/******************************************************************
* 函 数 名 称:Read_Byte
* 函 数 说 明:IIC读时序
* 函 数 形 参:无
* 函 数 返 回:读到的数据
* 作 者:LC
* 备 注:无
******************************************************************/
unsigned char Read_Byte(void)
{
unsigned char i,receive=0;
SDA_IN();//SDA设置为输入
for(i=0;i<8;i++ )
{
SCL(0);
delay_us(5);
SCL(1);
delay_us(5);
receive<<=1;
if( SDA_GET() )
{
receive|=1;
}
delay_us(5);
}
SCL(0);
return receive;
}
/**********************************************************
* 函 数 名 称:MS5611_Reset
* 函 数 功 能:MS5611的复位
* 传 入 参 数:无
* 函 数 返 回:0=复位成功 1=器件地址错误 2=命令无应答
* 作 者:LC
* 备 注:无
**********************************************************/
char MS5611_Reset(void)
{
IIC_Start();//起始信号
Send_Byte(0xee|0); //器件地址+写
if( I2C_WaitAck() == 1 )return 1;
Send_Byte(0x1e); //复位命令
if( I2C_WaitAck() == 1 )return 2;
IIC_Stop();
return 0;
}
//C1-C6 16位 6个地址 每一个地址16位
/**********************************************************
* 函 数 名 称:MS5611_Read_PROM
* 函 数 功 能:读取出厂校准值
* 传 入 参 数:无
* 函 数 返 回:无
* 作 者:LC
* 备 注:无
**********************************************************/
void MS5611_Read_PROM(void)
{
uint8_t data_H=0,data_L=0;
uint8_t i = 0;
for( i = 0; i < 8; i++ )
{
IIC_Start();//起始信号
Send_Byte(0xee|0); //器件地址+写
I2C_WaitAck();
Send_Byte( 0xA0 + i * 2 ); //寄存器地址
I2C_WaitAck();
IIC_Stop();
delay_us(200);
IIC_Start();//起始信号
Send_Byte(0xee|1); //器件地址+读
I2C_WaitAck();
data_H = Read_Byte();//读取的数据高8位
IIC_Send_Ack(0);
data_L = Read_Byte();//读取的数据低8位
IIC_Send_Ack(1);
IIC_Stop();
//保存出厂校准数据
Cal_C1_6[i] = (data_H<<8) | data_L;
}
}
/**********************************************************
* 函 数 名 称:MS5611_Read_D1_D2
* 函 数 功 能:读取气压D1和温度D2的初始数据
* 传 入 参 数:regaddr=0x48或0x58
* 函 数 返 回:返回读取后整合为24位的数据
* 作 者:LC
* 备 注:
* regaddr= 0x48 读取D1数据(OSR=4096)
* regaddr= 0x58 读取D2数据(OSR=4096)
**********************************************************/
uint32_t MS5611_Read_D1_D2(uint8_t regaddr)
{
uint32_t dat = 0;
uint8_t buff[3] ={0};
IIC_Start();//起始信号
Send_Byte(0xee|0); //器件地址+写
if( I2C_WaitAck() == 1 )printf("D1 NACK -1\r\n");
Send_Byte(regaddr); //OSR = 4096
if( I2C_WaitAck() == 1 )printf("D1 NACK -2\r\n");
IIC_Stop();
delay_ms(10);
IIC_Start();//起始信号
Send_Byte(0xee|0); //器件地址+写
if( I2C_WaitAck() == 1 )printf("D1 NACK -3\r\n");
Send_Byte(0X00);
if( I2C_WaitAck() == 1 )printf("D1 NACK -4\r\n");
IIC_Stop();
delay_ms(10);
IIC_Start();//起始信号
Send_Byte(0xee|1); //器件地址+读
if( I2C_WaitAck() == 1 )printf("D1 NACK -5\r\n");
buff[0] = Read_Byte();
IIC_Send_Ack(0);
buff[1] = Read_Byte();
IIC_Send_Ack(0);
buff[2] = Read_Byte();
IIC_Send_Ack(1);
IIC_Stop();
dat = (((buff[0]<<16) | ( buff[1]<<8)) | buff[2]);
return dat;
}
uint32_t D1 = 0, D2 = 0, dT = 0;
/**********************************************************
* 函 数 名 称:Get_TEMP
* 函 数 功 能:换算温度
* 传 入 参 数:无
* 函 数 返 回:没有小数点后的温度数据
* 作 者:LC
* 备 注:无
**********************************************************/
float Get_TEMP(void)
{
float dat = 0;
long long TEMP = 0;
D1 = MS5611_Read_D1_D2(0x48);
delay_ms(10);
D2 = MS5611_Read_D1_D2(0x58);
delay_ms(10);
dT = D2 - (Cal_C1_6[5] * 256.0);
TEMP = 2000 + (((float)dT * Cal_C1_6[6]) / 8388608.0);
// printf("temp = %lld%lld.%lld%lld\r\n",TEMP/1000, TEMP/100%10,TEMP/10%10,TEMP%10);
//没有小数的温度
dat = (((TEMP/1000)*10) + (TEMP/100%10)) ;
return dat;
}
/**********************************************************
* 函 数 名 称:Get_pressure
* 函 数 功 能:换算气压数据
* 传 入 参 数:无
* 函 数 返 回:返回气压,单位(HPa)
* 作 者:LC
* 备 注:无
**********************************************************/
float Get_pressure(void)
{
long long SENS = 0;
long long P =0;
long long OFF = 0;
Get_TEMP();
OFF = Cal_C1_6[2] * 65536.0 + Cal_C1_6[4] * dT / 128;
SENS = (Cal_C1_6[1] * 32768.0) + ((Cal_C1_6[3] * dT ) / 256.0);
P = (D1 * SENS / 2097152.0 - OFF) / 32768.0;
return (P/100.0);
}
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
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
在文件bsp_ms5611.h中,编写如下代码。
/*
* 立创开发板软硬件资料与相关扩展板软硬件资料官网全部开源
* 开发板官网:www.lckfb.com
* 技术支持常驻论坛,任何技术问题欢迎随时交流学习
* 立创论坛:https://oshwhub.com/forum
* 关注bilibili账号:【立创开发板】,掌握我们的最新动态!
* 不靠卖板赚钱,以培养中国工程师为己任
* Change Logs:
* Date Author Notes
* 2024-05-28 LCKFB-LP first version
*/
#ifndef _BSP_MS5611_H_
#define _BSP_MS5611_H_
#include "board.h"
//设置SDA输出模式
#define SDA_OUT() {\
DL_GPIO_initDigitalOutput(GPIO_SDA_IOMUX);\
DL_GPIO_setPins(GPIO_PORT, GPIO_SDA_PIN);\
DL_GPIO_enableOutput(GPIO_PORT, GPIO_SDA_PIN);\
}
//设置SDA输入模式
#define SDA_IN() { DL_GPIO_initDigitalInput(GPIO_SDA_IOMUX); }
//获取SDA引脚的电平变化
#define SDA_GET() ( ( ( DL_GPIO_readPins(GPIO_PORT,GPIO_SDA_PIN) & GPIO_SDA_PIN ) > 0 ) ? 1 : 0 )
//SDA与SCL输出
#define SDA(x) ( (x) ? (DL_GPIO_setPins(GPIO_PORT,GPIO_SDA_PIN)) : (DL_GPIO_clearPins(GPIO_PORT,GPIO_SDA_PIN)) )
#define SCL(x) ( (x) ? (DL_GPIO_setPins(GPIO_PORT,GPIO_SCL_PIN)) : (DL_GPIO_clearPins(GPIO_PORT,GPIO_SCL_PIN)) )
char MS5611_Reset(void);
void MS5611_Read_PROM(void);
float Get_TEMP(void);
float Get_pressure(void);
#endif
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
四、移植验证
在empty.c中输入代码如下:
#include "board.h"
#include <stdio.h>
#include "bsp_ms5611.h"
int main(void)
{
//开发板初始化
board_init();
MS5611_Reset();//器件复位
delay_ms(300);//等待初始化完成;
MS5611_Read_PROM();//读取出厂校准值
printf("start\r\n");
while(1)
{
uint32_t TEMP = Get_TEMP() * 100;
uint32_t PRES = Get_pressure() * 100;
//输出温度
printf("温度 = %d.%02d℃\r\n",TEMP/100,TEMP%100 );
//输出气压
printf("气压 = %d.%02dHPa\r\n",PRES/100,PRES%100 );
printf("\n");
delay_ms(1000);
}
}
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
上电效果:每隔一秒左右测量一次温度和气压。
代码下载
链接在开发板介绍
章节的离线资料下载!!