A51 - 基于STM32的DHT11和LCD显示串口通信仿真

任务

  1. 完成STM32F103R6在Proteus上仿真运行
  2. 使用LCD屏幕作为显示,编写驱动
  3. 驱动DHT11,用于采集模拟温湿度
  4. 驱动串口1,用于进行串口通信
  5. 按键可设置阈值
  6. 超出阈值报警

效果

在这里插入图片描述
在这里插入图片描述特别注意:

  • 一般外部晶振不太好用。使用内部的HSI晶振,当前项目频率设置为40MHz。

  • 本工程使用的是Protesu8.9SP2版本。

源代码

/*******************************************************************************

\* 文件名称:基于STM32的DHT11和LCD显示串口通信仿真

\* 实验目的:1.

\* 2.

\* 程序说明:完整程序Q:2772272579;@: itworkstation@ hotmail.com

\* 日期版本:本项目分享关键细节,熟悉使用单片机的可做参考代码。完整讲解+源代码工程可联系获取,可定制。

*******************************************************************************/
#include "main.h"
#include "delay.h"
#include "USART1.h"
#include "gui.h"
#include "lcd.h"
#include "dht11.h"
#include "BEEP.h"
#include "key.h" 

void Proc_Key(void);
u8 LCD_SetNow=0;
u8 TH=30,TL=20;
u8 HH=80,HL=60;
void LCD_SHOW(void);


char buff[128];

int main(void)
{
    
        
	u8 T,H;
	u16 readTime = 0;
	
	BEEP_Init();
	BEEP_Tips(1);
	
	Key_Init();
	
	USART1_Config();
	printf("Made By ****\r\n");
	LCD_Init();
	DHT11_InAndOutConfig();
	Show_Str(10,200,RED,0,(u8 *)"************ M3课程设计\r\n",16,1);//字体颜色为RED  //非叠加方式
			
	POINT_COLOR = GREEN;
	BACK_COLOR = BLUE;
	
	LCD_SHOW();
	while(1)
	{
    
    
		if(readTime>500)
		{
    
    
			readTime = 0;
			DHT11_ReadTAndH(&T,&H);
			printf("%d,%d\r\n",T,H);
			
			sprintf(buff,"T:%d,H:%d",T,H);
			LCD_ShowString(20,50,16,(u8 *)buff,0); 
			
			if((T>TH || T <TL)||(H > HH || H < HL))
			{
    
    
				BEEP_Control(ON);
			}
			else
			{
    
    
				BEEP_Control(OFF);
			}
		}
			
		Proc_Key();
		
		
		readTime++;
		Delay_nms(1);		
	}
}

/*
功能要求:
首先在串口上显示当前的温湿度数值,在屏幕上也显示小组成员信息以及温湿度数值,
设置温度和湿度的报警值,如果当前的温度或者湿度超过报警值,则蜂鸣器响,如果没
有超过报警值则蜂鸣器不响,按下按键的话LED灯亮或者灭交替执行。

*/

void Proc_Key2Add(void);
void Proc_Key3Dec(void);

