基于GEC6818的QT开发之——通过不同按键控制DHT11模块的数据采集与动态显示

基于GEC6818的QT开发之——通过不同按键控制DHT11模块的数据采集与动态显示

使用环境:
ubantu16
QT5.7
开发板GEC6818
实现要求:
利用A53按键1、按键2与温湿度传感器完成QT界面动态显示温湿度记录,并指定温湿度记录超过指定范围,进行报警(LED,BEEP),按下key1时,允许进行采集;当key2按下,关闭数据采集。
效果演示视频:基于GEC6818的QT开发之——通过按键控制DHT11模块的数据采集与动态显示
视频效果为升级版。

文章目录

  • 基于GEC6818的QT开发之——通过不同按键控制DHT11模块的数据采集与动态显示
    • 一、驱动的加载
      • 1.1 dht11驱动加载
      • 1.2 按键驱动加载
      • 1.3蜂鸣器驱动加载
    • 二、DHT11引脚
    • 三、UI界面的设置
    • 四、DHT11
      • 4.1 DHT11使用的QTimer类的介绍
      • 4.2 dht11.cpp 代码
      • 4.3 dht11.h 代码
    • 五、按键
      • key 相关的代码
    • 六、蜂鸣器
    • 七、主类的完整代码

一、驱动的加载

我们在使用GEC6818开发板时,板上是没有DHT11的,而且与前面我们使用LED相同,我们同样需要一个与DHT11相配套的驱动,关于的撰写这里就不详细描述了,但是可以参考ARM开发之基于IIC协议的TM1650驱动实现,这篇文章是关于IIC协议的TM1605的驱动编写,可以仿照这些步骤对DHT11进行驱动编写。

将驱动下载到开发板并且进行加载

相关驱动已经与工程一起打包发在文章末尾的地址了。

1.1 dht11驱动加载


rx dht11_drv
rmmod dht11_drv.ko//先卸载,没有可以不用卸载

insmod dht11_drv.ko//再加载

1.2 按键驱动加载

rx buttons_drv.ko

rmmod buttons_drv.ko//先卸载,没有可以不用卸载

insmod buttons_drv.ko//再加载

1.3蜂鸣器驱动加载


rx pwm.ko

rmmod pwm.ko//先卸载,没有可以不用卸载

insmod pwm.ko//再加载

//****这个如果提示....busy 的话则执行*****

rmmod gec6818_beep.ko

再执行
insmod pwm.ko//再加载

二、DHT11引脚

有了相关驱动后,就可以对DHT11进行数据的读取啦,根据驱动:
在这里插入图片描述

可以看到GEC_6818的底板引脚图:
在这里插入图片描述

我们可以将DHT11的引脚如下图插入对应引脚。
在这里插入图片描述

三、UI界面的设置

一个简单的数据显示:
在这里插入图片描述

可以使用以上的方法,对应的控件名称如下:
在这里插入图片描述

关于如何对控件进命名,更换颜色等,可以参考博客:GEC6818的QT计算器计算的结果控制LED的亮灭的中间部分。

四、DHT11

4.1 DHT11使用的QTimer类的介绍

QTimer类提供了定时器信号单触发定时器。它在内部使用定时器事件来提供更通用的定时器。QTimer很容易使用:创建一个QTimer对象,使用start()来开始并且把它的timeout()连接到适当的槽函数。当这段时间过去了,它将会发射timeout()信号,对应的槽函数将被调用执行。值得注意的是当QTimer的父对象被销毁时,它也会被自动销毁。另外,QTimer的精确度依赖于底下的操作系统和硬件,绝大多数平台支持20毫秒的精确度,有些平台可以提供更高的,但是,如果您想获得更精确的毫秒级甚至微秒级的定时,不用考虑它了。

在主函数中的使用方法如下:

    QTimer *my_Timer;
    my_Timer = new QTimer;
    connect(my_Timer,SIGNAL(timeout()),this,SLOT(Main_Function()));
    my_Timer->setTimerType(Qt::PreciseTimer);
    my_Timer->start(500);

4.2 dht11.cpp 代码

由于这个案例涉及多个模块,所以我有多个cpp文件和.h文件,可以先看着理解一下,完整工程在文章末尾可以进行下载。


#include "dht11.h"
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <errno.h>

