在第一次的时候已经给出步骤大家搭建一个可以运行仿真的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函数之前首先要把相关的头文件和一些库文件加入到工程中,在如图的安装路径下找打这个头文件和一个库文件,复制到工程所在的文件夹
接着在工程右键打开build option选项里把头文件的路径加进去即可,最后还要把54xdsp.lib这个库文件导入工程的library中,不然会有报错
接着编写C文件的程序和cmd文件,下面给出编写完成后的程序
#include
#include
#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
#include
#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 */