0
\$\begingroup\$

I am new enough with STM32 programming. But now I am working with a environmental parameter monitoring module based on STM32F401RE development board. Now I am facing a strange problem. When I try to display data from DHT11 module to OLED screen (ssd1306), the data is visible on the screen but does not update at all. When I press the reset button on the board, then the data is updated and I can see the changes. Maybe someone was facing a similar problem? Maybe I'm facing with a badly configured clock? I add my code:

main.c

 /* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2021 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"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "fonts.h"
#include "ssd1306.h"
#include "dwt_stm32_delay.h"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/
I2C_HandleTypeDef hi2c1;

UART_HandleTypeDef huart2;

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_USART2_UART_Init(void);
static void MX_I2C1_Init(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

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

uint8_t Rh_byte1, Rh_byte2, Temp_byte1, Temp_byte2;
uint16_t sum, RH, TEMP;
int temp_low, temp_high, rh_low, rh_high;
char temp_char1[2], temp_char2, rh_char1[2], rh_char2;
uint8_t check = 0;
GPIO_InitTypeDef GPIO_InitStruct;
void set_gpio_output (void)
{
    /*Configure GPIO pin output: PA2 */
  //GPIO_InitStruct.Pin = GPIO_PIN_1;
    GPIO_InitStruct.Pin = GPIO_PIN_4;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}

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

void DHT11_start (void)
{
    set_gpio_output ();  // set the pin as output
//  HAL_GPIO_WritePin (GPIOA, GPIO_PIN_1, 0);   // pull the pin low
    HAL_GPIO_WritePin (GPIOA, GPIO_PIN_4, 0);   // pull the pin low
    DWT_Delay_us (18000);   // wait for 18ms
    set_gpio_input ();   // set as input
}

void check_response (void)
{
    DWT_Delay_us (40);
    //if (!(HAL_GPIO_ReadPin (GPIOA, GPIO_PIN_1)))
    if (!(HAL_GPIO_ReadPin (GPIOA, GPIO_PIN_4)))
    {
        DWT_Delay_us (80);
        //if ((HAL_GPIO_ReadPin (GPIOA, GPIO_PIN_1))) check = 1;
        if ((HAL_GPIO_ReadPin (GPIOA, GPIO_PIN_4))) check = 1;
    }
    //while ((HAL_GPIO_ReadPin (GPIOA, GPIO_PIN_1)));   // wait for the pin to go low
    while ((HAL_GPIO_ReadPin (GPIOA, GPIO_PIN_4)));   // 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_1)));   // wait for the pin to go high
        while (!(HAL_GPIO_ReadPin (GPIOA, GPIO_PIN_4)));   // wait for the pin to go high
        DWT_Delay_us (40);   // wait for 40 us
        //if ((HAL_GPIO_ReadPin (GPIOA, GPIO_PIN_1)) == 0)   // if the pin is low
        if ((HAL_GPIO_ReadPin (GPIOA, GPIO_PIN_4)) == 0)   // 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 (GPIOA, GPIO_PIN_1)));  // wait for the pin to go low
        while ((HAL_GPIO_ReadPin (GPIOA, GPIO_PIN_4)));  // wait for the pin to go low
    }
    return i;
}
/* 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_USART2_UART_Init();
  MX_I2C1_Init();
  /* USER CODE BEGIN 2 */
  DWT_Delay_Init();
  SSD1306_Init();  // initialise
  /* USER CODE END 2 */

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

    /* USER CODE BEGIN 3 */
    DHT11_start ();
    check_response ();
    Rh_byte1 = read_data ();
    Rh_byte2 = read_data ();
    Temp_byte1 = read_data ();
    Temp_byte2 = read_data ();
    sum = read_data();
    if (sum == (Rh_byte1+Rh_byte2+Temp_byte1+Temp_byte2))    // if the data is correct
    {

        SSD1306_GotoXY (0,0);
        SSD1306_Puts("TEMP:- ",&Font_11x18, 1);
        SSD1306_Putc((Temp_byte1/10)+48,&Font_11x18, 1);
        SSD1306_Putc((Temp_byte1%10)+48,&Font_11x18, 1);
        SSD1306_Puts("C",&Font_11x18, 1);
        //display
        SSD1306_GotoXY (0,30);
        SSD1306_Puts("RH:- ",&Font_11x18, 1);
        SSD1306_Putc((Rh_byte1/10)+48,&Font_11x18, 1);
        SSD1306_Putc((Rh_byte1%10)+48,&Font_11x18, 1);
        SSD1306_Puts("%",&Font_11x18, 1);
        SSD1306_UpdateScreen();
        //HAL_Delay (1000);
        }
    }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Configure the main internal regulator output voltage 
  */
  __HAL_RCC_PWR_CLK_ENABLE();
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE2);
  /** Initializes the CPU, AHB and APB busses clocks 
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  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_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV2;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

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

/**
  * @brief I2C1 Initialization Function
  * @param None
  * @retval None
  */
