关于I2S的数据接收的问题

2019-07-20 14:08发布

功能:通过I2S的半双工配置,使用DMA接收480个长度的数据,放到数组中,
        程序有问题,实现不了,
         下面是程序,帮忙把程序修改一下,谢谢。


int main(void)
{
        u32 t=0;
        u8 BUFF0[256];
        u8 BUFF1[256];
       NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
        LED_Init();
        uart_init(115200);
        delay_init(168);
        /***************  I2S2接口相关初始化  ***********************/
        I2S2_GPIO_Init();
        I2S2_Init(I2S_Standard_Phillips,I2S_Mode_MasterRx,I2S_CPOL_High,I2S_DataFormat_16b);
       I2S2_SampleRate_Set(I2S_AudioFreq_48k);
       I2S2_RX_DMA_Init(BUFF0,BUFF1,128);

       I2S2_Rec_Start();    //I2S开始接收数据
        delay_us(100);
       I2S2_Rec_Stop();
      printf("BUFF0=%s ",BUFF0);
}

#include "STEVAL_I2S.h"


/******    I2S2 相关配置      **********/


// I2S2的硬件GPIO配置
void I2S2_GPIO_Init(void)
{
        GPIO_InitTypeDef  GPIO_InitStructure;
       
        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB|RCC_AHB1Periph_GPIOC, ENABLE);                        //使能外设GPIOB,GPIOC时钟

        //PB12/13 复用功能输出
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
  GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化
       
        //PC2/PC3/PC6复用功能输出
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3|GPIO_Pin_6;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
  GPIO_Init(GPIOC, &GPIO_InitStructure);//初始化
       
        GPIO_PinAFConfig(GPIOB,GPIO_PinSource12,GPIO_AF_SPI2); //PB12,AF5  I2S_LRCK---4
        GPIO_PinAFConfig(GPIOB,GPIO_PinSource13,GPIO_AF_SPI2);        //PB13,AF5  I2S_SCLK---5
        GPIO_PinAFConfig(GPIOC,GPIO_PinSource3,GPIO_AF_SPI2);        //PC3 ,AF5  I2S_DACDATA
        GPIO_PinAFConfig(GPIOC,GPIO_PinSource6,GPIO_AF_SPI2);        //PC6 ,AF5  I2S_MCK
//        GPIO_PinAFConfig(GPIOC,GPIO_PinSource2,GPIO_AF6_SPI2);        //PC2 ,AF6  I2S_ADCDATA  I2S2ext_SD是AF6!!!
}


//I2S2初始化
//参数I2S_Standard:  @ref SPI_I2S_Standard  I2S标准,
//I2S_Standard_Phillips,飞利浦标准;
//I2S_Standard_MSB,MSB对齐标准(右对齐);
//I2S_Standard_LSB,LSB对齐标准(左对齐);
//I2S_Standard_PCMShort,I2S_Standard_PCMLongCM标准
//参数I2S_Mode: @ref SPI_I2S_Mode  I2S_Mode_SlaveTx:从机发送;I2S_Mode_SlaveRx:从机接收;I2S_Mode_MasterTx:主机发送;I2S_Mode_MasterRx:主机接收;
//参数I2S_Clock_Polarity  @ref SPI_I2S_Clock_Polarity:  I2S_CPOL_Low,时钟低电平有效;I2S_CPOL_High,时钟高电平有效
//参数I2S_DataFormat: @ref SPI_I2S_Data_Format :数据长度,I2S_DataFormat_16b,16位标准;I2S_DataFormat_16bextended,16位扩展(frame=32bit);I2S_DataFormat_24b,24位;I2S_DataFormat_32b,32位.
void I2S2_Init(u16 I2S_Standard,u16 I2S_Mode,u16 I2S_Clock_Polarity,u16 I2S_DataFormat)
{
  I2S_InitTypeDef I2S_InitStructure;
       
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);//使能SPI2时钟
       
        RCC_APB1PeriphResetCmd(RCC_APB1Periph_SPI2,ENABLE); //复位SPI2
        RCC_APB1PeriphResetCmd(RCC_APB1Periph_SPI2,DISABLE);//结束复位

        I2S_InitStructure.I2S_Mode=I2S_Mode;//IIS模式
        I2S_InitStructure.I2S_Standard=I2S_Standard;//IIS标准
        I2S_InitStructure.I2S_DataFormat=I2S_DataFormat;//IIS数据长度
        I2S_InitStructure.I2S_MCLKOutput=I2S_MCLKOutput_Disable;//主时钟输出禁止       ????
        I2S_InitStructure.I2S_AudioFreq=I2S_AudioFreq_Default;//IIS频率设置
        I2S_InitStructure.I2S_CPOL=I2S_Clock_Polarity;//空闲状态时钟电平
        I2S_Init(SPI2,&I2S_InitStructure);//初始化IIS


        //SPI_I2S_DMACmd(SPI2,SPI_I2S_DMAReq_Tx,ENABLE);//SPI2 TX DMA请求使能.
        SPI_I2S_DMACmd(SPI2,SPI_I2S_DMAReq_Rx,ENABLE);
  I2S_Cmd(SPI2,ENABLE);//SPI2 I2S EN使能.       
}




