基于matlab和CCS3.3的Fir滤波器仿真的设计与实现

在第一次的时候已经给出步骤大家搭建一个可以运行仿真的helloworld工程,趁着自己还熟悉操作,基于课程的要求一开始先在matlab上实现了一个Fir滤波器,需要同样的要求在CCS上仿真实现,于是就各种看资料,才能够逐渐搭建起来,其中遇到很多问题,不好解决,有些解决了在此分享出来。

第一步:产生输入信号

一开始还是先建立工程,C文件,cmd文件,还有库文件都添加到工程中。程序里主要是产生不同频率的正弦波,存入到一个数组中,大小为1024
在这里插入图片描述在这里插入图片描述
在这里插入图片描述
进行编译一下会发现有两个警告在这里插入图片描述
这是因为这两个段的大小在工程中大小不足,需要重新定义一下
在这里插入图片描述
在这里插入图片描述
修改好再次编译便没有警告了,然后下载程序,点击运行,看到有helloworld输出说明程序在跑,接着要查看波形
在这里插入图片描述
按照图片给出的修改数据,依次选择FFT频谱,开始地址为输入数组名称,因为输入的数组大小是1024,所以两个size大小要设置为1024,FFT阶数为12,数据类型为16位的有符号整形,这跟matlab输出的滤波系数也是16位有符号整形是相关的,最后一个是采样频率,程序已经设置为4096,这跟FFT阶数也有关,2的12次方是4096,所以FFT阶数为12在这里插入图片描述
点击OK就可以看到输入信号的频谱了,这里一共产生10个不同频率,幅度一样的信号,50-2000Hz,第一步产生输入信号搞定
在这里插入图片描述

第二步:产生滤波系数

利用matlab的fdatool滤波器工具可以非常方便的产生不同滤波器的不同系数,在matlab的命令行输入fdatool即可打开设计工具,详细的使用大家可以摸索,这里我们只是设置需要用到的
在这里插入图片描述
设置好参数后记得点击生成,从波形图可以很直观的看出滤波的效果,接着要把生成的滤波系数导出来,加载到CCS中。在这里插入图片描述
在这里插入图片描述
点击generate后保存头文件到工程所在的文件夹中,打开文件,把那个滤波系数的数组复制到程序里头
在这里插入图片描述

第三步:使用fir函数进行滤波

在使用fir函数之前首先要把相关的头文件和一些库文件加入到工程中,在如图的安装路径下找打这个头文件和一个库文件,复制到工程所在的文件夹
在这里插入图片描述
接着在工程右键打开build option选项里把头文件的路径加进去即可,最后还要把54xdsp.lib这个库文件导入工程的library中,不然会有报错
在这里插入图片描述
接着编写C文件的程序和cmd文件,下面给出编写完成后的程序

#include <stdio.h>
#include <math.h>
#include "dsplib.h"
#define pi 3.1415926
//采样频率,单位Hz 
int fs=4096;

//产生正弦波频率,单位为Hz
int f1=50,f2=100,f3=200,f4=500,f5=800,f6=1000,f7=1200,f8=1500,f9=1800,f10=2000;

//定义信号角频率
#define w1 	2*pi*f1/fs
#define w2 	2*pi*f2/fs
#define w3 	2*pi*f3/fs
#define w4 	2*pi*f4/fs
#define w5 	2*pi*f5/fs
#define w6 	2*pi*f6/fs
#define w7 	2*pi*f7/fs
#define w8 	2*pi*f8/fs	
#define w9 	2*pi*f9/fs
#define w10 2*pi*f10/fs

//输入波形数组大小
DATA In[1024];

/*------------等波纹设计法(Equiripple),阶数64,通带幅值衰减 Wpass=1dB,阻带幅值衰减 Wstop1=80dB---------------*/
/*通带频率 Fpass=100Hz,截止频率 Fstop=150Hz,采样频率 Fs=4096Hz*/
#pragma DATA_SECTION(lowpass,".lowpass")//定义一个数据段,需要在cmd文件中有相应的段定义
DATA lowpass[64] = { 
     -129,      4,     11,     24,     43,     67,     98,    136,    180,
      232,    291,    357,    430,    510,    596,    686,    782,    880,
      981,   1083,   1185,   1285,   1381,   1474,   1560,   1638,   1708,
     1769,   1818,   1856,   1882,   1895,   1895,   1882,   1856,   1818,
     1769,   1708,   1638,   1560,   1474,   1381,   1285,   1185,   1083,
      981,    880,    782,    686,    596,    510,    430,    357,    291,
      232,    180,    136,     98,     67,     43,     24,     11,      4,
     -129
};

