STM32F103 UART 接收

参考https://www.devcoons.com/stm32-uart-receive-unknown-size-data-using-dma-and-freertos/

最近在用STM32F103的单片机,想使用串口接收发送功能, 结果各种坑,已开始使用了中断模式,要么进不了中断,要么就hardfault,

网上看了很多帖子都没有解决,果断放弃

In the end of this page you can find the github links (soon).

Step 1: Create your project using the CubeMX and place both RX/TX DMAs on the serial interface. The Tx DMA should be in Normal Mode and the Rx should be in Circular Mode.

Step 2: Activate the NVIC Interrupt for the serial. (it is needed by the DMA)

Step 3: Basically, what we are going to do is to leave the DMA reading the UART and put them in an array. By changing the Mode to circular the DMA will indefinitely continue this operation without interrupting (circular buffering). On top of this, a thread will collect the data and parse them. For that reason we need the following definitions

#define UART_DMA_BUFFER_SIZE 2048
#define PARSER_MESSAGE_LIST_SIZE 8
#define PARSER_MESSAGE_SIZE 1024

Step 4: Assign and activate the UART reception using the DMA and give a (large enough) buffer. Please note that this approach will never fire an interrupt on RX and the array will be used as a circular buffer.

static uint8_t buffer[UART_DMA_BUFFER_SIZE];
...
...
{
    // This should be done before the beginning of our parser, 
    // you can place it in the main or inside the parser
    HAL_UART_Receive_DMA(&huart2, buffer, UART_DMA_BUFFER_SIZE);
}

Step 5: Create a FreeRTOS thread which will monitor the buffer and copy any new data to an intermediate buffer for further processing.

static osThreadId_t uartParserTaskHandle;
...
...
void UARTParser(void* arguments);
...
...
{
  const osThreadAttr_t uartParserTask_attributes2 = {
    .name = "UARTParserTask",
    .priority = (osPriority_t) osPriorityLow,
    .stack_size = 128};
  uartParserTaskHandle = osThreadNew(UARTParser, NULL, &uartParserTask_attributes2);
}

Step 6: Now we will fill the Parser of the UART. As we said before the main purpose is to get all the new available data from the DMA buffer and put them in a list of messages (each complete message should be ended with the ‘\r\n’ characters).

static uint8_t msg_list[PARSER_MESSAGE_LIST_SIZE][PARSER_MESSAGE_SIZE];
...
...
void UARTParser(void* arguments)
{
    size_t dma_head = 0, dma_tail = 0;
    size_t cur_msg_sz = 0;
    size_t cur_msg = 0;
    uint8_t found = 0;
    
    for(;;)
    {
    	do
    	{
    	    __disable_irq();
    	    dma_tail = UART_DMA_BUFFER_SIZE - huart2.hdmarx->Instance->CNDTR;
            __enable_irq();

            if(dma_tail!=dma_head)
            {
            	if(dma_head < dma_tail)
            	{
       		    for(register size_t i=dma_head; i<dma_tail; i++)
            	    {
            	        found = (found == 0 && buffer[i] == '\r') ? 1
            		      : (found == 1 && buffer[i] == '\n') ? 2
            		      : 0;
       			msg_list[cur_msg][cur_msg_sz++]= buffer[i];

       			if(found==2)
            		{
            		    cur_msg = cur_msg == PARSER_MESSAGE_LIST_SIZE-1 ? 0 : cur_msg + 1;
            		    memset(msg_list[cur_msg],0,PARSER_MESSAGE_SIZE);
            		    cur_msg_sz=0;
            		}
            	    }
            	}
            	else
            	{
            	    for(register size_t i=dma_head; i<UART_DMA_BUFFER_SIZE; i++)
		    {
		        found = (found == 0 && buffer[i] == '\r') ? 1
			      : (found == 1 && buffer[i] == '\n') ? 2
			      : 0;
			msg_list[cur_msg][cur_msg_sz++]= buffer[i];

			if(found==2)
			{
 			    cur_msg = cur_msg == PARSER_MESSAGE_LIST_SIZE-1 ? 0 : cur_msg + 1;
			    memset(msg_list[cur_msg],0,PARSER_MESSAGE_SIZE);
            		    cur_msg_sz=0;
			}
		    }
		    for(register size_t i=0; i<dma_tail; i++)
		    {
		        found = (found == 0 && buffer[i] == '\r') ? 1
			      : (found == 1 && buffer[i] == '\n') ? 2
			      : 0;

			msg_list[cur_msg][cur_msg_sz++]= buffer[i];

     		        if(found==2)
			{
			    cur_msg = cur_msg == PARSER_MESSAGE_LIST_SIZE-1 ? 0 : cur_msg + 1;
			    memset(msg_list[cur_msg],0,PARSER_MESSAGE_SIZE);
            		    cur_msg_sz=0;
			}
		    }
            	}
            	dma_head=dma_tail;
            }
        }while(dma_head!=(UART_DMA_BUFFER_SIZE- huart2.hdmarx->Instance->CNDTR));
        osDelay(25); // this should be the minimum time difference between each frame
    }
}

Now, if you run this application and send data through UART, you will see them in the messages list separated by ‘\r\n’.

弃,直到看到上面链接这片文章。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值