OpenEdv-开源电子网

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

STM32F407 使用USART+DMA方式有些小问题

[复制链接]

54

主题

140

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
420
金钱
420
注册时间
2014-5-13
在线时间
66 小时
发表于 2014-12-10 15:23:54 | 显示全部楼层 |阅读模式
5金钱
本来最近在学习STM32F407 使用USART+DMA方式接收数据。思路如下:
利用USART3的空闲中断,获取USART接收到的数据个数。


USART3配置:空闲中断
DMA配置:数据传输完成中断

现在出现的问题是:

进入USART空闲中断后:
if(USART_GetITStatus(USART3, USART_IT_IDLE) != RESET)
USART_ClearITPendingBit(USART3,USART_IT_IDLE);
DMA_Cmd(DMA1_Stream1, DISABLE); //关闭DMA,防止处理其间有数据
USART_ITConfig(USART3,USART_IT_IDLE,DISABLE); //关闭串口空闲中断
                DATA_LEN = MaxBufLength - DMA_GetCurrDataCounter(DMA1_Stream1);  //获取剩余长度
if(DATA_LEN > 0)
{
//接收到了数据的
Usart3.len = DATA_LEN;
USART3_RxOneFrameFlag = 1;
USART3_ProcessIRQSrc();
}
DMA1_Stream1->NDTR =512; //重装填
DMA1_Stream1->M0AR = (uint32_t)USART3_RECEIVE_DATA;
USART_ITConfig(USART3,USART_IT_IDLE,ENABLE); //使能串口空闲中断
//读SR后读DR清除Idle
i = USART3->SR;
i = USART3->DR;
DMA_Cmd(DMA1_Stream1, ENABLE); //处理完,重开DMA
}
DMA的Buf设置为512,USART3接收的数据为10个。

当USART3中断执行完后,又进入了DMA中断,不知道是怎么进来的,而且我也测试过,进入的是数据传输完成中断。

最佳答案

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

