本帖最后由 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)
*/
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
不知道楼主在发送是怎么处理的(也采用DMA):
比如前面已经有包数据DMA正在发送中, 此时数据处理中又需要发送一包(可以直接加在上一包的末尾,然后DMA一起发送出去)?
还是一定要等到上一包发送完,DMA空闲下来,才能再装下一包发送
我跑的ucos系统,我是先准备几个缓冲区 比如准备3个缓冲区,每次发送的时候循环用不同的缓冲区,我只管把要发送的数写进缓冲区即可,然后等上一次dma发送完后,再发这次的,由于跑系统,所以等待上一次dma处理完的时间不浪费 可以干别的事情
至于采用几个缓冲区 缓冲区多大 要根据实际情况自己来设置
明白了,谢谢!
一周热门 更多>