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

news2025/2/27 8:40:41

基于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数据

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

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

相关文章

十四届蓝桥杯 BC A.日期统计

思路&#xff1a; 循环2023的每一天&#xff0c;一共八位数&#xff1b;年份是确定的&#xff0c;只需要循环月份和天数&#xff0c;注意这里已知2023的2月份天数为28天。用b数组 int b[8]{2,0,2,3,month/10,month%10,d/10,d%10};//枚举2023的每一天来和已知数据的八位数字比较…

ESP32蓝牙系列二:协议和规范

本文以ESP32的API接口对GAP GATT ATT再做分析 一、GAP ESP32 BLE 通⽤用访问规范 (GAP) 接口 API 的实现和使⽤用流程&#xff0c; GAP 协议层定义了了 BLE 设备的发现流程&#xff0c;设备管理理和设备连接的建立。 BLE GAP 协议层采⽤用 API 调⽤和事件 (Event) 返回的设计…

从零开始学习在VUE3中使用canvas(四):globalAlpha(全局透明度)

一、简介 在canvas中&#xff0c;我们可以使用下面的方式设置全局透明度&#xff1a; const ctx canvas.getContext("2d");ctx.globalAlpha 0.5; 当然&#xff0c;在设置透明度的时候也可以直接填充带透明度的颜色 ctx.fillStyle "rgba(175, 20, 184, 0.5…

白酒:新型酶制剂在酿造过程中的作用与应用

随着生物技术的不断发展&#xff0c;新型酶制剂在许多领域都得到了广泛的应用。在豪迈白酒的酿造过程中&#xff0c;新型酶制剂也发挥了重要作用。云仓酒庄紧跟科技前沿&#xff0c;积极探索新型酶制剂在酿造过程中的应用&#xff0c;以提高产品质量和生产效率。 首先&#xff…

YOLOV4-车道线检测-车距离预测

1.前言 最近在看华为的CANN框架&#xff0c;发现了一些很有意思的开源算法(本文所有的代码都出自华为开源git发布的代码)&#xff0c;华为最近出了AI PRO开发板&#xff0c;想着现在开发板上用用(不想重新配置环境了&#xff0c;麻烦还累)&#xff0c;看着代码有onnx的模型&…

《深入Linux内核架构》第2章 进程管理和调度 (3)

目录 2.5 调度器的实现 2.5.1 概观 2.5.2 数据结构 2.5.3 处理优先级 2.5.3.1 nice和prior 2.5.3.2 vruntime 2.5.3.3 weight权重 2.5.4 核心调度器 2.5 调度器的实现 调度器的任务&#xff1a; 1. 执行调度策略。 2. 执行上下文切换。 无论用户态抢占&#xff0c;还是…

Spring MVC入门(4)

