SYD8821 I2S模块发送功能使用说明
SYD8821 I2S模块使用说明
SYD8821崇尚高性能与低功耗,增加I2S接口也就是必然的选择。
SYD8821的I2S接口完全符合标准I2S协议,关于I2S协议这里不再深入说明,有兴趣可看:I2S总线原理及其实例:《https://blog.****.net/chengdong1314/article/details/81210205》
本博客将做这样的测试:使用syd8821播放音乐《擦肩而过.wav》(关于WAV文件的转换和提取:https://blog.****.net/chengdong1314/article/details/54670702)的前面200KB数据,大约是6.3S的数据!
这里首先介绍一下硬件平台,因为SYD8821开发板上并没有I2S的模块,所以这里借用WIFI开发板上的I2S模块进行音频的解码,测试实物图如下:
WIFI开放板的IIS模块的原理图如下:
因为该WIFI开发板上已经集成了发出MCLK的有源时钟晶振,所以这里SYD8821只要和该I2S模块连接三根线即可,分别为:SCLK(GPIO7)、LRCLK(GPIO8)、SDO(GPIO9)即可。具体连接图请看上面的实物图!
SYD8821的main函数如下:
#define WAV_FILE_HEADER 0x2c //WAV文件数据头
#define CONST_BUFF_LEN 204800 //WAV文件的大小
#define RAM_BUFF_LEN 16*1024 //分配给I2S模块的DMA内存大小
static __align(4) uint8_t buf_Ram[RAM_BUFF_LEN]={0};
const uint8_t buf_const[CONST_BUFF_LEN];
int DMA_size = 0;
#define DEBUG_I2S_DMA //启用I2Sdebug打印功能
#ifdef DEBUG_I2S_DMA
unsigned char DMA_cnt = 0,DMA_cnt_last = 0;
#endif
const uint8_t * audio_data_p=buf_const;
uint8_t * audio_rambuff_p=buf_Ram;
/*
0:空闲状态 依旧发送静态音频
1:播放状态
2:播放完成
*/
char audio_state=0;
void i2s_test_init(void) //I2S初始化函数
{
int i;
for (i = 7; i < 12; i++) //初始化IO口
pad_mux_write(i, 9); // MCK, SCK, LRCK, DO, DI
// 8K 16-bit configuration
i2s_set_mclk(I2S_CLK_DIV31); //MCLK时钟的分频系数
i2s_set_bit_clk(I2S_MCLK_DIV4); //BIT CLOCK的风频系数,其中/BIT CLOCK来源于MCLK
i2s_set_channel_clock(I2S_LEFT_LOW); //设置发送左声道数据时LRCLK为低电平
i2s_set_channel(I2S_STEREO); //设置播放模式为立体声播放,两个声道都有数据
i2s_set_bit_order(I2S_TX, I2S_MSB_FIRST); //设置I2S数据模式为高位在前
i2s_set_transfer_format(I2S_FISRT_BIT_SECOND_CYCLE); //设置数据在LRCLK边沿的第二个上升沿有效
i2s_set_sample_width(I2S_16BIT); //设置音频数据为16BIT
i2s_enable_int(I2S_DMA_ALL_INT); //使能I2S模块的所有中断
NVIC_EnableIRQ(I2S_IRQn);
}
static void i2s_test_slient_irq_cb(uint32_t int_st) //I2S中断回调函数
{
DMA_cnt++;
if(audio_state==0)
{
//DBG("idle dma_cnt:%x\r\n",DMA_cnt);
}
else if(audio_state==1)
{
//DBG("play dma_cnt:%x ",DMA_cnt);
if (int_st & I2S_DMA_HALF_DONE_INT_ST) { //更具DMA是半中断或者全中断来填充数组
audio_rambuff_p=buf_Ram+DMA_size/2;
memcpy(audio_rambuff_p,audio_data_p,DMA_size/2);
audio_data_p+=DMA_size/2;
//DBG("buf_Ram_p2:%x ",(buf_Ram+DMA_size/2));
}
else if (int_st & I2S_DMA_DONE_INT_ST) {
audio_rambuff_p=buf_Ram;
memcpy(audio_rambuff_p,audio_data_p,DMA_size/2);
audio_data_p+=DMA_size/2;
//DBG("buf_Ram_p1:%x ",buf_Ram);
}
if(audio_data_p>=(buf_const+CONST_BUFF_LEN))
{
audio_state=2;
}
//DBG("data_p:%x\r\n",audio_data_p);
}
else if(audio_state==2)
{
//i2s_stop();
memset(buf_Ram,0xff,DMA_size);
audio_state=0;
//DBG("play finish dma_cnt:%x\r\n",DMA_cnt);
}
}
void i2s_test_Silent_TX(void) //I2S启动函数
{
DMA_size=RAM_BUFF_LEN;
memset(buf_Ram,0xff,DMA_size);
i2s_set_irq_callback(i2s_test_slient_irq_cb);
i2s_trigger_TXDMA(buf_Ram, DMA_size);
}
int main()
{
__disable_irq();
//GPO
pad_mux_write(LED1, 0);
pad_mux_write(LED2, 0);
pad_mux_write(LED3, 0);
pad_mux_write(LED4, 0);
gpo_config(LED1,1);
gpo_config(LED2,1);
gpo_config(LED3,1);
gpo_config(LED4,1);
//GPI
pad_mux_write(KEY1, 0);
pad_mux_write(KEY2, 0);
pad_mux_write(KEY3, 0);
pad_mux_write(KEY4, 0);
gpi_config(KEY1, PULL_UP);
gpi_config(KEY2, PULL_UP);
gpi_config(KEY3, PULL_UP);
gpi_config(KEY4, PULL_UP);
//uart 0
pad_mux_write(20, 7);
pad_mux_write(21, 7);
dbg_init();
dbg_printf("SYD8821 IIS DEMO\r\n");
i2s_test_init();
__enable_irq();
DMA_cnt=0;
audio_state=0;
i2s_test_Silent_TX();
while(1)
{
gpo_toggle(LED4);
#ifdef DEBUG_I2S_DMA
if(DMA_cnt !=DMA_cnt_last) //更具I2S模块的状态打印出I2S模块的运行信息
{
DMA_cnt_last=DMA_cnt;
if(audio_state==0)
{
DBG("idle dma_cnt:%x\r\n",DMA_cnt);
}
else if(audio_state==1)
{
DBG("play dma_cnt:%x buf_Ram_p2:%x data_p:%x",DMA_cnt,audio_rambuff_p,audio_data_p);
}
else if(audio_state==2)
{
DBG("play finish dma_cnt:%x\r\n",DMA_cnt);
}
}
#endif
if(!gpi_get_val(KEY1)){ //按下开发板上的按键1则开始I2S播放音乐
gpo_toggle(LED1);
if(audio_state==0)
{
audio_data_p=buf_const+WAV_FILE_HEADER;
audio_state=1;
}
}
}
}
const uint8_t buf_const[CONST_BUFF_LEN] =
{
0x52,0x49,0x46,0x46,0xd0,0x98,0x3a,0x00,0x57,0x41,0x56,0x45,0x66,0x6d,0x74,0x20,
0x10,0x00,0x00,0x00,0x01,0x00,0x02,0x00,0x40,0x1f,0x00,0x00,0x00,0x7d,0x00,0x00,
0x04,0x00,0x10,0x00,0x64,0x61,0x74,0x61,0xac,0x98,0x3a,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
。。。。。。。。。。。。。。。。。。。。。。。。
}
其中buf_const数据是《擦肩而过.wav》文件的前面两百KB的内容,代码运行后按下KEY1可看到如下打印:
20:54:46:912 SYD8821 IIS DEMO
20:54:47:169 idle dma_cnt:1
20:54:47:422 idle dma_cnt:2
20:54:47:676 idle dma_cnt:3
20:54:47:930 idle dma_cnt:4
20:54:48:183 idle dma_cnt:5
20:54:48:437 idle dma_cnt:6
20:54:48:684 idle dma_cnt:7
20:54:48:934 idle dma_cnt:8
20:54:49:200 idle dma_cnt:9
20:54:49:454 idle dma_cnt:a
20:54:49:708 idle dma_cnt:b
20:54:49:962 idle dma_cnt:c
20:54:50:216 idle dma_cnt:d
20:54:50:471 idle dma_cnt:e
20:54:50:723 idle dma_cnt:f
20:54:50:977 idle dma_cnt:10
20:54:51:231 idle dma_cnt:11
20:54:51:490 play dma_cnt:12 buf_Ram_p2:20000044 data_p:10003a3e
20:54:51:740 play dma_cnt:13 buf_Ram_p2:20002044 data_p:10005a3e
20:54:51:994 play dma_cnt:14 buf_Ram_p2:20000044 data_p:10007a3e
20:54:52:248 play dma_cnt:15 buf_Ram_p2:20002044 data_p:10009a3e
20:54:52:502 play dma_cnt:16 buf_Ram_p2:20000044 data_p:1000ba3e
20:54:52:756 play dma_cnt:17 buf_Ram_p2:20002044 data_p:1000da3e
20:54:53:010 play dma_cnt:18 buf_Ram_p2:20000044 data_p:1000fa3e
20:54:53:264 play dma_cnt:19 buf_Ram_p2:20002044 data_p:10011a3e
20:54:53:518 play dma_cnt:1a buf_Ram_p2:20000044 data_p:10013a3e
20:54:53:772 play dma_cnt:1b buf_Ram_p2:20002044 data_p:10015a3e
20:54:54:026 play dma_cnt:1c buf_Ram_p2:20000044 data_p:10017a3e
20:54:54:279 play dma_cnt:1d buf_Ram_p2:20002044 data_p:10019a3e
20:54:54:533 play dma_cnt:1e buf_Ram_p2:20000044 data_p:1001ba3e
20:54:54:787 play dma_cnt:1f buf_Ram_p2:20002044 data_p:1001da3e
20:54:55:048 play dma_cnt:20 buf_Ram_p2:20000044 data_p:1001fa3e
20:54:55:295 play dma_cnt:21 buf_Ram_p2:20002044 data_p:10021a3e
20:54:55:549 play dma_cnt:22 buf_Ram_p2:20000044 data_p:10023a3e
20:54:55:803 play dma_cnt:23 buf_Ram_p2:20002044 data_p:10025a3e
20:54:56:057 play dma_cnt:24 buf_Ram_p2:20000044 data_p:10027a3e
20:54:56:311 play dma_cnt:25 buf_Ram_p2:20002044 data_p:10029a3e
20:54:56:565 play dma_cnt:26 buf_Ram_p2:20000044 data_p:1002ba3e
20:54:56:819 play dma_cnt:27 buf_Ram_p2:20002044 data_p:1002da3e
20:54:57:071 play dma_cnt:28 buf_Ram_p2:20000044 data_p:1002fa3e
20:54:57:321 play dma_cnt:29 buf_Ram_p2:20002044 data_p:10031a3e
20:54:57:580 play finish dma_cnt:2a
20:54:57:834 idle dma_cnt:2b
20:54:58:087 idle dma_cnt:2c
20:54:58:334 idle dma_cnt:2d
20:54:58:595 idle dma_cnt:2e
20:54:58:835 idle dma_cnt:2f
20:54:59:100 idle dma_cnt:30
20:54:59:350 idle dma_cnt:31
20:54:59:599 idle dma_cnt:32
20:54:59:865 idle dma_cnt:33
20:55:00:118 idle dma_cnt:34
20:55:00:367 idle dma_cnt:35
20:55:00:616 idle dma_cnt:36
20:55:00:866 idle dma_cnt:37
20:55:01:131 idle dma_cnt:38
20:55:01:381 idle dma_cnt:39
20:55:01:630 idle dma_cnt:3a
20:55:01:895 idle dma_cnt:3b
20:55:02:145 idle dma_cnt:3c
20:55:02:395 idle dma_cnt:3d
20:55:02:644 idle dma_cnt:3e
20:55:02:909 idle dma_cnt:3f
20:55:03:159 idle dma_cnt:40
20:55:03:409 idle dma_cnt:41
具体打印内容请看文件;《https://download.****.net/download/chengdong1314/10564274》
然后使用逻辑分析仪可看到如下波形:
具体的逻辑分析仪数据请看文件:《https://download.****.net/download/chengdong1314/10564309》
注意这里因为是先出R再出L,所以数据分布和数组是不一样的,先出第一个16BIT,然后再出第二个16BIT!
这里上传本博客最后播放出来的音乐:《https://download.****.net/download/chengdong1314/10573643中的《I2S录音.m4a》》
这里上传本博客的源码:https://download.****.net/download/chengdong1314/10564315工程在:\Source Code\SYD8821\iis\Keil
有一个地方要注意的是buf_const数据的生成,这里专门做了一个tool来生成这个数组:
这里上传该工具:《https://download.****.net/download/chengdong1314/10573643中的《syd_arr_release》》
关于WAV的知识请看:《https://blog.****.net/chengdong1314/article/details/54171667》
最后上传wifi开发板的硬件资料:《https://download.****.net/download/chengdong1314/10564336》