我正在尝试在FRDMKL25Z板的C中实现IIR过滤器。我当前的代码如下所示:
#include "Cpu.h"
#include "Events.h"
#include "ADC_1.h"
#include "AdcLdd1.h"
#include "DAC_1.h"
#include "PE_Types.h"
#include "PE_Error.h"
#include "PE_Const.h"
#include "IO_Map.h"
#define NSP 16
static uint16_t DACvalue, ADCvalue;
static LDD_TError Error;
static LDD_TDeviceData *MyDacPtr;
int N=10; // Filter order
double NumCoeff[11]={0.8017, -8.0174, 36.0785, -96.2094, 168.3664, -202.0397,
168.3664, -96.2094, 36.0785, -8.0174, 0.8017};
double DenomCoeff[11]={1.0000, -9.5582, 41.1210, -104.8588, 175.5143, -201.4924,
160.6706 , -87.8720, 31.5447, -6.7119, 0.6428};
double Signal[NSP], FilteredSignal[NSP];
int main(void)
{
/* Write your local variable definition here */
/*** Processor Expert internal initialization. DON'T REMOVE THIS CODE!!! ***/
int j, k;
double y, Reg[NSP];
PE_low_level_init();
MyDacPtr = DAC_1_Init(NULL);
for(j=0; j<NSP; j++) Reg[j] = 0.0; // Init the delay registers
for(;;){
for(j=0;j<NSP;j++)
{
for(k=N; k>0; k--) Reg[k] = Reg[k-1]; // Shift the delay register values.
(void)ADC_1_Measure(TRUE); /* do conversion and wait for the result */
(void)ADC_1_GetValue16(&ADCvalue); /* get the result into value variable */
Signal[j]=(ADCvalue/65535)*3.5; /*Convert to volts*/
Reg[0] = Signal[j]; // The denominator
for(k=1; k<=N; k++) Reg[0] -= DenomCoeff[k] * Reg[k];
y = 0; // The numerator
for(k=0; k<=N; k++)y += NumCoeff[k] * Reg[k];
FilteredSignal[j] = y;
DACvalue=(FilteredSignal[j]*65535)*3.5; //Convert back to 16 bit
Error = DAC_1_SetValue(MyDacPtr, DACvalue); /* Set DA converter output */
}
}
代码的一些细节:
我正在使用飞思卡尔的Processor Expert(PE)来对嵌入式板进行编程。
使用MATLAB生成的IIR滤波器系数;
由于设备需要实时过滤数据,因此我从
ADC并对其进行滤波,然后在处理之后立即将其输出到DAC;
一旦刷新到板上,我就不会从DAC端口获得任何输出。
我愿意接受所有建议和调试方法。
最佳答案
这是你做错了
您还需要跟踪以前的输出
也许您正在尝试,但是有趣的嵌套循环无法正常工作
分母应用于输出,而不是输入
应用系数时,分母不是真正的分母;之所以这样称呼是因为频率响应就像分母一样工作。分母系数乘以输出历史,并从输出中减去它们的和。 (请考虑将所有y(n-1)... y(n-k)
项移到等号的另一侧,而仅将过滤器输出留在一侧)
有趣的分母系数是第一个,它乘以您实际尝试计算的新输出!您将整个结果除以该结果,以找出新的输出。 (在大多数IIR过滤器中,该值为1.0,因此您可以跳过此步骤)。
16位整数除以65535等于0 !,无需转换为伏特(正如其他人所提到的)。
仅在需要时才进行工程设计;你不
这是我的建议,同时尝试保持相同的代码结构...
unsigned int ADCvalue,
int Reg[NSP]; // use signed values instead of unsigned, and no need for double for history of ADCvalue
for(j=0; j<NSP; j++) Reg[j] = 0; // Init the delayed input registers
for(j=0; j<NSP; j++) FilteredSignal[j] = 0.0; // Init the delayed output registers
for(;;)
{
for(k=N; k>0; k--) Reg[k] = Reg[k-1]; // Shift the delay register values.
for(k=N; k>0; k--) FilteredSignal[k] = FilteredSignal[k-1];
(void)ADC_1_Measure(TRUE); /* do conversion and wait for the result */
(void)ADC_1_GetValue16(&ADCvalue); /* get the result into value variable */
Reg[0] = ADCvalue - 0x8000; // Save the previous inputs samples (and shift the zero value to 0)
y = 0;
for(k=0; k<=N; k++) y += NumCoeff[k] * Reg[k]; // The numerator
for(k=1; k<=N; k++) y -= DenomCoeff[k] * FilteredSignal[k]; // The denominator
FilteredSignal[0] = y/DenomCoeff[0];
DACvalue= FilteredSignal[0] + 0x8000; // shift the zero value back to unsigned, centered at 0x8000
Error = DAC_1_SetValue(MyDacPtr, DACvalue); /* Set DA converter output */
}