利用Proteus仿真STM32实现DHT11温湿度检测

发布时间: 2024-06-11
来源: 电子工程世界

1. 前言

Proteus是英国著名的EDA工具(仿真软件),从原理图布图、代码调试到单片机与外围电路协同仿真,一 键切换到PCB设计,真正实现了从概念到产品的完整设计。是世界上唯一将电路仿真软件、PCB设计软 件和虚拟模型仿真软件三合一的设计平台,其处理器模型支持8051、HC11、 PIC10/12/16/18/24/30/DSPIC33、AVR、ARM、8086和MSP430等,2010年又增加了Cortex和DSP系 列处理器,并持续增加其他系列处理器模型。在编译方面,它也支持IAR、Keil和MATLAB等多种编译 器。 前面文章介绍了Proteus的下载,安装,建立工程,完成LED灯仿真运行。这篇文章在这基础上增加串口打印,DHT11温湿度检测。

2. 设计程序

先使用keil软件就将程序设计设计好,然后生成HEX文件,等待设计好原理图后进行仿真测试。


注意: 当前使用的芯片是STM32F103。Proteus的版本是8.9

image-20220524143658130

#include "stm32f10x.h"

#include "led.h"

#include "delay.h"

#include "key.h"

#include "dht11.h"


/*

(3)温湿度传感器: DHT11

VCC--VCC

GND---GND

DAT---PA5 

*/


#include "stm32f10x.h"

#include 

#include 

#include "sys.h"

#include 


#define USART1_RX_LENGTH 1024

extern u8 USART1_RX_BUFFER[USART1_RX_LENGTH]; //保存接收数据的缓冲区

extern u32 USART1_RX_CNT; //当前接收到的数据长度

extern u8 USART1_RX_FLAG; //1表示数据接收完毕 0表示没有接收完毕


#define USART2_RX_LENGTH 1024

extern u8 USART2_RX_BUFFER[USART2_RX_LENGTH]; //保存接收数据的缓冲区

extern u32 USART2_RX_CNT; //当前接收到的数据长度

extern u8 USART2_RX_FLAG; //1表示数据接收完毕 0表示没有接收完毕


#define USART3_RX_LENGTH 1024

extern u8 USART3_RX_BUFFER[USART3_RX_LENGTH]; //保存接收数据的缓冲区

extern u32 USART3_RX_CNT; //当前接收到的数据长度

extern u8 USART3_RX_FLAG; //1表示数据接收完毕 0表示没有接收完毕


void USART1_Init(u32 baud);

void USART2_Init(u32 baud);

void USART3_Init(u32 baud);

void USARTx_StringSend(USART_TypeDef *USARTx,char *str);

void USARTx_DataSend(USART_TypeDef *USARTx,u8 *data,u32 len);


//定义按键IO口

#define KEY_S3 PAin(1) 


//函数声明

void KEY_Init(void);

u8 KEY_Scan(u8 mode);



//LED定义

#define LED1 PBout(6)

#define LED2 PBout(7)

#define LED3 PBout(8)

#define LED4 PBout(9)


//蜂鸣器IO口定义

#define BEEP PAout(6)


//函数声明

void LED_Init(void);

void BEEP_Init(void);




//IO方向设置

#define DHT11_IO_IN()  {GPIOA->CRL&=0XFF0FFFFF;GPIOA->CRL|=0x00800000;}

#define DHT11_IO_OUT() {GPIOA->CRL&=0XFF0FFFFF;GPIOA->CRL|=0x00300000;}

////IO操作函数                                            

#define DHT11_DQ_OUT PAout(5) //数据端口    PA5 

#define DHT11_DQ_IN  PAin(5) //数据端口    PA5



u8 DHT11_Init(void);        //初始化DHT11

u8 DHT11_Read_Data(u8 *temp,u8 *humi);//读取温湿度

u8 DHT11_Read_Byte(void);   //读出一个字节