#define GEC6818_GET_DHTDATA  _IOR('K', 0, unsigned int) //注册宏
unsigned char get_data[2];//存放数据的数组--(全局变量)
// ----------------------dht11 get data function-------
int dht11_get_data(void)
{

    int ret, cnt_yes=0, cnt_err=0;

    int ultrasonic_fd = open("/dev/dht11_dev", O_RDWR);//打开dht11的设备文件
    if(ultrasonic_fd < 0)//打开失败
    {
        perror("open dht11_dev driver");
        return -1;
    }

    printf("检测中\n");
    ret = ioctl(ultrasonic_fd, GEC6818_GET_DHTDATA, &get_data[0]);//读取
    if(ret != 0)
    {
        cnt_err++;
        perror("GEC6818_GET_DHTDATA error");
    }
    else
    {
        cnt_yes++;
        printf("湿度= %hhd  温度=%hhd  错误%d  正确%d\n", get_data[1], get_data[0], cnt_err, cnt_yes);
    }

    sleep(1);

    close(ultrasonic_fd);//关闭设备文件
    return 0;
}

ps:我觉得这个驱动没写的很好,可以从上面的数据输出看出湿度的值太小了!

4.3 dht11.h 代码

#ifndef DHT11_H
#define DHT11_H

extern unsigned char get_data[4];
int dht11_get_data(void);


#endif // DHT11_H

五、按键

一共有四个按键,如下:
在这里插入图片描述

key 相关的代码

    fd_key1=open("/dev/gecBt",O_RDONLY);
    if(fd_key1<0)
    {
        printf("open  buttons fail!\n");
    }
    notifier = new QSocketNotifier(fd_key1,QSocketNotifier::Read,this);
    connect(notifier,SIGNAL(activated(int)),this,SLOT(key_get()));
//------------------------key----------
// 延时函数
void delay(unsigned value)
{
    while(value--);
}

int beep_state=1;
int led_state=1;
void DHT11_KEY::key_get()
{
    char buttonValue[4];
    memset(buttonValue, 0, 4);
    ::read( fd_key1, buttonValue, sizeof(buttonValue));
    for(int i=0;i < (int)sizeof(buttonValue); i++)
    {
        switch(i)
        {
            case 0://key1
                if(buttonValue[i]=='1')
                {
                    state=1;
                    printf("KEY1\n");

                }
            break;
            case 1://key2
                if(buttonValue[i]=='1')
                {
                    state=0;
                    printf("KEY2\n");
                }
            break;
            case 2://key4
                if(buttonValue[i]=='1')
                {
                    beep_state=!beep_state;//反转
                    printf("KEY3 press beep_state=%d\n",beep_state);
                }
            break;
            case 3://key4
                if(buttonValue[i]=='1')
                {
                    led_state=!led_state;
                    printf("KEY4 press led_state=%d\n",led_state);
                }
            break;
        }
    }
    Main_Function();
}

这段代码是一个简单的实现了读取嵌入式系统中按键状态的功能。

  1. fd_key1=open("/dev/gecBt",O_RDONLY);:这行代码打开了名为"/dev/gecBt"的设备文件,该设备文件用于读取按键状态。它返回一个文件描述符(file descriptor),如果打开失败,则文件描述符为负值。

  2. if(fd_key1<0):检查文件描述符是否有效。如果文件描述符小于0,则说明打开失败,输出错误消息。

  3. notifier = new QSocketNotifier(fd_key1,QSocketNotifier::Read,this);:创建一个QSocketNotifier对象,用于监听文件描述符fd_key1的读取事件。这样,当有数据可读取时,就会触发信号activated(int)。

  4. connect(notifier,SIGNAL(activated(int)),this,SLOT(key_get()));:将notifier的activated(int)信号连接到key_get()槽函数。这意味着当文件描述符fd_key1上有数据可读取时,将调用key_get()函数。

  5. void DHT11_KEY::key_get():key_get()函数是一个槽函数,用于处理文件描述符上的数据读取事件。它从文件描述符fd_key1中读取按键状态,并根据按键状态执行相应的操作。

  6. char buttonValue[4];:定义一个大小为4的字符数组,用于存储按键状态。

  7. ::read(fd_key1, buttonValue, sizeof(buttonValue));:从文件描述符fd_key1中读取4个字节的数据,即按键状态,并将其存储到buttonValue数组中。

  8. for(int i=0;i < (int)sizeof(buttonValue); i++):遍历buttonValue数组中的每个元素,以检查每个按键的状态。

  9. switch(i):根据当前迭代的索引值,选择不同的按键进行处理。

  10. case 0::处理第一个按键(key1)的状态。

  11. case 1::处理第二个按键(key2)的状态。

  12. case 2::处理第三个按键(key3)的状态。

  13. case 3::处理第四个按键(key4)的状态。

