当前位置:文档之家› 数字信号处理的实现

数字信号处理的实现

数字信号处理的实现
数字信号处理的实现

4 数字信号处理的软件设计实现

4.1 程序设计概述

前两章介绍了信号采集和处理所涉及的软硬件开发环境和关键技术,本章将采用C语言对数字信号处理算法进行编程实现,设计中使用Keil software公司开发的单片机C语言软件开发系统Keil C51来进行编程开发,下面将做具体介绍。

4.1.1 Keil集成开发环境简介

Keil开发环境是专门为51单片机设计的C语言开发环境,可在Windows系统中运行,它将编译和仿真集成在了一起,通常称为μVision。Keil C51提供了C编译器、宏汇编、连接器、库管理和一个功能强大的仿真调试器,支持C语言与汇编语言的混合编程,且支持在线调试。Keil系统的各种功能模块的结构如图4.1 所示。

图4.1 Keil C51系统工具包结构

Keil C51编译器是在标准C编译器的基础上进行改进后得到,与标准C相比,特点是根据单片机一些特点进行了优化,如存储组织、库函数优化等。例如,我们将会用到的标准输入输出函数的输出设备被改变为串口而非显示器。经过优化的编译器生成的目标代码效率非常高,多数语句生成的汇编代码很紧凑,容易理解,在开发大型软件时更能体现高级语言的优势。这也是设计中采用这个开发环境的重要原因。另外,Keil

C51的仿真功能强大,配合单片机提供的JTAG接口,可方便地进行在线调试使开发更为简单[6]。

4.1.2 程序整体结构

本课题将实现信号的采集和处理程序设计,其中信号处理为主要内容,需着重实现,而在信号处理的诸多算法中,希望能够实现快速傅里叶变换算法和FIR滤波器算法。据此,我们可以设计出程序的流程如图4.2所示。

图4. 2 程序总体结构

程序实现过程:假设以一个受噪声污染的正弦信号作为输入信号,则经过信号采集后(可以设定采样频率),离散信号值被存在相应的存储器中;之后对采集到的信号值进行FFT变换;将变换结果输出并进行频谱分析,得出有用信号频率值与噪声频率值;设定滤波器截止频率等参数;进行滤波运算;得到处理后信号并输出。对比输出信号与输入信号,则可以检验出滤波效果。在程序设计中,为了更容易进行程序性能的分析,希望输入的含噪声信号特点突出,因此可以人为地产生一个测

试信号而不是采用A/D采集到的信号。

4.2 系统的初始化程序设计

在进行程序设计之初,需要先对单片机系统进行初始化以使单片机可以运行,这是进行其他开发的基础。在进行初始化时,需要考虑单片机系统的基本部件的设定,如系统时钟、端口等,只有正确设定这些系统基础模块,才能使单片机正常工作。下面侧重介绍单片机系统的初始化和本设计中用到的主要模块的初始化。

4.2.1 端口和时钟的初始化

端口初始化:端口初始化的工作主要是根据系统可能用到的功能模块和外部设备来为各个设备分配相应的引脚。分配时需根据交叉开关译码器的优先级规则配置交叉开关配置寄存器。本课题中需要用到的功能模块主要有:UART0、A/D、定时器,其中只有UART0需要分配I/O端口,因此只需将XBR0的UART0EN位置为1即可。另外,需要设置XBR2的XBARE 位以使能交叉开关。经分配,UART0的输出引脚TX0为P0.0,可设置此引脚为推挽方式,即置P0MDOUT的最低位为1。

时钟初始化:此系统的特点决定我们需要选择较高的时钟频率,因此我们将使用外部晶体振荡时钟发生。这里十分重要的一点是:系统上电后首先选择内部时钟,而外部时钟建立需要一定的时间,因此必须要等外部时钟建立稳定后,才能取消内部时钟,否则将造成时钟丢失。

外部振荡器的控制寄存器为OSCXCN,需要对此寄存器进行合适的设置以使系统正常工作[2][3]。OSCXCN寄存器的定义为:

最高位表示晶体振荡器是否稳定,可以根据此位的值判断是否可以取消内部振荡器。第4-6位决定外部振荡器的选择,110时为晶体振荡器。低3位确定振荡器频率,根据外部晶体频率选择为111B。综上所述,OSCXCN寄存器的值为0x67。

当检测到OSCXCN寄存器的最高位为1时,表示外部振荡器已经稳定,此时可以取消内部振荡器,设置内部振荡器控制寄存器OSCICN的系统时钟选择位为1,同时使能时钟丢失检测。因此,OSCICN寄存器的值应为