static void MX_I2C1_Init(void)
{

  /* USER CODE BEGIN I2C1_Init 0 */

  /* USER CODE END I2C1_Init 0 */

  /* USER CODE BEGIN I2C1_Init 1 */

  /* USER CODE END I2C1_Init 1 */
  hi2c1.Instance = I2C1;
  hi2c1.Init.ClockSpeed = 400000;
  hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;
  hi2c1.Init.OwnAddress1 = 0;
  hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
  hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
  hi2c1.Init.OwnAddress2 = 0;
  hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
  hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
  if (HAL_I2C_Init(&hi2c1) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN I2C1_Init 2 */

  /* USER CODE END I2C1_Init 2 */

}

/**
  * @brief USART2 Initialization Function
  * @param None
  * @retval None
  */
static void MX_USART2_UART_Init(void)
{

  /* USER CODE BEGIN USART2_Init 0 */

  /* USER CODE END USART2_Init 0 */

  /* USER CODE BEGIN USART2_Init 1 */

  /* USER CODE END USART2_Init 1 */
  huart2.Instance = USART2;
  huart2.Init.BaudRate = 115200;
  huart2.Init.WordLength = UART_WORDLENGTH_8B;
  huart2.Init.StopBits = UART_STOPBITS_1;
  huart2.Init.Parity = UART_PARITY_NONE;
  huart2.Init.Mode = UART_MODE_TX_RX;
  huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart2.Init.OverSampling = UART_OVERSAMPLING_16;
  if (HAL_UART_Init(&huart2) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN USART2_Init 2 */

  /* USER CODE END USART2_Init 2 */

}

/**
  * @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_GPIOH_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_RESET);

  /*Configure GPIO pin : B1_Pin */
  GPIO_InitStruct.Pin = B1_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(B1_GPIO_Port, &GPIO_InitStruct);

  /*Configure GPIO pin : PA4 */
  GPIO_InitStruct.Pin = GPIO_PIN_4;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  /*Configure GPIO pin : LD2_Pin */
  GPIO_InitStruct.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(LD2_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 */

  /* 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,
     tex: 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****/

Clock config

enter image description here

\$\endgroup\$
3
  • 1
    \$\begingroup\$ You should use some kind of debugger. If you don't have a hardware for that then employ some other debugging techniques, such as GPIO output connected to LEDs or testpoints accessible with a scope probe. Or even some serial port output. We definitely can't debug the whole design for you. \$\endgroup\$ – Eugene Sh. Apr 20 at 16:37
  • \$\begingroup\$ If the received checksum is a byte, the sum of four previous bytes can be larger than the checksum and they might not match. What if you simply update the screen every time, and even include a counter that advances by one each loop to see where it gets stuck or does it run. Also, which board is it? If it has a debugger, you should already be debugging it. \$\endgroup\$ – Justme Apr 20 at 16:52
  • 4
    \$\begingroup\$ @remark Which while loop? there are several \$\endgroup\$ – Voltage Spike Apr 20 at 16:58
0
\$\begingroup\$

I think I solved the problem. I can't say that I did a very big job, but I tried to launch all the DHT functions one after the other, and see if the main loop gets stuck. The code did not crash at any point.

Then I slightly changed the functions of DHT sensor, and then the whole sequence of DHT code was like this:

uint8_t Rh_byte1, Rh_byte2, Temp_byte1, Temp_byte2;
uint16_t sum, RH, TEMP;
int temp_low, temp_high, rh_low, rh_high;
char temp_char1[2], temp_char2, rh_char1[2], rh_char2;
uint8_t check = 0;
GPIO_InitTypeDef GPIO_InitStruct;



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



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



void DHT11_start (void)
{
    DWT_Delay_Init();
    set_gpio_output ();  // set the pin as output
    HAL_GPIO_WritePin (GPIOA, GPIO_PIN_4, 0);   // pull the pin low
    DWT_Delay_us (18000);   // wait for 18ms
    HAL_GPIO_WritePin (GPIOA, GPIO_PIN_4, 1);   // pull the pin high
    DWT_Delay_us (20);   // wait for 20us
    set_gpio_input ();   // set as input
}



void check_response (void)
{
    DWT_Delay_us (40);
    if (!(HAL_GPIO_ReadPin (GPIOA, GPIO_PIN_4)))
    {
        DWT_Delay_us (80);
        if ((HAL_GPIO_ReadPin (GPIOA, GPIO_PIN_4))) check = 1;
        else check = -1;
    }
    while ((HAL_GPIO_ReadPin (GPIOA, GPIO_PIN_4)));   // wait for the pin to go low
    //if ((HAL_GPIO_ReadPin (GPIOA, GPIO_PIN_4)));   // wait for the pin to go low
    //return check;
}



uint8_t read_data (void)
{
    uint8_t i,j;
    for (j=0;j<8;j++)
    {
        while (!(HAL_GPIO_ReadPin (GPIOA, GPIO_PIN_4)));   // wait for the pin to go high
        //if (!(HAL_GPIO_ReadPin (GPIOA, GPIO_PIN_4)));   // wait for the pin to go high
        DWT_Delay_us (40);   // wait for 40 us
        if (!(HAL_GPIO_ReadPin (GPIOA, GPIO_PIN_4)))   // 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 (GPIOA, GPIO_PIN_4)));  // wait for the pin to go low
        //if ((HAL_GPIO_ReadPin (GPIOA, GPIO_PIN_4)));  // wait for the pin to go low
    }
    return i;
}

In my main while loop I added LED blinking routine and also I started sending test messages to the terminal:

while (1)
  {

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

if (sum == (Rh_byte1+Rh_byte2+Temp_byte1+Temp_byte2))    // if the data is correct
    {
        SSD1306_GotoXY (0,0);
        SSD1306_Puts("TEMP:- ",&Font_11x18, 1);
        SSD1306_Putc((Temp_byte1/10)+48,&Font_11x18, 1);
        SSD1306_Putc((Temp_byte1%10)+48,&Font_11x18, 1);
        SSD1306_Puts("C",&Font_11x18, 1);
        //display
        SSD1306_GotoXY (0,30);
        SSD1306_Puts("RH:- ",&Font_11x18, 1);
        SSD1306_Putc((Rh_byte1/10)+48,&Font_11x18, 1);
        SSD1306_Putc((Rh_byte1%10)+48,&Font_11x18, 1);
        SSD1306_Puts("%",&Font_11x18, 1);
        SSD1306_UpdateScreen();
        HAL_Delay (1000);
        //NVIC_SystemReset(); //worst case scenario

        // Green on-board LED
        HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET);
        HAL_Delay (1000);
        //DWT_Delay_us (40);
        HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET);
        HAL_UART_Transmit(&huart2, "1", 10, 100);
        HAL_Delay (1000);

     }
  }

So far, after connecting the power supply and restarting the board, the program is running smoothly without much interruption.

\$\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.