STM32应用(八)数字温度传感器DS18B20、数字温湿度传感器DHT11(软件模拟I2C)
文章目錄
- 1.DS18B20 數字溫度傳感器實驗
- 1.1 DS18B20簡介
- 1.2 硬件與IO口配置
- 1.3 實物圖與接線
- 1.4 工程配置
- 1.5 驅動和檢測代碼編寫
- 1.5.1 ds18b20.c
- 1.5.2 ds18b20.h
- 1.5.3 main測試
- 1.6 測試結果
- 2.DHT11 數字溫濕度傳感器實驗
- 2.1 DHT11簡介和接線
- 2.2 通信時序簡述
- 2.2.1 數據格式
- 2.2.2 通訊時序
- 2.3.2 數字信號0/1表示方式
- 2.3工程配置
- 2.2.1 輸出GPIO_PG_11
- 2.2.2 打開串口USART1
- 2.2.3 開啟TIM7,與1.4相同
- 2.4 編寫代碼
- 2.4.1 初始化、封裝IO的輸入輸出
- 2.4.2 復位和響應模塊
- 2.4.3 數據的解算
- 2.4.4 測試代碼
- 2.5 測試結果
這兩個傳感器F4的開發板上都沒有,如果要閱讀此博客,請先買好傳感器喲(^U^)ノYO
1.DS18B20 數字溫度傳感器實驗
1.1 DS18B20簡介
1.2 硬件與IO口配置
將 DS18B20 傳感器插入到這個上面就可以通過 STM32 來讀取 DS18B20 的溫度了。
1.3 實物圖與接線
1.4 工程配置
1.開啟GPIOG_9
2.開啟串口
3.開啟TIMX,實現us級定時
在tim.c文件中加入:
1.5 驅動和檢測代碼編寫
驅動代碼移植原子哥。驅動代碼有很多,可以自行修改。
1.5.1 ds18b20.c
#include "ds18b20.h"void DS18B20_IO_IN(void) {GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.Pin = GPIO_PIN_9;GPIO_InitStructure.Mode = GPIO_MODE_INPUT;HAL_GPIO_Init(GPIOG,&GPIO_InitStructure); }void DS18B20_IO_OUT(void) {GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.Pin = GPIO_PIN_9;GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;HAL_GPIO_Init(GPIOG,&GPIO_InitStructure); } //復位DS18B20 void DS18B20_Rst(void) {DS18B20_IO_OUT();DS18B20_DQ_OUT_LOW;delay_us(750);DS18B20_DQ_OUT_HIGH;delay_us(15); } //等待DS18B20的回應 //返回1:未檢測到DS18B20的存在 //返回0:存在 uint8_t DS18B20_Check(void) {uint8_t retry = 0;DS18B20_IO_IN();while(DS18B20_DQ_IN && retry < 200){retry++;delay_us(1);}if(retry >= 200)return 1;elseretry = 0;while(!DS18B20_DQ_IN && retry < 240){retry++;delay_us(1);}if(retry >= 240)return 1;return 0; } //從DS18B20讀取一個位 //返回值:1/0 uint8_t DS18B20_Read_Bit(void) {uint8_t data;DS18B20_IO_OUT();DS18B20_DQ_OUT_LOW;delay_us(2);DS18B20_DQ_OUT_HIGH;DS18B20_IO_IN();delay_us(12);if(DS18B20_DQ_IN)data = 1;elsedata = 0;delay_us(50);return data; } //從DS18B20讀取一個字節 //返回值:讀到的數據 uint8_t DS18B20_Read_Byte(void) {uint8_t i,j,data;data = 0;for(i=1;i<=8;i++){j = DS18B20_Read_Bit();data = (j<<7)|(data>>1);}return data; } //寫一個字節到DS18B20 //dat:要寫入的字節 void DS18B20_Write_Byte(uint8_t data) {uint8_t j;uint8_t testb;DS18B20_IO_OUT();for(j=1;j<=8;j++){testb=data&0x01;data=data>>1;if(testb){DS18B20_DQ_OUT_LOW;delay_us(2);DS18B20_DQ_OUT_HIGH;delay_us(60);}else{DS18B20_DQ_OUT_LOW;delay_us(60);DS18B20_DQ_OUT_HIGH;delay_us(2);}} } //開始溫度轉換 void DS18B20_Start(void) {DS18B20_Rst();DS18B20_Check();DS18B20_Write_Byte(0xcc);DS18B20_Write_Byte(0x44); }uint8_t DS18B20_Init(void) {GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.Pin = GPIO_PIN_9;GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;GPIO_InitStructure.Pull = GPIO_PULLUP;GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;HAL_GPIO_Init(GPIOG,&GPIO_InitStructure);DS18B20_Rst();return DS18B20_Check(); } //初始化DS18B20的IO口 DQ 同時檢測DS的存在 //返回1:不存在 //返回0:存在 short DS18B20_Get_Temperature(void) {uint8_t t;uint8_t TL,TH;short temperature;DS18B20_Start();DS18B20_Rst();DS18B20_Check();DS18B20_Write_Byte(0xcc);DS18B20_Write_Byte(0xbe);TL = DS18B20_Read_Byte();TH = DS18B20_Read_Byte();if(TH>7){TH = ~TH;TL = ~TL;t = 0;}elset = 1;temperature = TH;temperature <<= 8;temperature += TL;temperature = (short)temperature*0.625;if(temperature)return temperature;elsereturn -temperature; }DS18B20讀取溫度需要發送一些命令,
溫度轉換指令:0x44(啟動Ds18b20啟動轉換溫度)。
讀暫存器指令:0xBE(讀取暫存器中的九字節數據)。
1.5.2 ds18b20.h
#ifndef __DS18B20_H #define __DS18B20_H #include "main.h" #include "tim.h"#define DS18B20_DQ_OUT_HIGH HAL_GPIO_WritePin(GPIOG,GPIO_PIN_9,GPIO_PIN_SET) #define DS18B20_DQ_OUT_LOW HAL_GPIO_WritePin(GPIOG,GPIO_PIN_9,GPIO_PIN_RESET)#define DS18B20_DQ_IN HAL_GPIO_ReadPin(GPIOG,GPIO_PIN_11)void DS18B20_IO_IN(void); void DS18B20_IO_OUT(void);uint8_t DS18B20_Init(void); //初始化DS18B20 void DS18B20_Rst(void); //復位DS18B20 uint8_t DS18B20_Check(void);//檢測是否存在DS18B20uint8_t DS18B20_Read_Bit(void);//讀出一個位 uint8_t DS18B20_Read_Byte(void);//讀出一個字節 void DS18B20_Write_Byte(uint8_t data);//寫入一個字節void DS18B20_Start(void);//開始溫度轉換 short DS18B20_Get_Temperature(void); //獲取溫度#endif1.5.3 main測試
/* USER CODE BEGIN 2 */printf("DS18B20 Test!\r\n");while(DS18B20_Init()){printf("DS18B20 checked failed!!!\r\n");HAL_Delay(500);}//DS18B20_Init();/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){temperature=DS18B20_Get_Temperature(); if(temperature < 0)printf("temperature = -%.2f degree\r\n",temperature/10);elseprintf("temperature = %.2f degree\r\n",temperature/10);HAL_Delay(200);/* USER CODE END WHILE *//* USER CODE BEGIN 3 */}1.6 測試結果
2.DHT11 數字溫濕度傳感器實驗
在此將介紹數字溫濕度傳感器DHT11 的使用,該傳感器不但能測溫度,還能測濕度。
2.1 DHT11簡介和接線
DHT11 和 DS18B20 的接口是共用一個的,不過 DHT11 有 4 條腿,需要把 U12 的 4 個接口都用上, 將 DHT11 傳感器插入到這個上面就可以通過 STM32F4來讀取溫濕度值了。
2.2 通信時序簡述
以下內容來自客服給的DHT11說明書。
2.2.1 數據格式
微處理器與 DHT11之間的通訊和同步,采用單總線數據格式,一次通訊時間4ms左右,數據分小數部分和整數部分,具體格式在下面說明,當前小數部分用于以后擴展,現讀出為零.操作流程如下:
一次完整的數據傳輸為40bit,高位先出。
數據格式: 8bit濕度整數數據+8bit濕度小數數據
+8bi溫度整數數據+8bit溫度小數數據
+8bit校驗和
據傳送正確時校驗和數據等于 “8bit濕度整數數據+8bit濕度小數數據+8bi溫度整數數據+8bit溫度小數數據” 所得結果的末8位。
2.2.2 通訊時序
通訊過程如圖:
總線空閑狀態為高電平,主機把總線拉低等待DHT11響應,主機把總線拉低必須大于18毫秒,保證DHT11能檢測到起始信號。 DHT11接收到主機的開始信號后,等待主機開始信號結束,然后發送80us低電平響應信號。主機發送開始信號結束后,延時等待20-40us后,讀取DHT11的響應信號,主機發送開始信號后,可以切換到輸入模式,或者輸出高電平均可,總線由上拉電阻拉高。
開始傳輸信號:
總線為低電平,說明DHT11發送響應信號,DHT11發送響應信號后,再把總線拉高80us,準備發送數據,每一bit數據都以50us低電平時隙開始,高電平的長短定了數據位是0還是1。
2.3.2 數字信號0/1表示方式
2.3工程配置
2.2.1 輸出GPIO_PG_11
2.2.2 打開串口USART1
2.2.3 開啟TIM7,與1.4相同
2.4 編寫代碼
依據時序圖,編寫程序。
2.4.1 初始化、封裝IO的輸入輸出
由于是一個IO口,要滿足輸出和檢測電平,所以用兩個函數來切換引腳的模式,可以使引腳在輸出和輸入之間切換
//初始化DHT11的IO口 DQ 同時檢測DHT11的存在 //返回1:不存在 //返回0:存在 uint8_t DHT11_Init(void) { DHT11_Rst();return DHT11_Check(); } #define DHT11_DQ_OUT_HIGH HAL_GPIO_WritePin(GPIOG,GPIO_PIN_11,GPIO_PIN_SET) #define DHT11_DQ_OUT_LOW HAL_GPIO_WritePin(GPIOG,GPIO_PIN_11,GPIO_PIN_RESET) #define DHT11_DQ_IN HAL_GPIO_ReadPin(GPIOG,GPIO_PIN_11)void DHT11_IO_IN(void) {GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.Pin = GPIO_PIN_11;GPIO_InitStructure.Mode = GPIO_MODE_INPUT;HAL_GPIO_Init(GPIOG,&GPIO_InitStructure); }void DHT11_IO_OUT(void) {GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.Pin = GPIO_PIN_11;GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;HAL_GPIO_Init(GPIOG,&GPIO_Ini2.4.2 復位和響應模塊
//復位DHT11 void DHT11_Rst(void) { DHT11_IO_OUT(); //設置為輸出DHT11_DQ_OUT_LOW; //拉低DQHAL_Delay(20); //拉低至少18msDHT11_DQ_OUT_HIGH; //DQ=1 delay_us(30); //主機拉高20~40us }//等待DHT11的回應 //返回1:未檢測到DHT11的存在 //返回0:存在 uint8_t DHT11_Check(void) { uint8_t retry=0;DHT11_IO_IN(); //設置為輸出 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 uint8_t DHT11_Read_Bit(void) {uint8_t 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);//等待40usif(DHT11_DQ_IN)return 1;else return 0; }//從DHT11讀取一個字節 //返回值:讀到的數據 uint8_t DHT11_Read_Byte(void) { uint8_t i,dat;dat=0;for (i=0;i<8;i++) {dat<<=1; dat|=DHT11_Read_Bit();} return dat; }2.4.3 數據的解算
//從DHT11讀取一次數據 //temp:溫度值(范圍:0~50°) //humi:濕度值(范圍:20%~90%) //返回值:0,正常;1,讀取失敗 uint8_t DHT11_Read_Data(uint16_t *temp,uint16_t *humi) { uint8_t buf[5];uint8_t 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];*temp=(buf[2]<<8) + buf[3];}}else return 1;return 0; }2.4.4 測試代碼
uint16_t temperature; uint16_t humidity;while(DHT11_Init()){printf("DHT11 Checked failed!!!\r\n");HAL_Delay(200);}printf("DHT11 Checked Sucess!!!\r\n"); while (1) {DHT11_Read_Data(&temperature,&humidity);printf("DHT11 Temperature = %d.%d degree\r\n",temperature>>8,temperature&0xff);printf("DHT11 Humidity = %d.%d%%\r\n",humidity>>8,humidity&0xff);HAL_Delay(200); }2.5 測試結果
總結
以上是生活随笔為你收集整理的STM32应用(八)数字温度传感器DS18B20、数字温湿度传感器DHT11(软件模拟I2C)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 数字温度传感器
- 下一篇: 某音直播协议实现技术探讨