void Proc_Key(void)
{
    
    
	u8 keyValue = 0xff;
	keyValue = Key_Scan();
	if(keyValue != 0xff)
	{
    
    		
		switch(keyValue)
		{
    
    
			case 1:
				LCD_SetNow++;
				if(LCD_SetNow > 4)
				{
    
    
					LCD_SetNow = 0;				
				}						
				break;
			case 2:
				Proc_Key2Add();
				break;
			case 3:
				Proc_Key3Dec();
				break;
			default:break;
		}		
		LCD_SHOW();
		GPIO_SetBits(GPIOC,GPIO_Pin_7); //LED指示灯,按键松开
	}
}
void LCD_SHOW(void)
{
    
    
	u16 POINT_COLOR_LAST = 0x0000,BACK_COLOR_LAST = 0xFFFF;  
	
	POINT_COLOR_LAST = POINT_COLOR;
	BACK_COLOR_LAST = BACK_COLOR;
	
	POINT_COLOR = YELLOW;
	BACK_COLOR = BLUE;
	switch(LCD_SetNow)
	{
    
    
		case 0:
			sprintf(buff," TH:%d    TL:%d",TH%100,TL%100);
			LCD_ShowString(20,100,16,(u8 *)buff,0); 
			sprintf(buff," HH:%d    HL:%d",HH%100,HL%100);
			LCD_ShowString(20,120,16,(u8 *)buff,0); 
			break;
		case 1:
//				sprintf(buff,"~TH:30    TL:10",TH,TL);
			sprintf(buff,"~TH:%d    TL:%d",TH%100,TL%100);
			LCD_ShowString(20,100,16,(u8 *)buff,0); 
			sprintf(buff," HH:%d    HL:%d",HH%100,HL%100);
			LCD_ShowString(20,120,16,(u8 *)buff,0); 
			break;
		case 2:
			sprintf(buff," TH:%d   ~TL:%d",TH%100,TL%100);
			LCD_ShowString(20,100,16,(u8 *)buff,0); 
			sprintf(buff," HH:%d    HL:%d",HH%100,HL%100);
			LCD_ShowString(20,120,16,(u8 *)buff,0); 
			break;
		case 3:
			sprintf(buff," TH:%d    TL:%d",TH%100,TL%100);
			LCD_ShowString(20,100,16,(u8 *)buff,0); 
			sprintf(buff,"~HH:%d    HL:%d",HH%100,HL%100);
			LCD_ShowString(20,120,16,(u8 *)buff,0); 
			break;
		case 4:
			sprintf(buff," TH:%d    TL:%d",TH%100,TL%100);
			LCD_ShowString(20,100,16,(u8 *)buff,0); 
			sprintf(buff," HH:%d   ~HL:%d",HH%100,HL%100);
			LCD_ShowString(20,120,16,(u8 *)buff,0); 
			break;
		default:break;
	}
	POINT_COLOR = POINT_COLOR_LAST;
	BACK_COLOR = BACK_COLOR_LAST;
}
void Proc_Key2Add(void)
{
    
    
	switch(LCD_SetNow)
	{
    
    
		case 0:
			
			break;
		case 1:
			TH++;
			if(TH>99)
				TH = 99;
			break;
		case 2:
			TL++;
			if(TL>=TH)
				TL = TH-2;
			break;
		case 3:
			HH++;
			if(HH>99)
				HH = 99;
			break;
		case 4:
			HL++;
			if(HL>=HH)
				HL = HH-2;
			break;
		default:break;
	}
}
void Proc_Key3Dec(void)
{
    
    
	switch(LCD_SetNow)
	{
    
    
		case 0:
			
			break;
		case 1:
			TH--;
			if(TH<=TL)
				TH = TL+2;
			break;
		case 2:
			TL--;
			if(TL<1)
				TL = 1;
			break;
		case 3:
			HH--;
			if(HH<=HL)
				HH = HL+2;
			break;
		case 4:
			HL--;
			if(HL<1)
				HL = 1;
			break;
		default:break;
	}
}




DHT11模块驱动

#ifndef _DHT11_H_
#define _DHT11_H_

#include "stm32f10x.h"
#define DHT11_HL(x) x?(GPIOA->ODR |= (1<<11)):(GPIOA->ODR &= ~(1<<11))
#define DHT11_RD()  (GPIOA->IDR & (1<<11))


void DHT11_InAndOutConfig(void);
u8 DHT11_ReadTAndH(u8 *t,u8 *h);



#endif


 #include "dht11.h"
#include "delay.h"
#include "stdio.h"

