STM32+ESP8266+QT客户端上位机显示DHT11温湿度与点灯

简介: STM32+ESP8266+QT客户端上位机显示DHT11温湿度与点灯

1、简介

本文使用STM32F103C8T6单片机使用单片机通过ESP8266WIFI模块与QT设计的上位机进行通讯,ESP8266设置AP模式。实现DHT11传感器温湿度的显示与远程控制LED小灯的亮灭。


2、硬件连接

PB9---DHT11(5V)

PA9----RX

PA10---TX

ESP8266(3.3V)

PB0----LED(高电平有效)


3、上位机源码

3.1 widget.h

#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QWidget>
#include <QTcpServer>
#include <QTcpSocket>
namespace Ui {
class Widget;
}
#pragma pack(1)
struct QT_info
{
    unsigned char Head[2];
    uint8_t DHT11_BUF[2];//用于存放DHT11数据
};
#pragma pack()
class Widget : public QWidget
{
    Q_OBJECT
public:
    explicit Widget(QWidget *parent = nullptr);
    ~Widget();
    //QTcpServer *tcpserver;//声明一个QTcpserver的对象,用于监听
    QTcpSocket *tcpsocket;//创建服务器的套接字,用于与客户端进行通信
private slots:
    void on_open_Button_clicked();
    void on_close_Button_clicked();
    void on_send_Button_clicked();
    void connected_Slot();
    void readyRead_Slot();
    void on_pushButton_clicked();
private:
    Ui::Widget *ui;
};
#endif // WIDGET_H

3.2 widget.c

#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    //tcpserver = new QTcpServer(this);
    tcpsocket = new QTcpSocket(this);
}
Widget::~Widget()
{
    delete ui;
}
//client端的连接服务器按钮
void Widget::on_open_Button_clicked()
{
     // 根据输入的ip和port连接指定的服务器
//    tcpsocket->connectToHost(ui->IP_line->text(),ui->port_line->text().toUShort());
    tcpsocket->connectToHost("192.168.4.1",333);
    connect(tcpsocket,SIGNAL(connected()),this,SLOT(connected_Slot()));
    if(tcpsocket->waitForConnected(1000) == true){
    tcpsocket->write("Q");
    }
}
void Widget::connected_Slot()
{
    connect(tcpsocket,SIGNAL(readyRead()),this,SLOT(readyRead_Slot()));
}
void Widget::readyRead_Slot()
{
    QByteArray mytemp = tcpsocket->readAll();
    //ui->rece_TextEdit->appendPlainText(tcpsocket->readAll());
    if(!mytemp.isEmpty()){
    ui->rece_T_Edit->clear();
    ui->rece_S_Edit->clear();
    struct QT_info* info_RX = (struct QT_info*)mytemp.data(); // unsigned char *
    if(info_RX->Head[0]==0x55 && info_RX->Head[1]==0xFF) {
        QString T = QString::asprintf("%.2d",info_RX->DHT11_BUF[1]);
        QString S = QString::asprintf("%2d",info_RX->DHT11_BUF[0]);
        ui->rece_T_Edit->insertPlainText(T);
        ui->rece_S_Edit->insertPlainText(S);
    }
    mytemp.clear();
    }
}
void Widget::on_close_Button_clicked()
{
    tcpsocket->write("B");
    tcpsocket->close();
    ui->rece_T_Edit->clear();
    ui->rece_S_Edit->clear();
} 
void Widget::on_send_Button_clicked()
{
//    tcpsocket->write(ui->send_line->text().toLocal8Bit().data());
   tcpsocket->write("Q");
}
void Widget::on_pushButton_clicked()
{
    tcpsocket->write("B");
}

3.3 显示图



4、下位机源码

4.1 cubemax配置

GPIO配置。


串口配置,中断打开。


4.2 keil部分源码

func

#include "func.h"
struct QT_info QT_info_TX;
extern char buf;
uint16_t len;
void CSH(void)
{
  len = sizeof(QT_info_TX);
  DHT11_Init();//传感器芯片初始化
  DHT11_ReadData(QT_info_TX.DHT11_BUF);//读出DHT11传感器数据(参数是存放数据的数组指针)
  HAL_Delay(200);
  //1 工作在路由模式
  printf("AT+CWMODE=2\r\n");
  HAL_Delay(200);
  //2 使能多链接
  printf("AT+CIPMUX=1\r\n");
  HAL_Delay(200);
  //3 建立TCPServer port = 333
  printf("AT+CIPSERVER=1\r\n");
  HAL_Delay(200);
  LED_OFF;
  QT_info_TX.Head[0]=0x55;
  QT_info_TX.Head[1]=0xFF;
}
void oled_ui(void)
{ 
  DHT11_ReadData(QT_info_TX.DHT11_BUF);//读出DHT11传感器数据(参数是存放数据的数组指针)
  HAL_Delay(100);
  HAL_UART_Receive_IT(&huart1, (uint8_t *)&buf, 1);   
  //发送数据
  printf("AT+CIPSEND=0,%d\r\n",len);
  HAL_Delay(200);
  HAL_UART_Transmit(&huart1,(uint8_t *)&QT_info_TX,sizeof(QT_info_TX),10);
}
#include "main.h"
#include "dht11.h"
#include "usart.h"
#include "string.h"
void CSH(void);
void alarm(void);
void oled_ui(void);
void Qt_UART_RxCallBack(unsigned char *Data,unsigned int Len);
__packed struct QT_info
{
  unsigned char Head[2];
  uint8_t DHT11_BUF[2];//用于存放DHT11数据
};

