基于单片机设计的气压与海拔高度检测计(采用MPL3115A2芯片实现)

news2024/11/16 7:55:40

一、前言

随着科技的不断发展,在许多领域中,对气压与海拔高度的测量变得越来越重要。例如,对于航空和航天工业、气象预报、气候研究等领域,都需要高精度、可靠的气压与海拔高度检测装置。针对这一需求,基于单片机设计的气压与海拔高度检测计应运而生。

本项目采用了MPL3115A2芯片作为气压与温度传感器,能够实现高精度、高分辨率的气压与海拔高度测量。主控芯片采用STC89C52,具有强大的控制能力和丰富的资源,能够更好地满足系统设计的要求。此外,通过LCD1602显示检测到的信息,可以使用户更加方便地查看和使用系统。

image-20230913135126593

image-20230913135101946

image-20230913135017633

二、项目设计思路

在设计此项目时,需要考虑硬件设计和软件设计两个方面。

2.1 硬件设计思路

(1)主控芯片:选择STC89C52作为主控芯片,它具有51系列单片机的特点,拥有强大的处理能力和丰富的资源,可以满足系统的需求。

(2)传感器选择:采用MPL3115A2芯片作为气压与温度传感器,它具有高精度、高分辨率的特点,并且支持I2C通信协议,方便与主控芯片进行数据交互。

(3)显示模块:选择LCD1602作为显示模块,它可以显示检测到的信息,如气压和海拔高度,让用户直观地了解测量结果。

(4)连接方式:根据MPL3115A2芯片规格书和STC89C52芯片手册,确定它们之间的连接方式,通常使用I2C总线进行通信。

2.2 软件设计思路

(1)初始化:在程序开始时,需要对主控芯片和传感器进行初始化设置,包括引脚配置、寄存器初始化等。

(2)数据采集:通过I2C通信协议,主控芯片向传感器发送指令,读取气压和温度数据。然后对数据进行处理,得到实际的气压值和海拔高度值。

(3)数据显示:将测量到的气压和海拔高度值通过LCD1602显示出来,可以使用LCD1602的相关库函数来实现。

(4)循环检测:为了持续监测气压和海拔高度的变化,可以使用一个循环,在每次循环中执行数据采集和显示操作。

三、项目代码实现

#include <reg52.h>
#include <intrins.h>

#define MPL3115A2_ADDRESS (0xC0>>1)  // MPL3115A2 I2C地址
#define MPL3115A2_CTRL_REG1 (0x26)   // 控制寄存器1地址
#define MPL3115A2_PT_DATA_CFG (0x13) // 气压和温度数据寄存器地址
#define MPL3115A2_STATUS (0x00)      // 状态寄存器地址
#define MPL3115A2_OUT_P_MSB (0x01)   // 气压输出数据MSB字节地址
#define MPL3115A2_OUT_P_CSB (0x02)   // 气压输出数据CSB字节地址
#define MPL3115A2_OUT_P_LSB (0x03)   // 气压输出数据LSB字节地址
#define MPL3115A2_OUT_T_MSB (0x04)   // 温度输出数据MSB字节地址
#define MPL3115A2_OUT_T_LSB (0x05)   //温度输出数据LSB字节地址

#define LCD1602_DATA_PORT P1         // LCD1602数据口
sbit LCD1602_RS = P3^1;              //LCD1602命令/数据选择引脚
sbit LCD1602_RW = P3^2;              //LCD1602读写选择引脚
sbit LCD1602_E = P3^3;               //LCD1602使能引脚

//延时函数
void Delay1ms(void)          
{
    unsigned char i, j;
    _nop_();
    i = 12;
    j = 169;
    do
    {
        while (--j);
    } while (--i);
}

//写一个字节到LCD1602
void LCD1602_WriteByte(unsigned char byte, bit isData)
{
    LCD1602_E = 0;
    LCD1602_RS = isData;
    LCD1602_RW = 0;
    LCD1602_DATA_PORT = byte;
    Delay1ms();
    LCD1602_E = 1;
    Delay1ms();
    LCD1602_E = 0;
}

//初始化LCD1602
void LCD1602_Init(void)
{
    LCD1602_WriteByte(0x38, 0); // 设置数据总线为8位,显示模式为2行,5*7点阵字符
    LCD1602_WriteByte(0x0c, 0); // 开启LCD显示,关闭光标显示和闪烁
    LCD1602_WriteByte(0x06, 0); // 输入方式设置(光标移动方向向右,字符不移动)
    LCD1602_WriteByte(0x01, 0); // 清屏
}

