OpenEdv-开源电子网

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

DMA发送数据总是丢掉最后的两个字节是怎么回事??

[复制链接]

25

主题

138

帖子

0

精华

高级会员

Rank: 4

积分
612
金钱
612
注册时间
2016-6-7
在线时间
59 小时
发表于 2016-12-13 09:52:32 | 显示全部楼层 |阅读模式
3金钱
昨天问的串口引脚配置问题,使用重定义已经解决了,可是今天又出现了新的问题!
串口数据的发送和接收都使用DMA传输方式,但是发送的数据在最后总是会丢掉两个字节!
在网上看到了一个帖子,跟我遇到的应该是相同的问题,可是我没看懂楼主的解决办法啊!
原帖在这里:http://bbs.21ic.com/icview-276047-1-1.html
我的中断配置:
void DMA1_Channel7_IRQHandler(void)
{
        if(DMA_GetITStatus(DMA1_IT_TC7))
        {
                       
                DMA_ClearITPendingBit(DMA1_IT_GL7);
                DMA_ClearITPendingBit(DMA1_IT_TE7);       
                while(USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET);        //发送完标志
                USART_ClearFlag(USART1,USART_FLAG_TC);
                DMA_Cmd(DMA1_Channel7, DISABLE);//关闭DMA
                GPIO_ResetBits(GPIOD,GPIO_Pin_7);               
        }
}
但是这样依然不行,到底该清哪个标志位啊??

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

使用道具 举报

3

主题

85

帖子

0

精华

高级会员

Rank: 4

积分
586
金钱
586
注册时间
2016-5-13
在线时间
106 小时
发表于 2016-12-13 17:15:57 | 显示全部楼层
while(USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET);        //发送完标志USART_ClearFlag(USART1,USART_FLAG_TC);
一个串口1 一个串口2 你到底用的哪个...
回复

使用道具 举报

25

主题

138

帖子

0

精华

高级会员

Rank: 4

积分
612
金钱
612
注册时间
2016-6-7
在线时间
59 小时
 楼主| 发表于 2016-12-14 16:36:27 | 显示全部楼层
abdfgh 发表于 2016-12-13 17:15
while(USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET);        //发送完标志USART_ClearFlag(USAR ...

啊,用的串口2,这句纯属笔误,不过话又说回来,USART的标志位好像也不用在这里清...最主要的,有没有清这个标志位对结果没有一点影响,还是少两个字节
回复

使用道具 举报

25

主题

138

帖子

0

精华

高级会员

Rank: 4

积分
612
金钱
612
注册时间
2016-6-7
在线时间
59 小时
 楼主| 发表于 2016-12-14 16:38:19 | 显示全部楼层
abdfgh 发表于 2016-12-13 17:15
while(USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET);        //发送完标志USART_ClearFlag(USAR ...

    if(DMA_GetITStatus(DMA1_FLAG_TC7))
    {
                DMA_ClearITPendingBit(DMA1_IT_GL7);
                DMA_ClearFlag(DMA1_FLAG_GL7);         // 清除标志
//                while(USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET);                       
                DMA_Cmd(DMA1_Channel7, DISABLE);   // 关闭DMA通道                       
                GPIO_ResetBits(GPIOD,GPIO_Pin_7);       
        }
这样也不行
回复

使用道具 举报

3

主题

85

帖子

0

精华

高级会员

Rank: 4

积分
586
金钱
586
注册时间
2016-5-13
在线时间
106 小时
发表于 2016-12-14 16:59:56 | 显示全部楼层
给你个小建议
DMA的传输是自己的一套东西,有它自己的传输完成中断等等一系列中断,
如果你用串口的DMA功能,配置好发送缓冲区,数据长度,DMA会自己去发送你需要发送数据的长度,并且在发送完指定长度后给你一个传输完成中断(非循环模式)
这里面完全不牵扯到串口的中断,如果你需要发送完成后知道发送完成,可以在DMA的中断中放置传输完成标志位
回复

使用道具 举报

25

主题

138

帖子

0

精华

高级会员

Rank: 4

