美文网首页我爱编程
STM32+DHT11温湿度检测

STM32+DHT11温湿度检测

作者: NooneIam | 来源:发表于2017-10-24 21:40 被阅读0次
1.DHT11温湿度检测模块

湿度测量范围:20%-95% 湿度测量误差-+5%
温度测量范围:0度-50度 温度测量误差:-+2度
引脚:VCC DATE GND
工作电压 3.3v-5v
输出形式 数字输出

2.温湿度采用单总线协议

一、单总线协议(1-wire)
1.定义:主机和从机通过1根线进行通信,在一条总线上可挂接的从器件数量几乎不受限制。
2.特点:这是由达拉斯半导体公司推出的一项通信技术。它采用单根信号线,既可传输时钟,又能传输数据,而且数据传输是双向的。
3.优点:单总线技术具有线路简单,硬件开销少,成本低廉,便于总线扩展和维护等。
二、单总线通信过程
1.初始化
初始化过程 = 复位脉冲 + 从机应答脉冲。
主机通过拉低单总线480 ~ 960 us产生复位脉冲,然后释放总线,进入接收模式。主机释放总线时,会产生低电平跳变为高电平的上升沿,单总线器件检测到上升沿之后,延时15 ~ 60 us,单总线器件拉低总线60 ~ 240 us来产生应答脉冲。主机接收到从机的应答脉冲说明单总线器件就绪,初始化过程完成。
初始化时序图如下所示:

/*
DHT11所用管脚配置
PB9--VCC
输出模式
*/

void DHT11_OUT(void)
{
    GPIO_InitTypeDef  GPIO_InitStruct;
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);//时能PB时钟
    
    GPIO_InitStruct.GPIO_Pin =GPIO_Pin_9;//PB9管脚
    GPIO_InitStruct.GPIO_Mode =GPIO_Mode_Out_PP;//推挽输出
    GPIO_InitStruct.GPIO_Speed =GPIO_Speed_50MHz;//输出速度
    GPIO_Init(GPIOB, &GPIO_InitStruct);//GPIOB的初始化
    VCC_H;//总线拉高
}
/*
输入模式
*/
void DHT11_IN(void)
{
    GPIO_InitTypeDef  GPIO_InitStruct;
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);//时能PB时钟
    
    GPIO_InitStruct.GPIO_Pin =GPIO_Pin_9;//PB9管脚
    GPIO_InitStruct.GPIO_Mode =GPIO_Mode_IN_FLOATING;//浮空输入
    GPIO_Init(GPIOB, &GPIO_InitStruct);//GPIOB的初始化
}
void DTH11_Config(void)
{
    DHT11_OUT();
    DHT11_IN();
}

2.写间隙
写间隙有两种,包括写0的时间隙和写1的时间隙。
当数据线拉低后,在15 ~ 60 us的时间窗口内对数据线进行采样。如果数据线为低电平,就是写0,如果数据线为高电平,就是写1。主机要产生一个写1时间隙,就必须把数据线拉低,在写时间隙开始后的15 us内允许数据线拉高。主机要产生一个写0时间隙,就必须把数据线拉低并保持60 us。
写时间隙时序图如下所示:



3.读时间隙
当主机把总线拉低是,并保持至少1 us后释放总线,必须在15 us内读取数据。
读时间隙时序图如下所示:


