cancel
Showing results for 
Search instead for 
Did you mean: 

How to transmit five byte data transmit in UART_DMA?

mrsmile
Associate III

I already try for send five byte data in UART DMA. I am using the controller in STM32G030K6T6. Data transmition is working properly but output is did not taken properly. The problem was am transmit data five bytes for UART_DMA but DMA transmit only two bytes data. HAL_UART_Transmit_DMA call in timer interrupt handler to check the output for just now. The output is came but this is not proper output. this method for just call in to the interrupt handler output is continuously came for five bytes data. I need a output for 500 millisec once Five Bytes data transmit.  I attach the output for picture and code. please tell what can I do for next step.


_legacyfs_online_stmicro_images_0693W00000bVgJtQAK.png
_legacyfs_online_stmicro_images_0693W00000bVgJjQAK.png

#include "main.h"
 
 TIM_HandleTypeDef htim3;
 
UART_HandleTypeDef huart2;
DMA_HandleTypeDef hdma_usart2_tx;
 
/* USER CODE BEGIN PV */
 
uint16_t tim=0;
 
uint8_t tx_buf[5]= {0x01,0x02,0x03,0x04,0x05};
 
 
/* USER CODE END PV */
 
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_DMA_Init(void);
static void MX_USART2_UART_Init(void);
static void MX_TIM3_Init(void);
 
int main(void)
{
 
  HAL_Init();
 
 
  SystemClock_Config();
 
 
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_USART2_UART_Init();
  MX_TIM3_Init();
  /* USER CODE BEGIN 2 */
	
	HAL_TIM_Base_Start_IT(&htim3);
	HAL_UART_Transmit_DMA(&huart2, tx_buf, sizeof(tx_buf));  // 500 msec once
  /* USER CODE END 2 */
 
  while (1)
  {
 
  }
}
 
void TIM3_IRQHandler(void)
{
  /* USER CODE BEGIN TIM3_IRQn 0 */
 
  /* USER CODE END TIM3_IRQn 0 */
  HAL_TIM_IRQHandler(&htim3);
  /* USER CODE BEGIN TIM3_IRQn 1 */
		 tim++;	
	
	 if(tim==500)
	 {
		__HAL_DMA_ENABLE(huart2.hdmatx);
		 tx_buf[0] = 0x01;
		 tx_buf[1] = 0x02;
		 tx_buf[2] = 0x03;
		 tx_buf[3] = 0x04;
		 tx_buf[4] = 0x05;
  	 		tim=0; 	
		__HAL_DMA_DISABLE(huart2.hdmatx);
	 }
  /* USER CODE END TIM3_IRQn 1 */
}

21 REPLIES 21

Hi @RomainR.​  sir,

 when i generated a new project and i followed the step to have provided me but it doesn't work it get stuck in error handler. Can you please explain me the process you have done.

Sorry, late reply. I started to write code but i got busy so couldn't finish it until now.

Actually you need to look at the HAL status. Maybe as a stripped down code that only transmit, then it may work when HAL_UART_TxCpltCallback is called and you set a flag.

ST has poor example code that doesn't show how to recover if a transmit (or receive) returns HAL_BUSY. Instead of calling Error_Handler they should show how to set a flag and check if you need to try to send the data again.

The below code shows how to set a flag if HAL_BUSY is returned and how to continue trying to send again. I am using a ring buffer that can currently hold up to 4 queues with up to 128 bytes. If the transmit fails then it won't increment the queue until HAL_OK all the while you can still add data to the queue without corrupting the pending queue to be sent.

/*
 * PollingRoutine.c
 *
 *  Created on: Jun 6, 2023
 *      Author: karl.yamashita
 */
 
 
#include "main.h"
 
extern UART_HandleTypeDef huart2;
 
UART_TxDataStruct uart2_tx = {0};
uint32_t prevTick = 0;
 
uint8_t tx_buf[5]= {0x01,0x02,0x03,0x04,0x05};
 // called before main while loop
void PollingInit(void)
{
 
}
 
// called from inside main while loop
void PollingRoutine(void)
{
	if ((HAL_GetTick() - prevTick ) > 500)
	{
		UART_AddMessage(tx_buf, 5);
		HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);
		prevTick = HAL_GetTick();
	}
 
	UART_Transmit(&uart2_tx);
}
 
/*
 * Description: Add data to queue to be sent
 */
