您的位置: OpenADSP社区论坛 -> Blackfin专区 -> 新手上路 -> [求助]BF537 读取电脑wave音频文件并播放,... 
本帖共有623个阅读者
发表帖子 发表投票 回复主题
[求助]BF537 读取电脑wave音频文件并播放,求教DMA设置
qianchang(论坛新手)
qianchang
头衔:社区公民
帮派:无帮无派
帖数:7
金钱:166
积分:10
注册时间:2015/7/2
楼主信息 | 留言 | Email | 主页 | 编辑 | 管理 | 离线
[求助]BF537 读取电脑wave音频文件并播放,求教DMA设置
新手刚开始学习DSP,从talkthrough工程开始学起,然后有点疑问. 在Talkthrough的main函数前面,有4个变量定义,和两个buffer定义。
// left input data from AD1871
int iChannel0LeftIn;
// right input data from AD1871
int iChannel0RightIn;
// left ouput data for AD1854    
int iChannel0LeftOut;
// right ouput data for AD1854
int iChannel0RightOut;
// SPORT0 DMA transmit buffer
int iTxBuffer1[2];
// SPORT0 DMA receive buffer
int iRxBuffer1[2];
我不太明白,这几个定义是固定的吗?因为把iRxBuffer1[2]赋值给iChannel0LeftIn;iChannel0RightIn;好像就实现了DMA对ADC输入数据的搬运。而把iChannel0LeftOut;iChannel0RightOut;赋值给iRxBuffer1[2];就实现了DMA对DAC输出数据的搬运。 BF537怎么知道iRxBuffer1[2]就是ADC数据进来的位置呢?而且为什么只有3位呢?(初学者的问题希望大神指导一下)

接着,下载了本站的53x_audio_pcm工程。里面刚好有对电脑音频文件的读取模块,当时可高兴了。可是运行之后发现它用到I2C,而且编译之前要对GPIO进行重新配置,因为533只有一16个GPIO口,而537有48个,所以寄存器名称变了。而且DMA的设置也要变,对SPORT0_TX的控制是DMA4的事情,不再是DMA2了。
可是修改结束之后,还是无法成功。
而且个人认为I2C不需要用到,所以打算基于talkthrough进行修改,就有附件里面的这个工程PC_audio_read. 大神帮忙运行一下,多谢了。还有在53x_audio_pcm工程里面的DMA操作,自己理解好像是descriptor DMA模式,感觉很复杂。想着只要把ADC的数据弄到buffer,然后把buffer输出到DAC就好。就决定从talkthrough里面的DMA设置入手。可是无法实现。
本人对PLL,SDRAM, EBIU的初始化已经理解了,可对DMA搬运的工程不太理解。为什么Talkthrough里面进行循环的播放只要一个while(1)就行了,而PC_audio_read工程却实现不了。

多谢各位大神了。
Talkthrough用到的是I2S模式实现了对ADC/DAC的数据转换。而53x_audio_pcm用到了I2C实现了。(I2C不是通讯协议吗?为什么用I2C来实现ADC/DAC的初始化呢?)
在Audio_Reset函数中,
// set port f set register
    *pPORTFIO_SET = PF12;
PORTFIO_SET是FIO通用端口的SET寄存器,可PF12是FIO的第12个引脚,这样赋值对吗?而且也找不到PF12的宏定义。试着用一个int temp,实时跟踪这个PF12的值,发现它等于0x1000. 可它是个引脚也,怎么有16bit?

上传的附件
   20157621235918.zip [ 32.04 KB ]





「该帖子被 qianchang 在 2015-07-06 21:43:51 编辑过」

这家伙很懒,什么也没有留下!
等级:论坛新手 参考IP地址:*.*.*.*
2015/7/6 21:23:42
尊贵身份标志
andy(论坛版主)
andy
头衔:社区公民
帮派:无帮无派
帖数:2287
金钱:11132
积分:2263
注册时间:2011/6/8
1信息 | 留言 | Email | 主页 | 编辑 | 管理 | 离线
我不太明白,这几个定义是固定的吗?因为把iRxBuffer1[2]赋值给iChannel0LeftIn;iChannel0RightIn;好像就实现了DMA对ADC输入数据的搬运。而把iChannel0LeftOut;iChannel0RightOut;赋值给iRxBuffer1[2];就实现了DMA对DAC输出数据的搬运。 BF537怎么知道iRxBuffer1[2]就是ADC数据进来的位置呢?而且为什么只有3位呢?(初学者的问题希望大神指导一下)


定义 变量是随便定义的,目的是你能看懂这个代表什么。

这个例程实际实现的原理是,通过两个DMA,分别从SPORT接口的接收端读取AD的采集数据,每次采集2个32位数据,分别是一个左声道数据,一个又声道数据。SPORT数据宽度配置的为16位的(不知是你改为16位的不),这不影响按32位采集,高位会为空。
然后把采集的数据在DMA接收完成的中断中,赋值给传输数据的变量,然后再通过使能DMA,把传输数据发出去,实现输出端实时播放输入端的音频。
不知你在哪里看到了DMA地址为3位。iRxBuffer1[2]为2个32位的数组,分别存放一个32位的左声道数据和一个右声道数据。

所有的数据搬运是在以下代码实现的:
void Init_DMA(void)
{
// Configure DMA3
// 32-bit transfers, Interrupt on completion, Autobuffer mode
// *pDMA3_CONFIG = WNR | WDSIZE_32 | DI_EN | FLOW_1;
// Start address of data buffer
// *pDMA3_START_ADDR = iRxBuffer1;   // Why 3bit address is ok??
// DMA loop count
// *pDMA3_X_COUNT = 2;
// DMA loop address increment
// *pDMA3_X_MODIFY = 4;

// Configure DMA4
// 32-bit transfers, Autobuffer mode
*pDMA4_CONFIG = WDSIZE_32 | FLOW_1;
// Start address of data buffer
*pDMA4_START_ADDR = iTxBuffer1;  // Why 3bit address is ok??
// DMA loop count
*pDMA4_X_COUNT = 2;
// DMA loop address increment
*pDMA4_X_MODIFY = 4;
ssync();

}

这个为DMA的配置代码,DMA3配置的为采集数据方式,把数据采进 iRxBuffer1 数组中,每次采集2个数据,DMA3_X_MODIFY为采集地址增量,因为是32位的数组,所以要增加4个byte。
DMA4位传输数据的配置。

这些配置配置好后,只要使能DMA3,DMA3会自动从AD采集数据。并且采集完成后进入中断。
EX_INTERRUPT_HANDLER(Sport0_TX_ISR)
{
// confirm interrupt handling
*pDMA4_IRQ_STATUS = 0x0001;

// copy input data from dma input buffer into variables
iChannel0LeftIn = iRxBuffer1[INTERNAL_ADC_L0];
iChannel0RightIn = iRxBuffer1[INTERNAL_ADC_R0];
// call function that contains user code
Process_Data();

// copy processed data from variables into dma output buffer
iTxBuffer1[INTERNAL_DAC_L0] = iChannel0LeftOut;
iTxBuffer1[INTERNAL_DAC_R0] = iChannel0RightOut;


}

中断中,把
iRxBuffer1数组中的数据导入iTxBuffer1数组中,iChannel0RightOut和iChannel0RightIn  等这种中间数据实际作用不大,Process_Data函数也只是为了导数据,其实完全可以用两个数组直接导。





这家伙很懒,什么也没有留下!
等级:论坛版主 参考IP地址:*.*.*.*
2015/7/6 22:57:49
尊贵身份标志
andy(论坛版主)
andy
头衔:社区公民
帮派:无帮无派
帖数:2287
金钱:11132
积分:2263
注册时间:2011/6/8
2信息 | 留言 | Email | 主页 | 编辑 | 管理 | 离线
IIC是初始化音频芯片的,我们的开发板上用的是AIC23B,IIC配置他的工作模式,如采样率多少,时钟多少,音量大小等数据。
ADI的例子程序则不需要配置这些,因为他的采样率是随即的,或者说是默认的,他是以当前任意采样率采集的数据,再以这个采样率送出来,因为你的输入音频是模拟量,所以你不会感觉采样率的限制。
IIC实际就是GPIO,只要掌握了537的GPIO方法,把相关寄存器改一下,就能实现,你需要看硬件上哪个管脚连接到了芯片的GPIO。因为芯片不同,GPIO初始化是不一样的。若是想播放WAV,需要配置与WAV文件相同的采样率。
DMA肯定要修改,但537和533内核基本一样,仅仅寄存器名有些变动,操作方法差不多,理解的话移植也不难。
DMA在我们的533教学视频中有一章讲,可以看看。

这家伙很懒,什么也没有留下!
等级:论坛版主 参考IP地址:*.*.*.*
2015/7/6 23:03:44
尊贵身份标志
OpenADSP(管理员)
OpenADSP
头衔:社区公民
帮派:无帮无派
帖数:5195
金钱:34806
积分:6378
注册时间:2011/6/7
3信息 | 留言 | Email | 主页 | 编辑 | 管理 | 离线
等级:管理员 参考IP地址:*.*.*.*
2015/7/7 11:15:03
qianchang(论坛新手)
qianchang
头衔:社区公民
帮派:无帮无派
帖数:7
金钱:166
积分:10
注册时间:2015/7/2
4信息 | 留言 | Email | 主页 | 编辑 | 管理 | 离线
谢谢,Andy.
我现在搞懂了SPORT0 和DMA之间的数据传输过程。SPORT0初始化之后有两个FIFO,一个是输入的,连接了ADC, 一个是输出的连接的是DAC。 而DMA3是将SPORT0_RX的数据传输到iRxBuffer1;而DMA4是将 iTxBuffer1传输到SPORT0_TX,然后通过DAC输出到speaker。
这样理解是否正确?

我还有个疑问?
现在我用下面的函数读取了6M的voice.wav文件的音频数据,存到了buffer里面。
unsigned int buffer[1024*1024*6];
fp1 = fopen("../voice.wav", "rb");
fread(buffer, 1, 1024*1024*6, fp1);
fclose(fp1);

如果DSP要读取这个6M的数据并播放的话,只需要将*pDMA4_START_ADDR 指向buffer的第一个地址。是不是这样的意思?中断应该怎么修改呢?

这家伙很懒,什么也没有留下!
等级:论坛新手 参考IP地址:*.*.*.*
2015/7/9 6:51:44
尊贵身份标志
andy(论坛版主)
andy
头衔:社区公民
帮派:无帮无派
帖数:2287
金钱:11132
积分:2263
注册时间:2011/6/8
5信息 | 留言 | Email | 主页 | 编辑 | 管理 | 离线
是的,理解正确。

wav文件有很多格式,例子代码只是SPORT普通数据格式传输音频文件,但对于WAV文件来说,需根据文件格式配置sport参数,通常生成的WAV文件为16bit,双声道,48K采样,IIS传输格式,所以你的SPORT也必须配置为该采样率才可以。
另外,连续播放文件,必须采用一定的DMA机制才能完成。因为DMA一次搬运的数据量受寄存器长度限制,不可能连续播完一个完成的文件的。
论坛下载专区给你发了一个533的wav播放例子,你可以参考一下。

这家伙很懒,什么也没有留下!
等级:论坛版主 参考IP地址:*.*.*.*
2015/7/13 21:50:30
Powered by OpenADSP Copyright © 2010 www.Openadsp.com. All rights reserved.159963 Call, 1 Queries, Processed in 0.037109 second(s),