OpenEdv-开源电子网

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

STM32H7 DMA 空闲中断 数据缓冲区为空

[复制链接]

12

主题

40

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3127
金钱
3127
注册时间
2017-2-7
在线时间
387 小时
发表于 2019-11-24 11:55:43 | 显示全部楼层 |阅读模式
1金钱
本帖最后由 fengqiyunyong52 于 2019-11-24 16:40 编辑

在STM32H743的平台上,用DMA加空闲中断的方式实现了串口数据的接收。
问题如下:
串口中断触发后,偶尔出现,串口数据接收缓冲区的内容显示为空。板子重新上电后大部分情况下都能恢复正常。
个人思考,问题可能出现的方向有:1.是否跟UART初始化与DMA初始化过程的先后顺序有关?
2.是否跟KEIL程序配置时的IRAM1/IRAM2的勾选有关?
3.是否跟CACHE有关?但是在不打开Cache、打开Cache并开启透传的两种情况下都会发生问题。
苦苦寻找问题中,请各位老师指点迷津,谢谢谢谢~

附源码:
//UART1 初始化设置
        UART1_Handler.Instance                        =USART1;                                        //USART1
        UART1_Handler.Init.BaudRate                =uart1_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_RX;                        //接收模式
        HAL_UART_Init(&UART1_Handler);                                                            //HAL_UART_Init()会使能UART2
        
        __HAL_UART_ENABLE_IT(&UART1_Handler, UART_IT_IDLE);     //开启空闲接收中断
        __HAL_UART_CLEAR_IDLEFLAG(&UART1_Handler);                          //清除标志位
        
        HAL_UART_Receive_DMA(&UART1_Handler,uart1_recvbuf,UART1_RECVBUF_SIZE);//打开DMA接收,指定接收缓存区和接收大小


//void HAL_UART_MspInit(UART_HandleTypeDef *huart)
        GPIO_InitTypeDef GPIO_Initure;
        
        if(huart->Instance==USART1)
        {
                __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_FREQ_HIGH;   //高速
                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_NVIC_EnableIRQ(USART1_IRQn);                //使能USART1中断通道
                HAL_NVIC_SetPriority(USART1_IRQn,0,0);        //抢占优先级3,子优先级2
        }


/DMA配置        

        __HAL_RCC_DMA2_CLK_ENABLE();//DMA2时钟使能        
        HAL_NVIC_SetPriority(DMA2_Stream7_IRQn,0,0);
        HAL_NVIC_EnableIRQ(DMA2_Stream7_IRQn);


        UART1RxDMA_Handler.Instance                                =DMA2_Stream7;                     //数据流选择
        UART1RxDMA_Handler.Init.Request                        =DMA_REQUEST_USART1_RX;
        UART1RxDMA_Handler.Init.Direction                        =DMA_PERIPH_TO_MEMORY;   //外设到存储器
        UART1RxDMA_Handler.Init.PeriphInc                        =DMA_PINC_DISABLE;             //外设非增量模式
        UART1RxDMA_Handler.Init.MemInc                        =DMA_MINC_ENABLE;              //存储器增量模式
        UART1RxDMA_Handler.Init.PeriphDataAlignment        =DMA_PDATAALIGN_BYTE;       //外设数据长度:8位
        UART1RxDMA_Handler.Init.MemDataAlignment        =DMA_MDATAALIGN_BYTE;      //存储器数据长度:8位
        UART1RxDMA_Handler.Init.Mode                                =DMA_NORMAL;                      //外设流控模式
        UART1RxDMA_Handler.Init.Priority                        =DMA_PRIORITY_MEDIUM;      //中等优先级
        UART1RxDMA_Handler.Init.FIFOMode                        =DMA_FIFOMODE_DISABLE;              
        UART1RxDMA_Handler.Init.FIFOThreshold                =DMA_FIFO_THRESHOLD_FULL;      
        UART1RxDMA_Handler.Init.MemBurst                        =DMA_MBURST_SINGLE;          //存储器突发单次传输
        UART1RxDMA_Handler.Init.PeriphBurst                        =DMA_PBURST_SINGLE;           //外设突发单次传输
        HAL_DMA_DeInit(&UART1RxDMA_Handler);   
        HAL_DMA_Init(&UART1RxDMA_Handler);
        __HAL_LINKDMA(&UART1_Handler,hdmarx,UART1RxDMA_Handler);                     //将DMA与USART1联系起来(接收DMA)


最佳答案

查看完整内容[请看2#楼]

谢谢各位大佬,问题已解决。
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

12

主题

40

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3127
金钱
3127
注册时间
2017-2-7
在线时间
387 小时
 楼主| 发表于 2019-11-24 11:55:44 | 显示全部楼层
谢谢各位大佬,问题已解决。
回复

使用道具 举报

6

主题

1127

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1656
金钱
1656
注册时间
2019-8-15
在线时间
102 小时
发表于 2019-11-24 12:54:27 | 显示全部楼层
帮顶            
成功没有捷径
回复

使用道具 举报

3

主题

1907

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4106
金钱
4106
注册时间
2018-8-14
在线时间
696 小时
发表于 2019-11-24 17:24:35 | 显示全部楼层
接收数据的地扯都没指定
回复

使用道具 举报

31

主题

2183

帖子

0

精华

资深版主

Rank: 8Rank: 8

积分
14422
金钱
14422
注册时间
2018-8-3
在线时间
1157 小时
发表于 2019-11-25 10:36:41 | 显示全部楼层
回复

使用道具 举报

12

主题

40

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3127
金钱
3127
注册时间
2017-2-7
在线时间
387 小时
 楼主| 发表于 2019-11-25 10:41:08 | 显示全部楼层
edmund1234 发表于 2019-11-24 17:24
接收数据的地扯都没指定

HAL_UART_Receive_DMA(&UART1_Handler,uart1_recvbuf,UART1_RECVBUF_SIZE);

老师,不是通过这一句指定接收缓冲区吗?
回复

使用道具 举报

12

主题

40

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3127
金钱
3127
注册时间
2017-2-7
在线时间
387 小时
 楼主| 发表于 2019-11-25 10:45:33 | 显示全部楼层
翼行园子 发表于 2019-11-25 10:36
参考下这个帖子:http://www.openedv.com/forum.php?mod=viewthread&tid=293299&extra=

谢谢老师 我就是参考的您这个帖子做的DMA设计
回复

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2025-6-9 11:45

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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