0x88。

4.2.2 定时器的初始化

定时器3:对于T3,主要是对其控制寄存器和计数初值的确定。其中TMR3CN控制寄存器主要是对定时器3采用的时钟进行设定。本设计中系统时钟频率已经很高,因此可直接使用系统时钟,设定TMR3CN=

0x02。

重载值的选择需根据所需的ADC采样率计算得到。在满足采样定理的前提下,假设ADC的采样率为SAMPLE_RATE,则定时器重载值寄存器中的

值应为:

TMR3RL= -SYSCLK/SAMPLE_RATE (4.1)

这实际上是比较显而易见的,重载值的意义即每经过这一数值的计数时间,产生一次中断。这样,在一秒钟时间内,系统产生了SAMPLE_RATE 次中断。而且由于C8051F系列单片机的计数器是向上加计数的,因此重装入值取负值。

定时器1:T1用于产生UART0的波特率。需要对方式寄存器TMOD进行设置,选择为方式2工作,因为只有通过自动重载才能作为波特率的发生器来工作。通过CKCON寄存器选择T1的时钟为系统时钟。另外,需要注意电源控制寄存器PCON中的SMOD0位,它是UART0 波特率加倍使能位,通常我们可以使之为1,即波特率加倍[2]。

这样,我们就可以计算T1的自动重载值了。根据公式:

波特率=(2SMOD0/32)*SYSCLK/(256-TH1)(4.2)

其中,波特率一般设定为115200。这样即可计算出TH1的值(同样应该取负值),

TH1= -(SYSCLK/BAUDRATE/16) (4.3)

再开启定时器1即可完成。开启定时器可通过设定定时器控制寄存器(TCON)的TR1位。

4.3 数据信号产生程序设计

本课题需完成的工作是对某一外部电路的信号进行采集并对之以相应的信号处理算法进行时频变换、分析和滤波。系统实现的第一步就是进行信号的采集。对外部电路信号进行采集需要进行A/D转换,这就需要相应的AD采集程序实现。但是,外部电路信号不方便电路设计且未必具有合适的噪声特点。为更方便的对信号处理算法进行研究,我们不妨人工产生一个特点突出的信号进行分析,既方便设计又不失一般性。

4.3.1 A/D采集程序设计

对于ADC模块的设计,主要分成两步进行,分别为ADC的初始化和中断程序设计。初始化完成ADC模块的配置,而中断程序进行对采集到数据的处理和存取。我们可以以ADC0为例来进行设计。

ADC0的初始化:ADC的初始化主要是对ADC0CN控制寄存器的设置[2] [3]。

在编程中,为方便选择合适的采样频率,设定ADC的启动方式为定时器3溢出启动,这样就可以通过设定T3的计数初值来确定采样率。启动方式是由ADC0CN中的 ADC0启动转换方式位AD0CM1和AD0CM0确定的,值为01。另外可选择右对齐,置AD0LJST为1。其它位如使能位

(AD0EN)、中断标志(AD0INT)、跟踪方式位(AD0TM)、忙标志位

(AD0BUSY)等均可取值0。这样,ADC0CN控制寄存器的初值可设置为0x04。

对于ADC的参考电压,一般可以选择为内部电压基准2.4V,即设置寄存器REF0CN的值为0x07。但是,当输入信号不同时,需要根据不同的输入信号进行相应得设置。

另外,还需要确定ADC0的转换频率和增益,它们均是通过ADC0CF寄存器进行设定。寄存器的低3位表示增益值,设增益为2,即取值001。转换频率可以取最大值2.5MHz,通过公式ADC0SC=SYSCLK/2.5MHz-1得到寄存器高5位的值。

ADC0的中断程序:当AD0BUSY位由高电平(正在进行转换)变为低电平(转换结束)时,中断标志位AD0INT被置1,进入ADC0中断程序。中断程序中,首先须清除中断标志位,以使下次中断可以发生;之后,进行相应的数据处理程序。当获得ADC0寄存器中的数值后,通过公式:转换代码=Vin*Gain/VREF*212,计算Vin的值,但是由于本单片机不支持浮点运算,因此计算出的数值会存在一定的误差,以整数形式保存。当采集得到128点信号数据时,即可对此数据序列进行相应的信号处理,如FFT变换等。

4.3.2 测试用染噪声信号的产生

