打印
[STM32F1]

VSCODE STM32 裸机之DHT11

[复制链接]
764|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 zero949079783 于 2021-10-30 21:37 编辑

开发环境:VSCODE(gcc编译链)+STM32CubeMX(也可以使用HUAWEI-LiteOS-Studio) 。
代码:链接:https://pan.baidu.com/s/1uXfIR0GFQOBZPl1NfQP08w  
提取码:6b0c




◎单总线说明
DHT11 器件采用简化的单总线通信。单总线即只有一根数据线,系统中的数据交换、控制均由单总线
完成。设备(主机或从机)通过一个漏枀开路或三态端口连至该数据线,以允许设备在不发送数据时能够
释放总线,而让其它设备使用总线;单总线通常要求外接一个约 4.7kΩ 的上拉电阻,这样,当总线闲置时,
其状态为高电平。由于它们是主从结极,只有主机呼叫从机时,从机才能应答,因此主机访问器件都必须
严格遵循单总线序列,如果出现序列混乱,器件将不响应主机。
◎单总线传送数据位定义
DATA 用于微处理器与 DHT11 之间的通讯和同步,采用单总线数据格式,一次传送 40 位数据,高位先
出。
数据格式:
8bit 湿度整数数据 + 8bit 湿度小数数据 + 8bit 温度整数数据 + 8bit 温度小数数据 + 8bit 校验位。
注:其中湿度小数部分为 0。
◎校验位数据定义
“8bit 湿度整数数据 + 8bit 湿度小数数据 + 8bit 温度整数数据 + 8bit 温度小数数据”8bit 校验位等于
所得结果的末 8 位。

示例一:接收到的 40 位数据为:
0011 0101 0000 0000 0001 1000 0000 0100 0101 0001
湿度高 8 位 湿度低 8 位 温度高 8 位 温度低 8 位 校验位
计算:
0011 0101+0000 0000+0001 1000+0000 0100= 0101 0001
接收数据正确:
湿度:0011 0101(整数)=35H=53%RH 0000 0000(小数)=00H=0.0%RH =>53%RH + 0.0%RH =
53.0%RH
温度:0001 1000(整数)=18H=24℃ 0000 0100(小数)=04H=0.4℃ =>24℃ + 0.4℃ = 24.4℃ ◎特殊说明:
当温度低于 0 ℃ 时温度数据的低 8 位的最高位置为 1。
示例: -10.1 ℃ 表示为 0000 1010 1000 0001
温度:0000 1010(整数)=0AH=10℃,0000 0001(小数)=01H=0.1℃ =>-(10℃+0.1℃)= -10.1℃
示例二:接收到的 40 位数据为:
0011 0101 0000 0000 0001 1000 0000 0100 0100 1001
湿度高 8 位 湿度低 8 位 温度高 8 位 温度低 8 位 校验位
计算:
0011 0101+0000 0000+0001 1000+0000 0100= 0101 0001
0101 0001 不等于 0100 1001
本次接收的数据不正确,放弃,重新接收数据。
◎数据时序图
用户主机(MCU)发送一次开始信号后,DHT11 从低功耗模式转换到高速模式,待主机开始信号结束
后,DHT11 发送响应信号,送出 40bit 的数据,并触发一次信采集。信号发送如图所示。


步骤二:
微处理器的 I/O 设置为输出同时输出低电平,且低电平保持时间不能小于 18ms(最大不得超过 30ms),
然后微处理器的 I/O 设置为输入状态,由于上拉电阻,微处理器的 I/O 即 DHT11 的 DATA 数据线也随之变
高,等待 DHT11 作出回答信号,发送信号如图所示:


步骤三:
DHT11 的 DATA 引脚检测到外部信号有低电平时,等待外部信号低电平结束,延迟后 DHT11 的 DATA
引脚处于输出状态,输出 83 微秒的低电平作为应答信号,紧接着输出 87 微秒的高电平通知外设准备接
收数据,微处理器的 I/O 此时处于输入状态,检测到 I/O 有低电平(DHT11 回应信号)后,等待 87 微秒
的高电平后的数据接收,发送信号如图所示:


步骤四: 由 DHT11 的 DATA 引脚输出 40 位数据,微处理器根据 I/O 电平的变化接收 40 位数据,位数据“0”
的格式为: 54 微秒的低电平和 23-27 微秒的高电平,位数据“1”的格式为: 54 微秒的低电平加 68-74
微秒的高电平。位数据“0”、“1”格式信号如图所示:


