网上其实已经介绍了很多dht11这种单线通讯协议
这里就不多重复大佬们的工作了,直接上keil5工程
keil5工程百度网盘链接:https://pan.baidu.com/s/1HDNe7gUM_dplRzR_j17wtA
提取码:xpfj
另外我把dht11.c和dht11.h直接贴在下面,小伙伴可以直接移植到自己的代码中就行了
之后会把stm32的两个实验组合起来实现一个简单的室内温度计,温湿度数据显示在oled上,学以致用嘛
岂不美哉
1 #ifndef __DHT11_H 2 #define __DHT11_H 3 4 #include "stm32f10x.h" 5 #include "delay.h" 6 7 #define HIGH 1 8 #define LOW 0 9 10 #define DHT11_CLK RCC_APB2Periph_GPIOC 11 #define DHT11_PIN GPIO_Pin_4 12 #define DHT11_PORT GPIOC 13 14 //带参宏,可以像内联函数一样使用,输出高电平或低电平 15 #define DHT11_DATA_OUT(a) if (a) 16 GPIO_SetBits(GPIOC,GPIO_Pin_4);17 else 18 GPIO_ResetBits(GPIOC,GPIO_Pin_4) 19 //读取引脚的电平 20 #define DHT11_DATA_IN() GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_4) 21 22 typedef struct 23 { 24 uint8_t humi_int; //湿度的整数部分 25 uint8_t humi_deci; //湿度的小数部分 26 uint8_t temp_int; //温度的整数部分 27 uint8_t temp_deci; //温度的小数部分 28 uint8_t check_sum; //校验和 29 30 }DHT11_Data_TypeDef; 31 32 void DHT11_GPIO_Config(void); 33 static void DHT11_Mode_IPU(void); 34 static void DHT11_Mode_Out_PP(void); 35 uint8_t Read_DHT11(DHT11_Data_TypeDef *DHT11_Data); 36 static uint8_t Read_Byte(void); 37 38 #endif /* __DHT11_H */
bsp_dht11.h
1 #include "bsp_dht11.h" 2 3 4 /* 5 * 函数名:DHT11_GPIO_Config 6 * 描述 :配置DHT11用到的I/O口 7 * 输入 :无 8 * 输出 :无 9 */ 10 void DHT11_GPIO_Config(void) 11 { 12 /*定义一个GPIO_InitTypeDef类型的结构体*/ 13 GPIO_InitTypeDef GPIO_InitStructure; 14 15 /*开启DHT11_PORT的外设时钟*/ 16 RCC_APB2PeriphClockCmd(DHT11_CLK, ENABLE); 17 18 /*选择要控制的DHT11_PORT引脚*/ 19 GPIO_InitStructure.GPIO_Pin = DHT11_PIN; 20 21 /*设置引脚模式为通用推挽输出*/ 22 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 23 24 /*设置引脚速率为50MHz */ 25 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 26 27 /*调用库函数,初始化DHT11_PORT*/ 28 GPIO_Init(DHT11_PORT, &GPIO_InitStructure); 29 30 /* 拉高GPIOC 4 */ 31 GPIO_SetBits(DHT11_PORT, GPIO_Pin_4); 32 } 33 34 /* 35 * 函数名:DHT11_Mode_IPU 36 * 描述 :使DHT11-DATA引脚变为上拉输入模式 37 * 输入 :无 38 * 输出 :无 39 */ 40 static void DHT11_Mode_IPU(void) 41 { 42 GPIO_InitTypeDef GPIO_InitStructure; 43 44 /*选择要控制的DHT11_PORT引脚*/ 45 GPIO_InitStructure.GPIO_Pin = DHT11_PIN; 46 47 /*设置引脚模式为浮空输入模式*/ 48 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU ; 49 50 /*调用库函数,初始化DHT11_PORT*/ 51 GPIO_Init(DHT11_PORT, &GPIO_InitStructure); 52 } 53 54 /* 55 * 函数名:DHT11_Mode_Out_PP 56 * 描述 :使DHT11-DATA引脚变为推挽输出模式 57 * 输入 :无 58 * 输出 :无 59 */ 60 static void DHT11_Mode_Out_PP(void) 61 { 62 GPIO_InitTypeDef GPIO_InitStructure; 63 64 /*选择要控制的DHT11_PORT引脚*/ 65 GPIO_InitStructure.GPIO_Pin = DHT11_PIN; 66 67 /*设置引脚模式为通用推挽输出*/ 68 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 69 70 /*设置引脚速率为50MHz */ 71 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 72 73 /*调用库函数,初始化DHT11_PORT*/ 74 GPIO_Init(DHT11_PORT, &GPIO_InitStructure); 75 } 76 77 /* 78 * 从DHT11读取一个字节,MSB先行 79 */ 80 static uint8_t Read_Byte(void) 81 { 82 uint8_t i, temp=0; 83 84 for(i=0;i<8;i++) 85 { 86 /*每bit以50us低电平标置开始,轮询直到从机发出 的50us 低电平 结束*/ 87 while(DHT11_DATA_IN()==Bit_RESET); 88 89 /*DHT11 以26~28us的高电平表示“0”,以70us高电平表示“1”, 90 *通过检测 x us后的电平即可区别这两个状 ,x 即下面的延时 91 */ 92 delay_us(40); //延时x us 这个延时需要大于数据0持续的时间即可 93 94 if(DHT11_DATA_IN()==Bit_SET)/* x us后仍为高电平表示数据“1” */ 95 { 96 /* 等待数据1的高电平结束 */ 97 while(DHT11_DATA_IN()==Bit_SET); 98 99 temp|=(uint8_t)(0x01<<(7-i)); //把第7-i位置1,MSB先行 100 } 101 else // x us后为低电平表示数据“0” 102 { 103 temp&=(uint8_t)~(0x01<<(7-i)); //把第7-i位置0,MSB先行 104 } 105 } 106 return temp; 107 } 108 /* 109 * 一次完整的数据传输为40bit,高位先出 110 * 8bit 湿度整数 + 8bit 湿度小数 + 8bit 温度整数 + 8bit 温度小数 + 8bit 校验和 111 */ 112 uint8_t Read_DHT11(DHT11_Data_TypeDef *DHT11_Data) 113 { 114 /*输出模式*/ 115 DHT11_Mode_Out_PP(); 116 /*主机拉低*/ 117 DHT11_DATA_OUT(LOW); 118 /*延时18ms*/ 119 delay_ms(18); 120 121 /*总线拉高 主机延时30us*/ 122 DHT11_DATA_OUT(HIGH); 123 124 delay_us(30); //延时30us 125 126 /*主机设为输入 判断从机响应信号*/ 127 DHT11_Mode_IPU(); 128 129 /*判断从机是否有低电平响应信号 如不响应则跳出,响应则向下运行*/ 130 if(DHT11_DATA_IN()==Bit_RESET) 131 { 132 /*轮询直到从机发出 的80us 低电平 响应信号结束*/ 133 while(DHT11_DATA_IN()==Bit_RESET); 134 135 /*轮询直到从机发出的 80us 高电平 标置信号结束*/ 136 while(DHT11_DATA_IN()==Bit_SET); 137 138 /*开始接收数据*/ 139 DHT11_Data->humi_int= Read_Byte(); 140 141 DHT11_Data->humi_deci= Read_Byte(); 142 143 DHT11_Data->temp_int= Read_Byte(); 144 145 DHT11_Data->temp_deci= Read_Byte(); 146 147 DHT11_Data->check_sum= Read_Byte(); 148 149 150 /*读取结束,引脚改为输出模式*/ 151 DHT11_Mode_Out_PP(); 152 /*主机拉高*/ 153 DHT11_DATA_OUT(HIGH); 154 155 /*检查读取的数据是否正确*/ 156 if(DHT11_Data->check_sum == DHT11_Data->humi_int + DHT11_Data->humi_deci + DHT11_Data->temp_int+ DHT11_Data->temp_deci) 157 return SUCCESS; 158 else 159 return ERROR; 160 } 161 else 162 { 163 return ERROR; 164 } 165 } 166 167 /*************************************END OF FILE******************************/
bsp_dht11.c
1 #include "sys.h" 2 #include "delay.h" 3 #include "usart.h" 4 #include "bsp_dht11.h" 5 6 DHT11_Data_TypeDef DHT11_Data; 7 8 uint16_t times=0; 9 10 int main(void) 11 { 12 13 delay_init(); //延时函数初始化 14 uart_init(115200); //串口初始化为115200 15 DHT11_GPIO_Config(); 16 delay_ms(500); 17 while(1) 18 { 19 /*调用Read_DHT11读取温湿度,若成功则输出该信息*/ 20 if( Read_DHT11(&DHT11_Data)==SUCCESS) 21 { 22 printf("\r\n读取DHT11成功!\r\n\r\n湿度为%d.%d %RH ,温度为 %d.%d℃ \r\n",23 DHT11_Data.humi_int,DHT11_Data.humi_deci,DHT11_Data.temp_int,DHT11_Data.temp_deci); 24 delay_ms(1500); /* 1s 读取一次温度值 */ 25 } 26 else 27 { 28 printf("Read DHT11 ERROR!\r\n");//读取数据失败,串口打印:Read DHT11 ERROR. 29 30 } 31 } 32 }
main.c
把在串口助手显示的效果图也贴出来
坚持天天更新,今天也是充满希望的一天啊
原文地址:https://www.cnblogs.com/hjf-log/p/stm32-dht11.html
时间: 2024-11-09 22:30:56