usart1实现DMA的发送和接收功能,出现的接收问题

2020-01-01 17:36发布

小弟刚上手stm32不久,我现在搞了一个用usart1实现了DMA的发送和接收功能。已经成功了,但是我设置的是一次接收32

个字符,如果接收的超过或者少于32个字符,就会出现问题,就无法接收了(我们实现的是用ZigBee无线传输,一次定义32

个字符为一个数据包,但是就怕zigbee的接收的问题,使得DMA无法收到定义好的32个字符,这样就会无法完成后续的任务



我的思路是这样的:
1.先配置USART1的时钟以及相应的GPIO,初始化USART1,使能USART1;
2.0使能DMA时钟
2.1配置DMA发送:
----配置DMA发送中断(DMA1_Channel4)
----DMA发送设置,DMA_BufferSize设为32,都是8bit(DMA_PeripheralDataSize_Byte,DMA_MemoryDataSize_Byte),DMA_Mode为循环模式,然后:
        DMA_Cmd (DMA1_Channel4,ENABLE);       
        DMA_ITConfig(DMA1_Channel4,DMA_IT_TC,ENABLE);
2.2配置DMA接收:
----配置DMA接收中断(DMA1_Channel5)
----DMA接收设置,DMA_BufferSize设为32,都是8bit(DMA_PeripheralDataSize_Byte,DMA_MemoryDataSize_Byte),DMA_Mode为循环模式,然后:
        DMA_Cmd (DMA1_Channel5,ENABLE);       
        DMA_ITConfig(DMA1_Channel5,DMA_IT_TC,ENABLE);
2.3串口向 DMA发出请求(先让DMA接收,接收到了在发送)
USART_DMACmd(USART1, USART_DMAReq_Rx, ENABLE);
3.1在DMA接收中断函数中(void DMA1_Channel5_IRQHandler(void))
----如果接收完成 //if(DMA_GetFlagStatus(DMA1_FLAG_TC5)==SET)
----就先给一个全局变量flag=1(为了在main函数中的循环里识别)
----再关闭串口的DMA接收请求  //USART_DMACmd(USART1, USART_DMAReq_Rx, DISABLE);
----清除标志        //DMA_ClearFlag(DMA1_FLAG_TC5);
3.2在main函数的while循环中 如果发现flag==1,说明接收完成,可以传想要传输的数据了;
----于是,打开串口的DMA发送请求  //USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE);       
----同时flag=0
3.3在DMA发送中断函数中(void DMA1_Channel4_IRQHandler(void))
----如果发送完成  //if(DMA_GetFlagStatus(DMA1_FLAG_TC4)==SET)
----就关闭串口的DMA发送请求,再打开串口的DMA接收请求:
        USART_DMACmd(USART1, USART_DMAReq_Tx, DISABLE);
        USART_DMACmd(USART1, USART_DMAReq_Rx, ENABLE);
----清除标志        //DMA_ClearFlag(DMA1_FLAG_TC4);
//////////////////////////////////////////////////////////////////////////////////////////////
这就是整个函数,函数实现的很好,接了32个字符(PC给stm32 发送32个字符),马上就发回32个字符,看似已经ok,但是遇到两种蛋疼的情况:

1.pc给stm32 发送的字符少于32个;
2.发送的多于32个;
这样都会导致,stm32无法在继续接收和发送字符了,即使我在向stm32发送正确的32个字符,必须复位才行,这样的话,我们的stm32就无法接收后续的数据了,这怎么办,我想了让它在先关闭串口的DMA请求,在打开,可惜还是不行,请求高人解答。
希望高人谈一下引起这种情况的原因,以及详细的解答方案,最好能有关键性的代码和解释。
谢谢。
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
26条回答
lovelywwei
1楼-- · 2020-01-03 19:41
总线空闲中断+DMA很方便啊。打开USART_IDLE中断,关闭RXNE中断,允许UART接收DMA,配置好DMA的源为USART的数据寄存器,大小比你最大一包数据的长度大就可以,然后在uart中断中查询空闲中断标记,读取DMA接收到的数据。
humanking7
2楼-- · 2020-01-03 23:17
lovelywwei 发表于 2013-3-29 17:40
总线空闲中断+DMA很方便啊。打开USART_IDLE中断,关闭RXNE中断,允许UART接收DMA,配置好DMA的源为USART的数 ...

谢谢,我现在用的是中断在做这个项目,感觉这个安全(项目中用stm32做飞控板与地面数据交互的枢纽,用dma发送还得延时后才能给下一个包赋值,有点怕),闲下来会研究一下,谢谢您
humanking7
3楼-- · 2020-01-04 04:19
wsfry 发表于 2013-3-29 17:28
上面的大侠提供的方法你有没有试一下呀,效果如何?

还没有呢,这段时间忙的焦头烂额,研究成功了,一定会通知你的,谢谢您的关注
wsfry
4楼-- · 2020-01-04 08:26
 精彩回答 2  元偷偷看……
tarzar
5楼-- · 2020-01-04 10:19
lovelywwei 发表于 2013-3-29 17:40
总线空闲中断+DMA很方便啊。打开USART_IDLE中断,关闭RXNE中断,允许UART接收DMA,配置好DMA的源为USART的数 ...

这个方法非常棒!
对最后一句进行再一次解释一下:在UART中断中查询空闲中断标志,方便其他人理解。  UART中断是由多种中断(发送中断,接收中断,空中断,空闲中断等9个)共用一个入口地址。
tarzar
6楼-- · 2020-01-04 15:55
补充:空闲中断,平时不会一直产生中断。只有当接收过字符后,然后一直接收直到没有再接收到数据,处于空闲状态,才会产生中断。

一周热门 更多>