/*------------------------------------------------------------------------------------------------------*/

/*低通滤波数据缓存*/
#pragma DATA_SECTION(buf1,".buffer1")//定义一个数据段,需要在cmd文件中有相应的段定义
DATA buf1[64] ;
DATA  *buf1ptr = &buf1[0];

DATA ff1[1024];//低通滤波输出数组


void main() 
{
   	int i;
 	printf("HelloWorld!\n");
	for(i=0;i<1024;i++)								//产生波形
		In[i]=1024*sin(w1*i)+1024*sin(w2*i)+1024*sin(w3*i)+1024*sin(w4*i)+1024*sin(w5*i)+1024*sin(w6*i)+1024*sin(w7*i)+1024*sin(w8*i)+1024*sin(w9*i)+1024*sin(w10*i);
	/*fir(DATA *x, DATA *h, DATA *r,DATA **d, ushort nh, ushort nx);
    *x:待滤波信号输入         
    *h:滤波系数,即一个数组
    *r:滤波输出
    *d:滤波输出缓存
    *nh:滤波器的阶数 
    *nx:待滤波信号输入的大小,即数组的大小 
	*/
	fir(In, lowpass, ff1, &buf1ptr, 64, 1024);		//	 调用函数,低通滤波
	while(1);	
}
MEMORY {
   PAGE 0:   VECT:      	origin = 0x80,         len = 0x80
   PAGE 0:   PROG:      	origin = 0x100,        len = 0x3f00  
   PAGE 1:   DATA:      	origin = 0x4000,       len = 0x3c00   
   PAGE 1:   f1aDATA:    	origin = 0x8000,       len = 0x80
   PAGE 1:   f1bDATA:    	origin = 0x8080,       len = 0x80 
} /* MEMORY */

SECTIONS {
   .text    > PROG PAGE 0               /* code                     */
   .switch  > PROG PAGE 0               /* switch table info        */
   .cinit   > PROG PAGE 0 
   .vectors > VECT PAGE 0                /* interrupt vectors         */
   
   .cio     > DATA PAGE 1               /* C I/O                     */  
   .data    > DATA PAGE 1       /* initialized data          */
   .bss     > DATA PAGE 1       /* global & static variables */
   .const   > DATA PAGE 1               /* constant data             */
   .sysmem  > DATA PAGE 1               /* heap                      */
   .stack   > DATA PAGE 1               /* stack                     */ 
   .buffer1:  {} align =64,  load = f1aDATA PAGE 1   
   .lowpass:  {} align =64,  load = f1bDATA PAGE 1      
}   /*SECTIONS */

由于在程序中定义了数据段,所以要在cmd文件中定义使用的数据段大小
在这里插入图片描述
再次编译一下,如果没有问题的话应该是没有错误和警告的,然后就可以查看频谱了,操作跟上面看输入信号频谱一样,需要修改的是开始的地址,改为滤波输出的数组的名称即可
在这里插入图片描述
正常的应该看到这样的波形,只剩下50和100Hz和一个波形,100Hz有明显的幅度衰减,其他信号都被滤除掉,这样说明滤波效果好,滤波起了作用
在这里插入图片描述
然后有时候看到的并不是预期的波形,具体原因我也不太清楚,一般操作我都是先清除一下工程,再全部重新编译,实在不行又关闭工程再打开,好像又可以比较稳定,比较玄学,有知道哪里有问题的小伙伴可以提出来,这个不知道怎么解决
在这里插入图片描述
好了,没有问题的话低通滤波的是可以做出来了,那高通和带通滤波的也顺带一起做了,同样的操作也是现在matlab那里利用工具箱生成滤波系数,然后导出系数复制到工程里,定义相关的数据段,输出缓存之类的
在这里插入图片描述
在这里插入图片描述
最后通过分别修改start address为ff2,ff3就能看到高通和带通后的频谱了
在这里插入图片描述
在这里插入图片描述
最后来个全家福,输入信号,低通,带通,高通后的频谱
在这里插入图片描述
至此,设计都全部完成,虽然这只是很小的一个设计,但是也花费了好几天的功夫,毕竟很不熟悉这方面的知识,网上的资料比较零散,只是讲了一部分,有些细节的都要靠自己错误中一步步摸索,最后再贴出完整的代码大家自己去下载验证

fir.c

#include <stdio.h>
#include <math.h>
#include "dsplib.h"
#define pi 3.1415926
//采样频率,单位Hz 
int fs=4096;

//产生正弦波频率,单位为Hz
int f1=50,f2=100,f3=200,f4=500,f5=800,f6=1000,f7=1200,f8=1500,f9=1800,f10=2000;

