OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 5003|回复: 6

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

[复制链接]

6

主题

14

帖子

0

精华

初级会员

Rank: 2

积分
59
金钱
59
注册时间
2018-8-2
在线时间
32 小时
发表于 2018-8-30 15:35:13 | 显示全部楼层 |阅读模式
5金钱
现象:把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("进入空闲中断了\r\n");
        __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个数据\r\n",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("\r\n");
    }

    HAL_UART_IRQHandler(&UART1_Handler);       
}





正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

0

主题

5

帖子

0

精华

新手入门

积分
9
金钱
9
注册时间
2018-4-12
在线时间
1 小时
发表于 2018-8-30 16:12:58 | 显示全部楼层
你需要重新设置DMA接受的数量  
回复

使用道具 举报

0

主题

5

帖子

0

精华

新手入门

积分
9
金钱
9
注册时间
2018-4-12
在线时间
1 小时
发表于 2018-8-30 16:16:51 | 显示全部楼层

                        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);
回复

使用道具 举报

6

主题

14

帖子

0

精华

初级会员

Rank: 2

积分
59
金钱
59
注册时间
2018-8-2
在线时间
32 小时
 楼主| 发表于 2018-9-3 10:00:43 | 显示全部楼层
水上的树 发表于 2018-8-30 16:16
DMA_Cmd(DMA2_Stream5,DISABLE);  
                        DMA_ClearFlag(DMA2_Stream5,DMA_FLAG_TCIF5);  
                        len = se ...

HAL_UART_Receive_DMA(&UART1_Handler,USART1_RX_BUF,200);//开启dma接收
这个函数里有设了,这个函数有调用DMA_SetConfig(hdma, SrcAddress, DstAddress, DataLength);。是设了的
回复

使用道具 举报

11

主题

95

帖子

0

精华

高级会员

Rank: 4

积分
598
金钱
598
注册时间
2017-3-19
在线时间
116 小时
发表于 2018-9-4 11:38:13 | 显示全部楼层
LZ要是搞定了,可以分享一下,曾经搞过单次模式DMA更新PWM也不行,要是循坏的,就没有问题
回复

使用道具 举报

11

主题

95

帖子

0

精华

高级会员

Rank: 4

积分
598
金钱
598
注册时间
2017-3-19
在线时间
116 小时
发表于 2018-9-4 11:46:23 | 显示全部楼层
在开启DMA接受后加多一句命令 开启串口DMA使能  USART_DMACmd(USART1,USART_DMAReq_Rx,ENABLE);
HAL库没有用过,你找下有没有跟上面功能相同的函数
回复

使用道具 举报

3

主题

1907

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4106
金钱
4106
注册时间
2018-8-14
在线时间
696 小时
发表于 2018-9-4 11:50:49 | 显示全部楼层
本帖最后由 edmund1234 于 2018-9-4 11:52 编辑
Yyyyy羊 发表于 2018-9-3 10:00
HAL_UART_Receive_DMA(&UART1_Handler,USART1_RX_BUF,200);//开启dma接收
这个函数里有设了,这个函数有 ...

在第二次重启DMA时, 要先DISABLE DMA, 再写BUFFER SIZE, 再使能DMA, 而不是说你初始时没写
否则BUFFER SIZE写不进去的
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-8 02:46

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表