止
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请求使能.
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}, {1102,429,4,19,0}, {1600,213,2,13,0}, {2205,429,4, 9,1},
//8Khz采样率 //11.025Khz采样率 //16Khz采样率 //22.05Khz采样率
5
{3200,213,2, 6,1}, {4410,271,2, 6,0}, {4800,258,3, 3,1}, {8820,316,2, 3,1}, {9600,344,2, 3,1}, {17640,361,2,2,0}, {19200,393,2,2,0},
//32Khz采样率 //44.1Khz采样率 //48Khz采样率 //88.2Khz采样率 //96Khz采样率 //176.4Khz采样率 //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++)//看看改采样率是否可以支持 { }
RCC_PLLI2SCmd(DISABLE);//先关闭PLLI2S
if(i==(sizeof(I2S_PSC_TBL)/10))return 1;//搜遍了也找不到
if(samplerate==I2S_PSC_TBL[i][0])break;
RCC_PLLI2SConfig((u32)I2S_PSC_TBL[i][1],(u32)I2S_PSC_TBL[i][2]);//设置I2SxCLK的频率(x=2) 设置PLLI2SN PLLI2SR
6
}
RCC->CR|=1<<26; //开启I2S时钟
//等待I2S时钟开启成功.
while((RCC->CR&1<<27)==0);
tempreg=I2S_PSC_TBL[i][3]<<0; //设置I2SDIV tempreg|=I2S_PSC_TBL[i][4]<<8; //设置ODD位 tempreg|=1<<9;
//使能MCKOE位,输出MCK //设置I2SPR寄存器
SPI2->I2SPR=tempreg; return 0;
//I2S2 TX DMA配置
//设置为双缓冲模式,并开启DMA传输完成中断 //buf0:M0AR地址. //buf1:M1AR地址. //num:每次传输数据量
void I2S2_TX_DMA_Init(u8* buf0,u8 *buf1,u16 num) {
NVIC_InitTypeDef NVIC_InitStructure; DMA_InitTypeDef DMA_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1,ENABLE);//DMA1时钟使能
DMA_DeInit(DMA1_Stream4);
while (DMA_GetCmdStatus(DMA1_Stream4) != DISABLE){}//等待DMA1_Stream1可配置
/* 配置 DMA Stream */
DMA_InitStructure.DMA_Channel = DMA_Channel_0; //通道0 SPI2_TX通道 DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&SPI2->DR;//外设地址为:(u32)&SPI2->DR
7
DMA_InitStructure.DMA_Memory0BaseAddr = (u32)buf0;//DMA 存储器0地址 DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;//存储器到外设模式 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_Stream4, &DMA_InitStructure);//初始化DMA Stream
DMA_DoubleBufferModeConfig(DMA1_Stream4,(u32)buf1,DMA_Memory_0);//双缓冲模式配置
DMA_DoubleBufferModeCmd(DMA1_Stream4,ENABLE);//双缓冲模式开启 DMA_ITConfig(DMA1_Stream4,DMA_IT_TC,ENABLE);//开启传输完成中断 NVIC_InitStructure.NVIC_IRQChannel = DMA1_Stream4_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00;//抢占优先级0 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00;//子优先级0
8
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能外部中断通道 NVIC_Init(&NVIC_InitStructure);//配置 }
//I2S DMA回调函数指针
void (*i2s_tx_callback)(void); //TX回调函数 //DMA1_Stream4中断服务函数 void DMA1_Stream4_IRQHandler(void) {
if(DMA_GetITStatus(DMA1_Stream4,DMA_IT_TCIF4)==SET)////DMA1_Stream4,传输完成标志
{
DMA_ClearITPendingBit(DMA1_Stream4,DMA_IT_TCIF4);
i2s_tx_callback(); //执行回调函数,读取数据等操作在这里面处理 }
//I2S开始播放
void I2S_Play_Start(void) { }
//关闭I2S播放
void I2S_Play_Stop(void) {
DMA_Cmd(DMA1_Stream4,DISABLE);//关闭DMA,结束播放
}
DMA_Cmd(DMA1_Stream4,ENABLE);//开启DMA TX传输,开始播放
9