STM32+ESP8266+QT client host computer displays DHT11 temperature and humidity and lighting

Table of contents

1 Introduction

2. Hardware connection

3. Host computer source code

3.1 widget.h

3.2 widget.c 

3.3 Display graph

 4. The source code of the lower computer

4.1 cubemax configuration

 4.2 keil source code


1 Introduction

This article uses STM32F103C8T6 single-chip microcomputer to communicate with the host computer designed by QT through ESP8266WIFI module, and ESP8266 sets AP mode. Realize the display of the temperature and humidity of the DHT11 sensor and the remote control of the LED light on and off.

2. Hardware connection

PB9---DHT11(5V)

PA9----RX

PA10---TX

ESP8266(3.3V)

PB0----LED (active high)

3. Host computer source code

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 Display graph

 4. The source code of the lower computer

4.1 cubemax configuration

 GPIO configuration.

 Serial port configuration, interrupt enabled.

 4.2 Part of the source code of 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

 

 

Guess you like

Origin blog.csdn.net/weixin_44597885/article/details/130273370