/*
函数名:DHT11_InAndOutConfig
函数功能:DHT11管脚配置为输入/输出功能  --PA11
函数参数:flag 0 -- 输入   1 -- 输出
函数返回值:无
*/
void DHT11_InAndOutConfig(void)
{
    
    
	//打开A端口时钟 -- PA11
	RCC->APB2ENR |= (1<<2);
	GPIOA->CRH &= ~(0xf<<11);
	GPIOA->CRH |= (0x3<<11);//推挽输出
}
/*
函数名:DHT11_ReadTAndH
函数功能:DHT11读取温度和湿度值
函数参数:t -- 保存温度值   h -- 湿度值
函数返回值:0 -- 不成功   1 -- 成功
*/
u8 DHT11_ReadTAndH(u8 *t,u8 *h)
{
    
    
	u8 rxbuffer[5];//保存40位数据
	u8 i,j;
	u32 errortime=0;
	//1.MCU发送开始信号
	//1.1 配置为输出模式
	GPIOA->CRH &= ~(0xf<<11);
	GPIOA->CRH |= (0x3<<11);
	//1.2 输出18ms的低电平
	DHT11_HL(0);
	Delay_nms(18);
	//1.3 输出高电平(20~40us)
	DHT11_HL(1);
	Delay_us(20);
	//2.DHT11返回应答信号
	//配置为输入模式
	GPIOA->CRH &= ~(0xf<<11);
	GPIOA->CRH |= (0x4<<11);
	while(DHT11_RD())//等待应答信号,低电平到来
	{
    
    
		if(errortime++>0xfffff)  // 2^40 -1
			return 0;
	}
	errortime = 0;
	while(DHT11_RD() == 0)//等待应答信号,高电平到来
	{
    
    
		if(errortime++>0xfffff)
			return 0;
	}
	errortime = 0;
//3.DHT11发送40位数据
	for(i=0;i<5;i++)
	{
    
    
		for(j=0;j<8;j++)
		{
    
    
			while(DHT11_RD())        //等待数据到来(低电平)
			{
    
    
				if(errortime++>0xfffff)
					return 0;
			}
			errortime = 0;
			while(DHT11_RD() == 0)//等待数据到来(高电平)
			{
    
    
				if(errortime++>0xfffff)
					return 0;
			}
			errortime = 0;
			Delay_us(30);
			rxbuffer[i]<<=1;     
			if(DHT11_RD())
				rxbuffer[i]++;  
		}
	}
//4.校验和
	if(rxbuffer[4] == (rxbuffer[0]+rxbuffer[1]+rxbuffer[2]+rxbuffer[3]))
	{
    
    
		*t = rxbuffer[2];
		*h = rxbuffer[0];
		return 1;
	}
	else
		return 0;
}

串口驱动

#ifndef _USART1_H_
#define _USART1_H_

#include "stm32f10x.h"
#include "stdio.h"

void USART1_Config(void);
void USART1_Echo(void);

#endif

#include "USART1.h"

//USART1	Tx:PA9		Rx:PA10
void USART1_Config(void)
{
    
    
	//时钟使能
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_USART1, ENABLE);
	
	//GPIO
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStructure);
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
	GPIO_Init(GPIOA,&GPIO_InitStructure);
	
	//USART1
	USART_InitTypeDef USART1_InitStructure;
	USART1_InitStructure.USART_BaudRate = 9600;
	USART1_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
	USART1_InitStructure.USART_Mode = USART_Mode_Rx|USART_Mode_Tx;
	USART1_InitStructure.USART_Parity = USART_Parity_No;
	USART1_InitStructure.USART_StopBits = USART_StopBits_1;
	USART1_InitStructure.USART_WordLength = USART_WordLength_8b;
	USART_Init(USART1,&USART1_InitStructure);
	
	USART_Cmd(USART1,ENABLE);
}

void USART1_Echo(void)
{
    
    
	u8 ch = 0;
	while(USART_GetFlagStatus(USART1,USART_FLAG_RXNE) == 0);
	ch = USART_ReceiveData(USART1);
	while(USART_GetFlagStatus(USART1,USART_FLAG_TXE) == 0);
	USART_SendData(USART1,ch);
	
}

int fputc(int c, FILE *stream)
{
    
    
	while(USART_GetFlagStatus(USART1,USART_FLAG_TXE) == 0);
	USART_SendData(USART1,c);
	return c;
}

猜你喜欢

转载自blog.csdn.net/qq_20467929/article/details/126119031