为了能够更好的验证FFT变换程序和FIR滤波器程序的性能,我们需要一个特点较为突出的信号。根据需要实现的功能,此信号最好为一个受到噪声干扰的信号,且具有不同的频率分量,这样才能检验频谱分析程序的正确性并进行滤波。但是,如果采用外部电路输入信号然后进行采样的话,难以找到合适的信号。假设采用信号发生器信号作为输入信号,一般波形是经过处理的,不存在噪声或噪声较低,这样即使滤波也难以看出效果。因此,可以选择人为地构造一个信号来作为测试信号。虽然这样没有通过ADC来采集信号,但是原理与采样相同。而只要信号处理算法正确,应用时只需用AD采集程序对待处理信号进行采样即可。

为测试效果明显又不失一般性,考虑构造一个双频正弦信号,一低频一高频,另外再叠加高斯噪声,这样既可验证频谱分析又可验证滤波程序。为构造信号,采用MATLAB软件进行设计,其强大的计算能力不仅可以轻松获得正弦数值,还可以得到高斯噪声信号。方法是等间隔的采样正弦波,在一个周期内将之分为256份,然后产生一个高斯噪声信号,同样以256点采样,将两信号叠加,最后再进行放大、平移等运算,将输出结果存储到正弦表即可。假设正弦信号的频率分别为100Hz 和500Hz,这样采样频率可设为1000Hz。但是考虑128点FFT变换程序,将采样频率设为1280Hz,这样可避免单片机的浮点运算[7]。

MATLAB产生波形程序如下:

t=1:128;

f1=100; f2=500;

fs=1280;

x1=sin(2*pi*f1*t/fs); %低频信号

subplot(3,1,1); plot(x1);

x2=sin(2*pi*f2*t/fs); %高频信号

subplot(3,1,2); plot(x2);

x=x1+x2+2; %叠加信号,并平移去掉负值

subplot(3,1,3); plot(x);

y=awgn(x,10); plot(y); %叠加高斯白噪声,信噪比10dB

图4.3 双频信号波形

图4.4 叠加噪声后信号波形

产生的波形如图4.3和图4.4所示,图4.3中第一个波形为100Hz信号,第二个波形为500Hz信号,而最后一个波形为它们叠加后的信号。图4.4为在此基础上叠加了高斯白噪声后的波形,信噪比为10dB,对比可发现存在一定失真。

4.4 单片机与PC机通信程序设计

在多数的应用场合都需要上位机与下位机有一定的信息交互,以便更好地对系统进行控制。因此,需要进行单片机与PC机通信的程序设计。在单片机中,普遍使用的通信接口为UART接口,通过编程可以方便地进行同步或异步通信。通过第二章的介绍,我们对UART接口已经有了一定的了解,下面将具体说明对其的控制和编程方法。

4.4.1 UART0的初始化

选取UART0的工作方式为方式1,为8位异步方式,采用定时器1的溢出频率作为波特率发生的时钟。在UART的初始化中,需要通过设定其控制寄存器(SCON0)来设定其工作方式。SCON0的高两位指示其工作方式,选择方式1时应为01。

位4决定是否允许接收,允许时置位为1。据此,可设定SCON0= 0x50。此外,初始化需要设定TI0和RI0的中断允许。此时完成初始化,可以开始发送和接收。

4.4.2 UART0中断程序设计

发送程序:在讨论UART的工作过程时提到过,将数据写入到缓存器SBUF0时将开始发送,而发送结束时将会置位TI0。利用这一特点,程序

中可以不采用中断方式,而采用查询的方式来进行发送程序的设计[2] [3][6][9]。

首先将要发送的数据写入到SBUF0中,这时UART将自动开始发送,此时不断查询TI0位的状态,当TI0仍然为0时,说明发送未结束,继续查询;当TI0为1时,发送结束,可以进行下一步操作。此时十分重要的一点是:TI0必须要手工清零,否则无法进行下次发送。这样可以写出简单的发送单个字节的UART发送程序如下:

void Send_Char(char c) //发送单个字符

{ SBUF0 = c; //送入缓冲区

while(TI0 == 0); //等待发送完毕

TI0 = 0;} //手动清零

当需要发送字符串时,可以将以上程序进行扩展,增加一重循环。但是,当我们利用KEIL环境来开发的时候,更为简便的方式是使用标准输入输出函数printf()。KEIL环境为简化单片机的开发,已经将此函数的输出流定义为串口而非屏幕。通过此函数,可以以多种格式输出各种类型的数据,用法与标准C语言开发中基本相同。

