STM32WB55XX freertos 二值信号量+dma+idle 不定长串口接收 + dma传输完成中断

1、CUBE 配置

1.1硬件配置

在这里插入图片描述晶振配置
在这里插入图片描述系统时钟源配置 Tim1, systick给freertos用
在这里插入图片描述独立看门狗:预分频 32 喂狗超时 4095 个 分频后的周期数
在这里插入图片描述低功耗串口1 : 1、异步模式 2、开启全局中断
在这里插入图片描述低功耗串口1 : 添加 DMA
在这里插入图片描述时钟源选择

1.2 freertos 配置

添加串口任务
在这里插入图片描述
创建dma发送和接收的信号量
在这里插入图片描述

二、用户代码

如果使用信号量同步,要把使能空闲中断放在默认任务开头。
这样可以避免一种开机就死机的情况:
开启中断后串口在信号量初始化之前就收到一帧数据,
而在中断中释放的信号量还没有被创建。

void HalLpUartInit()
{
	if(HAL_OK != HAL_UART_Receive_DMA(&hlpuart1, g_lpUartRx.data, UART_RX_MAX))
		Error_Handler();
	__HAL_UART_ENABLE_IT(&hlpuart1, UART_IT_IDLE);
	__HAL_UART_ENABLE_IT(&hlpuart1, UART_FLAG_TC);
}
void StartDefaultTask(void *argument)
{
  /* USER CODE BEGIN StartDefaultTask */
  	HalLpUartInit();
	HAL_GPIO_TogglePin(GPIOA, LED_BLUE_Pin);
	osTimerStart(UI_TimerHandle, 500);
	//这里用printf会产生一个长度是0的空闲接收中断 后面打印正常
	//printf("Start Default Task!\r\n");
	LpUartTx(strlen("Start Default Task!\r\n"),(uint8_t *)"Start Default Task!\r\n");
	/* Infinite loop */
	for(;;)
	{
		HAL_IWDG_Refresh(&hiwdg);
		osDelay(1000);
	}
  /* USER CODE END StartDefaultTask */
}

串口任务

void LpUartTask(void *argument)
{
  /* USER CODE BEGIN LpUartTask */
  /* Infinite loop */
  for(;;)
  {
	  if(osOK == osSemaphoreAcquire(lpuartRxBinarySemHandle,osWaitForever))
	  {
		  printf("rx [%d]:",g_lpUartRx.size);
		  LpUartTx(g_lpUartRx.size, g_lpUartRx.data);
		  printf("\r\n");
	  }
  }
  /* USER CODE END LpUartTask */
}

dma发送

void LpUartTx(uint16_t len, uint8_t * buff)
{
	if(0 == len) 
		return;
	if(HAL_OK == osSemaphoreAcquire(lpuartTxBinarySemHandle,10))
		HAL_UART_Transmit_DMA(&hlpuart1, buff, len);
}

串口全局中断处理:1、空闲中断 2、DMA传输完成中断

void LPUART1_IRQHandler(void)
{
  /* USER CODE BEGIN LPUART1_IRQn 0 */
	uint32_t temp;
	uint32_t ret = taskENTER_CRITICAL_FROM_ISR();
    if(__HAL_UART_GET_FLAG(&hlpuart1,UART_FLAG_IDLE) != RESET)
    {
		HAL_UART_DMAStop(&hlpuart1);  
		temp = hlpuart1.hdmarx->Instance->CNDTR;  
		g_lpUartRx.size = UART_RX_MAX - temp;
		// starting uart dma rcv again
		HAL_UART_Receive_DMA(&hlpuart1, g_lpUartRx.data, UART_RX_MAX);  
		osSemaphoreRelease(lpuartRxBinarySemHandle);
		__HAL_UART_CLEAR_IDLEFLAG(&hlpuart1);
	}else if(__HAL_UART_GET_FLAG(&hlpuart1, UART_FLAG_TC) != RESET){
		osSemaphoreRelease(lpuartTxBinarySemHandle);
		__HAL_UART_CLEAR_TXFECF(&hlpuart1);
	}
  /* USER CODE END LPUART1_IRQn 0 */
  HAL_UART_IRQHandler(&hlpuart1);
  /* USER CODE BEGIN LPUART1_IRQn 1 */
	taskEXIT_CRITICAL_FROM_ISR(ret);
  /* USER CODE END LPUART1_IRQn 1 */
}

实验效果
在这里插入图片描述
(第一条打印用printf会产生接收长度为0的空闲中断,未找到原因)

猜你喜欢

转载自blog.csdn.net/qq_28851611/article/details/106853291