在每种情况下,根据按键的状态执行相应的操作,例如更改状态变量或输出调试信息。

六、蜂鸣器

在这里插入图片描述

#define  BUZZER_IOCTL_SET_FREQ 1
#define  BUZZER_IOCTL_STOP 0
    //---------------pwm----------------
    beep_fd = ::open("/dev/pwm", O_RDWR);
    if ( beep_fd < 0 )
        printf("open /dev/pwm  failed\n");
if(get_data[0]>25&&beep_state==1)
    {
      ::ioctl(beep_fd, BUZZER_IOCTL_SET_FREQ , freq );
        
    }
    else
    {
     ::ioctl(beep_fd , BUZZER_IOCTL_STOP , freq);
    }

七、主类的完整代码

#include "dht11_key.h"
#include "ui_dht11_key.h"

int state=0;
int beep_fd = -1;
int freq = 3000;
DHT11_KEY::DHT11_KEY(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::DHT11_KEY)
{
    ui->setupUi(this);

    //---------------key-------
    fd_key1=open("/dev/gecBt",O_RDONLY);
    if(fd_key1<0)
    {
        printf("open  buttons fail!\n");
    }
    notifier = new QSocketNotifier(fd_key1,QSocketNotifier::Read,this);
    connect(notifier,SIGNAL(activated(int)),this,SLOT(key_get()));

    //-------------led------------------
    Led_Init();
    //---------------pwm----------------
    beep_fd = ::open("/dev/pwm", O_RDWR);
    if ( beep_fd < 0 )
        printf("open /dev/pwm  failed\n");

    //-------DHT11--------------//

    my_Timer = new QTimer;
    connect(my_Timer,SIGNAL(timeout()),this,SLOT(Main_Function()));
    my_Timer->setTimerType(Qt::PreciseTimer);
    my_Timer->start(500);

}


DHT11_KEY::~DHT11_KEY()
{
    delete ui;
    if(beep_fd>0)
    {
        ::close(beep_fd);
    }
    if(fd_key1>0)
    {
        ::close(fd_key1);
    }

}

//------------------------key----------
// 延时函数
void delay(unsigned value)
{
    while(value--);
}

int beep_state=1;
int led_state=1;
void DHT11_KEY::key_get()
{
    char buttonValue[4];
    memset(buttonValue, 0, 4);
    ::read( fd_key1, buttonValue, sizeof(buttonValue));
    for(int i=0;i < (int)sizeof(buttonValue); i++)
    {
        switch(i)
        {
            case 0://key1
                if(buttonValue[i]=='1')
                {
                    state=1;
                    printf("KEY1\n");

                }
            break;
            case 1://key2
                if(buttonValue[i]=='1')
                {
                    state=0;
                    printf("KEY2\n");
                }
            break;
            case 2://key4
                if(buttonValue[i]=='1')
                {
                    beep_state=!beep_state;//反转
                    printf("KEY3 press beep_state=%d\n",beep_state);
                }
            break;
            case 3://key4
                if(buttonValue[i]=='1')
                {
                    led_state=!led_state;
                    printf("KEY4 press led_state=%d\n",led_state);
                }
            break;
        }
    }

    Main_Function();

}

//-----------------------main----------------

void DHT11_KEY::Main_Function()
{
    if(state == 1)
    {
        ui->Collect_State->setText(QString("open"));
        ui->Collect_State->setAlignment(Qt::AlignCenter);
        dht11_get_data();
        ui->humidity_data->setText(QString::number(get_data[1],10));
        ui->temperature_data->setText(QString::number(get_data[0],10));

    }
    else
    {
        ui->Collect_State->setText(QString("close"));
        ui->Collect_State->setAlignment(Qt::AlignCenter);
    }

    if(get_data[0]>25&&beep_state==1)
    {
      ::ioctl(beep_fd, BUZZER_IOCTL_SET_FREQ , freq );
        
    }
    else
    {
     ::ioctl(beep_fd , BUZZER_IOCTL_STOP , freq);
    }

    if(get_data[1]>5&&led_state==1)
    {
            Led2_open();
            Led1_open();
//            Led3_open();
//            Led4_open();
    }
    else
    {
        Led2_close();
        Led1_close();
//        Led3_close();
//        Led4_close();
    }


}

