串口1的接受,使用空闲中断加DMA,DMA初始化配置中的循环模式问题。

2019-07-20 06:23发布

现象:把DMA配置成循环模式就能正常接受串口1的数据,配置成普通模式只能正常接受第一次,第二次就不行了,这是为什么??? 使用的是阿波罗的板,STM32F429

串口初始化如下:
void uart_init(u32 bound)
{       
        //UART 初始化设置
        UART1_Handler.Instance=USART1;                                            //USART1
        UART1_Handler.Init.BaudRate=bound;                                    //波特率
        UART1_Handler.Init.WordLength=UART_WORDLENGTH_8B;   //字长为8位数据格式
        UART1_Handler.Init.StopBits=UART_STOPBITS_1;            //一个停止位
        UART1_Handler.Init.Parity=UART_PARITY_NONE;                    //无奇偶校验位
        UART1_Handler.Init.HwFlowCtl=UART_HWCONTROL_NONE;   //无硬件流控
        UART1_Handler.Init.Mode=UART_MODE_TX_RX;                    //收发模式
        HAL_UART_Init(&UART1_Handler);                                            //HAL_UART_Init()会使能UART1
       
        //HAL_UART_Receive_IT(&UART1_Handler, (u8 *)aRxBuffer, RXBUFFERSIZE);//该函数会开启接收中断:标志位UART_IT_RXNE,并且设置接收缓冲以及接收缓冲接收最大数据量(使用回调函数处理中断需要调用该函数)
}

//UART底层初始化,时钟使能,引脚配置,中断配置
//此函数会被HAL_UART_Init()调用
//huart:串口句柄
void HAL_UART_MspInit(UART_HandleTypeDef *huart)
{
    //GPIO端口设置
        GPIO_InitTypeDef GPIO_Initure;
       
        if(huart->Instance==USART1)//如果是串口1,进行串口1 MSP初始化
        {
                __HAL_RCC_GPIOA_CLK_ENABLE();                        //使能GPIOA时钟
                __HAL_RCC_USART1_CLK_ENABLE();                        //使能USART1时钟
       
                GPIO_Initure.Pin=GPIO_PIN_9;                        //PA9
                GPIO_Initure.Mode=GPIO_MODE_AF_PP;                //复用推挽输出
                GPIO_Initure.Pull=GPIO_PULLUP;                        //上拉
                GPIO_Initure.Speed=GPIO_SPEED_FAST;                //高速
                GPIO_Initure.Alternate=GPIO_AF7_USART1;        //复用为USART1
                HAL_GPIO_Init(GPIOA,&GPIO_Initure);                   //初始化PA9

                GPIO_Initure.Pin=GPIO_PIN_10;                        //PA10
                HAL_GPIO_Init(GPIOA,&GPIO_Initure);                   //初始化PA10
                __HAL_UART_DISABLE_IT(huart,UART_IT_TC);


        __HAL_UART_CLEAR_IDLEFLAG(&UART1_Handler);
        __HAL_UART_ENABLE_IT(huart,UART_IT_IDLE);                //开启空闲中断
        //SET_BIT(USART1->CR3,USART_CR3_DMAR); //使能串口1的DMA接受


#if EN_USART1_RX
        //        __HAL_UART_ENABLE_IT(huart,UART_IT_RXNE);                //开启接收中断
                HAL_NVIC_EnableIRQ(USART1_IRQn);                                //使能USART1中断通道
                HAL_NVIC_SetPriority(USART1_IRQn,3,3);                        //抢占优先级3,子优先级3
#endif       
        }
}



DMA初始化如下:
void My_DMA_Init()
{
    __HAL_RCC_DMA2_CLK_ENABLE();

    __HAL_LINKDMA(&UART1_Handler,hdmarx,Uart1Rx_DMA_handle);

    Uart1Rx_DMA_handle.Instance=DMA2_Stream5;
    Uart1Rx_DMA_handle.Init.Channel=DMA_CHANNEL_4;
    Uart1Rx_DMA_handle.Init.Direction=DMA_PERIPH_TO_MEMORY;
    Uart1Rx_DMA_handle.Init.PeriphInc=DMA_PINC_DISABLE;
    Uart1Rx_DMA_handle.Init.MemInc=DMA_MINC_ENABLE;
    Uart1Rx_DMA_handle.Init.PeriphDataAlignment=DMA_PDATAALIGN_BYTE;
    Uart1Rx_DMA_handle.Init.MemDataAlignment=DMA_MDATAALIGN_BYTE;
    Uart1Rx_DMA_handle.Init.Mode=DMA_CIRCULAR;  //就是这里,配置成DMA_NORMAL就不行了
    Uart1Rx_DMA_handle.Init.Priority=DMA_PRIORITY_MEDIUM;
    Uart1Rx_DMA_handle.Init.FIFOMode=DMA_FIFOMODE_DISABLE;
    Uart1Rx_DMA_handle.Init.FIFOThreshold=DMA_FIFO_THRESHOLD_FULL;
    Uart1Rx_DMA_handle.Init.MemBurst=DMA_MBURST_SINGLE;
    Uart1Rx_DMA_handle.Init.PeriphBurst=DMA_PBURST_SINGLE;

    HAL_DMA_DeInit(&Uart1Rx_DMA_handle);   
    HAL_DMA_Init(&Uart1Rx_DMA_handle);

    HAL_UART_Receive_DMA(&UART1_Handler,USART1_RX_BUF,200);//开启dma接收
}


串口中断如下:
void USART1_IRQHandler(void)                       
{   
    if((__HAL_UART_GET_FLAG(&UART1_Handler,UART_FLAG_IDLE)!=RESET))  //空闲中断
    {        
        printf("进入空闲中断了 ");
        __HAL_UART_CLEAR_IDLEFLAG(&UART1_Handler);
        HAL_UART_DMAStop(&UART1_Handler);  

        USART1_RX_NUM = UART1_Handler.hdmarx->Instance->NDTR;  
        USART1_RX_NUM =  200 - USART1_RX_NUM;
        printf("接受到了%d个数据 ",USART1_RX_NUM);
        HAL_UART_Receive_DMA(&UART1_Handler,USART1_RX_BUF,200);//开启dma接收

        for(i=0;i<USART1_RX_NUM;i++)
        {
            printf("%x ",USART1_RX_BUF[i]);      
        }   
        printf(" ");
    }

    HAL_UART_IRQHandler(&UART1_Handler);       
}





友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
6条回答
水上的树
2019-07-20 13:32

                        DMA_Cmd(DMA2_Stream5,DISABLE);  
                        DMA_ClearFlag(DMA2_Stream5,DMA_FLAG_TCIF5);  
                        len = set_recLen - DMA_GetCurrDataCounter(DMA2_Stream5);  
       
                       
                        DMA_SetCurrDataCounter(DMA2_Stream5,set_recLen);  
                        DMA_Cmd(DMA2_Stream5,ENABLE);

一周热门 更多>