main

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2023 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "i2c.h"
#include "usart.h"
#include "gpio.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "stdio.h"
char buf;
#include "func.h"
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
void  HAL_UART_RxCpltCallback(UART_HandleTypeDef  *huart)//涓插彛涓柇鍥炶皟鍑芥暟
{
  if(huart1.Instance == USART1)
  {
    if(buf == 'Q')
    {
       LED_ON;
      HAL_UART_Receive_IT(&huart1, (uint8_t *)&buf, 1);
    }
    else if(buf == 'B')
    {
       LED_OFF;
      HAL_UART_Receive_IT(&huart1, (uint8_t *)&buf, 1);
    }
    HAL_UART_Receive_IT(&huart1, (uint8_t *)&buf, 1);
  }   
}
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/**
  * @brief  The application entry point.
  * @retval int
  */
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();
  MX_USART2_UART_Init();
  /* USER CODE BEGIN 2 */
  CSH();
  /* USER CODE END 2 */
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  { 
    oled_ui();
//  printf("1\r\n");
    /* USER CODE END WHILE */
    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}
/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  {
    Error_Handler();
  }
}
/* USER CODE BEGIN 4 */
/* USER CODE END 4 */
/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  __disable_irq();
  while (1)
  {
  }
  /* USER CODE END Error_Handler_Debug */
}
#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

dht11

/*
 * dht11.c
 *
 *  Created on: Oct 21, 2021
 *      Author: Administrator
 */
/*
//杜洋工作室出品
//洋桃系列开发板应用程序
//关注微信公众号:洋桃电子
//洋桃开发板资料下载 www.DoYoung.net/YT
//即可免费看所有教学视频,下载技术资料,技术疑难提问
//更多内容尽在 杜洋工作室主页 www.doyoung.net
*/
/*
《修改日志》
1-201708202309 创建。
*/
#include "dht11.h"
#include "main.h"
void DHT11_IO_OUT (void){ //端口变为输出
  GPIO_InitTypeDef GPIO_InitStruct = {0};
  GPIO_InitStruct.Pin = DHT11_DA_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}
void DHT11_IO_IN (void){ //端口变为输入
  GPIO_InitTypeDef GPIO_InitStruct = {0};
  GPIO_InitStruct.Pin = DHT11_DA_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}
