STM32cubeMX+DMA+USART 接收任意长度的数据


DMA接收选用circle模式,如果是normal模式的话,需要每次在中断里面接收完成后重新开启DMA接收,circle模式不用每次都开启dma接收中断。如图

#define UART_BUFFER_SIZE	64

typedef struct _uart_rx_struct{
	uint8_t rx_flag;
	uint8_t rx_size;
	uint8_t buffer[UART_BUFFER_SIZE];
}uart_rx_struct;

uart_rx_struct uart1_rx;
uint8_t uart1_rx_buffer[UART_BUFFER_SIZE];
void MX_USART1_UART_Init(void)
{

  huart1.Instance = USART1;
  huart1.Init.BaudRate = 115200;
  huart1.Init.WordLength = UART_WORDLENGTH_8B;
  huart1.Init.StopBits = UART_STOPBITS_1;
  huart1.Init.Parity = UART_PARITY_NONE;
  huart1.Init.Mode = UART_MODE_TX_RX;
  huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart1.Init.OverSampling = UART_OVERSAMPLING_16;
  if (HAL_UART_Init(&huart1) != HAL_OK)
  {
    Error_Handler();
  }
    __HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);//使能idle中断
    HAL_UART_Receive_DMA(&huart1,uart1_rx_buffer,UART_BUFFER_SIZE);//打开DMA接收,数据存入

}

接收中断里面按如下所示

void USART1_IRQHandler(void)
{
	uint32_t temp;
    static uint8_t dma_rx_last_pt=0;
    uint8_t rx_len=0;
	uint32_t tmp_flag =__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE); //获取IDLE标志位
	if((tmp_flag != RESET))//idle标志被置位
	{ 
		__HAL_UART_CLEAR_IDLEFLAG(&huart1);//清除标志位
		temp  = hdma_usart1_rx.Instance->NDTR;// 获取DMA中未传输的数据个数,NDTR寄存器分析见下面
		if(dma_rx_last_pt > temp)
		{
            rx_len = dma_rx_last_pt - temp;
            for(uint8_t i=0;i<rx_len;i++)
            	uart1_rx.buffer[i] = uart1_rx_buffer[UART_BUFFER_SIZE-dma_rx_last_pt+i];
			uart1_rx.rx_flag = 1;
			uart1_rx.rx_size = rx_len;
		}
        else
        {
            rx_len = UART_BUFFER_SIZE + dma_rx_last_pt - temp;
            for(uint8_t i=0;i<dma_rx_last_pt;i++)
            	uart1_rx.buffer[i] = uart1_rx_buffer[UART_BUFFER_SIZE-dma_rx_last_pt+i];
            for(uint8_t i=0;i<UART_BUFFER_SIZE-temp;i++)
            	uart1_rx.buffer[dma_rx_last_pt+i] = uart1_rx_buffer[i];
			uart1_rx.rx_flag = 1;
			uart1_rx.rx_size = rx_len;
        }
		dma_rx_last_pt = temp;
    }
	tmp_flag =__HAL_UART_GET_FLAG(&huart1,USART_SR_TC);
	if((tmp_flag != RESET))
	{
		__HAL_UART_CLEAR_FLAG(&huart1, UART_IT_TC);
		huart1.gState = HAL_UART_STATE_READY;
	}
}

STM32F767单片机串口中断

void UART4_IRQHandler(void)
{
	uint32_t temp;
    static uint8_t dma_rx_last_pt=0;
    uint8_t rx_len=0;
	uint32_t tmp_flag =__HAL_UART_GET_FLAG(&huart4,UART_FLAG_IDLE); //获取IDLE标志
	if((tmp_flag != RESET))//idle标志被置
	{
		__HAL_UART_CLEAR_IDLEFLAG(&huart4);//清除标志
		temp  = hdma_uart4_rx.Instance->NDTR;// 获取DMA中未传输的数据个数,NDTR寄存器分析见下面
		if(dma_rx_last_pt > temp)
		{
            rx_len = dma_rx_last_pt - temp;
            for(uint8_t i=0;i<rx_len;i++)
            	uart4_rx.buffer[i] = uart4_rx_buffer[UART_BUFFER_SIZE-dma_rx_last_pt+i];
            uart4_rx.rx_flag = 1;
            uart4_rx.rx_size = rx_len;
		}
        else
        {
            rx_len = UART_BUFFER_SIZE + dma_rx_last_pt - temp;
            for(uint8_t i=0;i<dma_rx_last_pt;i++)
            	uart4_rx.buffer[i] = uart4_rx_buffer[UART_BUFFER_SIZE-dma_rx_last_pt+i];
            for(uint8_t i=0;i<UART_BUFFER_SIZE-temp;i++)
            	uart4_rx.buffer[dma_rx_last_pt+i] = uart4_rx_buffer[i];
            uart4_rx.rx_flag = 1;
            uart4_rx.rx_size = rx_len;
        }
		dma_rx_last_pt = temp;
	}
	tmp_flag =__HAL_UART_GET_FLAG(&huart4,USART_ISR_TC);
	if((tmp_flag != RESET))
	{
		__HAL_UART_CLEAR_FLAG(&huart1, UART_IT_TC);
		huart4.gState = HAL_UART_STATE_READY;
	}

}

void user_Uart1Handler()
{
	if((__HAL_UART_GET_FLAG(&huart1,UART_FLAG_RXNE)!=RESET))
	{
			if(uart1RxState==UART_RX_STATE_READY)   //接收到一帧中的第一个字节
			{
				   uart1RxState=UART_RX_STATE_START;
				  __HAL_UART_ENABLE_IT(&huart1,UART_IT_IDLE);   //打开空闲中断
				  uart1RxCounter=0;                             //计数清零
				  uart1RxBuf[uart1RxCounter]=(uint8_t)(huart1.Instance->DR & (uint8_t)0x00FF);
				  uart1RxCounter++;
			}
			else if(uart1RxState==UART_RX_STATE_START)  
			{
				  uart1RxBuf[uart1RxCounter]=(uint8_t)(huart1.Instance->DR & (uint8_t)0x00FF);
				  uart1RxCounter++;
			}
			__HAL_UART_CLEAR_FLAG(&huart1,UART_FLAG_RXNE);
		  
	}
	if((__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE)!=RESET))  //进入空闲中断
	{          
		  __HAL_UART_CLEAR_FLAG(&huart1, UART_FLAG_IDLE);    //关了空闲中断
		  __HAL_UART_DISABLE_IT(&huart1,UART_IT_RXNE);    //关了接收完成中断
		  uart1RxState=UART_RX_STATE_DEAL;                //状态表明一帧数据接收完成了,需要处理。处理完以后再把接收中断打开
	}
}


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM