早些时间写过一篇“STM32F4 UART1 DMA发送和接收不定长度数据”的博文。很多转载的都不注明出处的。后来就没再怎么用过F4的uart 也有朋友反映过会莫名的进接受完成中断,但是实际接受的数据量并没有达到设置的DMA接受长度,应该不会进DMA接收中断,我也没搞明白就不了了之了,可看这个链接:http://www.openedv.com/forum.php?mod=viewthread&tid=76091&extra=
最近有个项目用到了这个功能。之前能接受发送到程序,下载到单片机里面怎么都不行了。很调了很久发现了以下几个问题
1.串口DMA接收中断、DMA发送中断、空闲中断的优先级是有影响。按照以下设置faxi发现不会进接收wa完成中断
//Usart1 NVIC 空闲中断
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority =0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
//DMA NVIC 发送完成中断
NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream5_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
//DMA NVIC 接收完成中断
NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream7_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
这样看系统随时可能接收数据 所以优先级高、发送完中断次之、一般不会一次性接收超过DMA设置长度的数据量所以优先级最低。这种youx优先级发现就不会进jie接收完成中断。如果接收完成中断高于空闲中断。发现进入 空闲中断后 ,此时接收中断会打断空闲中断,清掉标志位以后读不到接收的数据长度。
2.空闲中断里面读取了DMA接收的数据量,在这里注意 在关闭DMA接收后 需要先读接收的数据量 再清除标志。如下:
//¿ÕÏÐÖжÏ
void USART1_IRQHandler(void)
{
u16 data;
if(USART_GetITStatus(USART1,USART_IT_IDLE) != RESET)
{
data = USART1->SR;
data = USART1->DR;
DMA_Cmd(DMA2_Stream5, DISABLE); //¹Ø±ÕDMA,·ÀÖ¹´¦ÀíÆä¼äÓÐÊý¾Ý
UART1_ReceiveSize =RECEIVE_BUF_SIZE - DMA_GetCurrDataCounter(DMA2_Stream5);
if(UART1_ReceiveSize !=0)
{
//OSSemPost(DMAReceiveSize_Sem);
}
DMA_ClearFlag(DMA2_Stream5,DMA_FLAG_TCIF5 | DMA_FLAG_FEIF5 | DMA_FLAG_DMEIF5 | DMA_FLAG_TEIF5 | DMA_FLAG_HTIF5);//
//DMA_SetCurrDataCounter(DMA2_Stream5, RECEIVE_BUF_SIZE);
/*------------------------- DMAy Streamx NDTR Configuration ----------------*/
/* Write to DMAy Streamx NDTR register */
DMA2_Stream5->NDTR = RECEIVE_BUF_SIZE;
/*------------------------- DMAy Streamx PAR Configuration -----------------*/
/* Write to DMAy Streamx PAR */
// DMAy_Streamx->PAR = DMA_InitStruct->DMA_PeripheralBaseAddr;
/*------------------------- DMAy Streamx M0AR Configuration ----------------*/
/* Write to DMAy Streamx M0AR */
DMA2_Stream5->M0AR = (u32)ReceiveBuff;
DMA_Cmd(DMA2_Stream5, ENABLE); //
}
}
否则先清除标志会导致DMA的NDTR清零 读不到接收的数据量。
有问题再补充;