最近准备用8266做i2s音频播放器,播放简单的wav格式声音,但是官方的开发板没有i2s输出音频处理芯片,在电子发烧友上看到一款基于8266esp的开发板叫“小e”,正在众筹,有兴趣的可以去看看作为参考,众筹地址http://z.elecfans.com/3?yitongwz。这款开发板上的功能非常完备,包括设计了9023音频芯片,实现了i2s裸流播出声音,买了一块,能播放声音。
8266的i2s资料主要是《8P-ESP8266 I2S Module description__CN_v1.0》文档,但是这个文档没有详细的寄存器讲解,在配置的时候就存在很多问题。
小e开发板实现了i2s,看了下他的代码,他的播放机制是微信发送声音到服务器,小e开发板(8266)下载声音到flash中,然后播放,资料可以参考下:http://pan.baidu.com/s/1sj5TtGp。
小e(8266)i2s的配置流程:
一、slc_init()
scl初始化,8266的i2s有两种模式,第一种是直接读写fifo,第二种方式是采用中断+dma的方式。采用中断+dma方式,寄存器配置如下:
SET_PERI_REG_MASK(SLC_CONF0,(1<<SLC_MODE_S)); //开启中断+DMA模式
ETS_SLC_INTR_ATTACH(slc_isr, NULL); //注册中断函数
ETS_SLC_INTR_ENABLE(); //开中断
二、创建dma缓冲区
创建两个dma缓冲区(可以是4个等)i2s_rx_queue1和i2s_rx_queue2,当音频播放的时候,将数据放入该缓冲区,dma自动将数据发送出去,创建:
creat_one_link(1,1,0,IIS_RX_BUF_LEN,IIS_RX_BUF_LEN,i2s_rx_buff1,&i2s_rx_queue2,&i2s_rx_queue1);
creat_one_link(1,1,0,IIS_RX_BUF_LEN,IIS_RX_BUF_LEN,i2s_rx_buff2,&i2s_rx_queue1,&i2s_rx_queue2);
这个函数实际上是将i2s_rx_buff1和i2s_rx_buff2缓冲区的首地址指向结构i2s_rx_queue1和i2s_rx_queue2的数据指针,并将i2s_rx_queue1和i2s_rx_queue2做成循环链表。
三、启动发送控制
开启slc模块: START_RXLINK();
该函数实际上是调用了SET_PERI_REG_MASK(SLC_RX_LINK, SLC_RXLINK_START),开启scl。
四、i2s模块初始化
初始化i2s本身,包括BCLK、WS、SDATA信号线的配置、时钟配置、通道、采样率、开启中断等。
(1)、8266的i2s与gpio是共用的,配置GPIO12为DATA、GPIO13为BCK,GPIO13为WS;
(2)、开启160M时钟供i2s使用:i2c_writeReg_Mask_def(i2c_bbpll, i2c_bbpll_en_audio_clock_out, 1);
(3)设置i2s模式
根据实际待播放音频的实际情况(可以查看声音的类型),设置为16位和24位,又分half和full模式。这个很重要,如果模式错误,播放的声音混乱。
SET_PERI_REG_MASK(I2S_FIFO_CONF,(I2S_I2S_RX_FIFO_MOD<<I2S_I2S_RX_FIFO_MOD_S)) //16位half模式
(4)声道设置
单、双声道,根据实际待播放音频的实际情况(可以查看声道的类型:
SET_PERI_REG_MASK(I2SCONF_CHAN,(I2S_TX_CHAN_MOD<<I2S_TX_CHAN_MOD_S)) //单声道
(5)设置采样率
根据声音的情况设置相同的采样率。播放器设置为发送主模式、接受从模式,采样率设置为50和25分频倍数(下面代码的数字50和25),BCLK为:160M/50/25=128K/s,由于设置的是16位单声道,因此采样率为128/16=8K/s,如果是其他采样率可计算出分频值(比如24位双声道,采样率44.1k,则160000K/24/2/44.1K=75,75=15*5,则如下设置:15&I2S_BCK_DIV_NUM,5&I2S_CLKM_DIV_NUM,注意前面数字一般比后边数字大,前面数 不超过63)
代码:
//trans master&rece slave mode
SET_PERI_REG_MASK(I2SCONF,I2S_RIGHT_FIRST|I2S_MSB_RIGHT|I2S_RECE_SLAVE_MOD|
I2S_RECE_MSB_SHIFT|I2S_TRANS_MSB_SHIFT|
((50&I2S_BCK_DIV_NUM )<<I2S_BCK_DIV_NUM_S)| //分频数50
((25&I2S_CLKM_DIV_NUM)<<I2S_CLKM_DIV_NUM_S)| //分频数25
(0<<I2S_BITS_MOD_S));
(6)开启中断。
五、中断处理
小e播放的机制:有音频数据到来,将其拷贝至i2s_rx_buff1或者i2s_rx_buff2中,dma自动将音频数据送入i2s总线至音频芯片,当dma发送完成一次数据,中断产生,在拷贝数据,周而复始直至数据播放完成。
中断处理每次拷贝接下来要播放数据,并判断是否播放完成:
void slc_isr(void *para)
{
et_uint32 slc_intr_status;
slc_intr_status = READ_PERI_REG(SLC_INT_STATUS); //读中断状态
if (slc_intr_status == 0)
{
return;
}
WRITE_PERI_REG(SLC_INT_CLR, 0xffffffff); //清中断
if (slc_intr_status & SLC_RX_EOF_INT_ST) //DMA缓冲区空
{
if(READ_PERI_REG(SLC_RX_EOF_DES_ADDR)==(((et_uint32)&i2s_rx_queue1))) //dma缓冲区1
{
if(file_total_size >= IIS_RX_BUF_LEN) //数据拷贝未至最后
{
memcpy(i2s_rx_buff1, buf, IIS_RX_BUF_LEN) //拷贝数据到缓冲区
file_total_size -= IIS_RX_BUF_LEN;
}
else
{
memcpy(i2s_rx_buff1, buf, file_total_size)
file_total_size = 0;
}
}
else if(READ_PERI_REG(SLC_RX_EOF_DES_ADDR)==(((et_uint32)&i2s_rx_queue1))) //dma缓冲区2
{
和缓冲区1相同
}
}
8266 i2s及音频播放代码实现
Re: 8266 i2s及音频播放代码实现
Postby ESP_Greg » Tue Jun 28, 2016 3:57 pm
Great introduction. 使用官方的例证基本设置也是如此,我们也要写一下类似的介绍放到FAQ里面
Who is online
Users browsing this forum: No registered users and 289 guests
Login
Newbies Start Here
Are you new to ESP8266?
Unsure what to do?
Dunno where to start?
Start right here!
Latest SDK
Documentation
Complete listing of the official ESP8266 related documentation release by ESPRESSIF!
Must read here!
- All times are UTC+08:00
- Top
- Delete all board cookies
About Us
Espressif Systems is a fabless semiconductor company providing cutting-edge low power WiFi SoCs and wireless solutions for wireless communications and Internet of Things applications. We are the manufacturer of ESP8266EX.