//LCD1602显示字符串
void LCD1602_ShowString(unsigned char x, unsigned char y, unsigned char *str)
{
    unsigned char i = 0;
    if (y == 1) x |= 0x40;   //设置显示行位置为第二行
    x |= 0x80;               //设置显示行位置
    LCD1602_WriteByte(x, 0);
    while (str[i] != '\0')
    {
        LCD1602_WriteByte(str[i], 1);
        i++;
    }
}

//I2C通信函数
unsigned char I2C_SendByte(unsigned char dat)
{
    unsigned char bit_ctr,ack;
    for(bit_ctr=0;bit_ctr<8;bit_ctr++) //循环8次,发送8位数据
    {
        SDA = (bit_ctr & 0x80); // 判断当前位是0还是1,设置SDA引脚
        _nop_();
        SCL = 1;                // 拉高SCL引脚,发送数据
        _nop_();
        SCL = 0;                // 拉低SCL引脚
    }
    SDA = 1;                    // 在最后一次时,SDA引脚设置为1,等待ACK确认
    _nop_();                   
    SCL = 1;                    // 拉高SCL引脚
    ack = SDA;                  // 读取ACK确认信号
    _nop_();
    SCL = 0;                    // 拉低SCL引脚,结束发送
    return ack;
}

//I2C通信函数
unsigned char I2C_ReadByte(void)
{
    unsigned char bit_ctr, dat = 0;
    for(bit_ctr=0;bit_ctr<8;bit_ctr++) //循环8次,接收8位数据
    {
        SDA = 1;              // 让SDA引脚保持为1,准备接收数据
        _nop_();
        SCL = 1;              // 拉高SCL引脚,让数据线上的数据进入芯片
        _nop_();
        dat |= SDA;           // 将当前接收到的数据bit复制到dat的对应bit上
        if(bit_ctr != 7) dat <<= 1; // 如果不是最后一位,就将dat左移一位,以接收下一个bit
        SCL = 0;              // 拉低SCL引脚,等待下一次数据输入
    }
    return dat;
}

//写字节到MPL3115A2芯片
void MPL3115A2_WriteByte(unsigned char regAddr, unsigned char data)
{
    I2C_Start();                         // 启动I2C总线
    I2C_SendByte(MPL3115A2_ADDRESS);     // 发送I2C设备地址+写标志
    I2C_SendByte(regAddr);               // 发送要写入的寄存器地址
    I2C_SendByte(data);                  // 发送要写入的数
    I2C_Stop();                          // 结束I2C通信
}

//读取MPL3115A2芯片的一个字节
unsigned char MPL3115A2_ReadByte(unsigned char regAddr)
{
    unsigned char data;
    I2C_Start();                         // 启动I2C总线
    I2C_SendByte(MPL3115A2_ADDRESS);     // 发送I2C设备地址+写标志
    I2C_SendByte(regAddr);               // 发送要读取的寄存器地址
    I2C_Start();                         // 启动I2C总线
    I2C_SendByte(MPL3115A2_ADDRESS+1);   // 发送I2C设备地址+读标志
    data = I2C_ReadByte();               // 读取一个字节
    I2C_Stop();                          // 结束I2C通信
    return data;
}

//启动一次MPL3115A2芯片的气压测量
void MPL3115A2_PressureMeasureStart(void)
{
    MPL3115A2_WriteByte(MPL3115A2_CTRL_REG1, 0x38); // 向控制寄存器1写入设置值,启动气压测量
}

//等待MPL3115A2芯片气压测量结束
void MPL3115A2_WaitForPressureMeasureFinish(void)
{
    unsigned char status;
    do
    {
        status = MPL3115A2_ReadByte(MPL3115A2_STATUS); // 读取状态寄存器
    } while ((status & 0x08) == 0);                    // 检查气压测量结束标志位
}

//读取MPL3115A2芯片测量的气压值,单位Pa
long MPL3115A2_ReadPressure(void)
{
    unsigned char msb, csb, lsb;
    long press;
    msb = MPL3115A2_ReadByte(MPL3115A2_OUT_P_MSB); // 读取气压数据的MSB字节
    csb = MPL3115A2_ReadByte(MPL3115A2_OUT_P_CSB); // 读取气压数据的CSB字节
    lsb = MPL3115A2_ReadByte(MPL3115A2_OUT_P_LSB); // 读取气压数据的LSB字节
    press = (msb << 16) | (csb << 8) | lsb;        // 将读取到的三个字节组合成一个长整型数值
    press >>= 4;                                   // 由于最后四位是不需要的,因此右移四位
    return press;
}