本文中涉及的工程代码在我的github中可以进行下载03-DHT11简单版
升级版可以对数据以表格的形式展示,两个UI界面可以来回切换
地址:QT开发之两个UI界面切换与表格显示DHT11数据

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

自主可控|工业机箱/控制器助力打造高性能、超稳定测试系统!

产品介绍 PXIeC-7318GN3L1-21DBM 是一款拥有出色性能和创新功能的18槽PXI Express机箱&#xff0c;具备1个system插槽和17个hybrid外设插槽&#xff0c;采用hybrid插槽设计&#xff0c;可以安装Compact PCI、PXI、Compact PCl Express和PXI Express模组到任何外设插槽内&…

PONAR电比例控制阀驱动器

控制PONAR WADOWICE比例方向阀&#xff0c;比例流量阀&#xff0c;比例压力阀&#xff0c;比例插装阀控制器放大器放大板&#xff0c;控制阀系列&#xff1a;WDUD10、WDUD6、WZCDE4、WZRS6、WZCR6、3WZCDE6、WZCPE10、WZPPE10、WZPSE20、WZPPE20、WZPSE10、WZPSE6、WZPPE10、WZ…

用Python直接获取Word文档页数、字数、段落数、节数等信息

计算 Word 文档的页数、字数等信息是出版、学术和内容管理等领域的一项基本任务。准确的页数和字数对于评估文档长度、估算印刷成本、分析文本复杂性以及确保符合格式化指南至关重要。逐个预览文档查看相关信息是非常麻烦的事情&#xff0c;我们可以在不预览文档的情况下&#…

产品说明书VS产品规格书:有什么区别

产品说明书和产品规格书是两个不同的文档&#xff0c;虽然它们都涉及到产品的描述和细节&#xff0c;但侧重点和用途有所不同。 | 内容侧重点不同 产品说明书更侧重于向用户解释产品的使用方法和操作细节。它就像是一本用户手册&#xff0c;告诉用户如何安装、操作、维护和保养…

记录收支明细,轻松导出表格,让家庭财务一目了然!

随着生活节奏的加快&#xff0c;家庭财务管理变得越来越重要。想要掌握家庭的收支情况&#xff0c;合理规划预算&#xff0c;却常常被琐碎的账目和复杂的表格困扰&#xff1f;别担心&#xff0c;我们为您带来一款全新的家庭财务管理工具&#xff0c;让您轻松记录收支明细&#…

【教程】APP加固的那些小事情

摘要 APP加固是保护APP代码逻辑的重要手段&#xff0c;通过隐藏、混淆、加密等操作提高软件的逆向成本&#xff0c;降低被破解的几率&#xff0c;保障开发者和用户利益。本文将介绍APP加固常见失败原因及解决方法&#xff0c;以及处理安装出现问题的情况和资源文件加固策略选择…

手把手教你搭建雾锁王国Enshrouded服务器

免费自建雾锁王国Enshrouded服务器&#xff0c;先领取阿里云300元无门槛代金券&#xff0c;然后在雾锁王国Enshrouded专题页一键部署&#xff0c;不需要基础&#xff0c;鼠标点选即可10秒钟创建一台雾锁王国游戏服务器&#xff0c;超简单&#xff0c;阿里云服务器网aliyunfuwuq…

Redis @type的一个坑

redis中type导致取数据解析报错 java.lang.ClassCastException: com.alibaba.fastjson.JSONObject cannot be cast to 新建一个对象存入redis中&#xff0c;对象中会出现一个字段type LoginUser user new LoginUser () ...... redisTemplate.opsForValue().set(key, user)存…

k8s集群部署elk

一、前言 本次部署elk所有的服务都部署在k8s集群中&#xff0c;服务包含filebeat、logstash、elasticsearch、kibana&#xff0c;其中elasticsearch使用集群的方式部署&#xff0c;所有服务都是用7.17.10版本 二、部署 部署elasticsearch集群 部署elasticsearch集群需要先优化…

洗涤杂质气体的仪器-PFA洗涤瓶

