[转]STM32CUBEIDE(MX续)学习笔记(七)——FREERTOS+DMA+队列+循环数组方式进行串口收发

一、收发主要逻辑

1、接收:利用DMA和空闲中断一次接收一帧的不定长数据,接收到数据后“暂停”(之后分析为何要暂停而不是停止)DMA,快速利用结构体存储接收到数据的地址和长度,再利用队列能够传递结构体的特点,将所收数据的地址和长度入队,然后打开DMA接收。数据处理任务检测队列状态,只要队列中有有效数据就开始数据处理。
2.发送:先将要发送的数据存入循环数组(伪)中,再利用队列将数据的地址和长度入队,利用一个串口输出的守护任务来保证数据传输的完整性,这个守护任务对地址和长度出队并使用DMA传输。

二、接收代码

接收和发送结构体

typedef struct
{
	uint8_t	lenth;
	uint8_t	offset_last;
}Usart3RXTempTypedef;

typedef struct
{
	uint8_t	lenth;
	uint8_t offset_last;
	uint8_t *addr;
}Usart3TxTypedef;

1.中断

void USART3_IRQHandler(void)
{
  /* USER CODE BEGIN USART3_IRQn 0 */
	uint32_t tmp_flag = 0;
	uint16_t temp;
	portBASE_TYPE xHigherPriorityTaskWoken= pdFALSE;
	tmp_flag =__HAL_UART_GET_FLAG(&huart3,UART_FLAG_IDLE);
	if((tmp_flag != RESET))
	{
		__HAL_UART_CLEAR_IDLEFLAG(&huart3);
		temp = huart3.Instance->SR;
		temp = huart3.Instance->DR;
		HAL_UART_DMAPause(&huart3);
		temp  = hdma_usart3_rx.Instance->CNDTR;

		if(temp	>=	(USART3_RxBuffer_Size - Usart3Temp.offset_last))//判断是否到达循环数组终点
			Usart3Temp.lenth =  2*USART3_RxBuffer_Size - temp - Usart3Temp.offset_last;
		else
			Usart3Temp.lenth =  USART3_RxBuffer_Size - temp - Usart3Temp.offset_last;
		Usart3Temp.offset_last = USART3_RxBuffer_Size - temp;
		xQueueSendFromISR(QueueUsart3RevHandle,(void *)&Usart3Temp,&xHigherPriorityTaskWoken);
		HAL_UART_DMAResume(&huart3);
	}
  /* USER CODE END USART3_IRQn 0 */
  HAL_UART_IRQHandler(&huart3);
  /* USER CODE BEGIN USART3_IRQn 1 */

  /* USER CODE END USART3_IRQn 1 */
}

这里DMA操作要使用HAL_UART_DMAPauseDMA暂停和HAL_UART_DMAResumeDMA恢复。
如果使用HAL_UART_DMAStopDMA停止和HAL_UART_Receive_DMADMA接收启用,会导致DMA一直从循环数组的开头存放数据。
这里Usart3Temp.offset_last是本次数据的尾地址偏移量。
当然,DMA参数配置中要把模式设置为循环模式。
在这里插入图片描述
2.接收数据任务:数据处理方式为收到数据后原样返回

void usart3RxTask(void const * argument)
{
  /* USER CODE BEGIN usart3RxTask */
  /* Infinite loop */
  for(;;)
  {
	  uint16_t	i;
	  uint8_t	RevCnt;
	  Usart3RxTypedef Usart3TempRev;
	  Usart3TxTypedef	Usart3Tx;
		/* Infinite loop */
		for(;;)
		{
			xQueueReceive(QueueUsart3RevHandle,(void*)&Usart3TempRev,portMAX_DELAY);
			if(Usart3TempRev.offset_last>=Usart3TempRev.lenth)
			{
				RevCnt=0;
				for(i=(Usart3TempRev.offset_last-Usart3TempRev.lenth);i USART3_TxBuffer_Size)//如果溢出,则从数组的第一个地�?�?始储�?
				Usart3Tx.offset_last = 0;
			for(i=0;i
  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值