u8 DHT11_Read_Bit(void);    //读出一个位

u8 DHT11_Check(void);       //检测是否存在DHT11

void DHT11_Rst(void);       //复位DHT11  


//复位DHT11

void DHT11_Rst(void)      

{         

     DHT11_IO_OUT();   //SET OUTPUT

  DHT11_DQ_OUT=0;     //拉低DQ

  DelayMs(20);       //拉低至少18ms

  DHT11_DQ_OUT=1;     //DQ=1 

     DelayUs(30);    //主机拉高20~40us

}

//等待DHT11的回应

//返回1:未检测到DHT11的存在

//返回0:存在

u8 DHT11_Check(void)      

{  

    u8 retry=0;

    DHT11_IO_IN();//SET INPUT    

 while (DHT11_DQ_IN&&retry<100)//DHT11会拉低40~80us

     {

         retry++;

         DelayUs(1);

     };   

     if(retry>=100)return 1;

    else retry=0;

  while (!DHT11_DQ_IN&&retry<100)//DHT11拉低后会再次拉高40~80us

     {

         retry++;

         DelayUs(1);

     };

     if(retry>=100)return 1;   

    return 0;

}

//从DHT11读取一个位

//返回值:1/0

u8 DHT11_Read_Bit(void)              

{

    u8 retry=0;

    while(DHT11_DQ_IN&&retry<100)//等待变为低电平

     {

         retry++;

         DelayUs(1);

     }

     retry=0;

     while(!DHT11_DQ_IN&&retry<100)//等待变高电平

     {

         retry++;

         DelayUs(1);

     }

     DelayUs(40);//等待40us

     if(DHT11_DQ_IN)return 1;

     else return 0;         

 }

 

 //从DHT11读取一个字节

 //返回值:读到的数据

 u8 DHT11_Read_Byte(void)    

 {        

     u8 i,dat;

     dat=0;

     for (i=0;i<8;i++) 

     {

         dat<<=1; 

         dat|=DHT11_Read_Bit();

     }                           

     return dat;

 }

 

 

 //从DHT11读取一次数据

 //temp:温度值(范围:0~50°)

 //humi:湿度值(范围:20%~90%)

 //返回值:0,正常;1,读取失败

 u8 DHT11_Read_Data(u8 *temp,u8 *humi)    

 {        

     u8 buf[5];

     u8 i;

     DHT11_Rst();

     //printf("------------------------rn");

     if(DHT11_Check()==0)

     {

         for(i=0;i<5;i++)//读取40位数据

         {

             buf[i]=DHT11_Read_Byte();

         }

         if((buf[0]+buf[1]+buf[2]+buf[3])==buf[4])

         {

             *humi=buf[0];

             *temp=buf[2];

         }

     }else return 1;

     return 0;       

 }

 

 

 //初始化DHT11的IO口 DQ 同时检测DHT11的存在

 //返回1:不存在

 //返回0:存在         

 u8 DHT11_Init(void)

 {

     RCC->APB2ENR|=1<<2;    //使能PORTA口时钟 

     GPIOA->CRL&=0XFF0FFFFF;//PORTA.5 推挽输出

    GPIOA->CRL|=0X00300000;

    GPIOA->ODR|=1<<5;      //输出1                    

     DHT11_Rst();

     return DHT11_Check();

 }

 

 

 /*

 函数功能:按键初始化

 硬件连接:PA1

 特性: 按下为低电平---没按下高电平

 */

 void KEY_Init(void)

 {

     //开时钟

     RCC->APB2ENR|=1<<2;

     //配置模式

     GPIOA->CRL&=0xFFFFFF0F;

  GPIOA->CRL|=0x00000080;

  //上拉

  GPIOA->ODR|=1<<1;

 }

 

 

 /*

 函数功能:函数扫描函数

 函数参数: mode=1表示使用连续模式  mode=0使用单击模式

 返回值:  2 3 4 5 表示具体的按钮   0表示没有按下

 */

 u8 KEY_Scan(u8 mode)

 {

    static u8 flag=1; //记录上一次按下的状态 

    if(mode)flag=1;

    if(flag&&(KEY_S3==0))

    {

        flag=0;

        delay_ms(20);

        if(KEY_S3==0)return 3;

    }

    else if(KEY_S3)

    {

        flag=1; 

    }

    return 0;

 }

 

 

 /*

 函数功能: LED初始化

 硬件连接: PB6 PB7 PB8 PB9

 特性: 低电平点亮

 */

 void LED_Init(void)

 {

     //开时钟

     RCC->APB2ENR|=1<<3;

     //配置GPIO口

     GPIOB->CRL&=0x00FFFFFF;

  GPIOB->CRL|=0x22000000;

  GPIOB->CRH&=0xFFFFFF00;

  GPIOB->CRH|=0x00000022;

  //上拉

  GPIOB->ODR|=1<<6;

     GPIOB->ODR|=1<<7;

     GPIOB->ODR|=1<<8;

     GPIOB->ODR|=1<<9;

 }

 

 /*

 函数功能: 蜂鸣器初始化

 硬件连接: PA6

 特性: 高电平响

 */

 void BEEP_Init(void)

 {

    RCC->APB2ENR|=1<<2;

    GPIOA->CRL&=0xF0FFFFFF;

  GPIOA->CRL|=0x02000000;

}



