目录
1、简介
2、硬件连接
3、上位机源码
3.1 widget.h
3.2 widget.c
3.3 显示图
4、下位机源码
4.1 cubemax配置
4.2 keil源码
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