PL2PS2PL v3.0 滤波处理

Matlab生成滤波器参数

filterDesigner

命令行输入filterDesigner

 设置滤波器参数

编辑可以设置滤波器结构(直接一型/二型等、单节/多节)

目标中选择导出c语言头文件

 得到滤波器参数

 Simulink验证

matlab simulink仿真的目的主要是提前观测滤波效果,在vitis实现后可以将滤波前后的情况与simulink仿真进行对比,记录一下仿真过程。

 添加滤波器到simulink中

 添加正弦波生成器200Hz与5000Hz以及示波器模块

 滤波前:

带通滤波后: 

将200Hz信号成功恢复出来,滤去了5kHz的正弦信号。

代码

 filter.h 



#ifndef _FILTER_
#define _FILTER_

#define TEMP_BASE_ADDR		0x20000000


#define MWSPT_NSEC 13
extern const int NL_mult[MWSPT_NSEC];
extern const double NUM_mult[MWSPT_NSEC][3];
extern const int DL_mult[MWSPT_NSEC];
extern const double DEN_mult[MWSPT_NSEC][3];
#include <stdio.h>
#include <math.h>
extern const int NL_single;
extern const double NUM_single[13];
extern const int DL_single;
extern const double DEN_single[13];

void filter_single(double* x, double* y, int xlen, double* a, double* b, int nfilt);

void filter_mult(double* RxBufferPtr, double* buffer_temp);

void filter_single_use(double* inaddr, double* outaddr);

void filter_all(double* inaddr, double* outaddr);

#endif

 filter_single是直接一型的单节滤波器代码,低通IIR,filter_single_use调用filter_single进行滤波操作,感觉是可以直接去掉filter_single_use这一环的,没试。可以输入一连串double数据,输出滤波后的一串double数据。

filter_mult是直接一型的二阶多节滤波器代码,带通IIR,输入单个double数据,输出滤波后的单个double数据。

两者代码结构是不同的,为什么不写成一样,是因为我copy的时候,两个大佬写的不一样,之后有时间再改。

filter_all是滤波的全过程,主要包含

filter.c


#include "filter.h"

#include <math.h>

#define k 0.2

double xDelay[26] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};		//初始化x的延迟,(x[n-1]...x[n-2])*13	多节二阶
double yDelay[26] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};		//初始化y的延迟,(y[n-1]...y[n-2])*13
double xDelay_single[6] = {0,0,0,0,0,0};							//初始化x的延迟,(x[n]...x[n-12])		单节13阶
double yDelay_single[6] = {0,0,0,0,0,0};							//初始化y的延迟,(y[n]...y[n-12])
int numjoint = 6;
int numStage = 13;

const int NL_mult[MWSPT_NSEC_MULT] = { 1,3,1,3,1,3,1,3,1,3,1,3,1 };					//滤波器分子系数
const double NUM_mult[MWSPT_NSEC_MULT][3] = {
		 {
		     0.5834802936154,                 0,                 0
		  },
		  {
		                   1, -0.09583101176903,                 1
		  },
		  {
		     0.5834802936154,                 0,                 0
		  },
		  {
		                   1,   -1.999802349761,                 1
		  },
		  {
		     0.6897246154972,                 0,                 0
		  },
		  {
		                   1,    1.455323776042,                 1
		  },
		  {
		     0.6897246154972,                 0,                 0
		  },
		  {
		                   1,   -1.999971691646,                 1
		  },
		  {
		    0.07983392337156,                 0,                 0
		  },
		  {
		                   1,   -0.633411429872,                 1
		  },
		  {
		    0.07983392337156,                 0,                 0
		  },
		  {
		                   1,   -1.999653971883,                 1
		  },
		  {
		                   1,                 0,                 0
		  }
		};
const int DL_mult[MWSPT_NSEC_MULT] = { 1,3,1,3,1,3,1,3,1,3,1,3,1 };					//滤波器分母系数
const double DEN_mult[MWSPT_NSEC_MULT][3] = {
		  {
		                   1,                 0,                 0
		  },
		  {
		                   1,   -1.437641216242,   0.7157935362898
		  },
		  {
		                   1,                 0,                 0
		  },
		  {
		                   1,    -1.97099085614,   0.9729983069548
		  },
		  {
		                   1,                 0,                 0
		  },
		  {
		                   1,    -1.89549235219,    0.900976018839
		  },
		  {
		                   1,                 0,                 0
		  },
		  {
		                   1,   -1.522167636734,   0.6198289328958
		  },
		  {
		                   1,                 0,                 0
		  },
		  {
		                   1,   -1.460250768155,    0.897554646763
		  },
		  {
		                   1,                 0,                 0
		  },
		  {
		                   1,    -1.99236891738,   0.9937430534111
		  },
		  {
		                   1,                 0,                 0
		  }
		};

