Overview
An environmental sensor has an additional feature over a single temperature sensor - that's it has both temperature and humidity data. The DH-XX Series is popular low cost temperature and humidity sensor for most of students and electronic hobbyists. It implements only one bi-directional data and command interface.

DHT22 Digital Temperature and Humidity Sensor from Ali Express
However for high precision environmental data we can select other sensor for instance the AHT10 that implements TWI interface.

AHT10 Sensor Module from Ali Express
The DHT-11 is a temperature and humidity sensor that use only one bidirectional serial data pin. The converted temperature is between 0 and 50 degree Celsius. Its working humidity is between 20 and 90 RH.
STM32F103R6 DHT-11 and LCD Programming in STM32CubeIDE
![]() |
| Program Simulation in Proteus |
The sensor data is very easy to decode using only ones microprocessor digital pin. I don't show the details of serial data transmission here. You can see the post that use a PIC1F84A to decode the signal.
![]() |
| DHT-11 Humidity & Temperature Sensor |
We can get this sensor at local electronics parts store around 1USD. In this example, I use the STM32F103R6 to read environmental data from this sensor. The temperature and humidity will show on a 20x4 character LCD.
/* USER CODE BEGIN Header */ /** ****************************************************************************** * @file : main.c * @brief : Main program body ****************************************************************************** * @attention * * <h2><center>© Copyright (c) 2023 STMicroelectronics. * All rights reserved.</center></h2> * * This software component is licensed by ST under BSD 3-Clause license, * the "License"; You may not use this file except in compliance with the * License. You may obtain a copy of the License at: * opensource.org/licenses/BSD-3-Clause * ****************************************************************************** */ /* USER CODE END Header */ /* Includes ------------------------------------------------------------------*/ #include "main.h" #include "lcd4bits.h" /* Private function prototypes -----------------------------------------------*/ void SystemClock_Config(void); static void MX_GPIO_Init(void); void delay_us(uint8_t dTime){ for(uint8_t i=0;i<dTime;i++) asm("nop"); } uint8_t *readDHT11(void){ uint8_t *dht11; for(uint8_t i=0;i<5;i++) dht11[i]=0; HAL_GPIO_WritePin(GPIOA,DQ_Pin,GPIO_PIN_SET); HAL_Delay(10); HAL_GPIO_WritePin(GPIOA,DQ_Pin,GPIO_PIN_RESET); HAL_Delay(18); HAL_GPIO_WritePin(GPIOA,DQ_Pin,GPIO_PIN_SET); delay_us(45); while(HAL_GPIO_ReadPin(GPIOA,DQ_Pin)==GPIO_PIN_RESET); delay_us(10); while(HAL_GPIO_ReadPin(GPIOA,DQ_Pin)==GPIO_PIN_SET); delay_us(10); for(uint8_t i=0;i<5;i++){ for(uint8_t j=0;j<8;j++){ delay_us(5); while(HAL_GPIO_ReadPin(GPIOA,DQ_Pin)==GPIO_PIN_RESET); delay_us(65); if(HAL_GPIO_ReadPin(GPIOA,DQ_Pin)==GPIO_PIN_SET) { while(HAL_GPIO_ReadPin(GPIOA,DQ_Pin)==GPIO_PIN_SET); dht11[i]|=(1<<7-j); } } delay_us(5); } delay_us(10); /*Check Sum Checking dht11[4] is checksum byte*/ //uint8_t checksum=dht11[0]+dht11[1]+dht11[2]+dht11[3]; uint8_t checksum=0; for(uint8_t i=0;i<4;i++) checksum+=dht11[i]; if(checksum!=dht11[4]){ for(uint8_t i=0;i<5;i++) dht11[i]=0; return; } return dht11; } /** * @brief The application entry point. * @retval int */ int main(void) { /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ HAL_Init(); /* Configure the system clock */ SystemClock_Config(); /* Initialize all configured peripherals */ MX_GPIO_Init(); lcdInit(); lcdClear(); lcdXY(1,1); lcdStr("STM32F103R6 DHT11"); uint8_t *temp,*dht11; uint8_t seconds=0,minutes=0,hours=0; uint16_t days=0;; HAL_Delay(1500); lcdClear(); HAL_Delay(5); //lcdXY(5,1); //lcdStr("Sensor Data:"); lcdXY(1,2); lcdStr("Humidity : "); lcdXY(1,3); lcdStr("Temperature : "); lcdXY(1,4); lcdStr("Checsum(DEC): "); lcdCmd(0x0C); HAL_Delay(5); /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { dht11=readDHT11(); seconds++; if(seconds>=60) {minutes++;seconds=0;} if(minutes>=60) {hours++; minutes=0;} if(hours>=24) {days++; hours=0;} sprintf(temp,"%d Days %d:%d:%d ",days,hours,minutes,seconds%60); lcdXY(1,1); lcdStr(temp); sprintf(temp,"%d RH ",dht11[0]); lcdXY(15,2); lcdStr(temp); sprintf(temp,"%d %cC ",dht11[2],223); lcdXY(15,3); lcdStr(temp); sprintf(temp,"%d ",dht11[4]); lcdXY(15,4); lcdStr(temp); HAL_Delay(700); } /* USER CODE END 3 */ } /** * @brief System Clock Configuration * @retval None */ void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct = {0}; RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; /** Initializes the RCC Oscillators according to the specified parameters * in the RCC_OscInitTypeDef structure. */ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI; RCC_OscInitStruct.HSIState = RCC_HSI_ON; RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI_DIV2; RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL8; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { Error_Handler(); } /** Initializes the CPU, AHB and APB buses clocks */ RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK) { Error_Handler(); } } /** * @brief GPIO Initialization Function * @param None * @retval None */ static void MX_GPIO_Init(void) { GPIO_InitTypeDef GPIO_InitStruct = {0}; /* GPIO Ports Clock Enable */ __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); /*Configure GPIO pin Output Level */ HAL_GPIO_WritePin(GPIOC, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3 |GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7, GPIO_PIN_RESET); /*Configure GPIO pin Output Level */ HAL_GPIO_WritePin(DQ_GPIO_Port, DQ_Pin, GPIO_PIN_RESET); /*Configure GPIO pins : PC0 PC1 PC2 PC3 PC4 PC5 PC6 PC7 */ GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3 |GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); /*Configure GPIO pin : DQ_Pin */ GPIO_InitStruct.Pin = DQ_Pin; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(DQ_GPIO_Port, &GPIO_InitStruct); } /* USER CODE BEGIN 4 */ /* USER CODE END 4 */ /** * @brief This function is executed in case of error occurrence. * @retval None */ void Error_Handler(void) { /* USER CODE BEGIN Error_Handler_Debug */ /* User can add his own implementation to report the HAL error return state */ __disable_irq(); while (1) { } /* USER CODE END Error_Handler_Debug */ } #ifdef USE_FULL_ASSERT /** * @brief Reports the name of the source file and the source line number * where the assert_param error has occurred. * @param file: pointer to the source file name * @param line: assert_param error line source number * @retval None */ void assert_failed(uint8_t *file, uint32_t line) { /* USER CODE BEGIN 6 */ /* User can add his own implementation to report the file name and line number, ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */ /* USER CODE END 6 */ } #endif /* USE_FULL_ASSERT */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
Click here to download its source file.







