0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

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

DS小龙哥-嵌入式技术 2022-09-17 15:53 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

1. 前言

Proteus是英国著名的EDA工具(仿真软件),从原理图布图、代码调试到单片机与外围电路协同仿真,一 键切换到PCB设计,真正实现了从概念到产品的完整设计。是世界上唯一将电路仿真软件、PCB设计软 件和虚拟模型仿真软件三合一的设计平台,其处理器模型支持8051、HC11、 PIC10/12/16/18/24/30/DSPIC33、AVR、ARM、8086和MSP430等,2010年又增加了Cortex和DSP系 列处理器,并持续增加其他系列处理器模型。在编译方面,它也支持IAR、KeilMATLAB等多种编译 器。 前面文章介绍了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
     RCC->APB1RSTR|=1<<18; //开启复位时钟
     RCC->APB1RSTR&=~(1<<18);//停止复位
     
     /*2. 配置GPIO口的模式*/
     GPIOB->CRH&=0xFFFF00FF;
  GPIOB->CRH|=0x00008B00;
  /*3. 配置波特率*/
  USART3->BRR=36000000/baud;
  /*4. 配置核心寄存器*/
  USART3->CR1|=1<<5; //开启接收中断
     STM32_SetPriority(USART3_IRQn,1,1); //设置中断优先级
     USART3->CR1|=1<<2; //开启接收
     USART3->CR1|=1<<3; //开启发送
     USART3->CR1|=1<<13;//开启串口功能
 }
 ​
 u8 USART1_RX_BUFFER[USART1_RX_LENGTH]; //保存接收数据的缓冲区
 u32 USART1_RX_CNT=0;  //当前接收到的数据长度
 u8 USART1_RX_FLAG=0; //1表示数据接收完毕 0表示没有接收完毕
 ​
 //串口1的中断服务函数
 void USART1_IRQHandler(void)
 {
     u8 data;
     //接收中断
     if(USART1->SR&1<<5)
     {
         TIM1->CNT=0; //清除计数器
    TIM1->CR1|=1<<0; //开启定时器1
         data=USART1->DR; //读取串口数据
   //  if(USART1_RX_FLAG==0) //判断上一次的数据是否已经处理完毕
     {
      //判断是否可以继续接收
      if(USART1_RX_CNTSR&1<<5)
     {
         TIM2->CNT=0; //清除计数器
    TIM2->CR1|=1<<0; //开启定时器2
         data=USART2->DR; //读取串口数据
   //  if(USART2_RX_FLAG==0) //判断上一次的数据是否已经处理完毕
     {
      //判断是否可以继续接收
      if(USART2_RX_CNTSR&1<<5)
     {
         TIM3->CNT=0; //清除计数器
    TIM3->CR1|=1<<0; //开启定时器3
         data=USART3->DR; //读取串口数据
   //  if(USART3_RX_FLAG==0) //判断上一次的数据是否已经处理完毕
     {
      //判断是否可以继续接收
      if(USART3_RX_CNTDR=*str++;
    while(!(USARTx->SR&1<<7)){}
    }
 }
 ​
 /*
 函数功能: 数据发送
 */
 void USARTx_DataSend(USART_TypeDef *USARTx,u8 *data,u32 len)
 {
    u32 i;
    for(i=0;iDR=*data++;
        while(!(USARTx->SR&1<<7)){}
    }
 }
 ​
 //printf函数底层函数接口
 int fputc(int c, FILE* stream)
 {
     USART1->DR=c;
  while(!(USART1->SR&1<<7)){}
     return c;
 }
 ​
 ​
 u8 dht11_temp;
 u8 dht11_humidity;
 ​
 int main()
 {
    u8 key_val;
    u32 time=0;
    LED_Init();
    BEEP_Init();
    KEY_Init();
    USART1_Init(115200);    //串口1初始化-打印调试信息
    //初始化DHT11
    DHT11_Init();
     
    while(1)
    {
       key_val=KEY_Scan(0); //PA1
       if(key_val)
       {
          BEEP=!BEEP;
          LED1=!LED1;   //PB6
       }
       delay_ms(5);
       
       time++;
       if(time>=10)
    {
    time=0;
    LED2=!LED2; //PB7
     
    //读取温湿度
    if(DHT11_Read_Data(&dht11_temp,&dht11_humidity))
     {
      printf("温度读取失败.rn");
     }    
    printf("T:%d,H:%drn",dht11_temp,dht11_humidity);
    
    //湿度大于80以上就关闭插座
    if(dht11_humidity>80)
     {
      LED1=1;
     }
    }
  }
}
复制代码

3. 设计电路图

3.1 添加DHT11器件

打开Proteus,搜索DHT11元器件

image-20220524143937845

鼠标选择空白区域,点击鼠标右键,放置电源和GND。

image-20220524144345503

设计好的效果如下:

image-20220524144418613

3.2 添加虚拟串口终端

为了方便查看程序的串口输出,添加一个串口终端显示框。

在虚拟仪表模式下,选择virtual terminal工具,然后在原理图空白区域点击一下就可以放virtual terminal工具。

image-20220524145332372

在绘制原理图的经常遇到连线复杂,或者布线很乱,如果元器件的引脚不方便直接与MCU单片机连接,可以采用标签的形式或者总线方式布线。这里以串口终端演示,采用标签方式连接IO口。

首先在坐标的菜单栏里选择终端模式,然后鼠标点击DEFAULT,然后在原理图的空白区域,点击一下鼠标左键,会出现一个空心的连接线条,将这个连接线条连接到元器件的IO口上就行。

image-20220524150145275image-20220524145810211

放置好之后,鼠标点击这个接线端子--空心圆圈,弹出对话框,设置连接的IO口。

image-20220524150321956

然后MCU的PA9和PA10的端子上也设置好标签名称。

image-20220524151328570

设置虚拟串口显示器的波特率为:115200

image-20220524150744558

如果在调试仿真时, Virtual Terminal无法自动弹出窗口,可以点击菜单栏的调试,选择恢复弹出窗口。

image-20220524151628962

设置STM32芯片的晶振为:71MHZ

image-20220524155200053

3.3 开始仿真

image-20220524155229691image-20220524155252228image-20220524155723214

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • Proteus
    +关注

    关注

    79

    文章

    1692

    浏览量

    110161
  • STM32
    +关注

    关注

    2305

    文章

    11121

    浏览量

    371175
  • DHT11
    +关注

    关注

    19

    文章

    277

    浏览量

    59353
收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    【瑞萨RA6E2地奇星开发板试用】串口打印DHT11温湿度数据

    【瑞萨RA6E2地奇星开发板试用】串口打印DHT11温湿度数据 本文介绍了 RA6E2 地奇星开发板驱动 DHT11 传感器实现串口打印环境温湿度
    发表于 12-07 16:20

    RA-Eco-RA6M4部分功能测评2

    RA-Eco-RA6M4开发板实战:集成DHT11实现温湿度采集与多端显示 在完成RA-Eco-RA6M4开发板的串口通信与OLED显示功能调试后,本次实践将进一步集成DHT11
    发表于 09-05 20:42

    【RA-Eco-RA6M4开发板评测】uart+OLED+DHT11

    继上一篇调通串口和OLED后,这次我们开始加传感器,这次的传感器是温湿度传感器DHT11DHT11 器件采用简化的单总线通信。单总线即只有一根数据线,系统中的数据交换、控制均由单总线完成。设备
    发表于 07-27 17:21

    STM32+esp8266连接机智云,上传温湿度数据并控制继电器开关(平台配置、代码生成、代码移植)

    本教程将详细介绍如何将STM32微控制器与ESP8266Wi-Fi模块连接到机智云平台,实现温湿度数据的上传与继电器的远程控制。通过此过程,您将学会如何配置机智云平台,烧录ESP8266固件,移植
    的头像 发表于 07-15 18:54 749次阅读
    <b class='flag-5'>STM32</b>+esp8266连接机智云,上传<b class='flag-5'>温湿度</b>数据并控制继电器开关(平台配置、代码生成、代码移植)

    常见的温湿度传感器类型?

    DHT11温湿度传感器 DHT11是一种常见的数字温湿度传感器,具有价格低廉、简单易用的优点,但其精度和响应速度较低。 HDC1080温湿度
    发表于 06-24 09:24

    【RA4L1-SENSOR】DHT11温湿度OLED显示

    为I2C接口,开漏输出 P107 设置为 DHT11 单总线接口 OLED 驱动代码如下: void OLED_SSD1306_Init(void) { u8 i
    发表于 06-12 11:02

    温湿度变送器功能有哪些?一文详细解析

    数据,帮助用户及时了解环境状况。 二、数据传输与远程监控 温湿度变送器可以将测量到的温湿度数据通过多种方式进行传输,如模拟信号、数字信号等。用户可以将变送器与监控系统相连,实现远程监控。这意味着即使不在现场
    发表于 06-03 10:56

    智能仓储:温湿度监控方案应用

    随着仓储环境要求提高,温湿度监控对保障货物品质至关重要。本文介绍一个工厂仓库温湿度监控方案,利用温湿度变送器、LoRa技术和智能监测平台,为仓库业主提供高效、可靠的监测解决方案。仓库
    的头像 发表于 05-29 11:35 596次阅读
    智能仓储:<b class='flag-5'>温湿度</b>监控方案应用

    STM32项目分享:智能鞋柜

    01—项目简介1.功能详解STM32智能鞋柜功能如下:DHT11检测鞋柜温湿度,温度低于阈值开启加热,湿度高于阈值开启加热和通风;P
    的头像 发表于 05-27 18:04 703次阅读
    <b class='flag-5'>STM32</b>项目分享:智能鞋柜

    用树莓派RP2350 DIY 桌面动态温湿度

    桌面动态温湿度计本文介绍了DFrobotBeetleRP2350开发板结合DHT11模块、锂电池模块、随机眨眼动画,实现OLED显示的桌面动态温湿度计的项目设计。一、项目介绍本项目包括
    的头像 发表于 05-27 08:05 677次阅读
    用树莓派RP2350 DIY 桌面动态<b class='flag-5'>温湿度</b>计

    【RA-Eco-RA4M2开发板评测】DHT11温湿度OLED显示

    DHT11 单总线接口 OLED 驱动代码如下: void OLED_SSD1306_Init(void) { u8 i; OLED_SSD1306_IIC_Init(); for (i=0
    发表于 05-11 13:53

    工厂温湿度监控系统

    在现代化工业生产环境中,温湿度控制是确保产品质量、生产效率和员工健康的关键因素之一。随着科技的进步,工厂温湿度监控系统应运而生,通过集成传感器技术、数据处理与通信技术,对工厂内部环境参数的实时监测
    的头像 发表于 02-25 17:11 890次阅读

    【正点原子STM32H7R3开发套件试用体验】DS18B20、DHT11温湿度采集

    传感器 (接在PG15上) 项目实现 检测是否有DHT11存在,如果没有,则提示错误; 检测DHT11后,开始读取
    发表于 01-01 11:16

    《DNESP32S3使用指南-IDF版_V1.6》第三十章 DHT11数字温湿度传感器

    高电平的持续时间,所以这个作为判断的依据。dht11_read_byte函数就是调用一字节读取函数进行实现。下面介绍读取温湿度函数,其定义如下:/** * @brief 从DHT11
    发表于 12-26 09:26

    STM32项目分享:机智云智慧农业系统

    01—项目简介1.功能详解基于STM32的机智云智慧农业系统。功能如下:温湿度采集:使用DHT11温湿度传感器采集环境温湿度土壤
    的头像 发表于 12-19 18:40 1907次阅读
    <b class='flag-5'>STM32</b>项目分享:机智云智慧农业系统