2021-02-26 01:03 PM
2021-03-01 02:13 AM
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
2021-03-01 03:03 AM
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.
2021-03-01 03:07 AM - edited 2024-05-21 03:14 AM
"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:
2021-03-01 03:29 AM
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
2021-03-01 04:16 AM
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.
2021-03-02 03:11 AM
@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
2021-03-02 03:17 AM
If you already have a working platform, record the bus signals in both instances (F0/F4 vs. F7/H7), and compare them.
2021-03-02 03:31 AM
"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.
2021-03-02 03:41 AM - edited 2024-04-10 07:23 AM
"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.