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