/*

函数功能: 串口1的初始化

硬件连接: PA9(TX)  和 PA10(RX)

*/

void USART1_Init(u32 baud)

{

  /*1. 开时钟*/

  RCC->APB2ENR|=1<<14; //USART1时钟

     RCC->APB2ENR|=1<<2;  //PA

     RCC->APB2RSTR|=1<<14; //开启复位时钟

     RCC->APB2RSTR&=~(1<<14);//停止复位

     /*2. 配置GPIO口的模式*/

     GPIOA->CRH&=0xFFFFF00F;

  GPIOA->CRH|=0x000008B0;

  /*3. 配置波特率*/

  USART1->BRR=72000000/baud;

  /*4. 配置核心寄存器*/

  USART1->CR1|=1<<5; //开启接收中断

     STM32_SetPriority(USART1_IRQn,1,1); //设置中断优先级

     USART1->CR1|=1<<2; //开启接收

     USART1->CR1|=1<<3; //开启发送

     USART1->CR1|=1<<13;//开启串口功能

 }

 

 /*

 函数功能: 串口2的初始化

 硬件连接: PA2(TX)  和 PA3(RX)

 */

 void USART2_Init(u32 baud)

 {

     /*1. 开时钟*/

     RCC->APB1ENR|=1<<17; //USART2时钟

     RCC->APB2ENR|=1<<2;  //PA

     RCC->APB1RSTR|=1<<17; //开启复位时钟

     RCC->APB1RSTR&=~(1<<17);//停止复位

     

     /*2. 配置GPIO口的模式*/

     GPIOA->CRL&=0xFFFF00FF;

  GPIOA->CRL|=0x00008B00;

  /*3. 配置波特率*/

  USART2->BRR=36000000/baud;

  /*4. 配置核心寄存器*/

  USART2->CR1|=1<<5; //开启接收中断

     STM32_SetPriority(USART2_IRQn,1,1); //设置中断优先级

     USART2->CR1|=1<<2; //开启接收

     USART2->CR1|=1<<3; //开启发送

     USART2->CR1|=1<<13;//开启串口功能

 }

 

 /*

 函数功能: 串口3的初始化

 硬件连接: PB10(TX)  和 PB11(RX)

 */

 void USART3_Init(u32 baud)

 {

     /*1. 开时钟*/

     RCC->APB1ENR|=1<<18; //USART3时钟

     RCC->APB2ENR|=1<<3;  //PB

文章来源于: 电子工程世界 原文链接

本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。