cancel
Showing results for 
Search instead for 
Did you mean: 

has anyone try to DHT11 or DHT22 with stm32f7 or stm32H7?

M abouhasem
Associate II
 
18 REPLIES 18
Eleon BORLINI
ST Employee

Hi @M abouhasem​ ,

I've added STM32 topics since I'm expert only of ST sensors and DHT11/DHT22 are not from ST.

I see that these sensors uses a Serial Interface (Single-Wire Two-Way) communication protocol: you can find a description of the use of the SWPMI interface on the H7 MCU family at this link (pdf) or this other link (video).

You can find examples on the use of the SWPMI in the STM32Cube MCU Package for STM32F7 and STM32H7 series (drivers in the HAL layer).

-Eleon

As with any other sensor, the sensor itself neither knows nor cares what microcontroller you use; all it sees is what happens on the wires - so what you need to do is to program your microcontroller - whatever it is - to generate the appropriate levels with the appropriate timings as specified in the sensor's documentation.

http://www.8052mcu.com/forum/read/160143

"I see that these sensors uses a Serial Interface (Single-Wire Two-Way) communication protocol"

 

Most of these "single-wire" protocols are proprietary - did you see any reason to believe that the specific protocol used by these sensors is compatible with the SWPMI on the H7 ?

 

@M abouhasem​ - Being proprietary, it is quite likely that any code you find on the interwebs will be bit-banging it, therefore that should be easy to port to any other microcontroller - the only bits specific to the particular microcontroller would be:

  1. How to pull a pin low;
  2. How to release a pin (Hi-Z);
  3. How to read the state of a pin;
  4. How to define the timing

Hi @Andrew Neil​ ,

No, I'm not sure, that has to be checked

I'm not an expert, that's why I added STM32 topics for support from my colleagues.

The bit-banging approach is anyway an solution, maybe a little tricky but effective.

-Eleon

Looking at the DHT22 datasheet, it looks rather similar to the Maxim (formerly Dallas) 1-Wire (TM) - it looks nothing like the SWPMI  described in the linked documents:

"The SWP is full-duplex on a single wire thanks to the following principle. The S1 signal is transmitted in the voltage domain from master to slave. The S2 signal is transmitted in the current domain from slave to master."

Apart from the initial low pulse, the DHT interface is output-only from the sensor, and is entirely voltage based.

M abouhasem
Associate II

@Andrew Neil​ 

I used that code with stm32f4 and stm32f0 and it worked fine I have used it with both F7 and H7 MCU and they couldn't fetch a response I have tried with both modes Pullup pin and No pull. then I tried it with timer input capture mode with Kindly review the sequence of Code below.

#include "main.h"
#include "string.h"
 
 
TIM_HandleTypeDef htim2;
 
UART_HandleTypeDef huart3;
 
 
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_TIM2_Init(void);
static void MX_USART3_UART_Init(void);
/* USER CODE BEGIN PFP */
uint16_t g[100];
 
void delay (uint16_t time)
{
	/* change your code here for the delay in microseconds */
 
	__HAL_TIM_SET_COUNTER(&htim2, 0);
	while ((__HAL_TIM_GET_COUNTER(&htim2))<time);
}
 
uint8_t Rh_byte1, Rh_byte2, Temp_byte1, Temp_byte2;
uint16_t SUM, RH, TEMP;
 
float Temperature = 0;
float Humidity = 0;
uint8_t Presence = 0;
 
void Set_Pin_Output (GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin)
{
	GPIO_InitTypeDef GPIO_InitStruct = {0};
	GPIO_InitStruct.Pin = GPIO_Pin;
	GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
	GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
	HAL_GPIO_Init(GPIOx, &GPIO_InitStruct);
}
 
void Set_Pin_Input (GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin)
{
	GPIO_InitTypeDef GPIO_InitStruct = {0};
	GPIO_InitStruct.Pin = GPIO_Pin;
	GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
	GPIO_InitStruct.Pull = GPIO_PULLUP;
	HAL_GPIO_Init(GPIOx, &GPIO_InitStruct);
}
 
void DHT11_Start (void)
{
	Set_Pin_Output(DHT22_GPIO_Port, DHT22_Pin);  // set the pin as output
	HAL_GPIO_WritePin (DHT22_GPIO_Port, DHT22_Pin, 0);   // pull the pin low
	delay (18000);   // wait for 18ms
    HAL_GPIO_WritePin (DHT22_GPIO_Port, DHT22_Pin, 1);   // pull the pin high
	delay (20);   // wait for 20us
	Set_Pin_Input(DHT22_GPIO_Port, DHT22_Pin);    // set as input
}
 