void DHT11_RST (void){ //DHT11端口复位,发出起始信号(IO发送)
  DHT11_IO_OUT();
  HAL_GPIO_WritePin(GPIOB,DHT11_DA_Pin, GPIO_PIN_RESET);
  HAL_Delay(20); //拉低至少18ms
  HAL_GPIO_WritePin(GPIOB,DHT11_DA_Pin, GPIO_PIN_SET);
  delay_us(30); //主机拉高20~40us
}
uint8_t Dht11_Check(void){ //等待DHT11回应,返回1:未检测到DHT11,返回0:成功(IO接收)
  uint8_t retry=0;
    DHT11_IO_IN();//IO到输入状态
    while (HAL_GPIO_ReadPin(GPIOB,DHT11_DA_Pin)&&retry<100){//DHT11会拉低40~80us
        retry++;
        delay_us(1);
    }
    if(retry>=100)return 1; else retry=0;
    while (!HAL_GPIO_ReadPin(GPIOB,DHT11_DA_Pin)&&retry<100){//DHT11拉低后会再次拉高40~80us
        retry++;
        delay_us(1);
    }
    if(retry>=100)return 1;
    return 0;
}
uint8_t Dht11_ReadBit(void){ //从DHT11读取一个位 返回值:1/0
  uint8_t retry=0;
    while(HAL_GPIO_ReadPin(GPIOB,DHT11_DA_Pin)&&retry<100){//等待变为低电平
        retry++;
        delay_us(1);
    }
    retry=0;
    while(!HAL_GPIO_ReadPin(GPIOB,DHT11_DA_Pin)&&retry<100){//等待变高电平
        retry++;
        delay_us(1);
    }
    delay_us(40);//等待40us //用于判断高低电平,即数据1或0
    if(HAL_GPIO_ReadPin(GPIOB,DHT11_DA_Pin))return 1; else return 0;
}
uint8_t Dht11_ReadByte(void){  //从DHT11读取一个字节  返回值:读到的数据
  uint8_t i,dat;
    dat=0;
    for (i=0;i<8;i++){
        dat<<=1;
        dat|=Dht11_ReadBit();
    }
    return dat;
}
uint8_t DHT11_Init (void){  //DHT11初始化
  DHT11_RST();//DHT11端口复位,发出起始信号
  return Dht11_Check(); //等待DHT11回应
}
uint8_t DHT11_ReadData(uint8_t *h){ //读取一次数据//湿度值(十进制,范围:20%~90%) ,温度值(十进制,范围:0~50°),返回值:0,正常;1,失败
  uint8_t buf[5];
  uint8_t i;
    DHT11_RST();//DHT11端口复位,发出起始信号
    if(Dht11_Check()==0){ //等待DHT11回应
        for(i=0;i<5;i++){//读取5位数据
            buf[i]=Dht11_ReadByte(); //读出数据
        }
        if((buf[0]+buf[1]+buf[2]+buf[3])==buf[4]){  //数据校验
            *h=buf[0]; //将湿度值放入指针1
      h++;
            *h=buf[2]; //将温度值放入指针2
        }
    }else return 1;
    return 0;
}
//===============================================us延时函数
void delay_us(uint32_t us)//主频72M
{
    uint32_t delay = (HAL_RCC_GetHCLKFreq() / 4000000 * us);
    while (delay--)
  {
    ;
  }
}
/*********************************************************************************************
 * 杜洋工作室 www.DoYoung.net
 * 洋桃电子 www.DoYoung.net/YT
*********************************************************************************************/
#ifndef __DHT11_H
#define __DHT11_H
#include "stm32f1xx_hal.h"
void DHT11_IO_OUT (void);
void DHT11_IO_IN (void);
void DHT11_RST (void);
uint8_t Dht11_Check(void);
uint8_t Dht11_ReadBit(void);
uint8_t Dht11_ReadByte(void);
uint8_t DHT11_Init (void);
uint8_t DHT11_ReadData(uint8_t *h);
void delay_us(uint32_t us);
#endif
相关文章
|
2月前
|
网络协议
【qt】TCP客户端信息的接受和发送
【qt】TCP客户端信息的接受和发送
31 0
|
2月前
|
网络协议
【qt】TCP客户端如何断开连接?
【qt】TCP客户端如何断开连接?
44 0
|
2月前
|
传感器
手把手在STM32F103C8T6上构建可扩展可移植的DHT11驱动
【8月更文挑战第29天】本文详细介绍在STM32F103C8T6上构建可扩展且可移植的DHT11温湿度传感器驱动的步骤,包括硬件与软件准备、硬件连接、驱动代码编写及测试。通过这些步骤,可根据实际项目需求优化和扩展代码。
|
2月前
【qt】客户端连接到服务器
【qt】客户端连接到服务器
47 0
|
2月前
|
网络协议
【qt】TCP服务端发消息给客户端
【qt】TCP服务端发消息给客户端
27 0
|
3月前
|
传感器 数据安全/隐私保护 数据格式
STM32CubeMX DHT11温湿度传感器
STM32CubeMX DHT11温湿度传感器
72 11
|
3月前
|
传感器 编解码 API
【STM32开发入门】温湿度监测系统实战:SPI LCD显示、HAL库应用、GPIO配置、UART中断接收、ADC采集与串口通信全解析
SPI(Serial Peripheral Interface)是一种同步串行通信接口,常用于微控制器与外围设备间的数据传输。SPI LCD是指使用SPI接口与微控制器通信的液晶显示屏。这类LCD通常具有较少的引脚(通常4个:MISO、MOSI、SCK和SS),因此在引脚资源有限的系统中非常有用。通过SPI协议,微控制器可以向LCD发送命令和数据,控制显示内容和模式。
105 0
|
5月前
|
网络协议 算法 网络性能优化
Qt TCP网络上位机的设计(通过网络编程与下位机结合)
Qt TCP网络上位机的设计(通过网络编程与下位机结合)
Qt TCP网络上位机的设计(通过网络编程与下位机结合)
|
4月前
|
传感器 数据格式
【STM32】DHT11温湿度模块传感器详解&代码
【STM32】DHT11温湿度模块传感器详解&代码
|
4月前
|
网络协议
了解AT指令以及STM32F103如何通过ESP8266连接到WiFi
AT指令是一组用于控制调制解调器的命令,最早由Hayes公司为其智能调制解调器开发。如今,AT指令已被广泛应用于各种通信模块中,包括GSM、Bluetooth和WiFi模块。AT指令通常以“AT”开头,后跟特定的命令和参数。通过这些指令,我们可以执行一系列操作,如设置网络参数、发送数据和查询状态等。
154 0