cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F042K6 USART not working

bongumsa12
Associate III
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 */
1 ACCEPTED SOLUTION

Accepted Solutions
bongumsa12
Associate III

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

View solution in original post

18 REPLIES 18
TDK
Guru

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.

If you feel a post has answered your question, please click "Accept as Solution".

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.

TDK
Guru

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

 

If you feel a post has answered your question, please click "Accept as Solution".
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.
Karl Yamashita
Lead III

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. 

Tips and Tricks with TimerCallback https://www.youtube.com/@eebykarl
If you find my solution useful, please click the Accept as Solution so others see the solution.

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.

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

If you feel a post has answered your question, please click "Accept as Solution".
Karl Yamashita
Lead III

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.

Tips and Tricks with TimerCallback https://www.youtube.com/@eebykarl
If you find my solution useful, please click the Accept as Solution so others see the solution.

If you're receiving variable length strings...


There is no "if" for stream interfaces and especially the simple ones like UART. A byte can always be lost because of wiring issues, noise, delayed interrupts, CPU/DMA/bus overload etc. If the code doesn't deal with it gracefully, then it's broken and the device is not reliable.