回复【2楼】 正点原子 :
你的DMA缓冲设置为多大了?
---------------------------------
缓存:2000
在前面的基础上做了修改(红色部分),采用了双缓存
UART数据益出现象少了很多。测试了一个多小时,只出现了三次。
如果每溢出一次,只丢失一个字节那还能接受。
但问题是每溢一次;则那一次的一整包数据DMA都接收不到
例如:一包数据有500个字节,若第一字节传输时使UART发生溢出,则这500个字节DMA都收不到。
非得下一包数据到来时DMA才能接收到
另外我把UART4的溢出中断打开了,溢出中断发生后,得清除溢出中断标号,否则DMA再也收到数据了。
清除溢出标号:
void UART4_IRQHander(void)
{
static u16 count = 0;
u8 i;
count++;
if(USART_GetITStatus(UART4,USART_IT_ORE))
{
i = *(volatile unsigned long *)UART4->SR;
i = UART4->DR;
printf("%d\n\r",count);
}
}
采用双缓存的代码:
/*****************************************************
** 查询DMA接收数据的状态
** buff: 存储接收到的数据
** 返回:没有接收数据返回0
否则返回接收到数据的个数
*****************************************************/
unsigned short Receive_UART4(unsigned char *buff)
{
static unsigned short remaining,i,num;
static unsigned short count = UART4_RX_SIZE;
//缓存标记:1--->UART4_RxBuff1;1--->UART4_RxBuff2
static unsigned char flag = 1;
if(USART_GetFlagStatus(UART4,USART_FLAG_IDLE))
{
//思想:Receive_UART4函数每隔2ms调度1次,
//若两次调度期间接收到的数据的数量没有发送变化。
//则串口处于空闲状态;即可复制DMA传输的数据
remaining = DMA_GetCurrDataCounter(DMA2_Channel3);
if((remaining == UART4_RX_SIZE) || (count != remaining))
count = remaining;
else
{
num = (UART4_RX_SIZE - remaining);
//再次判断总线是否空闲
if(!USART_GetFlagStatus(UART4,USART_FLAG_IDLE))
return 0;
if(flag == 1)
{
DMA2_Channel3->CCR &= ~(1 << 0); //停止DMA
DMA2_Channel3->CNDTR = UART4_RX_SIZE; //设置DMA传输大小
DMA2_Channel3->CMAR = (unsigned long)UART4_RxBuff2; //设置DMA缓存
DMA2_Channel3->CCR |= (1 << 0); //启动DMA
flag = 2;
for(i = 0; i < num; i++)
buff = UART4_RxBuff1;
}
else
{
DMA2_Channel3->CCR &= ~(1 << 0); //停止DMA
DMA2_Channel3->CNDTR = UART4_RX_SIZE; //设置DMA传输大小
DMA2_Channel3->CMAR = (unsigned long)UART4_RxBuff1; //设置DMA缓存
DMA2_Channel3->CCR |= (1 << 0); //启动DMA
flag = 1;
for(i = 0; i < num; i++)
buff = UART4_RxBuff2;
}
return num;
}
}
return 0;
} |