0
\$\begingroup\$

I'm trying to use a DHT22 (temperature and humidity sensor). Here is its datasheet: DHT22 Datasheet

In first few seconds, I can get values. But after a while it gets stuck in here:

it stucks in here

So I tried to implement a timeout to prevent this. I start another timer (TIM14,) and after 2 seconds I try pull the pin to low manually.

But as a result, variable 'i' (which is in the HAL_TIM_PeriodElapsedCallback function) never increments. So, again the code gets stuck in same line.

How can I implement a timeout to pull the pin low after a while?

EDIT: I learned that​ callbacks are operating in interrupt context. So I should change my alghoritm - but how can I do this without using another timer?

 /* Includes ------------------------------------------------------------------*/
#include "main.h"
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/
TIM_HandleTypeDef htim3;
TIM_HandleTypeDef htim14;

/* USER CODE BEGIN PV */
uint8_t Rh_byte1, Rh_byte2, Temp_byte1, Temp_byte2;
uint16_t sum, RH, TEMP;
uint8_t check = 0;
uint8_t volatile k=0;
/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_TIM3_Init(void);
static void MX_TIM14_Init(void);
/* USER CODE BEGIN PFP */
void set_gpio_output (void);
void set_gpio_input (void);
void delay_us(uint32_t);
/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */


void DHT22_start (void)
{
    set_gpio_output ();  // set the pin as output
    HAL_GPIO_WritePin (GPIOA, GPIO_PIN_2, 0);   // pull the pin low
    delay_us(500);   // wait for 500us
    HAL_GPIO_WritePin (GPIOA, GPIO_PIN_2, 1);   // pull the pin high
    delay_us(30);   // wait for 30us
    set_gpio_input ();   // set as input
}

void check_response (void)
{
     delay_us(40);
    if (!(HAL_GPIO_ReadPin (GPIOA, GPIO_PIN_2)))
    {
        delay_us (80);
        if ((HAL_GPIO_ReadPin (GPIOA, GPIO_PIN_2))) check = 1;
    }
    while ((HAL_GPIO_ReadPin (GPIOA, GPIO_PIN_2)));   // wait for the pin to go low
}

uint8_t read_data (void)
{
    uint8_t i,j;
    for (j=0;j<8;j++)
    {
        while (!(HAL_GPIO_ReadPin (GPIOA, GPIO_PIN_2)));   // wait for the pin to go high
        delay_us(40);   // wait for 40 us
        if ((HAL_GPIO_ReadPin (GPIOA, GPIO_PIN_2)) == 0)   // if the pin is low
        {
            i&= ~(1<<(7-j));   // write 0
        }
        else i|= (1<<(7-j));  // if the pin is high, write 1
        HAL_TIM_Base_Start(&htim14); //start timer
        while ((HAL_GPIO_ReadPin (GPIOA, GPIO_PIN_2))); //IT STUCKS HERE
        HAL_TIM_Base_Stop(&htim14); //stop timer

    }
    return i;
}

GPIO_InitTypeDef GPIO_InitStruct = {0};

