本文主要在AT32F403A芯片上演示
使用DMA半传输及传输完成中断的组合使用来实现DMA双缓冲存储I2S接收到的数据。
以下为主函数关键源码实现:
int main(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
RCC_Configuration();
GPIO_Configuration();
AT32_Board_Init();
SPI_I2S_Reset(SPI3);
SPI_I2S_Reset(SPI2);
I2S_DefaultInit(&I2S_InitStructure);
I2S_InitStructure.I2s_AudioProtocol = I2S_AUDIOPROTOCOL_PHILLIPS;
I2S_InitStructure.I2S_FrameFormat = I2S_FRAMEFORMAT_DL16BIT_CHL32BIT;
I2S_InitStructure.I2S_MCLKOE = I2S_MCLKOE_DISABLE;
I2S_InitStructure.I2S_AudioFreq = I2S_AUDIOFREQ_48K;
I2S_InitStructure.I2S_CPOL = I2S_CPOL_LOW;
I2S_InitStructure.I2S_Mode = I2S_MODE_MASTERTX;
I2S_Init(SPI3, &I2S_InitStructure);
I2S_InitStructure.I2S_Mode = I2S_MODE_SLAVERX;
I2S_Init(SPI2, &I2S_InitStructure);
DMA_Reset(DMA1_Channel4);
DMA_Reset(DMA2_Channel2);
DMA_DefaultInitParaConfig(&DMA_InitStructure);
DMA_InitStructure.DMA_BufferSize = 36;
DMA_InitStructure.DMA_PeripheralInc = DMA_PERIPHERALINC_DISABLE;
DMA_InitStructure.DMA_MemoryInc = DMA_MEMORYINC_ENABLE;
DMA_InitStructure.DMA_PeripheralDataWidth = DMA_PERIPHERALDATAWIDTH_HALFWORD;
DMA_InitStructure.DMA_MemoryDataWidth = DMA_MEMORYDATAWIDTH_HALFWORD;
DMA_InitStructure.DMA_Mode = DMA_MODE_NORMAL;
DMA_InitStructure.DMA_Priority = DMA_PRIORITY_HIGH;
DMA_InitStructure.DMA_MTOM = DMA_MEMTOMEM_DISABLE;
DMA_InitStructure.DMA_PeripheralBaseAddr = I2S3_DR_ADDRESS;
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&I2S3_Buffer_Tx;
DMA_InitStructure.DMA_Direction = DMA_DIR_PERIPHERALDST;
DMA_Init(DMA2_Channel2, &DMA_InitStructure);
DMA_InitStructure.DMA_PeripheralBaseAddr = I2S2_DR_ADDRESS;
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&I2S2_Buffer_Rx;
DMA_InitStructure.DMA_Direction = DMA_DIR_PERIPHERALSRC;
DMA_Init(DMA1_Channel4, &DMA_InitStructure);
DMA_ChannelEnable(DMA2_Channel2, ENABLE); ///<使用DMA2_Channel2发送数据
DMA_ChannelEnable(DMA1_Channel4, ENABLE); ///<使用DMA1_Channel4接收数据
SPI_I2S_DMAEnable(SPI2,SPI_I2S_DMA_RX,ENABLE);
I2S_Enable(SPI2, ENABLE);
I2S_Enable(SPI3, ENABLE);
SPI_I2S_DMAEnable(SPI3,SPI_I2S_DMA_TX,ENABLE);
while(DMA_GetFlagStatus(DMA1_FLAG_HT4)==RESET);///<等待半传输完成后处理前半部分接收到的数据
for(main_temp1 = 0; main_temp1 < 18 ;main_temp1++)
{
User_Buffer1[main_temp1] = I2S2_Buffer_Rx[main_temp1];
}
while(DMA_GetFlagStatus(DMA1_FLAG_TC4)==RESET);///<等待传输完成后处理后半部分接收到的数据
for(main_temp1 = 0; main_temp1 < 18 ;main_temp1++)
{
User_Buffer2[main_temp1] = I2S2_Buffer_Rx[main_temp1 + 18];
}
TransferStatus1 = Buffercmp(User_Buffer1, (uint16_t*)I2S3_Buffer_Tx, 18);///<前半部分数据准确性检查
TransferStatus2 = Buffercmp(User_Buffer2, (uint16_t*)(&I2S3_Buffer_Tx[18]), 18);///<后半部分数据准确性检查
if((TransferStatus1==PASSED) && (TransferStatus2==PASSED))
{
AT32_LEDn_ON(LED2);
}
else
{
AT32_LEDn_OFF(LED2);
}
while (1)
{
}
}
以下为中断函数关键源码实现:
void DMA1_Channel4_IRQHandler(void)
{
if(DMA_GetITStatus(DMA1_INT_HT4))
{
Ht_Int_Flag = 1;
DMA_ClearITPendingBit(DMA1_INT_HT4);
}
if(DMA_GetITStatus(DMA1_INT_TC4))
{
Tc_Int_Flag = 1;
DMA_ClearITPendingBit(DMA1_INT_TC4);
}
}
说明:本文只提供一种方法参考,可能切合某些实际应用的话(比如允许更改DMA目的地址等),还有更加合理的方法,所以需要具体问题具体讨论。