ARM技术论坛
直播中

张敏

7年用户 1585经验值
私信 关注
[经验]

求一种基于GD32F427开发板+DHT11温湿度监测的简易智能家居方案

在完成所有项目后会开源,本次依旧是想做一个通过DHT11采集信息,OLED显示,ESP8266上传,可通过小程序查看的简易智能家居事例。

MDK环境准备

这里遇到了不少坑,到时候专门开一篇来讲

DHT11工作原理

简单来说就是

/*

数据格式:

湿度整数 湿度小数 温度整数 温度小数 校验位

00000000 00000000 00000000 00000000 00000000

1 看原理图确认GPIO引脚

2、 输出模式, 输出起始信号 :输出低电平18~30ms, 20ms

3、 IO口配置浮空输入模式,准检测响应信号

传感器把数据总线( SDA)拉低 83μs,再接高 87μs 以响应主机的起始信号。

4、 40 个位的数据,高位先发;
> ```
>
> 一位一位的收,数据0: 54us低电平 + 23~27高电平
数据1: 54us低电平 + 68~74高电平
> 注意高位先发的(每个字节)
>
> ```
> 5、校验数据
> ```
>
> 前4个字节,求和,把和值的末八位和校验位对比
> 相同数据正确、否则数据异常
>
> ```
> */
> ```

接下来就开始写代码了

由于官方库的systick是ms级别的,需要改写成us级别或者另外实现,我这里都做了,各位可以按需使用~~

第一种基于官方库systick修改为us级别

systick.c
void systick_config(void)
{
    /* setup systick timer for 1000Hz interrupts */
    /*1000u是ms,1000000是us*/
    if(SysTick_Config(SystemCoreClock / 1000000U)) {
        /* capture error */
        while(1) {
        }
    }
    /* configure the systick handler priority */
    NVIC_SetPriority(SysTick_IRQn, 0x00U);
}

第二种,自己重新写

下边写的是delay_us,如果需要ms则*1000就可以了

delay.c
 void delay_us(uint32_t nus)
{
    int i;
    uint32_t temp;    
    for(i=0;i<8;i++)
    {
             
    SysTick->LOAD= nus *25;                     //时间加载               
    SysTick->VAL=0x00;                            //清空计数器
    SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ;    //开始倒数      
    do
    {
        temp=SysTick->CTRL;
    }while((temp&0x01)&&!(temp&(1<<16)));        //等待时间到达   
    SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk;    //关闭计数器
    SysTick->VAL =0X00;                           //清空计数器    
}
}

接下来开始写DHT11的代码了,主要是调用库,开发难度很低

dht11.c
#include "dht11.h"

void dht11_gpio_input(void)
{
    rcu_periph_clock_enable(RCU_GPIOB);
    /*配置输入*/
    gpio_mode_set(GPIOB, GPIO_MODE_INPUT, GPIO_PUPD_PULLDOWN, GPIO_PIN_12);
    gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_12);
    
}

void dht11_gpio_output(void)
{

    rcu_periph_clock_enable(RCU_GPIOB);
    /*配置下拉输出*/
    gpio_mode_set(GPIOB, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLDOWN, GPIO_PIN_12);
    gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_12);
    
}


void dht11_reset(void)//复位
{
    
    dht11_gpio_output();
    DHT11_OUT_L;
    delay_us(19000);
    DHT11_OUT_H;
    delay_us(30);
    dht11_gpio_input();
}

uint16_t dht11_scan(void)//判断总线状态
{
    return DHT11_IN;
}

uint16_t dht11_read_bit(void)//读取一个bit
{
    while (DHT11_IN == RESET);
    delay_us(40);
    if (DHT11_IN == SET)
    {
        while (DHT11_IN == SET);
        return 1;
    }
    else
    {
        return 0;
    }
}

uint16_t dht11_read_byte(void)//读取一个字节
{
    uint16_t i;
    uint16_t data = 0;
    for (i = 0; i < 8; i++)
    {
        data <<= 1;
        data |= dht11_read_bit();
    }
    return data;
}
uint8_t checksum;
uint16_t dht11_read_data(uint8_t buffer[5])//读取数据
{
    uint16_t i = 0;
    
    dht11_reset();
    if (dht11_scan() == RESET)
    {
        
        while (dht11_scan() == RESET);
        while (dht11_scan() == SET);
        for (i = 0; i < 5; i++)
        {
            buffer[i] = dht11_read_byte();
        }
        
        while (dht11_scan() == RESET);
        dht11_gpio_output();
        DHT11_OUT_H;
        
         checksum = buffer[0] + buffer[1] + buffer[2] + buffer[3];
        if (checksum != buffer[4])
        {
            // checksum error
            return 1;
        }
    }
    
    return 0;
}
dht11.h
#ifndef __DHT11_H__
#define __DHT11_H__

//#include "timer.h"
#include "gd32f4xx.h"
#include "gd32f427v_start.h"
#include "systick.h"

#define DHT11_GPIO_TYPE  GPIOB
#define DHT11_GPIO_PIN   GPIO_PIN_12
#define DHT11_RCC        RCC_APB2Periph_GPIOB

#define DHT11_OUT_H gpio_bit_set(DHT11_GPIO_TYPE, DHT11_GPIO_PIN)
#define DHT11_OUT_L gpio_bit_reset(DHT11_GPIO_TYPE, DHT11_GPIO_PIN)
#define DHT11_IN    gpio_input_bit_get(DHT11_GPIO_TYPE, DHT11_GPIO_PIN)

/*如果使用的是重新写delay_us,不需要下面的宏,如果是改官方的就需要*/
#define delay_us delay_1ms

#define RESET 0
#define SET   1

void dht11_gpio_input(void);
void dht11_gpio_output(void);
uint16_t dht11_scan(void);
uint16_t dht11_read_bit(void);
uint16_t dht11_read_byte(void);
uint16_t dht11_read_data(uint8_t buffer[4]);

#endif

写完了DHT11的代码,接下来验证下

在main里调用下

while (1)
    {
        if (dht11_read_data(buffer) == 0)
        {
            hum = buffer[0] + buffer[1] / 10.0;
            temp1 = buffer[2] + buffer[3] / 10.0;
            printf("hum:%f,temp:%f\r\n",hum,temp1);    
        }
        delay_1ms(1000000);/*因为改了systick,没在delay_1ms所以要把它单us用*/
    }

看下结果

1668323802309.png

总结

GD32F427使用库开发体验还行,不过像systick这个库少了delay_us得自己写或者改,要是更完善点会更好。

原作者:四季的温度

更多回帖

发帖
×
20
完善资料,
赚取积分