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条回答
gagaguojia
2019-12-22 19:12
acmilannast 发表于 2016-12-26 17:10
你坐的功能单一 应该没问题,实时性有保证,任务稍微复杂一点的话就不可靠了。 ...

任务稍微复杂一点的话就不可靠了?------能具体说一下什么情况下不可靠?不要一句话带过。我给公司写的GPS+gprs+mqqt+ucosiii的代码都成新产品了,2016年11月份又出了2000台左右,到现在还没出问题,如果你预见到了有bug,请指点一二,谢谢

一周热门 更多>