在项目中利用UART空闲中断接收外部信号,利用DMA接收,实现外部到内存的传输。通过分析其它文章的代码,大概如下:
/* 配置 DMA Stream */
void MYDMA_Config(DMA_Stream_TypeDef *DMA_Streamx,u32 chx,u32 par,u32 mar,u16 ndtr)
{
DMA_InitStructure.DMA_Channel = chx; //通道选择
DMA_InitStructure.DMA_PeripheralBaseAddr = par;//DMA外设地址
DMA_InitStructure.DMA_Memory0BaseAddr = mar;//DMA 存储器地址
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;//外设到存储器模式
DMA_InitStructure.DMA_BufferSize = ndtr;//数据传输量
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//外设非增量模式
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//存储器增量模式
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;//外设数据长度:8位
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;//存储器数据长度:8位
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;// 使用普通模式
DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;//中等优先级
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;//存储器突发单次传输
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;//外设突发单次传输
DMA_Init(DMA_Streamx, &DMA_InitStructure);//初始化DMA Stream
DMA_Cmd(DMA_Streamx, ENABLE); //开启DMA传输
}
/* 配置 UART IDEAL */
void USART1_IRQHandler(void) //串口1中断服务程序
{
u8 Res;
u8 clear;
u8 a=0;
if(USART_GetITStatus(USART1, USART_IT_IDLE) != RESET) //
{
Res = 1; //Event mask
clear= USART1->DR; //remove the mask of ideal
clear=USART1->SR;
USART_ClearITPendingBit(USART1,USART_IT_IDLE);//
num= SEND_BUF_SIZE-DMA_GetCurrDataCounter(DMA2_Stream5);//get the num of transfer
a=SEND_BUF_SIZE-DMA_GetCurrDataCounter(DMA2_Stream5);
printf("the num of transfer = %d",a);
a=0;
DMA_Cmd(DMA2_Stream5, DISABLE);
}
其中,去除空闲中断标志:
clear= USART1->DR;
clear=USART1->SR;
USART_ClearITPendingBit(USART1,USART_IT_IDLE);
主函数的部分函数
内容:将DMA接收到内存的信息通过串口发送
while(1)
{
if(Res==1)
{
LED1=!LED1;
Res=0;
for(j=0;j<20;j++)
{
USART_SendData(USART1,SendBuff[j]);
while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)!=SET){};
}
for(j=0;j<20;j++)
{
SendBuff[j]=33;
}
MYDMA_Enable(DMA2_Stream5 ,SEND_BUF_SIZE);
}
}
问题:三次接收信息如下,可以发现DMA只进行了一次传输,后续传输量为0,无信息传输
将USART1_IRQHandler函数中断的 DMA_Cmd(DMA2_Stream5, DISABLE); 和主函数中的MYDMA_Enable(DMA2_Stream5 ,SEND_BUF_SIZE); 注释掉,程序运行结果如下(第二行):
分析:DMA不进行关闭和开启处理,能够正常进行依次传输,个人分析可能是因为 DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;// 使用普通模式 ,此次为单次传输,传输量达到ndtr或者关闭DMA传输,都意味着此次传输完成,即使在开启也没用。
解决方案:DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;改成:DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;运行结果如下(第三行)