首先 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) |