adc3101 I2S 采集问题
您好:
我现在使用TLVADC3101采集音频数据,i2s接口立体声模式,ADC3101作为i2s主设备,采样率48Khz,数据长度16bit,DSP作为从设备,通过DMA方式采集,使用CSL库,
ADC3101配置如下
ADC3101_rset(ADC3101_I2C_ADDR_2, 27, 0x0d ); // BCLK and WCLK are set as o/p; AIC3204(Master)
ADC3101_rset(ADC3101_I2C_ADDR_2, 28, 0x00 ); // Data ofset = 0
ADC3101_rset(ADC3101_I2C_ADDR_2, 4, 0x03 ); // PLL setting: PLLCLK <- MCLK, CODEC_CLKIN <-PLL CLK
ADC3101_rset(ADC3101_I2C_ADDR_2, 6, 0x08 ); // PLL setting: adc3101 J=8
ADC3101_rset(ADC3101_I2C_ADDR_2, 7, 0x07 ); // PLL setting: HI_BYTE(D=1920)
ADC3101_rset(ADC3101_I2C_ADDR_2, 8, 0x80 ); // PLL setting: LO_BYTE(D=1920)
ADC3101_rset(ADC3101_I2C_ADDR_2, 30, 0x88 ); // For 32 bit clocks per frame in Master mode ONLY
ADC3101_rset(ADC3101_I2C_ADDR_2, 5, 0x91 ); // PLL setting: Power up PLL, P=1 and R=1
ADC3101_rset(ADC3101_I2C_ADDR_2, 20, 0x80 ); // AOSR for AOSR = 128 decimal or 0x0080 for decimation filters 1 to 6
ADC3101_rset(ADC3101_I2C_ADDR_2, 18, 0x88 ); // Power up NADC and set NADC value to 8
ADC3101_rset(ADC3101_I2C_ADDR_2, 19, 0x82 ); // Power up MADC and set MADC value to 2
DSP端具体设置如下,I2S接口配置:
hwConfig.dataType = I2S_STEREO_ENABLE;
hwConfig.loopBackMode = I2S_LOOPBACK_DISABLE;
hwConfig.fsPol = I2S_FSPOL_LOW;
hwConfig.clkPol = I2S_RISING_EDGE;
hwConfig.datadelay = I2S_DATADELAY_ONEBIT;
hwConfig.datapack = I2S_DATAPACK_ENABLE;
hwConfig.signext = I2S_SIGNEXT_DISABLE;
hwConfig.wordLen = I2S_WORDLEN_16;
hwConfig.i2sMode = I2S_SLAVE;
hwConfig.FError = I2S_FSERROR_ENABLE;
hwConfig.OuError = I2S_OUERROR_ENABLE;
DMA配置:
Int16 i2sDmaReadLeftBuff_U16[CSL_I2S_DMA_BUF_LEN] = {0X00};
dmaConfig_i2s2_lx.pingPongMode = CSL_DMA_PING_PONG_DISABLE;
dmaConfig_i2s2_lx.autoMode = CSL_DMA_AUTORELOAD_ENABLE;
dmaConfig_i2s2_lx.burstLen = CSL_DMA_TXBURST_1WORD;
dmaConfig_i2s2_lx.trigger = CSL_DMA_EVENT_TRIGGER;
dmaConfig_i2s2_lx.dmaEvt = CSL_DMA_EVT_I2S2_RX;
dmaConfig_i2s2_lx.dmaInt = CSL_DMA_INTERRUPT_ENABLE;
dmaConfig_i2s2_lx.chanDir = CSL_DMA_READ;
dmaConfig_i2s2_lx.trfType = CSL_DMA_TRANSFER_IO_MEMORY;
dmaConfig_i2s2_lx.dataLen = CSL_I2S_DMA_BUF_LEN*2;
dmaConfig_i2s2_lx.srcAddr = (Uint32)&(hI2s->hwRegs->I2SRXLT0);
dmaConfig_i2s2_lx.destAddr = (Uint32)i2sDmaReadLeftBuff_U16;
现在遇到问题,当采样数据信号频率为3khz,6khz的正弦信号时,通过ccs的graph查看波形为连续的正弦波信号,如图1 3k
当采样的数据信号频率为其他频率时(比如2k,4khz),看到的是不连续的正弦信号如下图2 4khz
有人能确定问题所在吗?是DSP端配置问题还是ADC3101端配置的问题?谢谢
你好:
你看下你的I2S的配置格式跟你保存的格式一致吗?
其次你用DMA搬运的时候你是有间隔的搬运吗?你可以尝试更改每次搬运的数量,看出现问题的地方是不是时间间隔变长。
DMA搬运间隔是指 dmaConfig_i2s2_lx.burstLen = CSL_DMA_TXBURST_1WORD;这个参数设置吗,我试过其他值,但采样到的数据完全不正确,您能说的再详细一点吗
你好:
是这个参数dmaConfig_i2s2_lx.dataLen = CSL_I2S_DMA_BUF_LEN*2;
你可以尝试把这个长度变长或者变短,看看出现错误的概率是不是变了。因为看起来我们的codec操作正常,是你的DMA配置有点问题。
您好:
dmaConfig_i2s2_lx.dataLen 长度变长之后,出现错误的概率降低了,但该错误是什么原因造成的,具体该怎么解决这个问题,望回复,谢谢
你好:
由于你改变了长度也就是改变了保存数据的时间,这样出现错误的概率降低。但是这个不能解决根本问题。能解决问题的方法就是你的中断的时间和你的采样率匹配。因为你在执行中断的时候,你的音频数据还在采集。要保证你在这个中断的时间内也就是你采样率的倒数这个时间内完成数据搬运。
谢谢您的回复,您的意思 中断的时间和你的采样率匹配 是指一次DMA中断就将48k数据全部搬运完成,就是长度设置为48000这个意思吗?问题是dsp没有这么大的空间,我试过采用ping-pong模式但是效果一样,数据搬运长度是512字节,但还是一样的现象。如下图
1k信号输入,DMA中断是512个点触发,但是在512点之间也存在同样错误。这好像又和中断时间没有关系,因为至少在每一次中断时间内,即在512个点之间应该是连续的波形才对。而且如果输入信号是1.5k ,3k,或者6k时候,波形一直都是连续的。希望您的再次回复。
你好:
你的中断时间要和WCLK匹配。你把数据设置小一点,因为数据多,搬移时间就长。争取搬移的时间在一个采样率时间之内,来采集下一组。
您好:
现在我将DMA 自动重装配置成为disbale; dmaConfig_i2s2_lx.autoMode = CSL_DMA_AUTORELOAD_DISABLE; 可以得到连续的1k完整波形,但是dma中断服务程序只触发了一次,就不在进入中断,i2s数据确定是存在的。在进入中断服务程序后先清除了DMAIFR标志,还需要做什么其他操作吗?dsp芯片是C5515。
如果不自动重装,那里面的数据会更新吗?你可以试下其它信号看数据能不能更新。
不自动重装,DMA只触发一次中断,自动重装,DMA传输完一次数据之后,自动开始下一次数据传输,所以数据错误,可以这样理解吗?如何让两个事件同步呢?
如果不自动重装,那DMA触发一次后,会一直重复传输吗并且DMA寄存器的值会更新吗?如果不行的话那就有问题。
你的理解没错,就是因为没有同步所以才会对不上。因为你传输数据的时候,你的音频还是在采样的。并没有保存下来。
还是要靠两个数据分别传。
如果不自动重装,DMA寄存器就不更新,但是I2S的接收寄存器一直在更新,为什么就不再次触发DMA中断呢?DMA的中断一直是使能状态,中断标志位也在进入中断之后手动清除了。
你好:
你看下你的中断使能没,还有就是你的中断条件满足么。