HAL库开发stm32 DHT11传感器
我的学记|刘航宇的博客

HAL库开发stm32 DHT11传感器

刘航宇
3年前发布 /正在检测是否收录...
温馨提示:
本文最后更新于2022年11月29日,已超过853天没有更新,若内容或图片失效,请留言反馈。

现象

图片[1] - HAL库开发stm32 DHT11传感器 - 我的学记|刘航宇的博客

dht11.h

#ifndef __HT11_H_
#define __HT11_H_
#include "main.h"
#include "stm32f1xx_hal.h"


//函数原型
//void delay_us(uint8_t);   //微妙延时函数,启用了一个定时器。因为DHT11通讯过程涉及微妙延时
void GPIO_Input(void);      //GPIO 状态转变的函数 CUBEMX默认的GPIO初始化我只开启了相关总线的使能
//把GPIO状态(输入 输出)封装成了两个函数
void GPIO_Output(void);
void DHT11_Rst(void);        //主机开始采集的信号
uint8_t DHT11_Check(void);  //检查DHT是否回应
uint8_t DHT11_Init(void);   //初始化函数
uint8_t DHT11_ReadBit(void);   //读取一位
uint8_t DHT11_ReadByte(void);  //读取一个字节
uint8_t DHT11_ReadData(uint8_t *);   //读取数据(40个位) 




#endif

dht11.c

#include "dht11.h"

#define CPU_FREQUENCY_MHZ 72                // CPU主频,根据实际进行修改
static void delay_us(uint32_t delay)
{
    int last, curr, val;
    int temp;

    while (delay != 0)
    {
        temp = delay > 900 ? 900 : delay;
        last = SysTick->VAL;
        curr = last - CPU_FREQUENCY_MHZ * temp;
        if (curr >= 0)
        {
            do
            {
                val = SysTick->VAL;
            }
            while ((val < last) && (val >= curr));
        }
        else
        {
            curr += CPU_FREQUENCY_MHZ * 1000;
            do
            {
                val = SysTick->VAL;
            }
            while ((val <= last) || (val > curr));
        }
        delay -= temp;
    }
}


void GPIO_Input(void)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};
     /*Configure GPIO pin : PB1 */
  GPIO_InitStruct.Pin = GPIO_PIN_1;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}

void GPIO_Output(void)
{
     GPIO_InitTypeDef GPIO_InitStruct = {0};
  /*Configure GPIO pin : PB1 */
  GPIO_InitStruct.Pin = GPIO_PIN_1;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

}

void DHT11_Rst(void)   //主机开始信号
{
    GPIO_Output();
    HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,GPIO_PIN_RESET);
    HAL_Delay(20);
    HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,GPIO_PIN_SET);
    delay_us(30);
}

uint8_t DHT11_Check(void)
{
    uint8_t retry = 0;
    GPIO_Input();
    while(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1) && retry <100)      //等待回应拉位低电平
    {
        retry++;
        delay_us(1);
    }
    
    if(retry >= 100)return 1;else retry =    0;                //当变量值大于100 返回1 说明无响应  返回 0 则为正确响应
    
        while(!HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1) && retry <100)      //等待变为高电平
    {
        retry++;
        delay_us(1);
    }
    if(retry >= 100)return 1;
    return 0;
}

uint8_t DHT11_Init(void)
{
    DHT11_Rst();
    return DHT11_Check();
}


uint8_t DHT11_ReadBit(void)   //读取一个位
{
    uint8_t retry = 0;
    while(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1) && retry <100)      //等待变为低电平
    {
        retry++;
        delay_us(1);
    }
    retry = 0;
            while(!HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1) && retry <100)      //等待变为高电平
    {
        retry++;
        delay_us(1);
    }
    delay_us(40);  //40us 后如果为低电平 数据为0   高电平数据为1
    if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1))return 1;else return 0;
}

uint8_t DHT11_ReadByte(void)    //读取一个字节  返回值位采集值
{
    uint8_t i,dat;
    dat = 0;
    for(i = 0;i < 8;i++)
    {
        dat <<= 1;                                    //数据左移一位
        dat |= DHT11_ReadBit();            //每读取到一个位 放到dat的最后一位
    }
    return dat;
}

uint8_t DHT11_ReadData(uint8_t *h)
{
    uint8_t buf[5];
    uint8_t i;
    DHT11_Rst();
    if(DHT11_Check() == 0){
        for(i = 0;i < 5;i++)
        {
            buf[i] = DHT11_ReadByte();
        }
        if(buf[0] + buf[1] + buf[2] + buf[3] == buf[4])
        {
            *h = buf[0];
            h++;
            *h = buf[2];
        }
    }else return 1;
    return 0;
}

main.c添加

//你自己要完成OLED显示出温度湿度哈,这个我就不写代码了,不然真的是再喂饭了呜呜
#include "dht11.h"  //引入头文件
#include "stdio.h"
uint8_t data[2];    //定义一个数据数组
uint8_t buff1[]="dht11 ok\r\n";
uint8_t buff2[]="dht11 error";
uint8_t str_buff[64];

//int main 死循环外面
if(DHT11_Init() == 0)
        {
        //这里显示了“温度”“湿度等字符”
     HAL_UART_Transmit(&huart1,buff1,sizeof(buff1),10000);
        }
        else{
            //OLED_ShowStr(0,0,"DHT11 error!",1);
            HAL_UART_Transmit(&huart1,buff2,sizeof(buff2),10000);
        }
        HAL_Delay(1000); 

   while (1)
  {
        if(DHT11_ReadData(data) == 0)
        {    //显示相关数据
       sprintf((char *)str_buff,"温度%d%d;湿度%d%d\r\n",data[0] /10 ,data[0] %10,data[1] /10,data[1] /10);
            HAL_UART_Transmit(&huart1,str_buff,sizeof(str_buff),10000);
        }
        HAL_Delay(1000);  //DHT11每次采集一定要间隔1s
        //你自己要完成OLED显示出温度湿度哈,这个我就不写代码了,不然真的是再喂饭了呜呜!

  }
© 版权声明
THE END
喜欢就支持一下吧
点赞 15 分享 赞赏
评论 抢沙发
取消