Skip to main content
Graduate II
October 19, 2023
Solved

STM32F042K6 USART not working

  • October 19, 2023
  • 8 replies
  • 7026 views
The STM32F042K6 has been giving me issues lately when it comes to using the UART module. USART1 is not working and USART2 only transmits. Has anyone encountered the same problem? I have attached a sample code I was using to test USART2 for both transmission and reception.
 
 
#include "main.h"


/* Private variables ---------------------------------------------------------*/
UART_HandleTypeDef huart1;
UART_HandleTypeDef huart2;


/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_USART2_UART_Init(void);
static void MX_USART1_UART_Init(void);

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

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

SystemClock_Config();
MX_GPIO_Init();
MX_USART2_UART_Init();
MX_USART1_UART_Init();
/* USER CODE BEGIN 2 */
 
// modbus_memory modbus_rtu_memory;
// modbus_memory *modbus_rtu_memory_ptr = &modbus_rtu_memory;

// uint8_t *modbus_rtu_base = &(modbus_rtu_memory_ptr -> coils[0]);

// memset(&modbus_rtu_memory, 0, sizeof(modbus_rtu_memory)); // initialize modbus memory locations to 0

/* set up modbus slave */

/* setup complete */

/* USER CODE END 2 */

/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
char buffer[12];
HAL_UART_Receive(&huart2, buffer, sizeof(buffer), HAL_MAX_DELAY);

HAL_UART_Transmit(&huart2, buffer, sizeof(buffer), HAL_MAX_DELAY);
/* 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};
RCC_PeriphCLKInitTypeDef PeriphClkInit = {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_NONE;
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_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
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();
}
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART1;
PeriphClkInit.Usart1ClockSelection = RCC_USART1CLKSOURCE_SYSCLK;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
{
Error_Handler();
}
}

/**
* @brief USART1 Initialization Function
* @PAram None
* @retval None
*/
static void MX_USART1_UART_Init(void)
{

/* USER CODE BEGIN USART1_Init 0 */

/* USER CODE END USART1_Init 0 */

/* USER CODE BEGIN USART1_Init 1 */

/* USER CODE END USART1_Init 1 */
huart1.Instance = USART1;
huart1.Init.BaudRate = 115200;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
if (HAL_UART_Init(&huart1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN USART1_Init 2 */

/* USER CODE END USART1_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;
huart2.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
huart2.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
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)
{
/* USER CODE BEGIN MX_GPIO_Init_1 */
/* USER CODE END MX_GPIO_Init_1 */

/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOA_CLK_ENABLE();

/* USER CODE BEGIN MX_GPIO_Init_2 */
/* USER CODE END MX_GPIO_Init_2 */
}

/* 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 */
    This topic has been closed for replies.
    Best answer by bongumsa12

    By default, cubeMX assigns USART2 Tx and Rx to PA2 and PA3. According to the STM32 manual, for virtual communication (USB), only PA2 and PA15 are used. I had to change PA3 to PA15. Now the program works.

     

     

    image.png

    8 replies

    Super User
    October 19, 2023

    What board is this? How are USART1 and USART2 connected externally? Where is the signal on UARTx_RX coming from? Your code doesn't do anything with the received data. How do you know it's not working?

    Probably a hardware issue. Either the pin isn't connected, or the signal isn't coming in where you think it is. Or possibly a misunderstanding of what should be happening.

    Graduate II
    October 19, 2023

    I'm using the STM32F042K6. The received data is transmitted back through the same UART module. That's if there's any received data. The program for that is inside the main function.

    Super User
    October 19, 2023

    Those are blocking functions. If you want to receive at the same time as you're transmitting, you'll need to use HAL_UART_Receive_IT or HAL_UART_Receive_DMA.

    Perhaps look at some existing examples:

    https://github.com/STMicroelectronics/STM32CubeF0/blob/master/Projects/STM32F042K6-Nucleo/Examples/UART/UART_TwoBoards_ComDMA/Src/main.c

     

    Graduate II
    October 19, 2023
    The functions, HAL_UART_Receive(&huart2buffersizeof(buffer), HAL_MAX_DELAY), and
    HAL_UART_Transmit(&huart2buffersizeof(buffer), HAL_MAX_DELAY) do not need interrupts to work. As soon as data is received, the HAL_UART_Recieve function stores the received data in the buffer. The program then executes the HAL_UART_Transmit function. I think the problem has to do with solder bridges or the UART modules are faulty.
    Super User
    October 19, 2023

    > The received data is transmitted back through the same UART module. 

    If RX and TX are tied, as you said, you absolutely do need DMA or IT to work. Otherwise, your receive function blocks waiting for data and your transmit function never gets called. Debug your code, hit pause, see where it's waiting.

    Graduate II
    October 19, 2023

    You haven't shown any code for uart1 so we don't know how you're trying to receive data. 

    What you've posted works for uart2. However, HAL_UART_Receive is blocking and with max timeout, you're going to be waiting a little over 49 days before it returns or you receive 12+ bytes.

    If you're receiving variable length strings then use HAL_UARTEx_ReceiveToIdle_IT and  HAL_UARTEx_RxEventCallback or HAL_UARTEx_ReceiveToIdle_DMA instead. 

    Graduate II
    October 19, 2023

    I think you are ignoring the fact that the UART_MAX_DELAY flag is used in the program to block until there's data recieved. That's what I want to do. I want to block until the UART recieves data.

    Graduate II
    October 19, 2023

    No, i'm not ignoring. I'm just stating that you have to wait until the function returns and until then, you can't do anything else in the background. That's pretty inefficient  Use HAL_UARTEx_ReceiveToIdle_DMA and in the interrupt callback you can transmit what you received. Whilst you can do tons of other stuff in the background at the same time.

    Graduate II
    October 19, 2023

    Its not clear how it determines how many of the 12 bytes were received or not, but as it ping-pongs between the two blocking functions, there some 12 character times where it's not going to be sufficiently responsive to in-coming data, and is going to lose it, or get overrun errors.

    Graduate II
    October 19, 2023

    Thank you to all those who responded to the issue. There's nothing wrong with the program. The program simply waits until the UART Rx FIFO has 12 bytes of data. Then re-transmit the received data. There are two possible problems that might exist here. It's either the UART modules are faulty, or there are solder bridges to be configured. If you have an STM32F042K6, please test the program on your board to verify this. 

    Graduate II
    October 20, 2023

    You've mentioned solder bridges, so does that mean you have a Nucleo-F042K6?

    You haven't mentioned what is connected to uart1 and uart2? 

    bongumsa12AuthorAnswer
    Graduate II
    October 20, 2023

    By default, cubeMX assigns USART2 Tx and Rx to PA2 and PA3. According to the STM32 manual, for virtual communication (USB), only PA2 and PA15 are used. I had to change PA3 to PA15. Now the program works.

     

     

    image.png

    Graduate II
    October 20, 2023

    When you start a new Nucleo-F042K6 board project it configures VCP correctly. You ended up creating a new project for just a STM32F042 which defaults to PA2 and PA3. 

     

    f042K6.jpg

    Graduate II
    October 20, 2023

    Mine always defaults to PA2 and PA3 when I create a new project.

    Graduate II
    October 20, 2023

    I just explained that you need to start a new BOARD Project.