接收程序:接收时,需要RI0位为0。满足此条件时才会将接收到的数据放到接收寄存器SBUF0中,并将RI0置位。此时,可以通过查询RI0位的状态来确定接收是否完成。当RI0为0时,表明接收未完成,需要继续等待并不断查询。当RI0为1时,表明接收已完成,可以从SBUF0中获取数据存入相应的存储单元中。此时,同样需要将RI0位手动清零,否则将无法进行下一位的接收。根据这一过程,可以写出接收单个字符的程序:

Void Rec_Char(char c) //接收单个字符

{ while(!RI0); //等待接收完毕

if(RI0)

{ RI0=0; //手动清零

c=SBUF0;} //获取接收字符

}

当需要接收多个字节时,同样可以将上述程序加入循环中,以循环次数决定接收字符的位数。例如,若需要接收一个滤波器截止频率设定的数据,则可以设定此数据的输入方式为4位数据,不足4位数的在高位补零。这样只需将上述单字符接收程序循环4次即可实现。

4.5 频谱分析程序设计

利用FFT变换进行频谱分析是本课题最重要的一个功能,也是最难以实现的部分。上一章中已经详细地介绍了FFT变换的原理和重要问题,在

本节中将对具体程序实现的方法进行说明。

4.5.1 MATLAB与C语言混合编程研究

当进行数字信号处理算法的设计时,我们首先想到的软件一定是MATLAB,MATLAB拥有极强大的数学计算功能和信号处理专用函数的实现,往往可以用几个MATLAB函数实现C语言的大量代码编写。如果可以利用MATLAB设计出频谱分析程序再将其移植到C语言平台,将使开发过程大大简化,甚至可以忽略FFT算法的实现原理而直接进行计算和频谱分析。

MATLAB通过其内部接口,利用MATLAB编译器可以将MATLAB程序转换成C/C++代码,或者编译成可以在其他编程语言中使用的DLL文件,甚至可以直接把MATLAB代码编译成Windows可执行文件。另外,MATLAB也提供了其它方式的混合编程方法,如MAT文件、MEX语言等。这是一种十分实用的功能,利用这些接口可以在不同的开发环境中使用MATLAB 程序,进行复杂的数学计算[8]。

但是,这种方法虽然可以让数字信号处理算法实现十分容易,却不适合本课题的应用。MATLAB提供的这些接口主要是面对计算机程序的开发,对单片机环境并不支持。KEIL开发环境虽然也是C语言环境,但是为了单片机的应用做了相应的优化和改动。例如,C8051F020单片机不支持浮点运算,无法使用正弦、余弦函数等,这些特点使得通过MATLAB编译器转换的C语言程序并不适合在单片机中运行。因此,虽然此种方法十分实用,但是需要在计算机软件的开发中才能发挥其优势,在本课题中难以实现。

4.5.2 FFT算法程序设计

FFT算法的程序中,重点是对原理分析中的几个关键问题的解决。码位倒置、蝶形单元、分组和分级计算、确定Wr因子,只要将这些问题逐个解决,FFT算法也基本实现了,下面将详细介绍程序的设计过程[1] [10]。

码位倒置:在原理分析中已经说明,在进行时间抽取基-2FFT计算时,输入信号需要进行时间抽取,即奇偶分组,因此会产生码位倒置。倒置的规律为将序号以二进制形式表示;将二进制码反向;再转换为十进制值即为倒置后结果。据此可设计程序实现过程为:

1.将序号转为二进制表示。在计算机中,数值本身就是以二进制表示的,因此可以将序号的数值分别取每一位二进制数存储在不同的变量中,即将每位都表示了出来。

2.将存储每一位数值的变量反向乘以权重,即得到了反向的十进制值。

3.最后将信号值存储在倒置后新序号处的存储单元中即可。

蝶形单元:蝶形单元是FFT算法的基本单位,可以用一下算式表示:

X_1 (k)=X_0 (k)+W_N^r X(k+b)

X_1 (k+b)=X_0 (k)-W_N^r X(k+b) (4.5)

其中b是蝶形单元中每两个输入信号间的序号间隔,与蝶形单元所处的

级有关,当从1级开始计算时,b=2^(m-1)。对于W_N^r因子,由于其为

复数,在计算中可以将实部与虚部分别进行计算。我们知道:

W_N^r=?^(-j 2πr/N)=cos?(2πr/N)?-jsin(2πr/N) (4.6)

这样可将W_N^r因子以正弦和余弦函数值来表示,使计算更为简便。单

