您好!
我正在开发一种基于时域内卷积的信号处理应用。 我将外设学习套件与 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