const int NL_single = MWSPT_NSEC_SINGLE;														//滤波器分子系数
const double NUM_single[MWSPT_NSEC_SINGLE] = {
		  3.254338963004e-13,1.627169481502e-12,3.254338963004e-12,3.254338963004e-12,
		  1.627169481502e-12,3.254338963004e-13
		};
const int DL_single = MWSPT_NSEC_SINGLE;														//滤波器分母系数
const double DEN_single[MWSPT_NSEC_SINGLE] = {
        1,   -4.979373082966,    9.917704906665,   -9.876874869511,
4.918127356203,   -0.979584310381
};





//单节二阶滤波
double filter_double(double DataIn, double a[][3], double b[][3], int indexStage)
{
		double a1, a2;
		double b0, b1, b2;
		double result;



		b0 = b[indexStage][0];
		b1 = b[indexStage][1];
		b2 = b[indexStage][2];
		a1 = a[indexStage][1];
		a2 = a[indexStage][2];

      result = b0 * DataIn + b1 * xDelay[indexStage * 2] + b2 * xDelay[indexStage * 2 + 1] - a1 * yDelay[indexStage * 2] - a2 * yDelay[indexStage * 2 + 1];

      	//延时因子的移位			不同节之间的滤波器x[n]延迟相互独立,需要申请单独地址

		xDelay[indexStage * 2 + 1] = xDelay[indexStage * 2];
		xDelay[indexStage * 2] = DataIn;
		yDelay[indexStage * 2 + 1] = yDelay[indexStage * 2];
		yDelay[indexStage * 2] = result;

		return result;
}



//单节13阶滤波调用	(可以删掉
void filter_single_use(double* inaddr, double* outaddr){
	int data_len = 1024;
	double* input_data = (double*)inaddr;
	static double huangemingzi[1024];
//	double* output_data = (double*)singlefilter_addr;

	filter_single(input_data, huangemingzi, data_len, DEN_single, NUM_single, numjoint);

	double* ddr_buffer_temp = (double*)outaddr;
	for (int i = 0; i < data_len; i++) {
		if(output_data[i] > 0)
			ddr_buffer_temp[i] = huangemingzi[i];
		else
			ddr_buffer_temp[i] = 0;
	}

	    // 释放内存
//	    free(output_data);
}


//单节13阶滤波
void filter_single(double* x, double* y, int xlen, double* a, double* b, int nfilt)//nfilt为系数数组长度
{
	int i, j;
	a[0] = 0.0;
//	double y_r[xlen];
	memset(y,0,xlen*sizeof(double));
	for (i = 0; i<xlen; i++)
	{
//		xDelay_single[12] = xDelay_single[11];
//		xDelay_single[11] = xDelay_single[10];
//		xDelay_single[10] = xDelay_single[9];
//		xDelay_single[9] = xDelay_single[8];
//		xDelay_single[8] = xDelay_single[7];
//		xDelay_single[7] = xDelay_single[6];
//		xDelay_single[6] = xDelay_single[5];
//		xDelay_single[5] = xDelay_single[4];
//		xDelay_single[4] = xDelay_single[3];
//		xDelay_single[3] = xDelay_single[2];
//		xDelay_single[2] = xDelay_single[1];
//		xDelay_single[1] = xDelay_single[0];
//		xDelay_single[0] = x[i];
		for(int l = nfilt-1; l > 0; l--){
			xDelay_single[l] = xDelay_single[l-1];
		}
     	xDelay_single[0] = x[i];



		for (j = 0; j < nfilt; j++)
		{
			y[i] += (b[j] * xDelay_single[j] - a[j] * yDelay_single[j]);
//			xil_printf("b=%ld,a=%ld,j=%d,y=%ld\r\n",b[j],a[j],j,y[i]);
		}
//		yDelay_single[12] = yDelay_single[11];
//		yDelay_single[11] = yDelay_single[10];
//		yDelay_single[10] = yDelay_single[9];
//		yDelay_single[9] = yDelay_single[8];
//		yDelay_single[8] = yDelay_single[7];
//		yDelay_single[7] = yDelay_single[6];
//		yDelay_single[6] = yDelay_single[5];
//		yDelay_single[5] = yDelay_single[4];
//		yDelay_single[4] = yDelay_single[3];
//		yDelay_single[3] = yDelay_single[2];
//		yDelay_single[2] = yDelay_single[1];
//		yDelay_single[1] = y[i];
		for(int m = nfilt-1; m > 1; m--){
			yDelay_single[m] = yDelay_single[m-1];
		}
     	yDelay_single[1] = y[i];




	}


}

