This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

OMAPL137采用轮询方式接收输出音频信号,加上一些算法就不能运行了



Hi,您好,

        我用OMAPL137采用轮询方式接收输出音频信号,不加算法的话可以顺利接扬声器播放数据(自己写一个5s的信号循环播出的,采样率48000Hz),但是在程序中加入一些算法就不能拨出了?不知道是为什么啊?部分程序如下

//该部分用来产生左通道白噪声信号并得到麦克风信号
outdata = GaussRan[GaussPtr];                      // 全局变量GaussPtr = 0;
floutdata = outdata * vref;                                  // 将参考信号转换为浮点型
GaussPtr = (GaussPtr+1)% GaussLen;          // 5s数据播放完成后循环
output_sample((outdata << 15)| 0x00000000); // 左通道扬声器输出高斯白噪声信号
LeftSample = input_sample();                            // 左通道麦克风输入采集到的信号
dn = (Int16) (LeftSample >> 15);                       // 左通道得到麦克风信号
fldn = dn * vref;                                                   // 将麦克风信号转换为浮点型

// 右通道的输入输出信号不作处理
output_sample( 0x00000000);                           // 右通道扬声器输出为0
RightSample = input_sample();                         // 右通道麦克风信号

for (i=59; i>0; i--)
{
x[i] = x[i-1];
}
x[0] = floutdata;

        以上部分不加下边那个for循环还是可以运行的,但是加了for循环就不行了。之前也遇到一种情况,fldn = dn * vref,这个语句之前写成了fldn = dn * vref/Q,不加除法运算可以运行,加了也不能运行了,感觉很奇怪。

输入输出函数如下:

void output_sample(Int32 out_data)
{
AIC31_data.uint = out_data;
while ( ! ( MCASP1_SRCTL5 & 0x10 ) );
MCASP1_XBUF5_32BIT = AIC31_data.uint;
}

Int32 input_sample(void)
{
while ( ! ( MCASP1_SRCTL0 & 0x20 ) );
AIC31_data.uint = MCASP1_RBUF0_32BIT;
return (AIC31_data.uint);
}

  • 应该是实时性不够,卡住了。计算一下是不是一次处理的时间大于一个采样点的间隔了。

  • Tony Tang 说:

    应该是实际性不够,卡住了。计算一下是不是一次处理的时间大于一个采样点的间隔了。

    感谢Tony Tang的回复!我尝试了一下,应该是您说的原因,因为我把for循环的次数改成39次还可以运行,应该就是时间的问题。

    1.但是我实际中确实需要一些计算量,按理说DSP的计算能力应该是没问题的吧?是不是我用轮询访问I/0的方式的话占用了DSP大量的负荷,就来不及算这些运算了?如果用中断的方式会不会好些?

    2.如果是中断方式的话,我需要一次采样得到左右通道的数据,也就是音频数据采用DSP mode,mcasp相应采用burst mode,slot长度是32bit,但是我不太明白ACLKRCTL、AHCLKRCTL和PDIR这三个寄存器该怎么设置。主要是不明白两个问题:1.时钟是内部产生和外部产生是可以任意选择的吗?2.如果设置了 Synchronous模式,是不是接收时钟就可以不用设置了?

    非常感谢!

  • Yu Wang22 说:
    1.但是我实际中确实需要一些计算量,按理说DSP的计算能力应该是没问题的吧?是不是我用轮询访问I/0的方式的话占用了DSP大量的负荷,就来不及算这些运算了?如果用中断的方式会不会好些?

    --- 针对目前这种情况,如果采用中断方式,结果就是采样来的及,但处理来不及了,即在处理当前数据的时候,新的中断来了,取到了新的数据,但中断返回后还是继续处理前面未处理完的数据。

    真正要说效率,轮询是最高的,查到数据ready就读出来,马上处理,处理完又去查数据ready。只是中间的处理时间过长了而已,所以要解决的是中断处理的问题。你想如果换成中断,无非就是中断来了,进中断服务程序取数,退出中断,处理数据,再中断取数,从这个角度其实差不多的过程,反而中断效率更低,因为中断进入退出ISR有一堆的寄存器需要保护和恢复,也是占时间的。

    方法一:优化算法,让它跑的快一点。比如说前面的循环,只是往前移了一个数而已,直接把指针偏一下就行了,当然这可能只是个示例,实际算法不是这样子,但总之想办法优化你的算法。

    方法二:不采用按点处理,改用按帧处理,比如128个点或者更长处理一次,数据的接收采用EDMA,这样就比轮询效率高了,CPU只做运算处理。

    Yu Wang22 说:
    2.如果是中断方式的话,我需要一次采样得到左右通道的数据,也就是音频数据采用DSP mode,mcasp相应采用burst mode,slot长度是32bit,但是我不太明白ACLKRCTL、AHCLKRCTL和PDIR这三个寄存器该怎么设置。主要是不明白两个问题:1.时钟是内部产生和外部产生是可以任意选择的吗?2.如果设置了 Synchronous模式,是不是接收时钟就可以不用设置了?

    时钟选择是根据硬件实际要求来的,硬件上本来就是外部提供的,也不能设为内部提供啊,如果外部没有提供,那就必需内部提供。

    ASYNC=0时,接收时钟与帧同步跟发送的采用同一组,接收的是不用配置了。

  • 非常感谢您的回复!我也觉得EDMA方式可能更好,不过OMAPL137给的例程里没有EDMA配置的,想问一下有没有这样的例程可以下载?多谢!

  • L138的starterware里有McASP EDMA的例程可以参考,不过对于如果不熟悉EDMA的,这个代码有点复杂。

    我个人做了McBSP EDMA的例子,比较简单。

    http://www.deyisupport.com/question_answer/dsp_arm/omap_l1x/f/54/t/87941.aspx

  • 您好,我初学DSP,想问一下EDMA是不是可以在McASP接口来数据时直接把数据搬运到片外存储器,如DDR2或者在EMIF上的SDRAM?

    只要先对EMDA寄存器进行初始配置,在McASP数据到来和搬运的整个过程中,都不需要cpu参与吗?

  • chunyu Lee 说:
    只要先对EMDA寄存器进行初始配置,在McASP数据到来和搬运的整个过程中,都不需要cpu参与吗?

    是的。

    参考McBSP例程:http://www.deyisupport.com/question_answer/dsp_arm/omap_l1x/f/54/t/87941.aspx

    L138. C6748的starterware里有McASP的EDMA例程,都差不多,可以互相借鉴。