/*
读取DHT11的值
*/
void READ_Data(void)
{
    DHT11_OUT();//输出模式
    VCC_L;
    Delay_ms(20);
    VCC_H;
    Delay_us(30);
    
    DHT11_IN();//输入模式
    while(RD_DHT11_DATA);//响应信号 等待拉低
    while(!RD_DHT11_DATA);//等待拉高
    while(RD_DHT11_DATA);//等待电平间隙
    //接收数据
    for(i=0;i<40;i++)
    {
        while(!RD_DHT11_DATA);//等待电平拉高 接收数据
        Delay_us(50);//延时50 判断逻辑值
        if(RD_DHT11_DATA)
        {
            if(i<8)
            {
                data1 |=( 1<<(8-i-1));
            }
            if(i>=8&&i<16)
            {
                data2 |=(1<<(16-i-1));
            }
            if(i>=16&&i<24)
            {
                data3 |=(1<<(24-i-1));
            }
            if(i>=24&&i<32)
            {
                data4 |=(1<<(32-i-1));
            }
            if(i>=32&&i<40)
            {
                data0 |=(1<<(40-i-1));
            }
            while(RD_DHT11_DATA);
        }
        
    }
    DHT11_OUT();//输出模式
    Delay_us(50);
    VCC_H;//总线拉高
}
3.将采集的模拟信号经ADC转换成数字信号

设置PA5为模拟通道输入引脚:
-开启PA及ADC时钟
-设置端口模式—模拟输入
-设置ADC工作模式(使用提供的库函数定义,虽然方便开发,但不利于理解内部功能)

获取AD转换值

void Adc_Init(void)
{
    ADC_InitTypeDef ADC_InitStructure; 
    GPIO_InitTypeDef GPIO_InitStructure;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA |RCC_APB2Periph_ADC2    , ENABLE );   //使能ADC2通道时钟
 

    RCC_ADCCLKConfig(RCC_PCLK2_Div8);   //设置ADC分频因子6 72M/6=12,ADC最大时间不能超过14M

    //PA5 作为模拟通道输入引脚                         
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;       //模拟输入引脚
    GPIO_Init(GPIOA, &GPIO_InitStructure);  

    //ADC_DeInit(ADC2);  //复位ADC2,将外设 ADC2 的全部寄存器重设为缺省值

    ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;  //ADC工作模式:ADC2和ADC2工作在独立模式
    ADC_InitStructure.ADC_ScanConvMode = DISABLE;//不用扫描模式
    ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; //模数转换工作在单次转换模式
    ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //转换由软件而不是外部触发启动
    ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;  //ADC数据右对齐
    ADC_InitStructure.ADC_NbrOfChannel = 1; //顺序进行规则转换的ADC通道的数目
    ADC_Init(ADC2, &ADC_InitStructure); //根据ADC_InitStruct中指定的参数初始化外设ADCx的寄存器   

  
    ADC_Cmd(ADC2, ENABLE);  //使能指定的ADC2
    
    //ADC_ResetCalibration(ADC2);   //使能复位校准  
     
    //while(ADC_GetResetCalibrationStatus(ADC2));   //等待复位校准结束
    
    ADC_StartCalibration(ADC2);  //开启AD校准
 
    while(ADC_GetCalibrationStatus(ADC2));   //等待校准结束
 
//  ADC_SoftwareStartConvCmd(ADC2, ENABLE);     //使能指定的ADC2的软件转换启动功能
}
/*
得到AD转换值
*/
u16 Get_ADC_Data(void)
{
    //设置指定ADC的规则组通道,一个序列,采样时间
    ADC_RegularChannelConfig(ADC2, ADC_Channel_5, 1, ADC_SampleTime_239Cycles5 );   //ADC2,ADC通道,采样时间为239.5周期                   
  
    ADC_SoftwareStartConvCmd(ADC2, ENABLE);     //使能指定的ADC2的软件转换启动功能    
     
    while(!ADC_GetFlagStatus(ADC2, ADC_FLAG_EOC ));//等待转换结束

    return ADC_GetConversionValue(ADC2);    //返回最近一次ADC2规则组的转换结果
}
//u16 Get_vlaue()
//{
//  u16 adcvlaue=0;
//  adcvlaue=80*(float)Get_ADC_Data()/4096.0;
//  return adcvlaue;
//}

GitHub代码连接:
Test-environment/DHT11/DHT11.c

相关文章

网友评论

    本文标题:STM32+DHT11温湿度检测

    本文链接:https://www.haomeiwen.com/subject/uftfpxtx.html