//定义信号角频率
#define w1 	2*pi*f1/fs
#define w2 	2*pi*f2/fs
#define w3 	2*pi*f3/fs
#define w4 	2*pi*f4/fs
#define w5 	2*pi*f5/fs
#define w6 	2*pi*f6/fs
#define w7 	2*pi*f7/fs
#define w8 	2*pi*f8/fs	
#define w9 	2*pi*f9/fs
#define w10 2*pi*f10/fs

//输入波形数组大小
DATA In[1024];

/*------------等波纹设计法(Equiripple),阶数64,通带幅值衰减 Wpass=1dB,阻带幅值衰减 Wstop1=80dB---------------*/
/*通带频率 Fpass=100Hz,截止频率 Fstop=150Hz,采样频率 Fs=4096Hz*/
#pragma DATA_SECTION(lowpass,".lowpass")//定义一个数据段,需要在cmd文件中有相应的段定义
DATA lowpass[64] = { 
     -129,      4,     11,     24,     43,     67,     98,    136,    180,
      232,    291,    357,    430,    510,    596,    686,    782,    880,
      981,   1083,   1185,   1285,   1381,   1474,   1560,   1638,   1708,
     1769,   1818,   1856,   1882,   1895,   1895,   1882,   1856,   1818,
     1769,   1708,   1638,   1560,   1474,   1381,   1285,   1185,   1083,
      981,    880,    782,    686,    596,    510,    430,    357,    291,
      232,    180,    136,     98,     67,     43,     24,     11,      4,
     -129
};

/*高通,通带频率 Fpass=1000Hz,截止频率 Fstop=1200Hz,采样频率 Fs=4096Hz*/
#pragma DATA_SECTION(highpass,".highpass")
DATA highpass[64] = {
      -12,      8,     45,   -116,    100,     25,   -101,     -4,    139,
      -52,   -164,    134,    164,   -239,   -122,    357,     26,   -472,
      138,    561,   -382,   -595,    717,    533,  -1164,   -313,   1786,
     -211,  -2821,   1614,   5882, -13572,  13572,  -5882,  -1614,   2821,
      211,  -1786,    313,   1164,   -533,   -717,    595,    382,   -561,
     -138,    472,    -26,   -357,    122,    239,   -164,   -134,    164,
       52,   -139,      4,    101,    -25,   -100,    116,    -45,     -8,
       12
};

/*带通,下阻带截止频率 Fstop1=600Hz,下阻带通带频率 Fpass1=700Hz,上阻带截止频率Fstop1=1500Hz,下阻带通带频率Fpass1=1600Hz,采样频率Fs=4096Hz*/
#pragma DATA_SECTION(bandpass,".bandpass")
DATA bandpass[64] = {
      195,   -159,   -658,    565,    898,   -866,   -522,    366,    -48,
      608,    133,   -765,     27,   -305,    272,   1009,   -463,   -170,
     -471,   -873,   1391,    490,     -5,    295,  -2602,     81,   1759,
      194,   4044,  -3928,  -9530,   9008,   9008,  -9530,  -3928,   4044,
      194,   1759,     81,  -2602,    295,     -5,    490,   1391,   -873,
     -471,   -170,   -463,   1009,    272,   -305,     27,   -765,    133,
      608,    -48,    366,   -522,   -866,    898,    565,   -658,   -159,
      195
};
/*------------------------------------------------------------------------------------------------------*/

/*低通滤波数据缓存*/
#pragma DATA_SECTION(buf1,".buffer1")//定义一个数据段,需要在cmd文件中有相应的段定义
DATA buf1[64] ;
DATA  *buf1ptr = &buf1[0];

/*高通滤波数据缓存*/
#pragma DATA_SECTION(buf2,".buffer2")//定义一个数据段,需要在cmd文件中有相应的段定义
DATA buf2[64] ;
DATA  *buf2ptr = &buf2[0];

/*带通滤波数据缓存*/
#pragma DATA_SECTION(buf3,".buffer3")//定义一个数据段,需要在cmd文件中有相应的段定义
DATA buf3[64] ;
DATA  *buf3ptr = &buf3[0];

DATA ff1[1024];//低通滤波输出数组
DATA ff2[1024];//高通滤波输出数组
DATA ff3[1024];//带通滤波输出数组

