#include "i2s.h"
#include "delay.h"
const u16 I2S_PSC_TBL[][3]=
{
{800 ,140,1}, //8Khz采样率
{1102,13,0}, //11.025Khz采样率
{1600,9,0}, //16Khz采样率
{2205,6,1}, //22.05Khz采样率
{3200,9,0}, //32Khz采样率
{4410,25,1}, //44.1Khz采样率
{4800,3,0}, //48Khz采样率
{9600,2,0}, //96Khz采样率
};
void I2S2_Init(void)
{
//管脚已经初始化了
RCC->APB1ENR|=1<<14;
RCC->APB1RSTR|=1<<14; //复位SPI2
RCC->APB1RSTR&=~(1<<14);//结束复位
SPI2->I2SCFGR=0; //全部设置为0
SPI2->I2SPR=0X02; //分频寄存器为默认值
SPI2->I2SCFGR|=1<<11; //选择:I2S模式
SPI2->I2SCFGR|=(u16)2<<8;//I2S工作模式设置
SPI2->I2SCFGR|=0<<4; //I2S标准设置
SPI2->I2SCFGR|=1<<3; //空闲时钟电平设置
SPI2->I2SCFGR|=1<<0; //32位声道长度
SPI2->I2SCFGR|=0<<1; //I2S标准设置
SPI2->CR2|=1<<1; //SPI2 TX DMA请求使能.
SPI2->I2SCFGR|=1<<10; //SPI2 I2S EN使能.
}
u8 I2S2_SampleRate_Set(u32 samplerate)
{
u8 i=0;
u32 tempreg=0;
samplerate/=10;//缩小10倍
for(i=0;i<(sizeof(I2S_PSC_TBL)/6);i++)//看看改采样率是否可以支持
{
if(samplerate==I2S_PSC_TBL[i][0])break;
}
if(i==(sizeof(I2S_PSC_TBL)/6))return 1;//搜遍了也找不到
SPI2->I2SCFGR&=~(1<<10); //关闭I2S
tempreg=I2S_PSC_TBL[i][1]<<0; //设置I2SDIV
tempreg|=I2S_PSC_TBL[i][2]<<8; //设置ODD位
tempreg|=1<<9; //使能MCKOE位,输出MCK
SPI2->I2SPR=tempreg; //设置I2SPR寄存器
return 0;
}
void I2S2_TX_DMA_Init(u8* buf0,u16 num)
{
RCC->AHBENR|=1<<0;
delay_ms(10);
DMA1->IFCR&=~(0xf<<16);
DMA1->ISR=0x0;
DMA1_Channel5->CPAR=(u32)&SPI2->DR;
DMA1_Channel5->CMAR=(u32)buf0;
DMA1_Channel5->CNDTR=num;
DMA1_Channel5->CCR=0;
DMA1_Channel5->CCR|=1<<4;
DMA1_Channel5->CCR|=0<<5;
DMA1_Channel5->CCR|=1<<7;
DMA1_Channel5->CCR|=0<<6;
DMA1_Channel5->CCR|=1<<8;
DMA1_Channel5->CCR|=1<<10;
DMA1_Channel5->CCR|=2<<12;
DMA1_Channel5->CCR|=0<<14;
DMA1_Channel5->CCR|=1<<1;
MY_NVIC_Init(0,0,DMA1_Channel5_IRQn,2);
}
void (*i2s_tx_callback)(void); //TX回调函数
//I2S开始播放
void I2S_Play_Start(void)
{
DMA1_Channel5->CCR|=1<<0; //开启DMA TX传输
}
//关闭I2S播放
void I2S_Play_Stop(void)
{
DMA1_Channel5->CCR&=~(1<<0); //结束播放
}
void DMA1_Channel5_IRQHandler(void)
{
GPIOD->ODR&=~(1<<2);
}
===========================================================
#include "sys.h"
#include "usart.h"
#include "delay.h"
#include "led.h"
#include "key.h"
#include "myiic.h"
#include "wm8978.h"
#include "wavplay.h"
#include "spi.h"
#include "sdcard.h"
#include "ff.h"
#include "i2s.h"
#include "audioplay.h"
#include "malloc.h"
FATFS fs;
FIL fp;
__wavctrl wavctr; //WAV控制结构体
#define I2S_TX_DMA_BUF 50
void play_song(void)
{
u8 *i2sbuf1;
u8 *i2sbuf2;
u8 res;
u32 bread;
WM8978_ADDA_Cfg(1,0); //开启DAC
WM8978_Input_Cfg(0,0,0);//关闭输入通道
WM8978_Output_Cfg(1,0); //开启DAC输出
wav_decode_init((u8 *)"0:/MUSIC/奕跑青春.wav",&wavctr);
WM8978_I2S_Cfg(2,0); //飞利浦标准,16位数据长度
//需要设置相应DMA的通道
i2sbuf1=mymalloc(I2S_TX_DMA_BUF);
i2sbuf2=mymalloc(I2S_TX_DMA_BUF);
//打开文件
res=f_open(&fp,(TCHAR*)"0:/MUSIC/奕跑青春.wav",FA_READ); //打开文件
if(1==res)
{
printf("文件0:/MUSIC/奕跑青春.wav打开失败
");
}
f_lseek(&fp, wavctr.datastart); //跳过文件头
f_read(&fp,i2sbuf1,I2S_TX_DMA_BUF,(UINT*)&bread);//16bit音频,直接读取数据
I2S_Play_Stop();
I2S2_TX_DMA_Init(i2sbuf1,I2S_TX_DMA_BUF/2);
I2S2_Init(); //飞利浦标准,主机发送,时钟低电平有效,16位扩展帧长度
I2S2_SampleRate_Set(wavctr.samplerate);//设置采样率
I2S_Play_Start();
// GPIOD->ODR&=~(1<<2);
f_close(&fp);
myfree(i2sbuf1);
myfree(i2sbuf2);
}
int main(void)
{
u8 res;
Stm32_Clock_Init(9); //系统时钟设置
delay_init(72); //延时初始化
uart_init(72,9600); //串口初始化为9600
led_init();
key_init();
res=WM8978_Init();
printf("res is %d
",res);
WM8978_HPvol_Set(40,40); //耳机音量设置
WM8978_SPKvol_Set(55); //喇叭音量设置
while(SD_Initialize())//检测不到SD卡
{
printf("SD Card Error!");
delay_ms(500);
printf("Please Check! ");
delay_ms(500);
}
res=f_mount (&fs,"0:",1);
if(0==res)
{
printf("the fmount sucssful
");
}
play_song();
while(1)
{
}
}
在此向各位看客讨教,或者相互讨论,我不知道是不是我的配置哪出问题了,感觉DMA没有工作。
一周热门 更多>