zoukankan      html  css  js  c++  java
  • 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;                //状态表明一帧数据接收完成了,需要处理。处理完以后再把接收中断打开
    	}
    }
    
  • 相关阅读:
    xps坐标计算
    xps文档
    xps坐标提取
    javascript
    python 类的继承
    PHP parse_url函数示例
    PHP 二维数组按照指定键排序(正序或倒叙均可)
    PHP substr()函数参数解释 通俗易懂
    PHP四大经典排序算法源码
    X友 NC 远程命令执行
  • 原文地址:https://www.cnblogs.com/mengydz/p/13040877.html
Copyright © 2011-2022 走看看