STM32使用HAL库驱动DHT11读取温湿度程序
驱动DHT11、DHT22、DS18BB20等温湿度模块时序是比较简单的,关键在于控制好时序的延时时间,HAL库的延时函数HAL_Delay是毫秒级别延时函数,所关键点就是实现微秒级别的延时函数。
微秒级别延时函数实现见我的另一篇博客:https://blog.csdn.net/qq153471503/article/details/102930097
扫描以下二维码,关注公众号雍正不秃头获取更多STM32资源及干货!

sys.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| #ifndef _SYS_H_ #define _SYS_H_
#include "main.h"
#define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2)) #define MEM_ADDR(addr) *((volatile unsigned long *)(addr)) #define BIT_ADDR(addr, bitnum) MEM_ADDR(BITBAND(addr, bitnum))
#define GPIOA_ODR_Addr (GPIOA_BASE+12) //0x4001080C #define GPIOB_ODR_Addr (GPIOB_BASE+12) //0x40010C0C #define GPIOC_ODR_Addr (GPIOC_BASE+12) //0x4001100C #define GPIOD_ODR_Addr (GPIOD_BASE+12) //0x4001140C #define GPIOE_ODR_Addr (GPIOE_BASE+12) //0x4001180C #define GPIOF_ODR_Addr (GPIOF_BASE+12) //0x40011A0C #define GPIOG_ODR_Addr (GPIOG_BASE+12) //0x40011E0C
#define GPIOA_IDR_Addr (GPIOA_BASE+8) //0x40010808 #define GPIOB_IDR_Addr (GPIOB_BASE+8) //0x40010C08 #define GPIOC_IDR_Addr (GPIOC_BASE+8) //0x40011008 #define GPIOD_IDR_Addr (GPIOD_BASE+8) //0x40011408 #define GPIOE_IDR_Addr (GPIOE_BASE+8) //0x40011808 #define GPIOF_IDR_Addr (GPIOF_BASE+8) //0x40011A08 #define GPIOG_IDR_Addr (GPIOG_BASE+8) //0x40011E08
#define PAout(n) BIT_ADDR(GPIOA_ODR_Addr,n) // #define PAin(n) BIT_ADDR(GPIOA_IDR_Addr,n) //
#define PBout(n) BIT_ADDR(GPIOB_ODR_Addr,n) // #define PBin(n) BIT_ADDR(GPIOB_IDR_Addr,n) //
#define PCout(n) BIT_ADDR(GPIOC_ODR_Addr,n) // #define PCin(n) BIT_ADDR(GPIOC_IDR_Addr,n) //
#define PDout(n) BIT_ADDR(GPIOD_ODR_Addr,n) // #define PDin(n) BIT_ADDR(GPIOD_IDR_Addr,n) //
#define PEout(n) BIT_ADDR(GPIOE_ODR_Addr,n) // #define PEin(n) BIT_ADDR(GPIOE_IDR_Addr,n) //
#define PFout(n) BIT_ADDR(GPIOF_ODR_Addr,n) // #define PFin(n) BIT_ADDR(GPIOF_IDR_Addr,n) //
#define PGout(n) BIT_ADDR(GPIOG_ODR_Addr,n) // #define PGin(n) BIT_ADDR(GPIOG_IDR_Addr,n) // #endif
|
dht11.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| #ifndef __DHT11_H #define __DHT11_H
#include "main.h" #include "sys.h"
typedef uint8_t u8; typedef uint16_t u16; typedef uint32_t u32;
//IO方向设置 #define DHT11_IO_IN() {IODHT22_GPIO_Port->CRH &= 0xFFFFF0FF; IODHT22_GPIO_Port->CRH |= 8 << 8;} // PC10 IN MODE #define DHT11_IO_OUT() {IODHT22_GPIO_Port->CRH &= 0xFFFFF0FF; IODHT22_GPIO_Port->CRH |= 3 << 8;} // PC10 OUT MODE
IO操作函数 #define DHT11_DQ_OUT PCout(10) //数据端口 PC10 #define DHT11_DQ_IN PCin(10) //数据端口 PC10
u8 DHT11_Init(void);//初始化DHT11 u8 DHT11_Read_Data(u8 *temp, u8 *humi); //读取温湿度 u8 DHT11_Read_Byte(void);//读出一个字节 u8 DHT11_Read_Bit(void);//读出一个位 u8 DHT11_Check(void);//检测是否存在DHT11 void DHT11_Rst(void);//复位DHT11 u8 DHT11_Read_Data_Float(float *temp,float *humi);
#endif
|
dht11.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
| #include "dht11.h"
//复位DHT11 void DHT11_Rst(void) { DHT11_IO_OUT(); //SET OUTPUT DHT11_DQ_OUT=0; //拉低DQ delay_ms(20); //拉低至少18ms,(DHT22 500us) DHT11_DQ_OUT=1; //DQ=1 delay_us(30); //主机拉高20~40us }
//等待DHT11的回应 //返回1:未检测到DHT11的存在 //返回0:存在 u8 DHT11_Check(void) { u8 retry=0; DHT11_IO_IN();//SET INPUT while (DHT11_DQ_IN&&retry<100)//DHT11会拉低40~80us { retry++; delay_us(1); }; if(retry>=100)return 1; else retry=0; while (!DHT11_DQ_IN&&retry<100)//DHT11拉低后会再次拉高40~80us { retry++; delay_us(1); }; if(retry>=100)return 1; return 0; }
//从DHT11读取一个位 //返回值:1/0 u8 DHT11_Read_Bit(void) { u8 retry=0; while(DHT11_DQ_IN&&retry<100)//等待变为低电平 { retry++; delay_us(1); } retry=0; while(!DHT11_DQ_IN&&retry<100)//等待变高电平 { retry++; delay_us(1); } delay_us(40);//等待40us if(DHT11_DQ_IN)return 1; else return 0; }
//从DHT11读取一个字节 //返回值:读到的数据 u8 DHT11_Read_Byte(void) { u8 i,dat; dat=0; for (i=0; i<8; i++) { dat<<=1; dat|=DHT11_Read_Bit(); } return dat; }
//从DHT11读取一次数据 //temp:温度值(范围:0~50°) //humi:湿度值(范围:20%~90%) //返回值:0,正常;1,读取失败 u8 DHT11_Read_Data(u8 *temp,u8 *humi) { u8 buf[5]; u8 i; DHT11_Rst(); if(DHT11_Check()==0) { for(i=0; i<5; i++) //读取40位数据 { buf[i]=DHT11_Read_Byte(); } if((buf[0]+buf[1]+buf[2]+buf[3])==buf[4]) { *humi=buf[0]; *temp=buf[2]; } } else return 1; return 0; }
u8 DHT11_Read_Data_Float(float *temp,float *humi) { u8 buf[5]; u8 i; DHT11_Rst(); if(DHT11_Check()==0) { for(i=0; i<5; i++) //读取40位数据 { buf[i]=DHT11_Read_Byte(); } if((buf[0]+buf[1]+buf[2]+buf[3])==buf[4]) { *humi=((buf[0] << 8) + buf[1]) / 10.0; *temp=((buf[2] << 8) + buf[3]) / 10.0; } } else return 1; return 0; }
//初始化DHT11的IO口 DQ 同时检测DHT11的存在 //返回1:不存在 //返回0:存在 u8 DHT11_Init(void) { u8 ret = 1; DHT11_Rst(); //复位DHT11 ret = DHT11_Check(); printf("dht11 init %s. \r\n", ret == 0 ? "ok" : "failed"); return ret; }
|
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!