/*Configure GPIO pin : PA1 */
void set_gpio_input (void)
 {
 GPIO_InitStruct.Pin = GPIO_PIN_2;
 GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
 GPIO_InitStruct.Pull = GPIO_NOPULL;
 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
 }

 /*Configure GPIO pin : PA2 */
 void set_gpio_output (void)
 {
 GPIO_InitStruct.Pin = GPIO_PIN_2;
 GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
 GPIO_InitStruct.Pull = GPIO_NOPULL;
 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
 }

 void delay_ticks(uint32_t ticks)
 { //SYSTICK TIMER 24 BIT
     SysTick->LOAD = ticks;
     SysTick->VAL = 0;
     SysTick->CTRL = SysTick_CTRL_ENABLE_Msk;
     SysTick->CTRL &= ~SYSTICK_CLKSOURCE_HCLK_DIV8;
     SysTick->CTRL |= SYSTICK_CLKSOURCE_HCLK;
     // COUNTFLAG is a bit that is set to 1 when counter reaches 0.
     // It's automatically cleared when read.

     while ((SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk) == 0);
     SysTick->CTRL = 0;

 }

 void delay_us(uint32_t us)
 {
     delay_ticks(us * 8); //8 e boldun
 }

 static inline void delay_ms(uint32_t ms)
  {
      delay_ticks(ms * 8000); //8 e boldun
  }

 void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
 {
    if(htim->Instance == TIM3)
    {

        DHT22_start ();
        check_response ();
        Rh_byte1 = read_data ();
        Rh_byte2 = read_data ();
        Temp_byte1 = read_data ();
        Temp_byte2 = read_data ();
        sum = read_data();

        TEMP = ((Temp_byte1<<8)|Temp_byte2);
        RH = ((Rh_byte1<<8)|Rh_byte2);
        HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_4);
    }

    if(htim->Instance == TIM14)
    {
        k++; //increment i in every 500 ms
        if(k==4) //if it reaches two seconds pull the pin to low
        {
        HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_RESET);
        i=0;
        }

 }
 }

/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_TIM3_Init();
  MX_TIM14_Init();
  /* USER CODE BEGIN 2 */
  HAL_TIM_Base_Start_IT(&htim3);
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */

  }
  /* 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 CPU, AHB and APB busses clocks 
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
  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_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSE;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
  {
    Error_Handler();
  }
}

/**
  * @brief TIM3 Initialization Function
  * @param None
  * @retval None
  */
static void MX_TIM3_Init(void)
{

  /* USER CODE BEGIN TIM3_Init 0 */

  /* USER CODE END TIM3_Init 0 */

  TIM_ClockConfigTypeDef sClockSourceConfig = {0};
  TIM_MasterConfigTypeDef sMasterConfig = {0};

  /* USER CODE BEGIN TIM3_Init 1 */

  /* USER CODE END TIM3_Init 1 */
  htim3.Instance = TIM3;
  htim3.Init.Prescaler = 7999;
  htim3.Init.CounterMode = TIM_COUNTERMODE_DOWN;
  htim3.Init.Period = 3999;
  htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_Base_Init(&htim3) != HAL_OK)
  {
    Error_Handler();
  }
  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  if (HAL_TIM_ConfigClockSource(&htim3, &sClockSourceConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN TIM3_Init 2 */

  /* USER CODE END TIM3_Init 2 */

}

/**
  * @brief TIM14 Initialization Function
  * @param None
  * @retval None
  */
static void MX_TIM14_Init(void)
{

  /* USER CODE BEGIN TIM14_Init 0 */

  /* USER CODE END TIM14_Init 0 */

  /* USER CODE BEGIN TIM14_Init 1 */

  /* USER CODE END TIM14_Init 1 */
  htim14.Instance = TIM14;
  htim14.Init.Prescaler = 7999;
  htim14.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim14.Init.Period = 499;
  htim14.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim14.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_Base_Init(&htim14) != HAL_OK)
  {
    Error_Handler();
  }    
}
static void MX_GPIO_Init(void)
{ 
  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOF_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();
  /*Configure GPIO pin Output Level */
}  
\$\endgroup\$
  • \$\begingroup\$ You should declare i as volatile. \$\endgroup\$ – Ron Beyer Oct 18 '19 at 13:08
  • \$\begingroup\$ thank you, i did but still it doesn't increment ever \$\endgroup\$ – Hernan Crespo Oct 18 '19 at 18:07
  • \$\begingroup\$ Why does it get stuck? \$\endgroup\$ – Bruce Abbott Oct 18 '19 at 19:18
  • \$\begingroup\$ Unfortunately, I could not understand. \$\endgroup\$ – Hernan Crespo Oct 18 '19 at 20:28
0
\$\begingroup\$

I added these two lines and now it works.

uint32_t first_val = TIM3->CNT; 
while ((HAL_GPIO_ReadPin (GPIOA, GPIO_PIN_2 && (( TIM3->CNT - first_val) < 8000)  )));//continue after 1ms 
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.