//读取MPL3115A2芯片测量的温度值,单位0.0625°C
int MPL3115A2_ReadTemperature(void)
{
    unsigned char msb, lsb;
    int temp;
    msb = MPL3115A2_ReadByte(MPL3115A2_OUT_T_MSB); // 读取温度数据的MSB字节
    lsb = MPL3115A2_ReadByte(MPL3115A2_OUT_T_LSB); // 读取温度数据的LSB字节
    temp = (msb << 8) | lsb;                      // 将读取到的两个字节组合成一个整型数值
    return temp >> 4;                             // 由于最后四位是不需要的,因此右移四位
}

//将气压值转换成海拔高度值(单位:米)
float ConvertPressureToAltitude(long press)
{
    float altitude;
    altitude = 44330 * (1 - pow((press / 101325.0), 0.1903)); // 根据公式计算海拔高度
    return altitude;
}

void main()
{
    unsigned char str[16];
    long press;
    float altitude;
    int temperature;

    I2C_Init();         // 初始化I2C总线
    LCD1602_Init();     // 初始化LCD1602

    MPL3115A2_PressureMeasureStart(); // 启动一次气压测量
    MPL3115A2_WaitForPressureMeasureFinish(); // 等待气压测量结束
    press = MPL3115A2_ReadPressure(); // 读取气压值
    altitude = ConvertPressureToAltitude(press); // 将气压值转换成海拔高度值
    temperature = MPL3115A2_ReadTemperature(); // 读取温度值

    sprintf(str, "Press: %dPa", press); // 将气压值转换成字符串
    LCD1602_ShowString(0, 0, str);      // 在第一行LCD1602上显示气压值
    sprintf(str, "Altitude: %dm", (int)altitude); // 将海拔高度值转换成字符串
    LCD1602_ShowString(0, 1, str);      // 在第二行LCD1602上显示海拔高度值
    sprintf(str, "Temp: %dC", temperature); // 将温度值转换成字符串
    LCD1602_ShowString(11, 0, str);     // 在第一行LCD1602上显示温度值
    while (1);                         // 等待
}

四、MPL3115A2模块介绍

MPL3115A2 是一款集成式数字大气压力传感器模块,由NXP Semiconductors(前身为Freescale Semiconductor)生产。通过测量大气压力和温度,提供了高精度的大气压力和海拔测量功能。

下面是 MPL3115A2 模块的一些主要特点和功能:

(1)大气压力测量:MPL3115A2 可以测量大气压力,并提供绝对压力、相对压力和海拔高度等数据。它支持广泛的压力测量范围,通常为 20 kPa 至 110 kPa。这使得它适用于气象监测、高度测量、天气预报和气压趋势分析等应用。

(2)温度测量:MPL3115A2 还具有温度测量功能,可以提供环境温度数据。这对于需要考虑温度变化对压力测量的影响的应用非常重要。

(3)高精度测量:MPL3115A2 提供高精度的压力和温度测量。它使用16位的ADC(模数转换器)进行测量,并提供高分辨率的数据输出。这使得它能够提供准确的大气压力和温度数据。

(4)数字输出接口:MPL3115A2 通过I2C接口与主控制器通信。这种数字接口使得与微控制器、单片机或其他数字设备的集成变得简单。

(5)低功耗:MPL3115A2 设计为低功耗模式,可以在不太耗电的情况下运行。它具有多种省电模式,可根据应用需求进行配置,以延长电池寿命。

(6)自动补偿和校准:MPL3115A2 模块具有自动温度补偿和校准功能,以提高测量的准确性和稳定性。它可以根据环境条件自动调整并校准传感器输出,以减少温度和其他因素对测量结果的影响。

(7)应用领域:由于 MPL3115A2 模块提供了高精度的大气压力和温度测量,它适用于许多应用领域。例如,它可以用于气象站、高度计、无人机和飞行器的高度控制、室内导航系统以及气压计算设备等。

MPL3115A2 是一款功能强大的集成式数字大气压力传感器模块,具有高精度测量、低功耗和数字接口等特点,适用于多种大气压力和海拔测量应用。

五、总结

本项目主要涉及到硬件和软件两个方面,利用MPL3115A2气压传感器模块和LCD1602液晶显示屏实现气压测量和海拔高度计算,并将测得的数据在LCD1602上进行显示。

