单片机课程设计:基于STM32的温湿度检监测报警系统的设计
课程设计:STM32F103 + ESP8266 + DHT11简单实现温湿度检测报警以及WiFi数据传输(QvQ)
基于STM32的温湿度检监测报警系统
前言
温度是一项非常重要的参数,无论是农业还是工业都要对温度进行监测。目前大部分温度监测还在使用传统的温度计进行温度测星,这种测量方式即浪费人力和时间还不能对温度进行实时监测。如果采用远程监控设备对温度进行实时监测将会大大减少人工成本,还会降低由温度骤变造成的损失。
(文末附完整程序下载链接)
一、设计任务
1.可以通过温度传感器对环境温度进行采集,并用实时显示在LCD液晶屏上;
2.可以设定一个固定的报警温度值显示在液晶屏上;
3.环境温度超过报警温度后报警,报警形式包括:蜂鸣器声音响,LCD上显示的环境温度值显示红色;
4.能够通过按键动态修改报警温度阈值;
5.通过DS18B20数字温度传感器进行温度采集;
二、系统硬件设计
1.元器件选用
1、STM32f103VET6单片机一块
2、ESP8266一块
(此项目使用野火指南者,指南者自带ESP8266,其他型号单片机杜邦线自连即可)
3、DHT11温湿度监测模块
4、3.2寸LCD显示器(若无,传课输出部分信息,其他部分printf补全即可)
5、杜邦线3根
2.系统模型设计
按键1设置温度阈值,按键2设置湿度阈值,DHT11监测温度和湿度的值。当检测的温度大于温度阈值时LCD显示警告、蜂鸣器报警、红灯闪烁、串口输出警告;当检测的湿度大于湿度阈值时LCD显示温度超出警告、蜂鸣器报警、蓝灯闪烁、串口输出湿度超出警告。
3.硬件连接
1、本系统使用野火指南者,由于该单片机自带ESP8266,因此无需连接。如果使用其他型号单片机,根据ESP8266用户手册连接即可。
2、DHT11的VCC、GND连接单片机的+5V和GND,DHT11的DATA连接单片机PE6。
二、系统程序设计
1.程序流程
用户使用按键设置温度阈值和湿度阈值,系统采集当前环境温度和湿度。系统将当前环境温湿度与温湿度阈值比较,当检测的温度大于温度阈值时,LCD显示警告、蜂鸣器报警、红灯闪烁、串口输出警告;当检测的湿度大于湿度阈值时LCD显示温度超出警告、蜂鸣器报警、蓝灯闪烁、串口输出湿度超出警告。
2.主程序
main.c
#include "stm32f10x.h"
#include "stm32f10x_it.h"
#include "./lcd/bsp_ili9341_lcd.h"
#include "bsp_usart.h"
#include "bsp_SysTick.h"
#include "bsp_esp8266.h"
#include "bsp_esp8266_test.h"
#include "bsp_beep.h"
#include "bsp_dht11.h"
#include "bsp_led.h"
#include "key.h"
#include "./dwt_delay/core_delay.h"
#include "stm32f10x_exti.h"
extern uint16_t lcdid;
char set_t_char[10],set_p_char[10];
char get_t_char[10],get_p_char[10];
u8 set_t=31,set_p=45; //温湿度阈值设置
int get_t,get_p;
void LCD_show(void);
void ESP8266_SendDHT11DataTest(void);
DHT11_Data_TypeDef DHT11_Data;
int main()
{
/* 初始化 */
USART_Config (); //初始化串口1
CPU_TS_TmrInit(); //初始化DWT计数器,用于延时函数
LED_Init(); //初始化RGB彩灯
EXTI_Key_Config(); //KEY中断初始化
BEEP_GPIO_Config();
ESP8266_Init(); //初始化WiFi模块使用的接口和外设
DHT11_Init(); //初始化DHT11
ILI9341_Init(); //LCD 初始化
SysTick_Init();
ILI9341_GramScan(6); //配置 SysTick 为 10ms 中断一次,在中断里读取传感器数据
ESP8266_StaTcpClient_Unvarnish_ConfigTest(); //对ESP8266进行配置
LCD_SetFont(&Font8x16);
LCD_SetColors(WHITE,BLACK);
ILI9341_Clear(0,0,LCD_X_LENGTH,LCD_Y_LENGTH); /* 清屏,显示全黑 */
LCD_show();
while (1)
{
if( read_dht11_finish ) // read_dht11_finish == 1 or read_dht11_finish == -1
{
ESP8266_SendDHT11DataTest(); // ESP8266 发送一次温湿度数据
read_dht11_finish = 0; // 清零标志位
}
}
}
void ESP8266_SendDHT11DataTest(void)
{
char cStr[100]={0};
char aaa[100];
uint8_t ucStatus;
if( 1 == read_dht11_finish ){
sprintf ( cStr, "\r\n\r\n读取DHT11成功!\r\n湿度为:%d.%d %RH ,温度为:%d.%d℃ \r\n",
DHT11_Data.humi_int, DHT11_Data.humi_deci, DHT11_Data.temp_int, DHT11_Data.temp_deci );
get_t = DHT11_Data.temp_int;
get_p = DHT11_Data.humi_int;
/* 显示温度 */
if(get_t <= set_t){ //当前温度一栏显示绿色
LCD_ClearLine(LINE(16));
LCD_SetTextColor(GREEN);
sprintf(aaa," 当前温度: %d.%d℃",DHT11_Data.temp_int, DHT11_Data.temp_deci);
LCD_ClearLine(LINE(9)); /* 清除单行文字 */
ILI9341_DispStringLine_EN_CH(LINE(9),aaa);
PBout(5)=1;
BEEP( OFF ); //灯灭、蜂鸣器关
} else{ //当前温度超过阈值时颜色变红
LCD_SetTextColor(RED);
sprintf(aaa," 当前温度: %d.%d℃",DHT11_Data.temp_int, DHT11_Data.temp_deci);
LCD_ClearLine(LINE(9)); /* 清除单行文字 */
ILI9341_DispStringLine_EN_CH(LINE(9),aaa);
ILI9341_DispStringLine_EN_CH(LINE(16)," !!!WARRING !!! ");
printf("!!!温度超出阈值!!!"); //串口输出
PBout(5)=0;
BEEP( ON ); //灯亮、蜂鸣器开
}
/* 显示湿度 */
if(get_p <= set_p){ //当前湿度一栏显示绿色
LCD_ClearLine(LINE(17));
LCD_SetTextColor(GREEN);
sprintf(aaa," 当前湿度:%d.%d%%",DHT11_Data.humi_int, DHT11_Data.humi_deci);
LCD_ClearLine(LINE(10)); /* 清除单行文字 */
ILI9341_DispStringLine_EN_CH(LINE(10),aaa);
PBout(1)=1;
BEEP( OFF ); //灯灭、蜂鸣器关
} else{ //当前湿度超过阈值时颜色变蓝
LCD_SetTextColor(BLUE);
sprintf(aaa," 当前湿度:%d.%d%%",DHT11_Data.humi_int, DHT11_Data.humi_deci);
LCD_ClearLine(LINE(10)); /* 清除单行文字 */
ILI9341_DispStringLine_EN_CH(LINE(10),aaa);
ILI9341_DispStringLine_EN_CH(LINE(17)," !!!WARRING !!! ");
printf("!!!湿度超出阈值!!!"); //串口输出
PBout(1)=0;
BEEP( ON ); //灯亮、蜂鸣器开
}
}
else
sprintf ( cStr, "Read DHT11 ERROR!\r\n" );
printf ( "%s", cStr ); //打印读取 DHT11 温湿度信息
ESP8266_SendString ( ENABLE, cStr, 0, Single_ID_0 ); //发送 DHT11 温湿度信息到网络调试助手
if ( ucTcpClosedFlag ) //检测是否失去连接
{
ESP8266_ExitUnvarnishSend (); //退出透传模式
do ucStatus = ESP8266_Get_LinkStatus (); //获取连接状态
while ( ! ucStatus );
if ( ucStatus == 4 ) //确认失去连接后重连
{
printf ( "\r\n正在重连热点和服务器 ......\r\n" );
while ( ! ESP8266_JoinAP ( macUser_ESP8266_ApSsid, macUser_ESP8266_ApPwd ) );
while ( ! ESP8266_Link_Server ( enumTCP, macUser_ESP8266_TcpServer_IP, macUser_ESP8266_TcpServer_Port, Single_ID_0 ) );
printf ( "\r\n重连热点和服务器成功\r\n" );
}
while ( ! ESP8266_UnvarnishSend () );
}
}
//按键1中断 按键1调节温度阈值
void KEY1_IRQHandler(void)
{
if(EXTI_GetITStatus(KEY1_INT_EXTI_LINE) != RESET) //确保是否产生了EXTI Line中断
{
set_t++;
if(set_t >= 36){
set_t = 15;
}
LCD_ClearLine(LINE(6)); //温度阈值数据随按键发生改变 第6行
LCD_SetTextColor(GREEN); //设置绿色
sprintf(set_t_char," 温度阈值:%d℃ ",set_t);
LCD_ClearLine(LINE(6));
ILI9341_DispStringLine_EN_CH(LINE(6),set_t_char);
//清除中断标志位
EXTI_ClearITPendingBit(KEY1_INT_EXTI_LINE);
}
}
//按键2中断
void KEY2_IRQHandler(void)
{
if(EXTI_GetITStatus(KEY2_INT_EXTI_LINE) != RESET) //确保是否产生了EXTI Line中断
{
set_p++;
if(set_p >= 45){
set_p = 20;
}
LCD_ClearLine(LINE(7));
LCD_SetTextColor(GREEN);
sprintf(set_p_char," 湿度阈值:%dRH ",set_p);
LCD_ClearLine(LINE(7));
ILI9341_DispStringLine_EN_CH(LINE(7),set_p_char);
//清除中断标志位
EXTI_ClearITPendingBit(KEY2_INT_EXTI_LINE);
}
}
void LCD_show(void)
{
ILI9341_DispStringLine_EN_CH(LINE(3)," GPRS监测报警系统 ");
LCD_SetTextColor(GREEN);
sprintf(set_t_char," 温度阈值:%d℃ ",set_t);
LCD_ClearLine(LINE(6));
ILI9341_DispStringLine_EN_CH(LINE(6),set_t_char);
LCD_SetTextColor(GREEN);
sprintf(set_p_char," 湿度阈值:%dRH ",set_p);
LCD_ClearLine(LINE(7));
ILI9341_DispStringLine_EN_CH(LINE(7),set_p_char);
LCD_SetTextColor(GREEN);
sprintf(get_t_char," 当前温度:%d℃ ",get_t);
LCD_ClearLine(LINE(9));
ILI9341_DispStringLine_EN_CH(LINE(9),get_t_char);
LCD_SetTextColor(GREEN);
sprintf(get_p_char," 当前湿度:%dRH ",get_p);
LCD_ClearLine(LINE(10));
ILI9341_DispStringLine_EN_CH(LINE(10),get_p_char);
LCD_ClearLine(LINE(13));
}
esp8266_test.c
#include "bsp_esp8266_test.h"
#include "bsp_esp8266.h"
#include "./dwt_delay/core_delay.h"
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include "bsp_dht11.h"
#include "bsp_led.h"
#include "bsp_usart.h"
#include "./lcd/bsp_ili9341_lcd.h"
#include "bsp_SysTick.h"
#include "stm32f10x.h"
#define LED_CMD_NUMBER 8
char *ledCmd[8] = { "LED_RED","LED_GREEN","LED_BLUE","LED_YELLOW","LED_PURPLE","LED_CYAN","LED_WHITE","LED_RGBOFF" };
volatile uint8_t ucTcpClosedFlag = 0;
void ESP8266_StaTcpClient_Unvarnish_ConfigTest(void)
{
LCD_SetFont(&Font8x16);
LCD_SetColors(WHITE,BLACK);
printf( "\r\n正在配置 ESP8266 ......\r\n" );
printf( "\r\n使能 ESP8266 ......\r\n" );
ILI9341_Clear(0,0,LCD_X_LENGTH,LCD_Y_LENGTH); /* 清屏,显示全黑 */
ILI9341_DispStringLine_EN_CH(LINE(1),"正在配置 ESP8266 ......");
ILI9341_DispStringLine_EN_CH(LINE(2),"使能 ESP8266 ......");
macESP8266_CH_ENABLE();
while( ! ESP8266_AT_Test() );
while( ! ESP8266_DHCP_CUR () );
printf( "\r\n正在配置工作模式 STA ......\r\n" );
while( ! ESP8266_Net_Mode_Choose ( STA ) );
printf( "\r\n正在连接 WiFi ......\r\n" );
ILI9341_DispStringLine_EN_CH(LINE(8),"正在连接WiFi...... ");
while( ! ESP8266_JoinAP ( macUser_ESP8266_ApSsid, macUser_ESP8266_ApPwd ) );
ILI9341_DispStringLine_EN_CH(LINE(9),"WiFi 连接...... 成功");
printf( "\r\n禁止多连接 ......\r\n" );
while( ! ESP8266_Enable_MultipleId ( DISABLE ) );
ILI9341_DispStringLine_EN_CH(LINE(10),"多连接禁止 ...... 成功");
printf( "\r\n正在连接 Server ......\r\n" );
ILI9341_DispStringLine_EN_CH(LINE(11),"正在连接Server ...... ");
while( ! ESP8266_Link_Server ( enumTCP, macUser_ESP8266_TcpServer_IP, macUser_ESP8266_TcpServer_Port, Single_ID_0 ) );
ILI9341_DispStringLine_EN_CH(LINE(12),"Server 连接...... 成功");
printf( "\r\n进入透传发送模式 ......\r\n" );
while( ! ESP8266_UnvarnishSend () );
ILI9341_DispStringLine_EN_CH(LINE(13),"进入透传发送模式");
printf( "\r\n配置 ESP8266 完毕\r\n" );
ILI9341_DispStringLine_EN_CH(LINE(14),"配置 ESP8266 完毕");
ILI9341_DispStringLine_EN_CH(LINE(15),"读取DHT11成功!");
}
3.配置
led.c + led.h
led.c:
#include "bsp_led.h"
#include "stm32f10x.h"
#include "stm32f10x_it.h"
#include "bsp_SysTick.h"
void LED_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;//定义结构体变量
RCC_APB2PeriphClockCmd(LED1_PORT_RCC|LED2_PORT_RCC|LED3_PORT_RCC,ENABLE);
GPIO_InitStructure.GPIO_Pin=LED1_PIN; //选择你要设置的IO口
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP; //设置推挽输出模式
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; //设置传输速率
GPIO_Init(LED1_PORT,&GPIO_InitStructure); /* 初始化GPIO */
GPIO_SetBits(LED1_PORT,LED1_PIN); //将LED端口拉高,熄灭所有LED
GPIO_InitStructure.GPIO_Pin=LED2_PIN; //选择你要设置的IO口
GPIO_Init(LED2_PORT,&GPIO_InitStructure); /* 初始化GPIO */
GPIO_SetBits(LED2_PORT,LED2_PIN); //将LED端口拉高,熄灭所有LED
GPIO_InitStructure.GPIO_Pin=LED3_PIN; //选择你要设置的IO口
GPIO_Init(LED3_PORT,&GPIO_InitStructure); /* 初始化GPIO */
GPIO_SetBits(LED3_PORT,LED3_PIN); //将LED端口拉高,熄灭所有LED
}
led.h
#ifndef _gpio_H
#define _gpio_H
#include "system.h"
#include "stm32f10x.h"
#include "stm32f10x_it.h"
#include "bsp_SysTick.h"
//led
/* LED时钟端口、引脚定义 */
#define LED1_PORT GPIOB
#define LED1_PIN GPIO_Pin_5
#define LED1_PORT_RCC RCC_APB2Periph_GPIOB
#define LED2_PORT GPIOA
#define LED2_PIN GPIO_Pin_0
#define LED2_PORT_RCC RCC_APB2Periph_GPIOB
#define LED3_PORT GPIOB
#define LED3_PIN GPIO_Pin_1
#define LED3_PORT_RCC RCC_APB2Periph_GPIOB
void LED_Init(void);
void delays(uint32_t time);
void TIM3_Int_Init(u16 arr,u16 psc);
#endif
beep.c + beep.h
beep.c:
#include "bsp_beep.h"
void BEEP_GPIO_Config(void)
{
/*定义一个GPIO_InitTypeDef类型的结构体*/
GPIO_InitTypeDef GPIO_InitStructure;
/*开启控制蜂鸣器的GPIO的端口时钟*/
RCC_APB2PeriphClockCmd( BEEP_GPIO_CLK, ENABLE);
/*选择要控制蜂鸣器的GPIO*/
GPIO_InitStructure.GPIO_Pin = BEEP_GPIO_PIN;
/*设置GPIO模式为通用推挽输出*/
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
/*设置GPIO速率为50MHz */
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
/*调用库函数,初始化控制蜂鸣器的GPIO*/
GPIO_Init(BEEP_GPIO_PORT, &GPIO_InitStructure);
/* 关闭蜂鸣器*/
GPIO_ResetBits(BEEP_GPIO_PORT, BEEP_GPIO_PIN);
}
beep.h:
#ifndef __BEEP_H
#define __BEEP_H
#include "stm32f10x.h"
/* 定义蜂鸣器连接的GPIO端口, 用户只需要修改下面的代码即可改变控制的蜂鸣器引脚 */
#define BEEP_GPIO_PORT GPIOA /* GPIO端口 */
#define BEEP_GPIO_CLK RCC_APB2Periph_GPIOA /* GPIO端口时钟 */
#define BEEP_GPIO_PIN GPIO_Pin_8 /* 连接到蜂鸣器的GPIO */
/* 高电平时,蜂鸣器响 */
#define ON 1
#define OFF 0
/* 带参宏,可以像内联函数一样使用 */
#define BEEP(a) if (a) \
GPIO_SetBits(BEEP_GPIO_PORT,BEEP_GPIO_PIN);\
else \
GPIO_ResetBits(BEEP_GPIO_PORT,BEEP_GPIO_PIN)
void BEEP_GPIO_Config(void);
#endif /* __BEEP_H */
按键中断配置
key.c:
#include "key.h"
#include "stm32f10x_exti.h"
static void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
/* 配置NVIC为优先级组1 */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
/* 配置中断源:按键1 */
NVIC_InitStructure.NVIC_IRQChannel = KEY1_INT_EXTI_IRQ;
/* 配置抢占优先级 */
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
/* 配置子优先级 */
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
/* 使能中断通道 */
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
/* 配置中断源:按键2,其他使用上面相关配置 */
NVIC_InitStructure.NVIC_IRQChannel = KEY2_INT_EXTI_IRQ;
NVIC_Init(&NVIC_InitStructure);
}
void EXTI_Key_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
EXTI_InitTypeDef EXTI_InitStructure;
/*开启按键GPIO口的时钟*/
RCC_APB2PeriphClockCmd(KEY1_INT_GPIO_CLK,ENABLE);
RCC_APB2PeriphClockCmd(KEY2_INT_GPIO_CLK,ENABLE);
/* 配置 NVIC 中断*/
NVIC_Configuration();
/*--------------------------KEY1配置-----------------------------*/
/* 选择按键用到的GPIO */
GPIO_InitStructure.GPIO_Pin = KEY1_INT_GPIO_PIN; // 按键1 PA0
/* 配置为浮空输入 */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(KEY1_INT_GPIO_PORT, &GPIO_InitStructure);
/* 选择EXTI的信号源 */
GPIO_EXTILineConfig(KEY1_INT_EXTI_PORTSOURCE, KEY1_INT_EXTI_PINSOURCE);
EXTI_InitStructure.EXTI_Line = KEY1_INT_EXTI_LINE;
/* EXTI为中断模式 */
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
/* 上升沿中断 */
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; //按键按下开启中断
/* 使能中断 */
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
/*--------------------------KEY2配置-----------------------------*/
/* 选择按键用到的GPIO */
GPIO_InitStructure.GPIO_Pin = KEY2_INT_GPIO_PIN; //按键2 PC13
/* 配置为浮空输入 */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(KEY2_INT_GPIO_PORT, &GPIO_InitStructure);
/* 选择EXTI的信号源 */
GPIO_EXTILineConfig(KEY2_INT_EXTI_PORTSOURCE, KEY2_INT_EXTI_PINSOURCE);
EXTI_InitStructure.EXTI_Line = KEY2_INT_EXTI_LINE;
/* EXTI为中断模式 */
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
/* 下降沿中断 */
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
/* 使能中断 */
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
}
key.h:
#ifndef __EXTI_H
#define __EXTI_H
#include "stm32f10x.h"
//引脚定义
#define KEY1_INT_GPIO_PORT GPIOA //按键1 PA0
#define KEY1_INT_GPIO_CLK (RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO)
#define KEY1_INT_GPIO_PIN GPIO_Pin_0
#define KEY1_INT_EXTI_PORTSOURCE GPIO_PortSourceGPIOA
#define KEY1_INT_EXTI_PINSOURCE GPIO_PinSource0
#define KEY1_INT_EXTI_LINE EXTI_Line0
#define KEY1_INT_EXTI_IRQ EXTI0_IRQn
#define KEY1_IRQHandler EXTI0_IRQHandler
#define KEY2_INT_GPIO_PORT GPIOC //按键2 PC13
#define KEY2_INT_GPIO_CLK (RCC_APB2Periph_GPIOC|RCC_APB2Periph_AFIO)
#define KEY2_INT_GPIO_PIN GPIO_Pin_13
#define KEY2_INT_EXTI_PORTSOURCE GPIO_PortSourceGPIOC
#define KEY2_INT_EXTI_PINSOURCE GPIO_PinSource13
#define KEY2_INT_EXTI_LINE EXTI_Line13
#define KEY2_INT_EXTI_IRQ EXTI15_10_IRQn
#define KEY2_IRQHandler EXTI15_10_IRQHandler
#define KEY_ON 1
#define KEY_OFF 0
void EXTI_Key_Config(void);
uint8_t Key_Scan(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin);
#endif /* __EXTI_H */
dht11.c + dht11.h
dht11.c:
#include "bsp_dht11.h"
#include "./dwt_delay/core_delay.h"
static void DHT11_GPIO_Config( void );
static void DHT11_Mode_IPU( void );
static void DHT11_Mode_Out_PP( void );
static uint8_t DHT11_ReadByte( void );
void DHT11_Init ( void )
{
DHT11_GPIO_Config ();
macDHT11_Dout_1; // 拉高GPIOB10
}
/*
* 函数名:DHT11_GPIO_Config
* 描述 :配置DHT11用到的I/O口
* 输入 :无
* 输出 :无
*/
static void DHT11_GPIO_Config ( void )
{
/*定义一个GPIO_InitTypeDef类型的结构体*/
GPIO_InitTypeDef GPIO_InitStructure;
/*开启macDHT11_Dout_GPIO_PORT的外设时钟*/
macDHT11_Dout_SCK_APBxClock_FUN ( macDHT11_Dout_GPIO_CLK, ENABLE );
/*选择要控制的macDHT11_Dout_GPIO_PORT引脚*/
GPIO_InitStructure.GPIO_Pin = macDHT11_Dout_GPIO_PIN;
/*设置引脚模式为通用推挽输出*/
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
/*设置引脚速率为50MHz */
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
/*调用库函数,初始化macDHT11_Dout_GPIO_PORT*/
GPIO_Init ( macDHT11_Dout_GPIO_PORT, &GPIO_InitStructure );
}
/*
* 函数名:DHT11_Mode_IPU
* 描述 :使DHT11-DATA引脚变为上拉输入模式
* 输入 :无
* 输出 :无
*/
static void DHT11_Mode_IPU(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/*选择要控制的macDHT11_Dout_GPIO_PORT引脚*/
GPIO_InitStructure.GPIO_Pin = macDHT11_Dout_GPIO_PIN;
/*设置引脚模式为浮空输入模式*/
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU ;
/*调用库函数,初始化macDHT11_Dout_GPIO_PORT*/
GPIO_Init(macDHT11_Dout_GPIO_PORT, &GPIO_InitStructure);
}
/*
* 函数名:DHT11_Mode_Out_PP
* 描述 :使DHT11-DATA引脚变为推挽输出模式
* 输入 :无
* 输出 :无
*/
static void DHT11_Mode_Out_PP(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/*选择要控制的macDHT11_Dout_GPIO_PORT引脚*/
GPIO_InitStructure.GPIO_Pin = macDHT11_Dout_GPIO_PIN;
/*设置引脚模式为通用推挽输出*/
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
/*设置引脚速率为50MHz */
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
/*调用库函数,初始化macDHT11_Dout_GPIO_PORT*/
GPIO_Init(macDHT11_Dout_GPIO_PORT, &GPIO_InitStructure);
}
/*
* 从DHT11读取一个字节,MSB先行
*/
static uint8_t DHT11_ReadByte ( void )
{
uint8_t i, temp=0;
for(i=0;i<8;i++)
{
/*每bit以50us低电平标置开始,轮询直到从机发出 的50us 低电平 结束*/
while(macDHT11_Dout_IN()==Bit_RESET);
/*DHT11 以26~28us的高电平表示“0”,以70us高电平表示“1”,
*通过检测 x us后的电平即可区别这两个状 ,x 即下面的延时
*/
Delay_us(40); //延时x us 这个延时需要大于数据0持续的时间即可
if(macDHT11_Dout_IN()==Bit_SET)/* x us后仍为高电平表示数据“1” */
{
/* 等待数据1的高电平结束 */
while(macDHT11_Dout_IN()==Bit_SET);
temp|=(uint8_t)(0x01<<(7-i)); //把第7-i位置1,MSB先行
}
else // x us后为低电平表示数据“0”
{
temp&=(uint8_t)~(0x01<<(7-i)); //把第7-i位置0,MSB先行
}
}
return temp;
}
/*
* 一次完整的数据传输为40bit,高位先出
* 8bit 湿度整数 + 8bit 湿度小数 + 8bit 温度整数 + 8bit 温度小数 + 8bit 校验和
*/
uint8_t DHT11_Read_TempAndHumidity(DHT11_Data_TypeDef *DHT11_Data)
{
/*输出模式*/
DHT11_Mode_Out_PP();
/*主机拉低*/
macDHT11_Dout_0;
/*延时18ms*/
Delay_ms(18);
/*总线拉高 主机延时30us*/
macDHT11_Dout_1;
Delay_us(30); //延时30us
/*主机设为输入 判断从机响应信号*/
DHT11_Mode_IPU();
/*判断从机是否有低电平响应信号 如不响应则跳出,响应则向下运行*/
if(macDHT11_Dout_IN()==Bit_RESET)
{
/*轮询直到从机发出 的80us 低电平 响应信号结束*/
while(macDHT11_Dout_IN()==Bit_RESET);
/*轮询直到从机发出的 80us 高电平 标置信号结束*/
while(macDHT11_Dout_IN()==Bit_SET);
/*开始接收数据*/
DHT11_Data->humi_int= DHT11_ReadByte();
DHT11_Data->humi_deci= DHT11_ReadByte();
DHT11_Data->temp_int= DHT11_ReadByte();
DHT11_Data->temp_deci= DHT11_ReadByte();
DHT11_Data->check_sum= DHT11_ReadByte();
/*读取结束,引脚改为输出模式*/
DHT11_Mode_Out_PP();
/*主机拉高*/
macDHT11_Dout_1;
/*检查读取的数据是否正确*/
if(DHT11_Data->check_sum == DHT11_Data->humi_int + DHT11_Data->humi_deci + DHT11_Data->temp_int+ DHT11_Data->temp_deci)
return SUCCESS;
else
return ERROR;
}
else
return ERROR;
}
dht11.h:
#ifndef __DHT11_H
#define __DHT11_H
#include "stm32f10x.h"
typedef struct
{
uint8_t humi_int; //湿度的整数部分
uint8_t humi_deci; //湿度的小数部分
uint8_t temp_int; //温度的整数部分
uint8_t temp_deci; //温度的小数部分
uint8_t check_sum; //校验和
} DHT11_Data_TypeDef;
#define macDHT11_Dout_SCK_APBxClock_FUN RCC_APB2PeriphClockCmd
#define macDHT11_Dout_GPIO_CLK RCC_APB2Periph_GPIOE
#define macDHT11_Dout_GPIO_PORT GPIOE
#define macDHT11_Dout_GPIO_PIN GPIO_Pin_6
/************************** DHT11 函数宏定义********************************/
#define macDHT11_Dout_0 GPIO_ResetBits ( macDHT11_Dout_GPIO_PORT, macDHT11_Dout_GPIO_PIN )
#define macDHT11_Dout_1 GPIO_SetBits ( macDHT11_Dout_GPIO_PORT, macDHT11_Dout_GPIO_PIN )
#define macDHT11_Dout_IN() GPIO_ReadInputDataBit ( macDHT11_Dout_GPIO_PORT, macDHT11_Dout_GPIO_PIN )
/************************** DHT11 函数声明 ********************************/
void DHT11_Init ( void );
uint8_t DHT11_Read_TempAndHumidity ( DHT11_Data_TypeDef * DHT11_Data );
;
#endif /* __DHT11_H */
总结
基于ESP8266的温湿度检监测报警系统是一个适合初学者的STM32设计,本系统设计包含了GPIO的配置、ESP8266的配置与使用、传感器DHT11的使用、按键中断、串口发送信息、LCD显示等的使用。本系统主要部分即温湿度采集和WiFi数据传输,比较适合初学者学习理论知识后对知识的总结和融会贯通。
LCD的应用对于本系统是非必要的,一般来讲串口输出调试信息即可作为程序反馈,但谁又能拒绝一块看起来科技感十足的显示器呢(QVQ)。对于初学者来说如果想要走物联网这条线,本系统难度适中可以作为一个的炼手的例程,当然作为课程设计也是蛮不错的选择。
下载
更多推荐
所有评论(0)