片机中不支持正弦函数计算,因此须将正弦值和余弦值提前计算出来存

储在程序中。蝶形单元的计算程序为:

TR = FftReal[k]; TI = FftImage[k]; TEMP = FftReal[k+b];

FftReal[k] = FftReal[k] + (FftReal[k+b]*cos_tab[r]) + (FftImage[k+b]*sin_tab[r]);

FftImage[k] = FftImage[k] - (FftReal[k+b]*sin_tab[r]) + (FftImage[k+b]*cos_tab[r]);

FftReal[k+b] = TR - (FftReal[k+b]*cos_tab[r]) - (FftImage[k+b]*sin_tab[r]); FftImage[k+b] = TI + (TEMP*sin_tab[r]) - (FftImage[k+b]*cos_tab[r]);

其中FftReal表示信号实部值,FftImage表示虚部值,cos_tab 和sin_tab

分别存储了cos()和sin()的值。注意到在计算中采用了同址运算的方法,

这也是FFT算法的一个优点,可以节省存储单元,但是也需要注意变量

的临时保持,防止丢失。另外,程序中存在另一个变量r,这实际上就

是W_N^r因子中的r值。W_N^r因子的确定是和所处级数和所处组数都有

关系的,下面将说明分级和分组的方法以及W_N^r因子的确定。

分级和分组:原理分析中已经讲过,FFT计算可分级进行,每一级中将

采用一组W_N^r因子值。假设为第m级,则W_N^r因子为:

W_(2^m)^r=W_N^(r×2^(L-m) ),r=0,1,2…,2^(m-1)-1 (4.7)

其中N为FFT点数,L为总的级数。由此式可以看出,W_N^r因子可能的

取值是有限的,当我们进行128点FFT时,最高的级数为7,当进行第7级

计算时,W_N^r因子取值最多,r=0,1,2…,63,可根据此时取值计算其正

弦表,而不必计算全部正弦值,以节省存储空间。而每一级中又可分为

N/2m组,每一组的参数是相同的,即采用相同的W_N^r因子。当每一

级中的各个W_N^r因子均对每一组计算一遍蝶形单元时,这一级的计算

完成。

因此,使级数作为最外层循环,并确定每一级的蝶形单元间隔b;次一

层循环确定此一级的W_N^r因子值;最内层循环进行分组,以每一个

W_N^r因子对同一组内的各值进行蝶形单元的计算。这样循环完毕时则

完成全部信号的计算。对于本设计的128点FFT计算,可知级数为7级,

则根据上述分析得出的循环程序为:

for( i=1; i<=7; i++) // 最外层循环,确定级数