uint8_t DHT11_Check_Response (void)
{
	uint8_t Response = 0;
	delay (40);
	if (!(HAL_GPIO_ReadPin (DHT22_GPIO_Port, DHT22_Pin)))
	{
		delay (80);
		if ((HAL_GPIO_ReadPin (DHT22_GPIO_Port, DHT22_Pin))) Response = 1;
		else Response = -1; // 255
	}
	while ((HAL_GPIO_ReadPin (DHT22_GPIO_Port, DHT22_Pin)));   // wait for the pin to go low
 
	return Response;
}
 
uint8_t DHT11_Read (void)
{
	uint8_t i,j;
	for (j=0;j<8;j++)
	{
		while (!(HAL_GPIO_ReadPin (DHT22_GPIO_Port, DHT22_Pin)));   // wait for the pin to go high
		delay (40);   // wait for 40 us
		if (!(HAL_GPIO_ReadPin (DHT22_GPIO_Port, DHT22_Pin)))   // if the pin is low
		{
			i&= ~(1<<(7-j));   // write 0
		}
		else i|= (1<<(7-j));  // if the pin is high, write 1
		while ((HAL_GPIO_ReadPin (DHT22_GPIO_Port, DHT22_Pin)));  // wait for the pin to go low
	}
	return i;
}
 
int main(void)
{
 
 
  HAL_Init();
 
  SystemClock_Config();
  MX_GPIO_Init();
  MX_TIM2_Init();
  MX_USART3_UART_Init();
  /* USER CODE BEGIN 2 */
  HAL_TIM_Base_Init(&htim2);
  HAL_TIM_Base_Start_IT(&htim2);
  uint32_t i=0;
	char buffer[1999];
 
  /* USER CODE END 2 */
 
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
	  HAL_GPIO_TogglePin(LD2_GPIO_Port,LD2_Pin);
	  delay(50000);
	  DHT11_Start();
   //  Set_Pin_Input(DHT22_GPIO_Port, DHT22_Pin);    // set as input
	  Presence = DHT11_Check_Response();
	  Rh_byte1 = DHT11_Read ();
	  Rh_byte2 = DHT11_Read ();
	  Temp_byte1 = DHT11_Read ();
	  Temp_byte2 = DHT11_Read ();
	  SUM = DHT11_Read();
	  TEMP = Temp_byte1;
	  RH = Rh_byte1;
	  //Temperature = (float) TEMP;
	  // Humidity = (float) RH;
	  sprintf(buffer,"temp=%d.%d hum=%d.%d\n\r",Temp_byte1,Temp_byte2,Rh_byte1,Rh_byte2);
	  HAL_UART_Transmit(&huart3,buffer,strlen(buffer),1000);
	//  HAL_Delay(1000);
    /* USER CODE END WHILE */
 
    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}
 
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
  RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
 
  /** Supply configuration update enable 
  */
  HAL_PWREx_ConfigSupply(PWR_LDO_SUPPLY);
  /** Configure the main internal regulator output voltage 
  */
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
 
  while(!__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY)) {}
  /** Initializes the CPU, AHB and APB busses clocks 
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLM = 1;
  RCC_OscInitStruct.PLL.PLLN = 120;
  RCC_OscInitStruct.PLL.PLLP = 2;
  RCC_OscInitStruct.PLL.PLLQ = 20;
  RCC_OscInitStruct.PLL.PLLR = 2;
  RCC_OscInitStruct.PLL.PLLRGE = RCC_PLL1VCIRANGE_3;
  RCC_OscInitStruct.PLL.PLLVCOSEL = RCC_PLL1VCOWIDE;
  RCC_OscInitStruct.PLL.PLLFRACN = 0;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
  /** Initializes the CPU, AHB and APB busses clocks 
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2
                              |RCC_CLOCKTYPE_D3PCLK1|RCC_CLOCKTYPE_D1PCLK1;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.SYSCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB3CLKDivider = RCC_APB3_DIV2;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_APB1_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_APB2_DIV2;
  RCC_ClkInitStruct.APB4CLKDivider = RCC_APB4_DIV2;
 
  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK)
  {
    Error_Handler();
  }
  PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_USART3|RCC_PERIPHCLK_USB;
  PeriphClkInitStruct.Usart234578ClockSelection = RCC_USART234578CLKSOURCE_D2PCLK1;
  PeriphClkInitStruct.UsbClockSelection = RCC_USBCLKSOURCE_PLL;
  if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
  /** Enable USB Voltage detector 
  */
  HAL_PWREx_EnableUSBVoltageDetector();
}
 
 
 
 
 
 
static void MX_TIM2_Init(void)
{
 
 
  TIM_ClockConfigTypeDef sClockSourceConfig = {0};
  TIM_MasterConfigTypeDef sMasterConfig = {0};
 
 
  htim2.Instance = TIM2;
  htim2.Init.Prescaler = 239;//timer APB1 timer perpherial 240 MHz 
  htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim2.Init.Period = 0xFFFF;
  htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
  {
    Error_Handler();
  }
  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }
 
 
}
 
