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.

[参考译文] TMS320F28335:实时音频处理应用中的卷积性能误差

Guru**** 2551110 points
Other Parts Discussed in Thread: TMS320F28335

请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/624403/tms320f28335-convolution-performance-error-in-real-time-audio-processing-application

器件型号:TMS320F28335

您好!  

我正在开发一种基于时域内卷积的信号处理应用。 我将外设学习套件与 TMS320F28335配合使用。 我的应用程序可以正确接收和传输音频信号、但无法正确执行卷积。 即使卷积内核非常小、输出音频信号也会产生噪声和失真。 我使用的是乒乓缓冲技术、就像 TI 提供的一个文档示例一样。  

起初、我以为我的卷积函数是错误的、但我使用另一个编译器对其进行了测试、并将其与 Matlab 仿真的结果进行了比较。 他们还可以。

然后、我认为处理时间可能是问题、但我检查了所用的时钟周期卷积数量、它小于缓冲时间、因此这不是问题。  

我还´s 更改缓冲区大小、甚至使用2个以上的缓冲区。  

我还在需要快速计算的函数中使用静态内联格式。

另一方面、将输入信号乘以0.5等简单的处理效果很好。

总之、这是我使用的一段代码、希望任何人都能帮助我。

void main (void){

 inv31=1.0/E231;// inv31和 E231是浮点到 uint32和 viceversa 转换的变量
 TS=1/Fs;

 零(signal_reverb、120);//用120个零填充数组"signal_reverb"


  EALLOW;

//步骤1. 初始化系统控制:
// PLL、安全装置、启用外设时钟
   InitSysCtrl();
//步骤2. 初始化 GPIO:
//为 McBSP 操作启用 GPIO 引脚。
  InitMcbspGpio();

  对于(k2=0;k2<1024;k2++){ping_buffer[k2]= 0xDEADDEEAD;}

  对于(k2=0;k2<1024;k2++){pong_buffer[k2]= 0xDEADDEEAD;}


//步骤3. 清除所有中断并初始化 PIE 矢量表:
//禁用 CPU 中断
  Dint;

//将 PIE 控制寄存器初始化为默认状态。
//默认状态为禁用所有 PIE 中断和标志
//被清除。
//此函数位于 DSP2833x_PIECTRL.c 文件中。
  InitPieCtrl();
  EALLOW;
  DINT;        //再次禁用中断(目前)

//禁用 CPU 中断并清除所有 CPU 中断标志:
  IER = 0x0000;
  IFR = 0x0000;


//步骤4. 初始化外设

  PING_缓冲 器_OFFSET++;   //从位置1开始(从位置1开始32位 r/w、然后为0)
  pong_buff offset++;   //从位置1开始(从位置1开始32位 r/w、然后为0)
  SPIA_init();      //初始化
  AIC23_init(); //设置 AIC23

  init_dma();           //在 McBSP 之前初始化 DMA,以便 DMA 可以传输 McBSP 数据
  init_mcbspa();        //初始化 McBSP-A
  delay_loop();
  InitPieVectTable();  // PIE 中的默认 ISR

  InitAdc ();        //基本 ADC 设置、包括 校准
     AdcRegs.ADCTRL1.All = 0;
     AdcRegs.ADCTRL1.bit.ACQ_PS = 7;   // 7 = 8 x ADCCLK
     AdcRegs.ADCTRL1.bit.SEQ_CASC =1;   // 1=级联序列发生器
     AdcRegs.ADCTRL1.bit.CPS = 0;     //除以1
     AdcRegs.ADCTRL1.bit.CONT_RUN = 0;  //单次运行模式

     AdcRegs.ADCTRL2.all = 0;
     AdcRegs.ADCTRL2.bit.INT_ENA_SEQ1 = 1;  // 1=启用 SEQ1中断
     AdcRegs.ADCTRL2.bit.ePWM_SOCA_SEQ1 =1;  // 1=SEQ1从 ePWM_SOCA 触发器开始
     AdcRegs.ADCTRL2.bit.INT_MOD_SEQ1 = 0;  // 0=序列每结束后的中断

     AdcRegs.ADCTRL3.bit.ADCCLKPS = 3;  // ADC 时钟:FCLK = HSPCLK /2 * ADCCLKPS
                                // HSPCLK = 75MHz (请参阅 DSP2833x_SYSCTRL.c)
                                // FCLK = 12.5MHz
     AdcRegs.ADCMAXCONV.ALL = 0x0001;   //从序列发生器1进行2次转换
     AdcRegs.ADCCHSELSEQ1.bit.CONV00 = 0;//将 ADCINA0设置为第一个 SEQ1转换器
      AdcRegs.ADCCHSELSEQ1.bit.CONV01 = 1;//将 ADCINA1设置为第2个 SEQ1转换器

     EPwm2Regs.TBCTL.ALL = 0xC030;  //配置定时器控制寄存器
     EPwm2Regs.TBPRD = 2990;  // TPPRD +1 = TPWM /(HSPCLKDIV * CLKDIV * TSYSCLK)
                           //         = µs μ s / 6.667ns
     EPwm2Regs.ETPS.ALL = 0x0100;        //配置 ADC 从 ePWM2开始
     EPwm2Regs.ETSEL.ALL = 0x0A00;        //将 SOCA 启用到 ADC

   EALLOW;
   DmaRegs.ch1.control.bit.run = 1;//在通道1上启动 Rx

  PieVectTable.DINTCH1 =&LOCAL_D_INTCH1_ISR;
  PieVectTable.DINTCH2 =&LOCAL_D_INTCH2_ISR;
  PieVectTable.ADCINT =&ADC_ISR;
  PieVectTable.XINT2=&PB_1_ISR;
  GpioIntRegs.GPIOXINT2SEL.bit.GPIOSEL=0x11;//interruption 引脚17 PB1
  XIntrautRegs.XINT2CR.bit.Polity=1;//上升边沿
  XIntertRegs.XINT2CR.bit.enable = 1;//enabilitar interruption

  PieVectTable.XINT3=&PB_2_ISR;
  GpioIntRegs.GPIOXINT3SEL.bit.GPIOSEL=0x30;//interruption 引脚48 PB2
  XIntrautRegs.XINT3CR.bit.Polity=0;//下降边沿
  XIntertRegs.XINT3CR.bit.enable = 1;//enabilitar interruption

  PieCtrlRegs.PIECTRL.bit.ENPIE = 1; //启用从 PIE 块提取矢量
  PieCtrlRegs.PIEACK.all = 0xFFFF;   //启用 PIE 将脉冲驱动到 CPU

//可以在以下中断行中将中断置为有效


   PieCtrlRegs.PIEIER7.bit.INTx1 = 1;//启用 INT7的 INTx.1 (DMA CH1)
   PieCtrlRegs.PIEIER7.bit.INTx2 = 1;//启用 INT7的 INTx.2 (DMA CH2)
   PieCtrlRegs.PIEIER1.bit.INTx6 = 1;// ADC
   PieCtrlRegs.PIEIER1.bit.INTx5 = 1;//为 PB1启用 INTx.5
   PieCtrlRegs.PIEIER12.bit.INTx1 = 1;//为 PB1启用 INTx.1


  IER |= 0x0841;                  //启用 INT7 e INT 1
   EINT;                            //全局启用中断
   ERTM;
   EDIS;

    while (1){
    }                 //代码始终在此处循环

中断空 LOCAL_D_INTCH1_ISR (空)     // DMA 通道1 - McBSP-A Rx

 int i=0;
 volatile int32* buffer_ptr;


 EALLOW;

    if (first_interrupt=1)//无需处理(发生 B/c 中断
   {                     // DMA 传输开始时到 ping 缓冲区-尚未接收到数据)
       first_interrupt=0;//关闭标志并退出中断
   }
    否则{


   //处理

   if (DmaRegs.CH1.dst_ADDR_SHADDADDR_SHADD=0 pong_buff){
    Buffer_ptr =&ping_buffer[i];
   }
   否则{
    Buffer_ptr =&pong_buffer[i];}

  for (i=0;i<1024;i++){

     IntroduceValue (signal_reverb、120、* buffer_ptr * inv31); //inv31是一个变量、用于将 int32更改为 float
     proc = ScalarProduct (signal_reverb、reverb、120);/*"reverb"是一个不熟悉滤波器内核系数的数组:float reverb[120]=-0.001871、014558、0.036099、076234、0.144645、306967、-0.2038830.071、0.03872、0.04580、0.080、0.048、078、078、078、078、078、078、078、078、078、078、078、039、078、078、078、078、078、078、039、078、078、039、078、078、039、078、039、078、078、039、078、039、039、039、039、039、039、039、039、078、039、078、078、039、039、039、039、078、039、039、039、039、

*

  *buffer_pt+=proc*E231;//E231 是一个变量,用于从 float 更改为 int32

     }
  

  //  PieCtrlRegs.PIEACK.bit.ACK1 = 1;
   // PieCtrlRegs.PIEACK.bit.ACK12=1;
     //完成后,切换到另一个缓冲区
       DmaRegs.ch2.control.bit.run = 1;//在 CH1完成 ping 缓冲器后在 CH2上启动 TX
   }

    //当 DMA 首次开始处理 ping 缓冲区时,设置影子寄存器
    //  下次从 pong buffer 开始,反之亦然
    if (DmaRegs.CH1.dst_ADDR_SHADDADDR_SHADD=0 ping_buff)
   {
      DmaRegs.CH1.dst_ADDR_SHADDow = PON_缓冲 器_OFFSET;
        DmaRegs.CH1.dst_beg_ADDR_SHADDADDR_SHADOW = PON_缓冲 器_OFFSET;

   }
   其他
   {
      DmaRegs.CH1.dst_ADDR_SHADDow = ping_buff;
        DmaRegs.CH1.dst_beg_ADDR_shadow = ping_buff;
   }
 //要接收来自此 PIE 组的更多中断,请确认此中断
    PieCtrlRegs.PIEACX.ALL = PIEACK_group7;
    EDIS;

// INT7.2
中断空 LOCAL_D_INTCH2_ISR (空)     // DMA 通道2 - McBSP-A Tx

 EALLOW;
   //当 DMA 首次开始处理 ping 缓冲区时,设置影子寄存器
    //  下次从 pong buffer 开始,反之亦然
      if (DmaRegs.CH2.SRC_ADDR_SHADDADDR_SHADOW = ping_buff)
   {
       DmaRegs.CH2.SRC_ADDR_SHADDADDR_SHADOW = PON_BUK_OFFSET;
       DmaRegs.CH2.SRC_beg_ADDR_SHADDADDR_SHADOW = PON_缓冲 区偏移;
   }
   其他
   {
       DmaRegs.CH2.SRC_ADDR_SHADDow = ping_buff;
       DmaRegs.CH2.SRC_beg_ADDR_SHADDow = ping_buff 偏移;
   }

      PieCtrlRegs.PIEACK.all = PIEACK_group7;//要接收来自此 PIE 组的更多中断,请确认此中断
    EDIS;

这是我认为可能存在错误的代码部分。

卷积操作涉及以下功能:

静态内联 void Shift (浮点表[]、int size){
   int i;
   for (i=(size-1);i>=0;i--){
       tabla[i]=tabla[i-1];
   }

静态内联浮点比例乘积(float signal[]、float coeficientes[]、int n){
   浮点 YK=0;
   int i;
   对于(i=0 <n;i++){
       YK=YK+SIGNAL [I]*COeficientes[i];
   }
   返回 YK;

静态内联空 IntroduceValue (float signal[]、int n、float valor){

   SHIFT (信号、n);
   SIGNAL [0]=值;

我希望你能帮助我。

此致、

Ignacio

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    很抱歉 Ignacio、鉴于我们能够通过论坛提供的支持类型、我无法调试您的代码。 如果您对设备或我们提供的软件示例有任何特定的问题,我们将乐意为您提供帮助。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    实际上、代码基于您的文档示例、该示例称为"将 TMS320F2833x 连接到 AIC23B 立体声音频编解码器"。 我的代码正在正确编译、但正在进行的操作是覆盖缓冲区、从而破坏音频信号。 使用乒乓缓冲技术时、似乎出现了一些我无法滤除的噪声。