//采样率计算公式:Fs=I2SxCLK/[256*(2*I2SDIV+ODD)]
//I2SxCLK=(HSE/pllm)*PLLI2SN/PLLI2SR
//一般HSE=8Mhz
//pllm:在Sys_Clock_Set设置的时候确定,一般是8
//PLLI2SN:一般是192~432
//PLLI2SR:2~7
//I2SDIV:2~255
//ODD:0/1
//I2S分频系数表@pllm=8,HSE=8Mhz,即vco输入频率为1Mhz
//表格式:采样率/10,PLLI2SN,PLLI2SR,I2SDIV,ODD
const u16 I2S_PSC_TBL[][5]=
{
        {800 ,256,5,12,1},                //8Khz采样率
        {1102,429,4,19,0},                //11.025Khz采样率
        {1600,213,2,13,0},                //16Khz采样率
        {2205,429,4, 9,1},                //22.05Khz采样率
        {3200,213,2, 6,1},                //32Khz采样率
        {4410,271,2, 6,0},                //44.1Khz采样率
        {4800,258,3, 3,1},                //48Khz采样率
        {8820,316,2, 3,1},                //88.2Khz采样率
        {9600,344,2, 3,1},          //96Khz采样率
        {17640,361,2,2,0},          //176.4Khz采样率
        {19200,393,2,2,0},          //192Khz采样率
};  
//设置IIS的采样率(@MCKEN)
//samplerate:采样率,单位:Hz
//返回值:0,设置成功;1,无法设置.
u8 I2S2_SampleRate_Set(u32 samplerate)
{
        u8 i=0;
        u32 tempreg=0;
        samplerate/=10;//缩小10倍   
       
        for(i=0;i<(sizeof(I2S_PSC_TBL)/10);i++)//看看改采样率是否可以支持
        {
                if(samplerate==I2S_PSC_TBL[i][0])break;
        }

        RCC_PLLI2SCmd(DISABLE);//先关闭PLLI2S
        if(i==(sizeof(I2S_PSC_TBL)/10))return 1;//搜遍了也找不到
        RCC_PLLI2SConfig((u32)I2S_PSC_TBL[i][1],(u32)I2S_PSC_TBL[i][2]);//设置I2SxCLK的频率(x=2)  设置PLLI2SN PLLI2SR

        RCC->CR|=1<<26;                                        //开启I2S时钟
        while((RCC->CR&1<<27)==0);                //等待I2S时钟开启成功.
        tempreg=I2S_PSC_TBL[i][3]<<0;        //设置I2SDIV
        tempreg|=I2S_PSC_TBL[i][4]<<8;        //设置ODD位
        tempreg|=1<<9;                                        //使能MCKOE位,输出MCK
        SPI2->I2SPR=tempreg;                        //设置I2SPR寄存器
        return 0;
}  
//I2S2 RX DMA配置
//设置为双缓冲模式,并开启DMA传输完成中断
//buf0:M0AR地址.
//buf1:M1AR地址.
//num:每次传输数据量
void I2S2_RX_DMA_Init(u8* buf0,u8 *buf1,u16 num)      //DMA1 通道0  数据流3---SPI2_RX
{  
        NVIC_InitTypeDef   NVIC_InitStructure;
        DMA_InitTypeDef  DMA_InitStructure;
       

  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1,ENABLE);//DMA1时钟使能
       
        DMA_DeInit(DMA1_Stream3);
        while (DMA_GetCmdStatus(DMA1_Stream3) != DISABLE){}//等待DMA1_Stream3可配置
               
        DMA_ClearITPendingBit(DMA1_Stream3,DMA_IT_FEIF3|DMA_IT_DMEIF3|DMA_IT_TEIF3|DMA_IT_HTIF3|DMA_IT_TCIF3);//清空DMA1_Stream3上所有中断标志

  /* 配置 DMA Stream */

  DMA_InitStructure.DMA_Channel = DMA_Channel_0;  //通道0 SPI2_RX通道
  DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&SPI2->DR;//外设地址为u32)&SPI2->DR
  DMA_InitStructure.DMA_Memory0BaseAddr = (u32)buf0;//DMA 存储器0地址
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;//外设到存储器模式
  DMA_InitStructure.DMA_BufferSize = num;//数据传输量
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//外设非增量模式
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//存储器增量模式
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;//外设数据长度:16位
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;//存储器数据长度:16位
  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;// 使用循环模式
  DMA_InitStructure.DMA_Priority = DMA_Priority_High;//高优先级
  DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable; //不使用FIFO模式        
  DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_1QuarterFull;
  DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;//外设突发单次传输
  DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;//存储器突发单次传输
  DMA_Init(DMA1_Stream3, &DMA_InitStructure);//初始化DMA Stream
       
        DMA_DoubleBufferModeConfig(DMA1_Stream3,(u32)buf1,DMA_Memory_0);//双缓冲模式配置

  DMA_DoubleBufferModeCmd(DMA1_Stream3,ENABLE);//双缓冲模式开启

  DMA_ITConfig(DMA1_Stream3,DMA_IT_TC,ENABLE);//开启传输完成中断

        NVIC_InitStructure.NVIC_IRQChannel = DMA1_Stream3_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00;//抢占优先级0
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00;//子优先级0
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能外部中断通道
  NVIC_Init(&NVIC_InitStructure);//配置
}



void (*i2s2_rx_callback)(void);        //RX回调函数


//DMA1_Stream3中断服务函数
void DMA1_Stream3_IRQHandler(void)
{      
        if(DMA_GetITStatus(DMA1_Stream3,DMA_IT_TCIF3)==SET)        //DMA1_Stream3,传输完成标志
        {
                DMA_ClearITPendingBit(DMA1_Stream3,DMA_IT_TCIF3);        //清除传输完成中断
      //        i2s2_rx_callback();        //执行回调函数,读取数据等操作在这里面处理  
                DMA_Cmd(DMA1_Stream3,DISABLE);
        }                                                                                           
}

//I2S开始录音
void I2S2_Rec_Start(void)
{               
        DMA_Cmd(DMA1_Stream3,ENABLE);//开启DMA RX传输,开始录音       
}
//关闭I2S录音
void I2S2_Rec_Stop(void)
{  
        DMA_Cmd(DMA1_Stream3,DISABLE);//关闭DMA,结束录音         
         
}


0条回答

一周热门 更多>