//cd D:/studydata/chengdu/PL_DMA_PS/data


void filter_all(double* inaddr, double* outaddr){
	int data_len = 1024;
	double num;

	//分配地址
	double* input_data = (double*) inaddr;				//为中间变量申请储存地址
	//mrd -bin -file input.bin 0x001239f0 2048
	static double mid_data[1024];
	static double multfilter_data[1024];
	//mrd -bin -file multfilter.bin 0x00114228 2048
	static double sqr_data[1024];
	//mrd -bin -file sqr.bin 0x00116228 2048
	static double singlefilter_data[1024];
	//mrd -bin -file singlefilter.bin 0x00118228 2048
	static double sqrt_data[1024];
	//mrd -bin -file sqrt.bin 0x0011a228 2048
	static double div_data[1024];
	//mrd -bin -file div.bin 0x0011c228 2048
	static double mult_data[1024];//乘法
	//mrd -bin -file mult.bin 0x0011e228 2048
	//mrd -bin -file output.bin 0x001219f0 2048


	//-----------进行带通滤波-------------
	for (int i = 0; i < data_len ; i++){
		mid_data[i] = input_data[i];
		for(int indexStage = 0 ; indexStage < numStage ; indexStage++){
			multfilter_data[i] = filter_double(mid_data[i],DEN_mult,NUM_mult,indexStage);
			mid_data[i] = multfilter_data[i];
		}
	//----------平方----------

		sqr_data[i] = multfilter_data[i]*multfilter_data[i];
	}
	//----------低通----------
	filter_single_use(sqr_data, singlefilter_data);
	for(int l = 0; l < data_len;l++){	//防止滤波器瞬态响应产生的负值对后续开根号的影响
		if(singlefilter_data[l] > 0){
			num = singlefilter_data[l];
		}
		else
			singlefilter_data[l] = num;
	}
	//----------平方根、除法、乘法----------
	for(int j = 0; j < data_len; j++){
		sqrt_data[j] = sqrt(singlefilter_data[j]);
		div_data[j] = k/sqrt_data[j];
		mult_data[j] = div_data[j]*multfilter_data[j];
	}

//    double* ddr_buffer_temp = (double*)outaddr;
    for (int i = 0; i < data_len; i++) {
    	outaddr[i] = mult_data[i];
    }

}



数据可视化

(1)connect    【建立连接】

(2)target        【查看可连接目标】

(3)target 2     【连接到目标2】

(4)cd 文件存储路径    【进入到指定目录,生成文件会保存在该目录下,注意路径分隔符用左斜杠】

(5)mrd -bin -file filename.bin startaddr length     【通过该指令拷贝数据并保存在步骤(4)目录中,其中filename为文件名,必须用.bin为后缀,startaddr为拷贝的起始地址,length为拷贝的长度,单位感觉怪怪的,好像是length = data_num*data_len/32 = 1024*64/32

 在matlab中运行上述代码,读取bin文件数据。

 使用plot函数绘图。


 

测试

第一帧由于滤波器初始化,刚开始会导致波形的不稳定,但之后的帧滤波就不会产生有这个问题。

采用单步调试对所有滤波步骤进行测试

	while(1) //滤波器代码简单测试
	{
		frame++;
		for (i = 0; i < data_len; ++i)
		{
			datain[i] = 0.5 * (sin(2 * PI * 200 * (frame*data_len + i) / fs) + cos(2 * PI * 5000 * (frame*data_len + i) / fs + PI / 4));
		}

//		filter_single_use(datain, dataout);
		filter_all(datain, dataout);
	}

测试1

采样频率为31.25k,产生的200Hz和5000Hz正弦波叠加图样为:

 采样频率为31.25k。

带通滤波

平方

低通滤波

平方根

除法

乘法

测试2

 采样频率为31.25k,产生的20Hz和5000Hz正弦波叠加图样为:

带通滤波

平方

低通滤波

平方根

除法

乘法

总结

可以看出滤波器功能完美实现。

坑:

1.

分配长串且反复调用的数据地址时时尽量采用静态变量,以保证读取数据的稳定性,之前采用malloc函数分配临时地址或者直接使用double xxx[1024]时都会出现问题。

malloc经常出现返回NULL的情况(分配地址失败

double xxx[1024]则有时候会覆盖其他地址的数据,不知道出现原因,多次重新编译运行也无法解决,采用静态地址后解决。

2.

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值