網上其實已經介紹了很多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 */

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******************************/

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 }
把在串口助手顯示的效果圖也貼出來
堅持天天更新,今天也是充滿希望的一天啊