这个是这样的: 1,初始化串口,允许串口接收中断 2,配置好串口的DMA,不允许中断 3,在串口的接收中断服务函数里面关闭接收中断,开启空闲中断 4,这样才会当串口总线空闲时会发生正确的空闲中断, 5,数据接收的长度是你配置的DMA最大传输长度-当前DMA->NDTR的值 串口和DMA自己配置了,中断处理的例程如下: void USART6_ISR(void) {     //OS_ERR err;       v ...
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

2

主题

84

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
214
金钱
214
注册时间
2014-12-29
在线时间
36 小时
发表于 2014-12-10 15:23:55 | 显示全部楼层
这个是这样的:
1,初始化串口,允许串口接收中断
2,配置好串口的DMA,不允许中断
3,在串口的接收中断服务函数里面关闭接收中断,开启空闲中断
4,这样才会当串口总线空闲时会发生正确的空闲中断,
5,数据接收的长度是你配置的DMA最大传输长度-当前DMA->NDTR的值
串口和DMA自己配置了,中断处理的例程如下:
void USART6_ISR(void)
{
    //OS_ERR err;  
    volatile uint32_t i;
    if(USART6->CR1 & RXNEIE)                                                    //接收中断
    {  
        USART6->CR3 |= DMAR;                                                    //打开USART3的DMA接收
        USART6->CR1 &=~RXNEIE;                                               //关闭接受中断
        USART6->CR1 |= IDLEIE;                                                  //打开空闲中断
        
        DMA_ClearITPendingBit(DMA2_Stream1,DMA_IT_TCIF1);  //清除串口对应DMA的标记信息等
        DMA_Cmd(DMA2_Stream1,ENABLE);                                 //打开DMA,在串口的DMA初始化中配置好串口接收数据的存储地址,
                                                                                                 //因为之前是配置好DMA的,只不过没有打开,此时串口接收到的第一个数据已经存储到对应的位置了,
        //写一个事件标志,处于接收状态
        //OSFlagPost(&usartFlagGrp_A, usart_6_rxing, OS_OPT_POST_FLAG_SET|OS_OPT_POST_NO_SCHED, &err);
    }

    else if(USART6->CR1 & IDLEIE)                                              //空闲中断,
    {
        DMA_Cmd(DMA2_Stream1,DISABLE);                               //关闭DMA通道
        USART_RX[usart_6-1].rxLen = usartDataLength-DMA2_Stream1->NDTR;        //获取接收的数据长度    USART_RX[usart_6-1].rxLen这个换成你的数据长度接收位置 
        DMA_SetCurrDataCounter(DMA2_Stream1, usartDataLength);                          //usartDataLength是我定义的串口默认接收数据最大长度
        
        i = USART6->SR;
        i = USART6->DR;
        USART6->CR3 &=~DMAR;                                                   //关闭USART3的DMA接收
        USART6->CR1 &=~IDLEIE;                                                 //关闭空闲中断
        USART6->CR1 |= RXNEIE;                                                   //重新允许接收中断,也可以在数据处理好了后在接收
        //清除串口的接收状态
        //OSFlagPost(&usartFlagGrp_A, usart_6_rxing, OS_OPT_POST_FLAG_CLR|OS_OPT_POST_NO_SCHED, &err);
        //OSTaskQPost(&USART_RX_task_TCB, (void *)0, usart_6, OS_OPT_POST_FIFO|OS_OPT_POST_NO_SCHED, &err); 
    }
}

当需要再次转入接收时,
{
            i= USART6->SR;
            i= USART6->DR;
            USART6->CR1 |= RXNEIE; 
}
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2014-12-10 21:24:59 | 显示全部楼层
帮顶....
回复

使用道具 举报

54

主题

140

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
420
金钱
420
注册时间
2014-5-13
在线时间
66 小时
 楼主| 发表于 2014-12-10 22:01:22 | 显示全部楼层
再顶。。。。有大神帮忙试下的么?
回复

使用道具 举报

2

主题

31

帖子

0

精华

初级会员

Rank: 2

积分
63
金钱
63
注册时间
2015-3-31
在线时间
1 小时
发表于 2015-4-7 17:14:57 | 显示全部楼层
这个我建议从定时器中断做,比如10ms读取dma寄存器值,便知道现在接受多少数据,把buffer设置大一点,不需要dma满了再中断,没必要。
回复

使用道具 举报

5

主题

91

帖子

0

精华

初级会员

Rank: 2

积分
183
金钱
183
注册时间
2014-10-28
在线时间
14 小时
发表于 2015-4-7 23:05:01 | 显示全部楼层
我用USART+DMA运行时正常的,没有问题,
你这儿说加入DMA中断,不知道为什么要开DMA中断
说下我的思路
我开启usart dma是循环的 相当于一个硬件环形buffer 不用担心冲出去
开启usart的空闲中断  然后每一次传输完后会进入一次usart空闲中断   这个里面去处理下环形buffer的信息,首地址偏移 尾地址偏移等 
因为我用了ucos 我再空闲中断里面给任务发送信号 处理 你可以直接设置一个标志位就好

这里觉得没有必要用单次DMA
成功必然有成功的原因,
回复

使用道具 举报

7

主题

17

帖子

0

精华

初级会员

Rank: 2

积分
65
金钱
65
注册时间
2015-1-6
在线时间
0 小时
发表于 2015-6-2 16:10:08 | 显示全部楼层
回复【5楼】simplelifeNick:
---------------------------------
空闲中断 只连接 RX  TX  引脚就可以工作吗?还是需要连接 CTS  RTS 谢谢  还望回复啊
回复

使用道具 举报

5

主题

91

帖子

0

精华

初级会员

Rank: 2

积分
183
金钱
183
注册时间
2014-10-28
在线时间
14 小时
发表于 2015-6-4 18:11:16 | 显示全部楼层
回复【6楼】尼泊尔123:
---------------------------------
只用rx tx
检测的是rx 
我用的还蛮稳定的
成功必然有成功的原因,
回复

使用道具 举报

7

主题

17

帖子

0

精华

初级会员

Rank: 2

积分
65
金钱
65
注册时间
2015-1-6
在线时间
0 小时
发表于 2015-6-10 16:48:22 | 显示全部楼层
回复【7楼】simplelifeNick:
---------------------------------
谢谢回复啊!  不用开启流控,也不用硬件连接流控引脚 是吧?还想咨询一下,这个接收空闲,是多长时间空闲?只是RX引脚空闲会产生中断?如果DMA发送过程中RX接收空闲了,会产生空闲中断吗?  问的有点多,还望回复!非常感谢!
回复

使用道具 举报

2

主题

84

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
214
金钱
214
注册时间
2014-12-29
在线时间
36 小时
发表于 2015-6-11 17:03:23 | 显示全部楼层
回复【9楼】尼泊尔123:
---------------------------------
1,无需流控制相关内容;
2,按手册是3.5个字符的时间以后没有数据为空闲,我也没有具体测试;
3,STM32串口是双工的,这个空闲时指的是串口的接收的空闲,与发送和DMA无关。我的串口接收例程中用的中断都是串口本身的,没有使用DMA中断,DMA只负责传输,不产生中断。
4,这样的方式是解决串口无固定数据长度接收的问题,且你接收的数据是需要一个断点,及需要给串口一个判断是否出现空闲的机会,对于那种循环往复不停传输的场合不适用。一般发送的数据我们都是知道数据长度的,直接配置DMA按长度传送,完成后DMA中断就行。
另,我的串口通讯协议是modbus。通讯最好有协议,可以更具协议来确定数据传输方式。如何你接收的数据都是等长的,不用这么复杂,配DMA按固定长度接收就行,接收完成后DMA中断。
回复

使用道具 举报

5

主题

91

帖子

0

精华

初级会员

Rank: 2

积分
183
金钱
183
注册时间
2014-10-28
在线时间
14 小时
发表于 2015-6-13 16:25:42 | 显示全部楼层
回复【9楼】尼泊尔123:
---------------------------------
貌似芯片检测的是 rx脚接收数据   这个阈值时间和波特率有关  
当大于1个字节的时间没有收到数据就认为空闲了  所以另一端发送最好是DMA可以连续不断  
用CPU的话如果中间打断一下  你这边可能就进入空闲终端了
成功必然有成功的原因,
回复

使用道具 举报

2

主题

23

帖子

0

精华

初级会员

Rank: 2

积分
54
金钱
54
注册时间
2016-10-12
在线时间
14 小时
发表于 2016-11-8 19:27:19 | 显示全部楼层
hhlh2l 发表于 2015-6-11 17:03
回复【9楼】尼泊尔123:
---------------------------------
1,无需流控制相关内容;
2,按手册是3.5个字符 ...

你好,我现在在用DMA+空闲中断的方式接收数据,但是我就是需要满足我设置的最大的BufferSize才可以进我的中断,你说的“接收的数据需要一个断点,及需要给串口一个判断是否出现空闲的机会”是什么意思呢?求教!谢谢!
回复

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2025-6-17 07:32

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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