7.20 3周四:DHT11温湿度检测(下)

上节的代码我就在这里简单汇总下

#define  DHT11_BUS_HIGH   (DHT11_GPIOx->BSRR = (uint32_t)DHT11_PINx)   // DAT引脚 置高电平
#define  DHT11_BUS_LOW  (DHT11_GPIOx->BSRR = ((uint32_t)DHT11_PINx) << 16)// DAT引脚 置低电平
#define  DHT11_BUS_READ  ((DHT11_GPIOx->IDR & DHT11_PINx) ? 1: 0)     // 读取引脚的电平

static void DHT11_Mode_IPU(void);  //GPIO输入模式--上拉模式(电平保持高位)
static void DHT11_Mode_Out_PP(void); //GPIO输入模式--推挽输出

void DHT11_Init(GPIO_TypeDef *GPIOx, uint32_t PINx)
{
    DHT11_GPIOx = GPIOx;
    DHT11_PINx = PINx;

    // 时钟使能:引脚端口;用判断端口的方式使能时钟线, 减少移植时的工作
    if (GPIOx == GPIOA)  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    if (GPIOx == GPIOB)  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
    if (GPIOx == GPIOC)  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
    if (GPIOx == GPIOD)  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE);
    if (GPIOx == GPIOE)  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE);
    if (GPIOx == GPIOF)  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOF, ENABLE);
    if (GPIOx == GPIOG)  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOF, ENABLE);		
		
	  DHT11_Mode_IPU();  //  1
    DHT11_BUS_HIGH;      //  2
}

步骤一中说了, 上电后保持高电平,输入状态。

 这一步中说了,IO设置为低电平,输出,并且>18ms,之后就是高电平。下面就是对应的代码,在getdata()函数中。

// 1:主机产生开始信号
    DHT11_Mode_Out_PP();               // 输出模式
    DHT11_BUS_LOW;                     // 主机拉低电平
    TIM6_delay_ms(25);                      // 延时18~30ms
// 2:主机拉高等待
    DHT11_BUS_HIGH;                    // 总线拉高

 

 这一步中,我的理解是这个高电平或者低电平都是DHT11自己处理的,所以不用管他。但是需要将自己的IO设置为输入状态。因为DHT11要发送信号出来了。

// 1:主机产生开始信号
    DHT11_Mode_Out_PP();               // 输出模式
    DHT11_BUS_LOW;                     // 主机拉低电平
    TIM6_delay_ms(25);                      // 延时18~30ms
// 2:主机拉高等待
    DHT11_BUS_HIGH;                    // 总线拉高
    TIM6_delay_us(50);                 // 延时20~40us,这里设置50,是因为要直接进入下一个时序(电平状态),以方便检测
// 3: 从机产生响应和准备信号
    DHT11_Mode_IPU();                  // 主机设为输入 判断从机响应信号

if (DHT11_BUS_READ == 0)           // 判断从机是否产生响应信号_低电平, 如不响应则跳出
    {
        while (DHT11_BUS_READ == 0);   // 等待响应信号结束:低电平持续约80us
        while (DHT11_BUS_READ == 1);   // 等待标置信号结束:高电平持续约80us
      

 在这一步中,不管是数据“0”还是“1”,它都是先发送50us的低电平(响应信号)。后面的信号才能区分出来是0还是1。

readByte()代码:

这段函数的思维是一次读取8位,然后用while来等待50us的低电平,等低电平过了后,延时>28us的时间,我是40us,temp左移一位,相当于在temp二进制数的最低位添加一个0。判断现在的电平还是不是高电平,如果是,就说明这次数据就是1,等待数据1的高电平结束,使用temp |= 1;temp变量的最低位设置为1。如果不是,因为左移的原因,就不用管,它就是0。

static uint8_t readByte(void)
{
    uint8_t  temp = 0;
    uint8_t i = 0;
    for ( i = 0; i < 8; i++)
    {
        while (DHT11_BUS_READ == 0);             // 每bit以50us低电平标置开始,轮询直到从机发出 的50us 低电平 结束
        TIM6_delay_us(40);                             // 延时x us 这个延时需要大于数据0持续的时间即可
        temp <<= 1;
        if (DHT11_BUS_READ == 1)                 // x us后仍为高电平表示数据“1”
        {
            while (DHT11_BUS_READ == Bit_SET);  // 等待数据1的高电平结束
            temp |= 1;                           // 位置“1“
        }
    }
    return temp;
}

它会发送40位数据,那么就要用不同的变量来接收这些数据。

if (DHT11_BUS_READ == 0)           // 判断从机是否产生响应信号_低电平, 如不响应则跳出
    {
        while (DHT11_BUS_READ == 0);   // 等待响应信号结束:低电平持续约80us
        while (DHT11_BUS_READ == 1);   // 等待标置信号结束:高电平持续约80us
        // 4: 从机连续输出5字节数据
        humiInt = readByte();          // 湿度的整数部分// 开始接收数据
        humiDec = readByte();          // 湿度的小数部分
        TempInt = readByte();          // 温度的整数部分
        TempDec = readByte();          // 温度的小数部分
        sum     = readByte();          // 校验和

        DHT11_Mode_Out_PP();           // 读取结束,引脚改为输出模式
        DHT11_BUS_HIGH;                // 主机拉高

        // 5: 检查读取的数据是否正确
        if (sum == (humiInt + humiDec + TempInt + TempDec))
        {
            xDHT11.Humidity = humiInt + humiDec;
            xDHT11.Temperature = (float)TempInt  + (float)TempDec / 10;
            return SUCCESS;            // 校检正确, 返回:SUCCESS=1
        }
        return ERROR;                  // 校检错误,返回:ERROR=0
    }

读取结束后要把引脚改回输出模式,将主机拉高

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值