stm32f103应用DMA接收串口1数据的一点心得 采用循环列队

2019-12-18 18:50发布

本帖最后由 gagaguojia 于 2014-8-28 16:01 编辑

首先 DMA接收 采用循环模式接收 应用循环列队接收不定长的数据
#define USART1MAXSIZE 1024
g_usartRxForTemp[USART1MAXSIZE];//接收处理缓存
DMA_InitStructrue.DMA_MemoryBaseAddr = (uint32_t)(g_usartRxForTemp); //接收的都放在这里 这是接收大缓存
DMA_InitStructrue.DMA_BufferSize = (uint32_t)USART1MAXSIZE;//要接收的长度 在这里一般设个大点的值 保证接收的数据不会因为处理不及时,使得尾指针超过头指针
DMA_InitStructrue.DMA_Mode = DMA_Mode_Circular;//循环接收       
//其他设置在此略

//1、DMA循环计数值是递减的 当计数值为1以后,下一个值不是0,而是USART1MAXSIZE
//2、判断尾指针的位置  CurrDataCount = DMA_GetCurrDataCounter(DMA1_Channel5);
                                      usartRear=USART1MAXSIZE-CurrDataCount;
//3、队列其他函数
///////////////////////////////////////////////////////////////////////////

//判队空
u8 EmptyQueueForReceive(void)//判队空 1==队空
{  
         if(usartFront!=usartRear)
         {
                   return 0;//
          }
          else
          {
                   return 1;//
          }
}


//出队
u8 deQueueForReceive(void)
{   
            u8 temp;
            temp=*(g_usartRxForTemp+usartFront); //在这里要先出队再指针++ 因为入队是DMA自己完成的,它是一个先入队,再尾指针++的 我们得配合DMA这个特性
        usartFront=(usartFront+1)%USART1MAXSIZE
        return temp;  
}
/*
这样,
【入队】就不用管了,DMA自动完成,当接收到USART1MAXSIZE个数据后,DMA自动就帮咱们将尾指针指向初始了----队列循环
【出队】用u8 deQueueForReceive(void)出队(在出队之前别忘了判队空u8 EmptyQueueForReceive(void))
【注意】采用这样的方式,数据处理效率要跟的上, 保证接收的数据不会因为处理不及时,使得尾指针超过头指针,
避免出现这种情况的方法有2个:
<1>USART1MAXSIZE 加大他的值  1024---3000----5000等
<2>程序上做优化,使得数据处理函数(就是包含出队的函数),在总程序的大循环里比较经常的会调用,比如50ms调用一次,每次处理一条数据(20个字节左右的数据) 这样一般就没问题(USART1MAXSIZE=1024)
*/
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
39条回答
styleno1
1楼-- · 2019-12-18 19:57
之前用的256Byte的环形缓冲,遭遇重载出错,也能恢复正常工作。
gagaguojia
2楼-- · 2019-12-18 23:00
 精彩回答 2  元偷偷看……
franki
3楼-- · 2019-12-19 02:08
嗯    不错    可以试试
stely
4楼-- · 2019-12-19 02:18
mark环形队列
qs6361036
5楼-- · 2019-12-19 02:39
赞一个     很好的想法    学习啦
lrzxc
6楼-- · 2019-12-19 03:36
需要mark一下环形列队。

一周热门 更多>