USART DMA Communication in STM32 CubeMx
Hello everyone, In this article we will talk about USART communication on STM32 with CubeMx . First we need to have a STM32Fx series microprocessor or a developer board that has a STM32Fx microprocessor.First we need to start a CubeMx project and select our board. And configure our board for USART communicating with DMA.
Click New > Project and from new screen we need to select our microprocessor. I have STM32F051 Discovery board and I selected it.
First, I have selected Connectivity section on the left panel and and activated USART as Asyncronus . And then I have checked the pins and they are were not using with anything else. The PA10 pin is addicted to USART1_RX and PA9 pin addicted to USART1_TX. This means our microprocessor will use PA10 pin to Receive USART data; PA9 pin to Transmit USART data.
After selecting the pins now we will configure USART DMA settings.
Click on DMA Settings. Add USART1_RX and USART1_TX DMA channels. Select both of this DMA objects and set the Mode as Circular, Data Width as Byte. Now we have setted DMA will send and receive datas byte by byte. Also after completing the data transmission it will start again due to Circular Mode.
Pay Attention !!!
Also make sure not to activate USART1 interrupt. Cubemx will be already activated DMA. If both interrupt and DMA will be activated our program will not be working as we want.
After making DMA configuration now we will make our USART configuration. Below picture has my project configuration and you can set your own configuration values for your project.
Now we are ready to generate our code. I have generated for uVision Keil.
Let's take a look at codes now:
//variable to keep USART received data
uint8_t Rx_data[2];
uint8_t buffer[2];
HAL_StatusTypeDef HAL_UART_DMA_Tx_Stop(UART_HandleTypeDef *huart)
{
uint32_t dmarequest = 0x00U;
dmarequest = HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAT);
if((huart->gState == HAL_UART_STATE_BUSY_TX) && dmarequest)
{
CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAT);
/* Abort the UART DMA Tx channel */
if(huart->hdmatx != NULL)
{
HAL_DMA_Abort(huart->hdmatx);
}
//UART_EndTxTransfer(huart);
/* Disable TXEIE and TCIE interrupts */
CLEAR_BIT(huart->Instance->CR1, (USART_CR1_TXEIE | USART_CR1_TCIE));
huart->gState = HAL_UART_STATE_READY;
return HAL_OK;
}
else return HAL_ERROR;
}
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
HAL_GPIO_TogglePin(LD3_GPIO_Port,LD3_Pin);
HAL_UART_DMA_Tx_Stop(&huart1);
}
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
HAL_GPIO_TogglePin(LD4_GPIO_Port,LD4_Pin);
}
Normally Cube API has HAL_UART_DMA_Stop function but it stops receiving and transmiting together. In here we will just need to stop Transmitting process. Because sometimes maybe when we are transmitting datas we can receive another data. For keeping these datas we have just created the same function of HAL_UART_DMA_Stop and removed Receiving stop section. In program we will use this function. There are also two different functions. These functions will call when Transmitting and receiving process when held.
After configuration functions we need to start DMA receiving and wait for the data coming.
/* USER CODE BEGIN 2 */
HAL_UART_Receive_DMA(&huart1, (uint8_t *)Rx_data, 2);
/* USER CODE END 2 */
In while section we can build our own program has receiving and transmiting processes.
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
HAL_Delay(10);
HAL_UART_Receive_DMA(&huart1, (uint8_t *)Rx_data, 2);
buffer[0] = 0x41;
buffer[1] = 0x33;
HAL_UART_Transmit_DMA(&huart1, buffer, 2);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
Now we are ready to make use USART DMA in STM32 CubeMx.
I have builded this project using stm32f051 but in CubeMx Api library methods are the same. So we can use this in STM32F4 series or what serias what we want. Do as I do and have enjoy with USART DMA.
That all for this article. Thank you for reading me.
Good coding for everyone.
Burak Hamdi TUFAN.
Comments
Hi, TUFAN Thanks for sharing the article, you did a great job. I am trying to apply your example code in my Nulceo-g071rb board. Looks like our board is little bit different. Nucleo-g071rb board uses USART_CR1_TXEIE_TXFNFIE rather than USART_CR1_TXEIE and it's solved. No worries. my question is, 1. What condition that represent the "Transfer_cplt" condition ? Regards, Mahendra
2020/09/17 06:20:44Hello, "Transfer_cplt" is a statement word which I used it for my own application. I think I forget to remove it from the example. You can remove it from the while loop or define it at USART Receive Completed Callback. I prevent to run the HAL_UART_Receive_DMA method and the other calculations during the sending different values for different calculations to wait all type of datas are okay for all processing.
2020/09/17 10:20:25