结束信号:
DHT11 的 DATA 引脚输出 40 位数据后,继续输出低电平 54 微秒后转为输入状态,由于上拉电阻随
之变为高电平。但 DHT11 内部重测环境温湿度数据,并记录数据,等待外部信号的到来。

#include "DHT11.h"

#include "DHT11.h"

uint16_t Time =0;

/**
  * [url=home.php?mod=space&uid=247401]@brief[/url]   DHT11 GPIO初始化
  * @param  
  *                [url=home.php?mod=space&uid=2817080]@ARG[/url]
        *                                                  
  * @retval  无
  */
void DHT11_Config(void)
{
        DHT11_OUT_H();
}

/**
  * [url=home.php?mod=space&uid=247401]@brief[/url]   DHT11 GPIO输出设置
  * @param  
  *                [url=home.php?mod=space&uid=2817080]@ARG[/url] cmd: 1 : DHT11_WRITE  输出  
        *                                                  0 : DHT11_READ   输入
  * @retval  无
  */
//DHT11 GPIO输出设置
void DHT11_Write_Out_Input(uint8_t cmd)
{
         GPIO_InitTypeDef GPIO_InitStruct = {0};
        if(cmd == DHT11_WRITE )
        {
                 GPIO_InitStruct.Pin = GPIO_PIN_6;
         GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
         GPIO_InitStruct.Pull = GPIO_PULLUP;
         GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
         HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
        }
        
        else
  {
                GPIO_InitStruct.Pin = GPIO_PIN_6;
        GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
        GPIO_InitStruct.Pull = GPIO_PULLUP;
        HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
        }
}

/**
  * [url=home.php?mod=space&uid=247401]@brief[/url]   DHT11 读一个字节
  * @param  
  *                [url=home.php?mod=space&uid=2817080]@ARG[/url]
        *                                                  
  * @retval  dat 反回数据
  */

uint8_t DHT11_Read_Byte(void)
{
        uint8_t dat = 0;

        for(uint8_t i=0;i<8;i++)
        {
                DHT11_Write_Out_Input(DHT11_READ);
                while((DHT11_IN() == Bit_RESET) &&(Time++<1000)); //
                Time = 0;
               
                dat <<= 1;
                delay_us(4);
                if(DHT11_IN() == 1)  
                {
                        dat |=0x01;  
                        while((DHT11_IN() == Bit_SET) &&(Time++<1000)); //
                        
                }
//                else
//                {
//                        dat |=0x00;
//                }
        }
        
        return dat;
}

/**
  * [url=home.php?mod=space&uid=247401]@brief[/url]   DHT11 读湿度,温度
  * @param  
        *                                *HuimH :湿度整数部分
                                        *HuimL :湿度小数部分
                                        *TempH :温度整数部分
                                        *TempL :温度小数部分
  *                [url=home.php?mod=space&uid=2817080]@ARG[/url]
        *                                                  
  * @retval  0 :数据正确,1 :数据不正确
  */
uint8_t DHT11_Read_Huim_Temp(uint8_t *HuimH,uint8_t *HuimL,uint8_t *TempH,uint8_t *TempL)
{
        uint8_t DHT11_Date[5]; //用来保存数据 ,DHT11 一次读40位数据
        DHT11_Write_Out_Input(DHT11_WRITE);
        DHT11_OUT_L();
        delay_ms(20);  //拉低后至少18ms
        DHT11_OUT_H(); //释放总线
        delay_us(4);  //释放总线20-40us
        
        DHT11_Write_Out_Input(DHT11_READ);
        while((DHT11_IN() == Bit_RESET) &&(Time++<1000)); // 低电平否过去
        Time = 0;
        
        while((DHT11_IN() == Bit_SET) &&(Time++<1000)); //   高电平否过去
        Time = 0;
        
        for(uint8_t i=0;i<5;i++)
        {
                DHT11_Date[i] = DHT11_Read_Byte();
        }
        
        delay_ms(1);

        if(DHT11_Date[0]+DHT11_Date[1]+DHT11_Date[2]+DHT11_Date[3] == DHT11_Date[4] ) //校验和
        {
                        *HuimH = DHT11_Date[0];
                        *HuimL = DHT11_Date[1];
               
                        *TempH = DHT11_Date[2];
                    *TempL = DHT11_Date[3];
        }
        
        else
    {
                return 1; //数据不正确
        }
        
        return 0 ; //数据正确
        
}


   

1635593983(1).png (45.29 KB )

1635593983(1).png

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

33

主题

89

帖子

1

粉丝