void UART_AddMessage(uint8_t *data, uint32_t size)
{
	memcpy(&uart2_tx.Queue[uart2_tx.ptr.index_IN].data, data, size);
	uart2_tx.uartBufferSize = size;
	RingBuff_Ptr_Input(&uart2_tx.ptr, UART_QUEUE_SIZE);
}
 
/*
 * Description: Check if there is a message to be sent. Only increment output queue if status return HAL_OK.
 *				If HAL_BUSY then HAL did not accept the new data pointer so we need to try and send again on next go around
 */
void UART_Transmit(UART_TxDataStruct *buf)
{
	if(buf->ptr.cnt_Handle)
	{
		if(HAL_UART_Transmit_DMA(&huart2, buf->Queue[buf->ptr.index_OUT].data, buf->uartBufferSize) == HAL_OK)
		{
			RingBuff_Ptr_Output(&buf->ptr, UART_QUEUE_SIZE); //
		}
	}
}

/*
 * PollingRoutine.h
 *
 *  Created on: Jun 6, 2023
 *      Author: karl.yamashita
 */
 
#ifndef INC_POLLINGROUTINE_H_
#define INC_POLLINGROUTINE_H_
 
 
#define UART_BUFFER_SIZE 128
#define UART_QUEUE_SIZE 4 // increase if many messages are placed in queue before UART can finished with first message in order to avoid a buffer overrun
 
typedef struct
{
	struct
	{
		uint8_t data[UART_BUFFER_SIZE];
	}Queue[UART_QUEUE_SIZE];
	uint32_t uartBufferSize; // the size of data to be received in the DMA
	RING_BUFF_STRUCT ptr;
}UART_TxDataStruct;
 
void PollingInit(void);
void PollingRoutine(void);
 
void UART_AddMessage(uint8_t *data, uint32_t size);
void UART_Transmit(UART_TxDataStruct *buf);
 
#endif /* INC_POLLINGROUTINE_H_ */

/*
 * RingBuffer.c
 *
 *  Created on: Sep 18, 2019
 *      Author: Karl
 *
 *
*/
 
#include "main.h"
#include "ringBuffer.h"
 
 
void RingBuff_Ptr_Reset(RING_BUFF_STRUCT *ptr) {
	ptr->index_IN = 0;
	ptr->index_OUT = 0;
 
	ptr->cnt_Handle = 0;
	ptr->cnt_OverFlow = 0;
}
 
void RingBuff_Ptr_Input(RING_BUFF_STRUCT *ptr, uint32_t bufferSize) {
	ptr->index_IN++;
	if (ptr->index_IN >= bufferSize)
		ptr->index_IN = 0;
 
	ptr->cnt_Handle++;
	if (ptr->index_IN == ptr->index_OUT) {
		ptr->cnt_OverFlow++;
		if (ptr->cnt_OverFlow > RING_BUFF_OVERFLOW_SIZE)
			ptr->cnt_OverFlow = 0;
		if (ptr->index_IN == 0) {
			ptr->index_OUT = bufferSize - 1;
		} else {
			ptr->index_OUT = ptr->index_IN - 1;
		}
		ptr->cnt_Handle = 1;
	}
}
 
void RingBuff_Ptr_Output(RING_BUFF_STRUCT *ptr, uint32_t bufferSize) {
	if (ptr->cnt_Handle) {
		ptr->index_OUT++;
		if (ptr->index_OUT >= bufferSize)
			ptr->index_OUT = 0;
		ptr->cnt_Handle--;
	}
}

#ifndef RING_BUFFER_H
#define RING_BUFFER_H
 
#include "main.h"
 
#define RING_BUFF_OVERFLOW_SIZE 100
 
typedef struct {
	uint32_t index_IN; // pointer to where the data will be save to
	uint32_t index_OUT; // pointer to next available data in buffer if cnt_handle is not zero
	uint32_t cnt_Handle; // if not zero then message available
	uint32_t cnt_OverFlow; // has overflow if not zero
}RING_BUFF_STRUCT;
 
void RingBuff_Ptr_Reset(RING_BUFF_STRUCT *ptr);
void RingBuff_Ptr_Input(RING_BUFF_STRUCT *ptr, uint32_t bufferSize);
void RingBuff_Ptr_Output(RING_BUFF_STRUCT *ptr, uint32_t bufferSize);
 
 
 
#endif // RING_BUFFER_H

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.