/**
  * @brief USART3 Initialization Function
  * @param None
  * @retval None
  */
static void MX_USART3_UART_Init(void)
{
 
 
  huart3.Instance = USART3;
  huart3.Init.BaudRate = 115200;
  huart3.Init.WordLength = UART_WORDLENGTH_8B;
  huart3.Init.StopBits = UART_STOPBITS_1;
  huart3.Init.Parity = UART_PARITY_NONE;
  huart3.Init.Mode = UART_MODE_TX_RX;
  huart3.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart3.Init.OverSampling = UART_OVERSAMPLING_16;
  huart3.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
  huart3.Init.ClockPrescaler = UART_PRESCALER_DIV1;
  huart3.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
  if (HAL_UART_Init(&huart3) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_UARTEx_SetTxFifoThreshold(&huart3, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_UARTEx_SetRxFifoThreshold(&huart3, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_UARTEx_DisableFifoMode(&huart3) != HAL_OK)
  {
    Error_Handler();
  }
 
 
}
 
static void MX_GPIO_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};
 
  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOC_CLK_ENABLE();
  __HAL_RCC_GPIOH_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();
  __HAL_RCC_GPIOD_CLK_ENABLE();
  __HAL_RCC_GPIOG_CLK_ENABLE();
 
  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOB, LD3_Pin|LD2_Pin, GPIO_PIN_RESET);
 
  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(USB_PowerSwitchOn_GPIO_Port, USB_PowerSwitchOn_Pin, GPIO_PIN_RESET);
 
  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOD, GPIO_PIN_7, GPIO_PIN_RESET);
 
  /*Configure GPIO pin : USER_Btn_Pin */
  GPIO_InitStruct.Pin = USER_Btn_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(USER_Btn_GPIO_Port, &GPIO_InitStruct);
 
  /*Configure GPIO pins : LD3_Pin LD2_Pin */
  GPIO_InitStruct.Pin = LD3_Pin|LD2_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
  
  /*Configure GPIO pin : PD7 */
  GPIO_InitStruct.Pin = 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(GPIOD, &GPIO_InitStruct);
 
}
 
void Error_Handler(void)
{
 
}
 #ifdef  USE_FULL_ASSERT
void assert_failed(uint8_t *file, uint32_t line)
{ 
 
}
#endif
 

If you already have a working platform, record the bus signals in both instances (F0/F4 vs. F7/H7), and compare them.

"I used that code with stm32f4 and stm32f0 and it worked fine"

So, as @Ozone​ says, use an oscilloscope to view & record what is happening on the wire when it works.

Check that everything (timings, voltage levels, etc) in that case is well within the specifications - ie, you are not marginal.

"with both F7 and H7 MCU and they couldn't fetch a response"

Again, use an oscilloscope to view & record what is happening on the wire when it does not work. Compare what is happening against the requirements of the specification; also compare what is happening against your "working" case.

"Kindly review the sequence of Code below"

 

A couple of things stand out

/* change your code here for the delay in microseconds */

That is an instruction to you that you need to do something - have you done it?

If you have done it, then take that comment out!

Preferably, replace it with a description of how you achieved that - and how do you know it's correct?

 

 

HAL_GPIO_WritePin (DHT22_GPIO_Port, DHT22_Pin, 1);   // pull the pin high

That is wrong: you do not pull the line high - you release the line, and let the pullup pull it high.

If you actively drive it high, the sensor will not be able to pull low.