积分
612
金钱
612
注册时间
2016-6-7
在线时间
59 小时
 楼主| 发表于 2016-12-15 10:03:02 | 显示全部楼层
abdfgh 发表于 2016-12-14 16:59
给你个小建议
DMA的传输是自己的一套东西,有它自己的传输完成中断等等一系列中断,
如果你用串口的DMA功能 ...

以前用USART1的DMA功能,是可以正常收发数据的,现在改成了USART2,配置基本都差不多,唯一的区别就是串口1收发数据端没有控制位,但串口2有,所以我要在接收到数据后将串口改为接收使能,在发送完成后将串口改为接收使能(即上面的GPIO_ResetBits(GPIOD,GPIO_Pin_7); 这一句)。
但现在的现象 总好像DMA还没有发完数据就被关闭(或者被禁用)了一样。。可是当进入上面的DMA发送中断( DMA1_Channel7_IRQHandler)时,不是就代表已经发送完成了吗?怎么就是少了两个字节呢??
我将DMA的发送缓存区多加了两个字节,可是发送出来的数据就又多了不止两个字节!这真是怪事了。。。

多加两个缓存区字节,就会多发标红的那些字节
2.jpg
回复

使用道具 举报

25

主题

138

帖子

0

精华

高级会员

Rank: 4

积分
612
金钱
612
注册时间
2016-6-7
在线时间
59 小时
 楼主| 发表于 2016-12-15 10:06:03 | 显示全部楼层
abdfgh 发表于 2016-12-14 16:59
给你个小建议
DMA的传输是自己的一套东西,有它自己的传输完成中断等等一系列中断,
如果你用串口的DMA功能 ...

上面笔误 写错了。
接收到数据后将串口改为发送使能:

void USART2_IRQHandler(void)
{
        if(USART_GetITStatus(USART2, USART_IT_IDLE) != RESET)         
        {
//                uint16_t num = 0;
                DMA_Cmd(DMA1_Channel6, DISABLE);// 关闭DMA ,防止干扰       
                DMA_ClearFlag( DMA1_FLAG_GL6);           // 清DMA标志位
                g_MBDataLen = BUFLENGTH - DMA_GetCurrDataCounter(DMA1_Channel6);        //计算接收到多少字节数据
                DMA_SetCurrDataCounter(DMA1_Channel6,BUFLENGTH);                //重新赋值计数值 DMA通道的DMA缓存的大小
                DMA_Cmd(DMA1_Channel6, ENABLE);
                g_MBFrameFlag = 1;                                                                                //一个完整帧接收完毕置位
                g_Recvflag=1;         
                USART_ReceiveData(USART2); // 清IDLE中断标志位
//                num = USART2->SR;
//                num = USART2->DR; // 清IDLE中断标志位
        }
}
回复

使用道具 举报

25

主题

138

帖子

0

精华

高级会员

Rank: 4

积分
612
金钱
612
注册时间
2016-6-7
在线时间
59 小时
 楼主| 发表于 2016-12-16 14:07:34 | 显示全部楼层
回复

使用道具 举报

15

主题

56

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
231
金钱
231
注册时间
2015-3-12
在线时间
18 小时
发表于 2018-1-16 17:05:59 | 显示全部楼层
小弟也遇到这个问题了。现在知道是这样的。DMA--》UART  ,当DMA把数据发送完成后,就进入DMA发送完成中断。但是,此时串口并没有发送完成,还有两个字节待发。这个时候,不能把485切换成接收。要延时一会儿,等待发完。但是,问题就在于,不知道什么时候发完。真是麻烦
回复

使用道具 举报

25

主题

138

帖子

0

精华

高级会员

Rank: 4

积分
612
金钱
612
注册时间
2016-6-7
在线时间
59 小时
 楼主| 发表于 2018-1-16 18:27:53 | 显示全部楼层
挣点圆子 发表于 2018-1-16 17:05
小弟也遇到这个问题了。现在知道是这样的。DMA--》UART  ,当DMA把数据发送完成后,就进入DMA发送完成中断 ...

开启串口发送完成中断啊,在发送完成中断里(USART_IT_TC中断里)把485切换为接收模式。
回复

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2025-7-22 12:21

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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