具体实现过程如下:

(1)硬件方面,需要将MPL3115A2模块和LCD1602显示屏接入单片机,并进行相应的电路设计和连接。

(2)软件方面,需要使用8051单片机来控制MPL3115A2模块和LCD1602显示屏,包括初始化I2C总线、MPL3115A2芯片和LCD1602显示屏,启动气压测量并等待其完成,读取气压值和温度值,将气压值转换成海拔高度值,并通过LCD1602显示屏进行显示。

本项目在实际应用中可作为气压测量和海拔高度计算的一个基础模块,为相关领域的研究和应用提供了一定的技术支持。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1236385.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java语言的特点||运算符

Java语言的特点||运算符 1&#xff1a;2&#xff1a;JDK, JRE&#xff0c;JVM知识&#xff1a;3&#xff1a;注释4&#xff1a;标识符5&#xff1a; Java编译过程&#xff1a;6&#xff1a;赋值7&#xff1a;switch8:布尔表达式9&#xff1a;判定素数10&#xff1a;打印 1 - 10…

前端学习--React(1)

一、React简介 React由Meta公司研发&#xff0c;是一个用于 构建Web和原生交互界面的库 优势&#xff1a;组件化开发、不错的性能、丰富生态&#xff08;所有框架中最好&#xff09;、跨平台&#xff08;web、ios、安卓&#xff09; 开发环境搭建 打开相应文件夹 新建终端并…

Java引用类型String源码解析

目录 String解析 final的作用 String是否有长度限制 StringBuffer解析 StringBuilder解析 关键字、操作类相关 引用数据类型非常多大致包括&#xff1a;类、 接口类型、 数组类型、 枚举类型、 注解类型、 字符串型。String类型就是引用类型。 String解析 JVM运行时会分…

Flutter:多线程Isolate的简单使用

在flutter中如果要使用线程&#xff0c;需要借助Isolate来实现。 简介 在Flutter中&#xff0c;Isolate是一种轻量级的线程解决方案&#xff0c;用于在应用程序中执行并发任务。Isolate可以被认为是独立于主线程的工作单元&#xff0c;它们可以在后台执行任务而不会阻塞应用程…

8.Gin 自定义控制器

8.Gin 自定义控制器 前言 在上一篇路由文件抽离的过程中&#xff0c;我们发现接口的业务逻辑还写在路由配置中&#xff0c;如下&#xff1a; 1696385129126 但是如果业务逻辑比较多&#xff0c;如果写在路由之中&#xff0c;肯定不合适。 我们可以将业务逻辑抽离&#xff0c;单…

【C++进阶之路】第八篇:智能指针

文章目录 一、为什么需要智能指针&#xff1f;二、内存泄漏1.什么是内存泄漏&#xff0c;内存泄漏的危害2.内存泄漏分类&#xff08;了解&#xff09;3.如何检测内存泄漏&#xff08;了解&#xff09;4.如何避免内存泄漏 三、智能指针的使用及原理1.RAII2.智能指针的原理3.std:…

【兔子王赠书第8期】AI短视频制作一本通: 文本生成视频+图片生成视频+视频生成视频

文章目录 写在前面推荐图书关键点内容简介作者简介推荐理由写在后面 写在前面 1本书精通AI短视频制作&#xff0c;文本生成视频图片生成视频视频生成视频AI短视频应用&#xff01;高效视频制作技巧&#xff0c;助你快速成长为行业大咖&#xff01; 推荐图书 《AI短视频制作一…

Stable Diffusion XL网络结构-超详细原创

强烈推荐先看本人的这篇 Stable Diffusion1.5网络结构-超详细原创-CSDN博客 1 Unet 1.1 详细整体结构 1.2 缩小版整体结构 以生成图像1024x1024为例&#xff0c;与SD1.5的3个CrossAttnDownBlock2D和CrossAttnUpBlock2D相比&#xff0c;SDXL只有2个&#xff0c;但SDXL的Cros…

springboot集成nacos作配置中心,动态配置不生效

总体概要 springboot3.0&#xff0c;nacos&#xff0c;jdk17使用nacos配置中心&#xff0c;热更新&#xff0c;使配置动态生效 本文主要介绍springboot怎么集成nacos作为配置中心&#xff0c;使其配置在不重启服务的情况下&#xff0c;怎么生效的。 所用组件及其版本 组件版本…

