我是靠谱客的博主 健康小懒猪,最近开发中收集的这篇文章主要介绍UART接收不定长数据块(队列缓存数据块),觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

1,DMA,UART配置:
在这里插入图片描述
2,代码配置

所用全局变量类型:

typedef struct QUE
{
	uint8_t res_data[100];
	uint8_t FLAG;
	uint8_t res_counter;
	struct QUE *next;
}QUE_UE_RES;

QUE_UE_RES QUE_buff[QUE_LEN];
QUE_UE_RES *UART_buff,*HAND_buff;
uint8_t RxCounter;
uint8_t *RxBuffer; 
#define QUE_LEN 10					//uart缓存块长度

UART初始化:

void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
{

  GPIO_InitTypeDef GPIO_InitStruct = {0};
  if(uartHandle->Instance==LPUART1)
  {
  /* USER CODE BEGIN LPUART1_MspInit 0 */

  /* USER CODE END LPUART1_MspInit 0 */
    /* LPUART1 clock enable */
    __HAL_RCC_LPUART1_CLK_ENABLE();
  
    __HAL_RCC_GPIOB_CLK_ENABLE();
    /**LPUART1 GPIO Configuration    
    PB10     ------> LPUART1_TX
    PB11     ------> LPUART1_RX 
    */
    GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_11;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF4_LPUART1;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

    /* LPUART1 DMA Init */
    /* LPUART1_RX Init */
    hdma_lpuart1_rx.Instance = DMA1_Channel3;
    hdma_lpuart1_rx.Init.Request = DMA_REQUEST_5;
    hdma_lpuart1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
    hdma_lpuart1_rx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_lpuart1_rx.Init.MemInc = DMA_MINC_ENABLE;
    hdma_lpuart1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    hdma_lpuart1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
    hdma_lpuart1_rx.Init.Mode = DMA_NORMAL;
    hdma_lpuart1_rx.Init.Priority = DMA_PRIORITY_VERY_HIGH;
    if (HAL_DMA_Init(&hdma_lpuart1_rx) != HAL_OK)
    {
      Error_Handler();
    }

    __HAL_LINKDMA(uartHandle,hdmarx,hdma_lpuart1_rx);

    /* LPUART1 interrupt Init */
    HAL_NVIC_SetPriority(RNG_LPUART1_IRQn, 1, 0);
    HAL_NVIC_EnableIRQ(RNG_LPUART1_IRQn);
  /* USER CODE BEGIN LPUART1_MspInit 1 */

    __HAL_UART_ENABLE_IT(&hlpuart1, UART_IT_IDLE);//使能idle中断
    HAL_UART_Receive_DMA(&hlpuart1,UART_buff->res_data,BUFFER_SIZE);//重新打开DMA接收

  /* USER CODE END LPUART1_MspInit 1 */
  }

缓存区初始化配置:

void QUE_INIT(void){
	uint8_t i;
	memset(QUE_buff,0,sizeof(QUE_buff));
	for(i=0;i<QUE_LEN-1;i++){
	QUE_buff[i].next=&QUE_buff[i+1];
	QUE_buff[i].FLAG=0;
	QUE_buff[i].res_counter=0;
	}
	QUE_buff[QUE_LEN-1].next=&QUE_buff[0];
	QUE_buff[QUE_LEN-1].FLAG=0;
	QUE_buff[QUE_LEN-1].res_counter=0;
	UART_buff=QUE_buff;
	HAND_buff=QUE_buff;
}

中断函数:

void RNG_LPUART1_IRQHandler(void)
{
  /* USER CODE BEGIN RNG_LPUART1_IRQn 0 */

	if((__HAL_UART_GET_FLAG(&hlpuart1,UART_FLAG_IDLE) != RESET))//判断是否为空闲中断
	{
		__HAL_UART_CLEAR_IDLEFLAG(&hlpuart1);//清除中断标志位
		HAL_UART_DMAStop(&hlpuart1); //停止DMA传输
		UART_buff->res_counter =  BUFFER_SIZE - hdma_lpuart1_rx.Instance->CNDTR; //接收数据长度
		UART_buff->FLAG=1;		//可不要
		UART_buff=UART_buff->next;			//将指针指向下一个缓存区
	}
	HAL_UART_Receive_DMA(&hlpuart1,UART_buff->res_data,BUFFER_SIZE);//继续接收数据

  /* USER CODE END RNG_LPUART1_IRQn 0 */
  HAL_UART_IRQHandler(&hlpuart1);
  /* USER CODE BEGIN RNG_LPUART1_IRQn 1 */

  /* USER CODE END RNG_LPUART1_IRQn 1 */
}

读取UART缓存数据函数:


uint8_t RECCMD(uint16_t timeout){											
	uint32_t tickstart = HAL_GetTick();
	while((HAND_buff==UART_buff)&&((HAL_GetTick() - tickstart) < timeout))
	{
	}
	if(HAND_buff!=UART_buff){

		RxBuffer=HAND_buff->res_data;
		RxCounter=HAND_buff->res_counter;
		HAND_buff->res_counter=0;
		HAND_buff->FLAG=0;
		HAND_buff=HAND_buff->next;
		return 1;
	}
	return 0;
}

RxBuffer与RxCounter即为现在读出的数据,每次数据舍弃时将RxBuffer内容清空为0

最后

以上就是健康小懒猪为你收集整理的UART接收不定长数据块(队列缓存数据块)的全部内容,希望文章能够帮你解决UART接收不定长数据块(队列缓存数据块)所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(42)

评论列表共有 0 条评论

立即
投稿
返回
顶部