请求 获取Cookie/Session 获取Cookie 传统方式: RequestMapping("/m11")public String method11(HttpServletRequest request, HttpServletResponse response) {//获取所有Cookie信息Cookie[] cookies request.getCookies();//打印Cookie信息StringBuilder build…

大数据主要技术

1.大数据文件系统&#xff1a; GFS(谷歌的分布式文件系统&#xff09; HDFS&#xff08;hadoop distrubuted file system&#xff09;分布式文件系统&#xff0c;衍生自GFS 2.大数据平台 MapReduce &#xff1a;谷歌的大数据处理平台&#xff0c;服务于搜索 Hadoop&#…

C#混淆心得

C#混淆心得 近期遇到混淆C#代码的需求&#xff0c;在网上找了很多办法&#xff0c;在此记录一下。 混淆的本质就是让代码变丑&#xff0c;让别人看不懂。 为什么要混淆&#xff1a; 1.保护核心代码 可以在一定程度上避免别人偷代码&#xff0c;从而保护重要的部分&#xf…

蓝桥杯单片机快速开发笔记——超声波测距

一、原理分析 超声波测距是一种常见的测距方法&#xff0c;其原理是利用超声波在空气中传播的速度恒定且较快的特性&#xff0c;通过发送超声波信号并接收回波&#xff0c;计算出物体与传感器之间的距离。以下是超声波测距的原理和应用&#xff1a; 原理&#xff1a; 发送超声…

Linux安装Mysql5.7数据库

一、前置条件 系统版本&#xff1a;Linux CentOS 7.5 MySQL版本&#xff1a;mysql5.7.31 二、操作步骤 2.1、关闭mysql服务 service mysqld stop 提示使用命令&#xff1a;systemctl stop mysqld.service 2.2、grep查找已安装的mysql服务 rpm -qa | grep -i mysql 2.3、卸载…

机器学习(1)机器学习的概念与应用领域

文章目录 一、前提二、机器学习的概念与应用领域1.认识①亚瑟•塞缪尔的定义②汤姆米切尔的定义 2.相关术语数据术语训练模型术语获得模型后术语 3.应用领域语音识别计算机视觉自然语言处理①自然语言分析②自然语言生成 大数据分析 一、前提 Python语言具有数量庞大且功能相对…

记录一次爬虫接单项目【采集国际淘宝数据】

1.背景 前几天接了一个爬虫的单子&#xff0c;上周六已经完成这个单子&#xff0c;也收到了酬劳&#xff08;数目还不错&#xff0c;哈哈哈&#xff0c;小喜了一下&#xff09;。这个项目大概我用了两天写完了&#xff08;空闲时间写的&#xff09;。 2.介绍 大概要采集的数据…

Flutter-仿淘宝京东录音识别图标效果

效果 需求 弹起键盘&#xff0c;录制按钮紧挨着输入框收起键盘&#xff0c;录制按钮回到初始位置 实现 第一步&#xff1a;监听键盘弹起并获取键盘高度第二步&#xff1a;根据键盘高度&#xff0c;录制按钮高度计算偏移高度&#xff0c;并动画移动第三步&#xff1a;键盘收起…

深度学习_卷积

卷积 卷积&#xff08;Convolution&#xff09;是数学和计算机科学中的一个重要概念&#xff0c;特别在信号处理和图像处理中应用广泛。在信号处理领域&#xff0c;卷积是两个函数之间的一种数学操作&#xff0c;它表示两个函数的重叠部分的积分量。 在图像处理中&#xff0c…

KKVIEW远程: TODESK退出了还能远程吗

Todesk退出了还能远程吗 当我们谈论Todesk或其他远程桌面软件时&#xff0c;一个经常被提及的问题是&#xff1a;当我退出Todesk后&#xff0c;是否仍然可以远程访问我的计算机&#xff1f;为了回答这个问题&#xff0c;我们首先需要了解Todesk的工作原理和远程访问的基本条件…

WhatsApp商业推广有哪些推广技巧?

在现代化商业&#xff0c;与用户创造紧密、良好的互动体验&#xff0c;建立强大的品牌形象以及找到最佳的推广途径&#xff0c;变得尤为重要。而WhatsApp作为全球使用最广泛的即时通讯应用之一&#xff0c;成为无数企业选择优选的推广平台。那么&#xff0c;在WhatsApp商业推广…

图书推荐|西门子S7-1200 PLC编程与应用实例

一线资深工程师的全彩版PLC实战教程&#xff0c;软硬件及编程全方位详解&#xff08;配视频教学&#xff09; 本书内容 《西门子S7-1200 PLC编程与应用实例》对西门子S7-1200 PLC的硬件和编程软件的功能进行详细讲解&#xff0c;内容包括PLC编程基础、博途TIA软件入门、指令介…

使用OCC进行切割操作

OCC中切割操作以一个平面作为切割面&#xff0c;对物体进行切割操作 //要操作的图形 TopoDS_Shape shape getHanleShape(); //构造切割面 TopoDS_Shape faceShape getSplitterFace(); //切割操作 BOPAlgo_Splitter splitter; splitter.AddArgument(shape); splitter.AddTool(…

13.Python从入门到精通—Python 集合操作与方法概览

13.Python从入门到精通—Python 集合操作与方法概览 Python 集合集合的基本操作1、添加元素2、移除元素3、计算集合元素个数4、清空集合5、判断元素是否在集合中存在 集合内置方法完整列表 Python 集合 在Python中&#xff0c;集合是一种无序、不重复的数据类型。集合通常用于…