PFA洗气瓶是一种洗去气体中杂质的仪器&#xff0c;是将不纯气体通过选定的适宜液体介质鼓泡吸收&#xff08;溶解或由于发生化学反应&#xff09;&#xff0c;从而洗去杂质气体&#xff0c;以达净化气体的目的。在有可燃性气源的实验装置中&#xff0c;洗气瓶也可起到安全瓶的作…

基于Spring Boot框架的玩具销售系统的设计与实现

摘 要 随着信息时代的来临&#xff0c;过去的传统管理方式缺点逐渐暴露&#xff0c;对过去的传统管理方式的缺点进行分析&#xff0c;采取计算机方式构建玩具销售系统。本文通过课题背景、课题目的及意义相关技术&#xff0c;提出了一种玩具信息、购买订单、退货申请、换货申请…

AI算力池化赋能企业大模型价值探索

1. 大语言模型企业落地中的算力痛点 随着人工智能技术的飞速发展&#xff0c;自然语言处理&#xff08;NLP&#xff09;成为了热门的研究领域之一。在这一领域中&#xff0c;大语言模型&#xff08;Large Language Models&#xff09;凭借其强大的语言理解和生成能力&#xff…

每日OJ题_牛客HJ75 公共子串计算(IO型OJ)

目录 牛客HJ75 公共子串计算 解析代码 牛客HJ75 公共子串计算 公共子串计算_牛客题霸_牛客网 解析代码 #include <iostream> using namespace std; int main() {string str1 "", str2 "";cin >> str1 >> str2;int n1 str1.size()…

性能测试-Jmeter常用元件基础使用

一、Jmeter元件 #线程组 添加HTTP请求 #配置元件 配置元件内的元件都是用于进行初始化的东西 #监听器 监听器主要是用来获取我们使用取样器发送请求后的响应数据相关信息 #定时器 定时器主要用来控制我们多久后执行该取样器&#xff08;发送请求&#xff09; #前置处理器 前置处…

测试工具分享:高效完成测试工作!

说在前头 在社会上&#xff0c;特别是技术圈&#xff0c;大家会有刻板印象&#xff1a;测试工作的含金量不高。因为大家觉得测试不重要&#xff0c;导致给测试的薪水也偏低&#xff1b;这又反向导致好的人才不想来测试行业&#xff0c;测试从业人员的平均水平、工作体现的价值…

【ArcPy】栅格数据渲染

import arcpy # 输入数据 inRaster arcpy.Raster(r"C:\测试数据\dem\归一化处理.tif") # 用线性拉伸和NDVI配色方案渲染栅格 rendered_raster arcpy.Render(inRaster, rendering_rule{min: 0, max: 0.8}, colormapNDVI) #栅格单独一行可将栅格数据直接显示 rendere…

打开磁盘清理工具的9种方法,总有一种适合你

前言 你可以在Windows 10和11上使用许多第三方磁盘清理工具来进行清理。但是,别忘了Windows包含自己的磁盘清理工具,你可以使用该工具释放硬盘存储空间。一些第三方替代方案可能有更广泛的清理选项和功能,但磁盘清理仍然是消除多余文件的完美工具。 每个用户都应该不时地进…

使用 Python 编写网络爬虫:从入门到实战

网络爬虫是一种自动化获取网页信息的程序&#xff0c;通常用于数据采集、信息监控等领域。Python 是一种广泛应用于网络爬虫开发的编程语言&#xff0c;具有丰富的库和框架来简化爬虫的编写和执行过程。本文将介绍如何使用 Python 编写网络爬虫&#xff0c;包括基本原理、常用库…

LLM流式方案解决方案和客户端解决方案

背景 接上一篇《LLM大模型统一封装接口解决方案》架构确定后&#xff0c;流式方案非常规请求&#xff0c;需要特殊处理。 本解决方案就是针对上一篇中所需要的流式&#xff08;打字机效果进行编码&#xff09; 什么是SSE SSE&#xff08;Server-Sent Events&#xff0c;服务器发…

鸿蒙App开发学习 - TypeScript编程语言全面开发教程(上)

背景 根据鸿蒙官方的说明&#xff1a; ArkTS是HarmonyOS优选的主力应用开发语言。ArkTS围绕应用开发在TypeScript&#xff08;简称TS&#xff09;生态基础上做了进一步扩展&#xff0c;继承了TS的所有特性&#xff0c;是TS的超集。因此&#xff0c;在学习ArkTS语言之前&#…