void main() 
{
   	int i;
 	printf("HelloWorld!\n");
	for(i=0;i<1024;i++)								//产生波形
		In[i]=1024*sin(w1*i)+1024*sin(w2*i)+1024*sin(w3*i)+1024*sin(w4*i)+1024*sin(w5*i)+1024*sin(w6*i)+1024*sin(w7*i)+1024*sin(w8*i)+1024*sin(w9*i)+1024*sin(w10*i);
	/*fir(DATA *x, DATA *h, DATA *r,DATA **d, ushort nh, ushort nx);
    *x:待滤波信号输入         
    *h:滤波系数,即一个数组
    *r:滤波输出
    *d:滤波输出缓存
    *nh:滤波器的阶数 
    *nx:待滤波信号输入的大小,即数组的大小 
	*/
	fir(In, lowpass, ff1, &buf1ptr, 64, 1024);		//	 调用函数,低通滤波
	fir(In, highpass,ff2, &buf2ptr, 64, 1024);		//	 调用函数,高通滤波
	fir(In, bandpass,ff3, &buf3ptr, 64, 1024);		//	 调用函数,带通滤波
	while(1);	
}

fir.cmd

MEMORY {
   PAGE 0:   VECT:      	origin = 0x80,         len = 0x80
   PAGE 0:   PROG:      	origin = 0x100,        len = 0x3f00  
   PAGE 1:   DATA:      	origin = 0x4000,       len = 0x3c00   
   PAGE 1:   f1aDATA:    	origin = 0x8000,       len = 0x80
   PAGE 1:   f1bDATA:    	origin = 0x8080,       len = 0x80
   PAGE 1:   f2aDATA:     	origin = 0x8100,       len = 0x80 
   PAGE 1:   f2bDATA:     	origin = 0x8180,       len = 0x80 
   PAGE 1:   f3aDATA:       origin = 0x8200,       len = 0x80
   PAGE 1:   f3bDATA:       origin = 0x8280,       len = 0x80    
} /* MEMORY */

SECTIONS {
   .text    > PROG PAGE 0               /* code                     */
   .switch  > PROG PAGE 0               /* switch table info        */
   .cinit   > PROG PAGE 0 
   .vectors > VECT PAGE 0                /* interrupt vectors         */
   
   .cio     > DATA PAGE 1               /* C I/O                     */  
   .data    > DATA PAGE 1       /* initialized data          */
   .bss     > DATA PAGE 1       /* global & static variables */
   .const   > DATA PAGE 1               /* constant data             */
   .sysmem  > DATA PAGE 1               /* heap                      */
   .stack   > DATA PAGE 1               /* stack                     */ 
   .buffer1:  {} align =64,  load = f1aDATA PAGE 1   
   .lowpass:  {} align =64,  load = f1bDATA PAGE 1 
   .buffer2:  {} align =64,  load = f2aDATA PAGE 1
   .highpass: {} align =64,  load = f2bDATA PAGE 1 
   .buffer3:  {} align =64,  load = f3aDATA PAGE 1           
   .bandpass: {} align =64,  load = f3bDATA PAGE 1       
}   /*SECTIONS */

给出代码链接大家可以自行下载尝试一下 https://wwe.lanzous.com/iv6qQkzlqwj

  • 24
    点赞
  • 171
    收藏
    觉得还不错? 一键收藏
  • 19
    评论
基于MATLAB与FPGA的FIR滤波器设计仿真是一种常用的数字信号处理方法。首先,我们可以使用MATLAB设计FIR滤波器的系数。通过指定滤波器的截止频率、滤波器类型和滤波器阶数等参数,MATLAB可以生成滤波器的系数。 接下来,我们可以使用MATLAB来进行FIR滤波器仿真。通过输入信号和滤波器系数,我们可以得到滤波后的输出信号。MATLAB提供了丰富的信号处理工具箱,可以方便地进行滤波器仿真和性能评估。 然后,我们可以将设计好的FIR滤波器用HDL Coder工具箱进行FPGA代码的生成。HDL Coder可以自动将MATLAB代码转换为适用于FPGA的硬件描述语言(如VHDL或Verilog)代码。通过使用FPGA开发工具,我们可以将生成的硬件描述语言代码下载到FPGA芯片中进行硬件实现。 最后,利用FPGA进行FIR滤波器的硬件实现。将输入信号传入FPGA芯片,并通过外部接口连接FPGA芯片与其他系统。FPGA会根据设计好的硬件描述语言代码进行滤波处理,并将滤波后的信号传递给输出接口。 综上所述,基于MATLAB与FPGA的FIR滤波器设计仿真可以实现高效的数字信号处理。MATLAB提供了强大的信号处理工具,可以方便地进行滤波器设计仿真。而使用FPGA进行硬件实现,则可以获得更高的实时性能和处理能力。这种方法在许多领域,如通信、音频处理和图像处理等,都得到广泛应用。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值