【ArcGIS Pro微课1000例】0034:矢量数据几何校正案例(Spatial Adjustment)

本案例讲解矢量数据几何校正&#xff0c;根据一个矢量数据去校正另外一个矢量数据。 文章目录 一、加载实验数据二、空间校正三、注意事项 一、加载实验数据 在ArcGIS Pro中加载数据效果如下&#xff1a; design&#xff1a;需要校正的数据图层planroadcenter&#xff1a;目标…

118.184.158.111德迅云安全浅谈如何避免网络钓鱼攻击

随着互联网的不断发展&#xff0c;网络钓鱼攻击也越来越猖獗&#xff0c;给个人和企业带来了巨大的经济损失和安全威胁。本文对如何防范网络钓鱼攻击提出的一些小建议 希望对大家有所帮助。 1.防止XSS&#xff08;跨站脚本攻击&#xff09;攻击 XSS攻击指的是攻击者在网站中注入…

每日一练:组合不重复的四位数字

问题&#xff1a;有四个数字“1、2、3、4”&#xff0c;能组成多少个互不相同且无重复数字的四位数&#xff1f;各是多少&#xff1f; 程序分析 可填在千位、百位、十位、个位的数字都是1、2、3、4。组成所有的排列后再去掉不满足条件的排列。 实现方法1 1&#xff09;使用四…

909-2014-T1

文章目录 1.原题2.算法思想3.关键代码4.完整代码5.运行结果 1.原题 为带表头的单链表类Chain编写一个成员函数Reverse&#xff0c;该函数对链表进行逆序操作&#xff08;将链表中的结点按与原序相反的顺序连接&#xff09;&#xff0c;要求逆序操作就地进行&#xff0c;不分配…

Linux学习第44天:Linux 多点电容触摸屏实验:难忘记第一次牵你手的温存

Linux版本号4.1.15 芯片I.MX6ULL 大叔学Linux 品人间百味 思文短情长 本章的思维导图内容如下&#xff1a; 二、硬件原理图分析 三、实验程序编写 1、修改设备树 1&#xff09;、添加FT5426所使用的IO 一个复位 IO、一个中断 IO、…

【C++进阶之路】第五篇:哈希

文章目录 一、unordered系列关联式容器1.unordered_map&#xff08;1&#xff09;unordered_map的介绍&#xff08;2&#xff09;unordered_map的接口说明 2. unordered_set3.性能对比 二、底层结构1.哈希概念2.哈希冲突3.哈希函数4.哈希冲突解决&#xff08;1&#xff09;闭散…

【Python3】【力扣题】338. 比特位计数

【力扣题】题目描述&#xff1a; 题解&#xff1a;从0到n的整数&#xff0c;逐一统计二进制中1的个数&#xff0c;记录在一个新列表中。 【Python3】代码&#xff1a; 1、解题思路&#xff1a;Python函数。 知识点&#xff1a;bin(...)&#xff1a;转为二进制字符串&#xff…

秋招JAVA面经总结

面试的范围是Java基础+Java并发+Java框架+mysql+网络。 Java基础 重载与重写有什么区别? 重载(Overloading)指的是在同一个类中,可以有多个同名方法,它们具有不同的参数列表(参数类型、参数个数或参数顺序不同),编译器根据调用时的参数类型来决定调用哪个方法。 重写…

用VS编译ROS包

扩展安装 在扩展中搜索并安装ROS、C、python、CMake和CMake Tools。 打开工作空间 文件→打开文件夹 新建功能包 右键src文件夹&#xff0c;选择新建功能包&#xff08;通常是最后一条命令&#xff09; 编译 如果需要新建终端的话&#xff0c;就点击下图中的加号 创建la…

Java,数据结构与集合源码,数据结构概述

目录 数据结构概念&#xff1a; 数据结构的研究对象&#xff1a; 研究对象一&#xff0c;数据间逻辑关系&#xff1a; 研究对象二&#xff0c;数据的存储结构&#xff08;或物理结构&#xff09;&#xff1a; 研究对象三&#xff1a;运算结构 数据结构的相关介绍&#xff…

泵类设备常见的5种故障及监测方法

在各种工业领域中&#xff0c;泵是一种关键设备&#xff0c;用于输送液体或气体。然而&#xff0c;泵类设备常常会面临各种故障&#xff0c;这可能导致生产停顿和生产效率下降。为了及时监测并解决这些故障&#xff0c;设备状态监测系统成为一种重要的工具。本文将介绍泵类设备…