{ b=1;

b <<= (i-1); // 确定间隔b= 2^(i-1)

for( j=0; j<=b-1; j++) // 内层循环确定 W_N^r因子

{ r=1;

r <<= (7-i);

r = r*j;

for( k=j; k

{

TR = FftReal[k]; TI = FftImage[k]; TEMP = FftReal[k+b];

FftReal[k] = FftReal[k] + (FftReal[k+b]*cos_tab[r]) + (FftImage[k+b]*sin_tab[r]);

FftImage[k] = FftImage[k] - (FftReal[k+b]*sin_tab[r]) + (FftImage[k+b]*cos_tab[r]);

FftReal[k+b] = TR - (FftReal[k+b]*cos_tab[r]) - (FftImage[k+b]*sin_tab[r]);

FftImage[k+b] = TI + (TEMP*sin_tab[r]) - (FftImage[k+b]*cos_tab[r]); }

}

}

至此,FFT算法已经计算完毕,计算结果存储在了之前存储信号值的存

储单元中,可以取得计算结果进行分析。

FFT算法的流程图如图4.5所示:

图4.5 FFT算法流程图

4.5.3 频谱分析程序设计

取得FFT计算结果后,需要对计算结果进行频谱分析处理,以得到信号

的特征。对信号的频域分析可以分为多种,在本课题中只计算信号的幅

度谱,得到信号的频率特征,为后续滤波做准备。

计算信号的幅度谱实际上十分简单,程序运行得到的FFT计算结果为信号的复频谱,只需在此基础上计算相应的幅度值即可。真正重要的一步是计算出各个谱线所对应的频率值。根据频率分辨率的概念,Δf=

f_s/N,程序中即可表示为:

Df=SAMPLE_RATE/FFT_NUM;

其中SAMPLE_RATE表示采样率,而FFT_NUM表示FFT点数[5][10]。

对应于每个频率值,都可以计算出信号的幅度,可以将复值的频谱取绝对值实现。在程序中,通过平方和运算实现,由于单片机中不适合进行开方运算,因此幅度值与实际值存在差别。

FftReal[i]=FftReal[i]*FftReal[i]+FftImage[i]*FftImage[i];

此处仍然可以采用同址运算以节省存储空间。

当计算出幅度谱时,可以用串口将计算结果输出到计算机中,以方便观察其频谱特性。如果可以设计一个显示屏将此频谱以图形的方式进行显示,则更好地进行观察和分析。本课题中未进行此功能的设计,因此需观察计算结果的数值形式来得到其频谱特性的分析结果。当利用串口调试助手观察时,可以得到类似于图4.6所示的结果,虽然这样没有图像方式直接,但是也能够清楚地看出其频率特性。

图4.6 频谱结果显示

4.6 FIR滤波器程序设计

进行FIR滤波器设计的程序可以分为3步进行[1][5][11]:

1. 确定滤波类型,并输入截止频率值;

2. 根据类型和截止频率计算滤波器系数h(n);

3. 进行卷积运算,得到滤波输出。

滤波类型和截止频率的值可以在程序中获取,可根据FFT频谱分析的结果输入合适的值,在本课题中,将进行低通和高通滤波的设计,而截止频率则是根据测试信号的特点选取的,低通滤器截止频率设为100Hz,高通滤器截止频率设为500Hz。根据此截止频率分别计算出相应的滤波器系数,计算方法在滤波器原理分析时已经说明,此处不再赘述。

此处未在程序中进行滤波器系数的计算,主要是考虑到单片机的浮点运算能力不足,这也是本程序存在缺陷的地方,可以进行进一步优化程序以能在程序中计算,这样将只需输入相应的截止频率即可。利用MATLAB计算滤波器系数的程序为:

N=29; %阶数

fc=100; %截止频率

fs=1280; %采样频率

wc=2*pi*fc/fs;

n=0:1:N-1;

m=n-(N-1)/2;

h=sin(wc*m); %高通:h=sin(pi*m)-sin(wc*m);

h=h/pi./m;

h=h*2^15;

若滤波效果不好,可以通过增加滤波器阶数和加窗函数进行改进,在滤波器性能分析部分将会进一步说明此问题。

卷积运算可以通过FFT运算进行,也可以直接进行序列卷积,此处采用后一种方法:

for(i = 0;i < FRAME;i++)

{ sum = 0;

for(j = 0;j < nLen;j++) // nLen为滤波器阶数

{ sum += h[j] * nBuff[i - j + nLen -1]; //卷积运算

}

}

对于每一个信号输入,都将其与滤波器系数向量进行卷积运算,卷积的阶数取决于滤波器的阶数,当对每个输入值都进行了一次卷积计算以后,得到的输出序列将是滤波后的输出信号。可以将此信号与输入信号进行对比以分析滤波结果;另外,也可以计算此输出信号的频谱,分析其频率组成以进一步分析滤波器的滤波效果和频率特性。

4.7 总体控制程序设计

经过前面的各部分设计,程序的重要组成部分都已经分别实现,而主程序的目的就是将这些程序进行适当的组合和调用。

在程序的总体控制流程中,首先需要对系统进行初始化,即调用各个初始化函数;之后需要获取测试信号,并初始化FFT计算函数;进行FFT计算和频谱分析,输出结果到PC机;输入滤波器种类和截止频率;进行滤波运算并输出。在以上步骤中,获取测试信号部分已经存储在程序中,可以省略,其它部分只要按顺序调用即可。另外需进行适当的输入输出程序设计和提示,按照UART部分发送接收程序设计即可。

printf("The system has been initialized successfully.\n\n");

InitFft();

FFT();

printf("Choose a filter type:\n1:Low pass Filter\n2:High pass Filter\n");

while(!RI0) if(RI0) data_recv=SBUF0;

printf("%c",data_recv);

if(data_recv=='1') Filter(Input,Len,hlow); //进行低通滤波

if(data_recv=='2') Filter(Input,Len,hhigh); //进行高通滤波

4.8 本章小结

本章详细介绍了各部分程序的编程实现方法以及整体程序的设计,利用各部分程序的组合可以完整实现一个信号采集、分析和处理的数字信号系统,完成本课题的基本功能。本章所有程序均可在附录中找到。关于程序的测试和运行结果分析将在下一章进行介绍。

相关主题
文本预览
相关文档 最新文档