初级会员

- 积分
- 79
- 金钱
- 79
- 注册时间
- 2017-1-22
- 在线时间
- 20 小时
|
10金钱
UART+DMA实现是一件挺普通的事情了,不外乎串口空闲中断+DMA接收完成中断来处理。实际调试时发现了几个问题,这里向各位求助一下。
1.当检测到串口空闲中断时,这个时候需要DISABLE DMA读出数据后再ENABLE DMA。如果在这段时间内来数据了怎么办?各位有什么好办法?如果这个问题解决不了,还不如直接用接收中断来处理了。亦或者是DMA功能的应用场景就不适合这种会有数据突发传输的情况?仅适合于周期性数据传输的情况?
2.stm32f0系列是没有DMA双缓冲功能的,但之前看到过人工做两个buffer,在触发DMA完成中断里切换DMA内存基地址,进行人工的双缓冲buffer。但我实际测试时发现效果并不理想。
3.我使用XCOM串口调试助手,以10ms间隔不停发送100byte数据时,发现DMA接收到的数据周期性丢失2~3byte.我怀疑是描述的问题1导致的。但是按道理来讲,如果是问题1的情况,应该会触发ORE中断吧?但是并不是每次都能检测到ORE中断。
各位大佬,有什么想法???
代码如下:
- //初始化
- void UartRecvDMACommInit(UART_EXT_INTERFACE* pMe)
- {
- DMA_InitTypeDef DMA_InitStructure;
- DMA_DeInit(pMe->pDMARecv->channel);
- USART_ITConfig(pMe->USARTx, USART_IT_IDLE, ENABLE);
- DMA_RemapConfig(pMe->pDMARecv->DMAy, pMe->pDMARecv->map);
- /* Common DMA configuration */
- DMA_InitStructure.DMA_BufferSize = pMe->pDMARecv->maxLen;
- DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
- DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
- DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
- DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
- DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
- DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
- /* DMA1 Channel1 configuration */
- DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)pMe->pDMARecv->buf;
- DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
- DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
- DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)(&(pMe->USARTx->RDR));
- DMA_Init(pMe->pDMARecv->channel, &DMA_InitStructure);
- USART_DMACmd(pMe->USARTx, USART_DMAReq_Rx, ENABLE);// ??DMA?????????
- DMA_ClearFlag(pMe->pDMARecv->flagGL); // clear all DMA flags
- DMA_ITConfig(pMe->pDMARecv->channel,DMA_IT_TC,ENABLE); //open DMA send inttrupt
- DMA_Cmd(pMe->pDMARecv->channel, ENABLE);
- }
复制代码
- //串口中断
- if(USART_GetFlagStatus(pMe->USARTx, USART_FLAG_ORE) != RESET)
- {
- USART_ClearITPendingBit(pMe->USARTx,USART_IT_ORE);
- USART_ReceiveData(pMe->USARTx);
- UartTest.ORECnt++;
- }
- if(USART_GetITStatus(USART1,USART_IT_IDLE)!= RESET)
- {
-
- pMe->USARTx->ISR;//??SR,???DR????
- pMe->USARTx->RDR;
- //tem=tem;
- pMe->rxStatus = UART_IDLE;
- DMA_Cmd(pMe->pDMARecv->channel, DISABLE);
- pMe->curRecvLen = pMe->pDMARecv->maxLen - pMe->pDMARecv->channel->CNDTR;// ??buf??????buf??,??????????
- if(pMe->curRecvLen != 100)
- pMe->curRecvLen = pMe->curRecvLen;
- UartTest.recvLen += pMe->curRecvLen;
- if(PushBytesInQueue_Q(pMe->pQueue, pMe->pDMARecv->buf, pMe->curRecvLen))
- UartTest.recvPushInLen += pMe->curRecvLen;
- //memset(pMe->pDMARecv->buf, 0, pMe->pDMARecv->maxLen);
- pMe->pDMARecv->channel->CNDTR = pMe->pDMARecv->maxLen ;
- DMA_Cmd(pMe->pDMARecv->channel, ENABLE);
-
- USART_ClearITPendingBit(pMe->USARTx, USART_IT_IDLE);
- }
复制代码- //DMA接收完成中断
- if(DMA_GetITStatus(pMe->pDMARecv->flagTC) != RESET)
- {
- DMA_ClearFlag(pMe->pDMARecv->flagGL);
- pMe->rxStatus = UART_IDLE;
- DMA_Cmd(pMe->pDMARecv->channel, DISABLE);
- pMe->curRecvLen = pMe->pDMARecv->maxLen - pMe->pDMARecv->channel->CNDTR;
- UartTest.recvLen += pMe->curRecvLen;
- if(PushBytesInQueue_Q(pMe->pQueue, pMe->pDMARecv->buf, pMe->curRecvLen))
- UartTest.recvPushInLen += pMe->curRecvLen;
- //memset(pMe->pDMARecv->buf, 0, pMe->pDMARecv->maxLen);
- pMe->pDMARecv->channel->CNDTR = pMe->pDMARecv->maxLen ;
- DMA_Cmd(pMe->pDMARecv->channel, ENABLE);
复制代码
|
|