BB-World

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

0
阅读(138) 评论(0)


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

第一步:产生输入信号

一开始还是先建立工程,C文件,cmd文件,还有库文件都添加到工程中。程序里主要是产生不同频率的正弦波,存入到一个数组中,大小为1024

7.jpg

2.jpg

3.jpg

进行编译一下会发现有两个警告

4.jpg

这是因为这两个段的大小在工程中大小不足,需要重新定义一下

5.jpg

6.jpg

修改好再次编译便没有警告了,然后下载程序,点击运行,看到有helloworld输出说明程序在跑,接着要查看波形

8.jpg

按照图片给出的修改数据,依次选择FFT频谱,开始地址为输入数组名称,因为输入的数组大小是1024,所以两个size大小要设置为1024,FFT阶数为12,数据类型为16位的有符号整形,这跟matlab输出的滤波系数也是16位有符号整形是相关的,最后一个是采样频率,程序已经设置为4096,这跟FFT阶数也有关,2的12次方是4096,所以FFT阶数为12

9.jpg

点击OK就可以看到输入信号的频谱了,这里一共产生10个不同频率,幅度一样的信号,50-2000Hz,第一步产生输入信号搞定

10.jpg

第二步:产生滤波系数

利用matlab的fdatool滤波器工具可以非常方便的产生不同滤波器的不同系数,在matlab的命令行输入fdatool即可打开设计工具,详细的使用大家可以摸索,这里我们只是设置需要用到的11.jpg

设置好参数后记得点击生成,从波形图可以很直观的看出滤波的效果,接着要把生成的滤波系数导出来,加载到CCS中。

12.jpg

13.jpg

点击generate后保存头文件到工程所在的文件夹中,打开文件,把那个滤波系数的数组复制到程序里头

14.jpg

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

在使用fir函数之前首先要把相关的头文件和一些库文件加入到工程中,在如图的安装路径下找打这个头文件和一个库文件,复制到工程所在的文件夹

15.jpg

接着在工程右键打开build option选项里把头文件的路径加进去即可,最后还要把54xdsp.lib这个库文件导入工程的library中,不然会有报错

16.jpg

接着编写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);
}
EMORY {
   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文件中定义使用的数据段大小

18.jpg


再次编译一下,如果没有问题的话应该是没有错误和警告的,然后就可以查看频谱了,操作跟上面看输入信号频谱一样,需要修改的是开始的地址,改为滤波输出的数组的名称即可

19.jpg

正常的应该看到这样的波形,只剩下50和100Hz和一个波形,100Hz有明显的幅度衰减,其他信号都被滤除掉,这样说明滤波效果好,滤波起了作用

20.jpg

然后有时候看到的并不是预期的波形,具体原因我也不太清楚,一般操作我都是先清除一下工程,再全部重新编译,实在不行又关闭工程再打开,好像又可以比较稳定,比较玄学,有知道哪里有问题的小伙伴可以提出来,这个不知道怎么解决

17.jpg

好了,没有问题的话低通滤波的是可以做出来了,那高通和带通滤波的也顺带一起做了,同样的操作也是现在matlab那里利用工具箱生成滤波系数,然后导出系数复制到工程里,定义相关的数据段,输出缓存之类的

21.jpg

22.jpg

最后通过分别修改start address为ff2,ff3就能看到高通和带通后的频谱了

24.jpg

23.jpg

最后来个全家福,输入信号,低通,带通,高通后的频谱

25.jpg

至此,设计都全部完成,虽然这只是很小的一个设计,但是也花费了好几天的功夫,毕竟很不熟悉这方面的知识,网上的资料比较零散,只是讲了一部分,有些细节的都要靠自己错误中一步步摸索,最后再贴出完整的代码大家自己去下载验证

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 */