参考资料MFC编程

更新时间:2024-05-11 16:09:01 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

第4章 ASK数字通信系统的软件实现

4.1 使用MFC进行可视化编程

4.1.1 使用MFC进行窗口界面的设计

用MFC的AppWizard生成一个名为ASK_Pro应用程序的项目文件。编写应用程序,其主窗口如图4-1所示,标题为ASK_Pro。在这个窗口中,包含有四个标题为基本输入、滤波器特性、发射机和接收机的组合框,两个名字为噪声和信道命令按钮和两个名字分别为时域波形和频域波形的静态文本框及五个图像控件。在基本输入组合框中含有两个名字分别为学号和噪声强度的编辑框;在滤波器特性组合框中含有两个名字分别为低通滤波器和带通滤波器的命令按钮;在发射机组合框中含有三个名字分别为基带信号、过低通和调制的命令按钮;在接收机组合框中含有四个名字分别为过带通、解调、过低通和恢复判决的命令按钮。

图4-1 应用程序主窗口界面

该应用程序还含有一个名为窗函数选择的次窗口。该对话框的创建过程为:在Visual C++的主菜单栏中选择插入菜单中的窗体选项,出现一个新建窗体对话框,在名称中选择输入CChuangHanShu,单击右边的确定按钮,则出现一个对话框窗口。单击鼠标右键选择属性项,出现属性对话框,选择常规选项卡,在ID中设置其ID为ID_CHUANGHANSHU_DIALOG,在标题中输入对话框的名字“窗函数选择”,即完成对其名字的修改。对对话框进行编辑,如图4-2所示,这个窗口中含有三个名字分别为汉宁窗、哈名窗和布莱克曼窗的单选按钮。

图4-2 窗函数选择窗口界面

该应用程序窗口中各控件的功能如下:

(1)基本输入组合框中的控件 学号编辑框:学号编辑框用来接收用户输入的四位数字学号信息,如果用户没有输入,则显示对话框初始化时给它传入的数据。噪声强度编辑框:噪声强度编辑框用来接收用户输入的噪声强度信息,如果用户没有输入,则显示对话框初始化时给它传入的数据。

(2)滤波器特性组合框中的控件 低通滤波器按钮:单击此按钮,则弹出窗函数选择对话框,在窗函数组合框中有汉宁窗、哈名窗、布莱克曼窗三个单选按钮,单击其中的任何一项进行窗函数的选择。选完窗函数后关闭窗函数选择对话框,则在右边的时域波形和频域波形静态文本框中分别显示低通滤波器的时域波形和频域波形。带通滤波器按钮:单击此按钮,则在右边的时域波形和频域波形静态文本框中分别显示带通滤波器的时域波形和频域波形。

(3)发射机组合框中的控件 基带信号按钮:单击此按钮,则在右边的时域波形和频域波形静态文本框中分别显示编码采样后的数字基带信号的时域波形和频域波形。过低通按钮:单击此按钮,则在右边的时域波形和频域波形静态文本框中分别显示通过低通滤波器后的信号的时域波形和频域波形。调制按钮:单击调制按钮,则在右边的时域波形和频域波形静态文本框中分别显示调制后的信号的时域波形和频域波形。

(4)噪声按钮 单击此按钮,则右边的时域波形和频域波形静态文本框中分别显示高斯白噪声的时域波形和频域波形。

表4-1 对话框中个对象的属性

对象 基本输入组合框 “学号”编辑框 “噪声强度”编辑框 滤波器特性组合框 低通滤波器命令安扭 带通滤波器命令按钮 ID IDC_STATIC IDC_ID IDC_ Intensity IDC_STATIC IDC_Lpf IDC_Bpf Caption 基本输入 无 无 滤波器特性 低通滤波器 带通滤波器 发射机组合框 对象 基带信号命令按钮 过低通命令按钮 调制命令按钮 对象 噪声命令按钮 信道命令按钮 接收机组合框 过带通命令按钮 解调命令按钮 过低通命令按钮 判决恢复命令按钮 “时域波形”编辑框 “频域波形”编辑框 窗函数组合框 汉宁窗单选按钮 哈名窗单选按钮 布莱克曼窗单选按钮 IDC_STATIC ID IDC_BaseSignal IDC_PassLpf1 IDC_Modulate ID IDC_ Noise IDC_Channel IDC_STATIC IDC_PassBpf IDC_DeModulate IDC_PassLpf2 IDC_Adjust IDC_T IDC_F IDC_STATIC IDC_HanNing IDC_HaMing IDC_BuLaiKeMan 发射机 Caption 基带信号 过低通 调制 Caption 噪声 信道 接收机 过带通 解调 过低通 判决恢复 无 无 窗函数 汉宁窗 哈明窗 布莱克曼窗 (5)信道按钮 单击此按钮,则在右边的时域波形和频域波形静态文本框中分别显示过信道后的信号的时域波形和频域波形。

(6)接收机组合框 带通滤波器按钮:单击此按钮,在右边的时域波 形和频域波形静态文本框中分别显示过带通后的信号的时域波形和频域波形。解调按钮:单击此按钮,在右边的时域波形和频域波形静态文本框中分别显示解调后的信号的时域波形和频域波形。过低通按钮:单击此按钮,则在右边的时域波形和频域波形静态文本框中分别显示过低通滤波器后的信号的时域波形和频域波形。恢复判决按钮:单击此按钮,则在右边的时域波形和频域波形静态文本框中分别显示抽样判决后的信号的时域波形和频域波形。

(7)时域波形静态文本框 该静态文本框用来显示信号的时域波形。 (8)频域波形静态文本框 该静态文本框用来显示信号的频域波形。

表4-1是对话框中各个控件的显示内容和对应的ID号。

4.1.2 控件变量的设置

控件变量是MFC中一个很重要的机制。

第一,关于DDX(动态数据交换)的基础知识。

MFC提供了一套被称为“数据映射”的机制来完成对话框里控件的数据交换。同消息映射一样,数据映射将对话框里的控件同对话框里的成员变量连接起

来,使得这些成员变量的值能够自动反映相应控件的内容或状态。在这种机制的实现过程中,MFC还提供了类CDataExchang来实现对话框类与控件的数据交换(DDX),该类还提供了数据有效验证机制(DDV)。DDX(动态数据交换)看起来好象是在对话框中某控件和某成员变量之间建立连接,自动实现控件和变量之间的数据转移。但这只是一个幻觉,它的实际工作方式是这样的:当你用ClassWizard把某变量和控件连接起来时(通过Member Variables选项卡),它在数据映射中创建一个入口。实际上也就是在对话框的DoDataExchange函数中添加一个入口函数(DoDataExchange函数是Class Wizard产生和维护的函数) 。数据交换的工作由函数CDialog:: DoDataExchang完成。当程序需要交换数据时,不要直接调用DoDataExchang函数,而应该调用CWnd::UpdateData。UpdateData函数内部只有一个布尔型参数,它决定了数据传送的方向。当你调用UpdateData(FALSE)时,MFC调用DoDataExchange函数,Class Wizard放于DoDataExchange中的实现代码将把来自控件变量的数据拷贝到对应的控件上。相应的如果调用UpdateData(TRUE),MFC反过来把控件上的数据拷贝回其对应的变量(并且可能同时进行数据验证)。在对话框初始化函数CDialog::OnInitDialog中调用UpdateData(FALSE),这样在对话框创建时,数据成员的初值就会反映到相应的控件上。若用户是按了“OK”按钮退出对话框,则对话框认为输入有效,就会调用UpdateData(TRUE)将控件中的数据传输给对话框数据成员。

第二,ASK数字通信系统中控件变量的设置。

该系统中需要用户设定将要传输的学号信息和信道中的噪声强度,我们设定对话框中的“学号”和“噪声强度”编辑框用来接收用户输入的信息。为了将编辑框中的信息传入到通信系统中,需要分别给它们设置控件变量。设置方法已在第三章中讲述,原则是根据DDX工作机制来实现的,具体如表4-2所示:

控件名称 学号 噪声强度 表4-2 对话框的控件变量 对应的控件变量 控件ID 控件变量类型 IDC_ID IDC_Intensity nMyID nIntensity int int 当设置好控件变量以后,可以在初始化函数中给它们赋初值并调用UpdateData(FALSE)将初值传给编辑框控件,即显示在编辑框中。如果学号和噪声强度这两个编辑框里的值发生改变,就可以直接调用函数UpdateData(TRUE)来完成控件变量的即时更新。

4.1.3 关于ASK通信系统中对话框控件的消息响应

消息系统对于一个win32程序来说十分重要,它是一个程序运行的动力源泉。一个消息,是系统定义的一个32位的值,它唯一的定义了一个事件,向Windows发出一个通知,告诉应用程序某个事情发生了。例如,单击鼠标、改变窗口尺寸、按下键盘上的一个键都会使Windows发送一个消息给应用程序。在本次系统的设计中应用最多的是响应按扭单击的消息和编辑框值改变的消息。

Windows中的消息虽然很多,但是种类并不繁杂,大体上有3种:窗口消息、命令消息和控件通知消息。

窗口消息大概是系统中最为常见的消息,它是指由操作系统和控制其它窗口的窗口所使用的消息。例如CreateWindow、DestroyWindow和MoveWindow等都会激发窗口消息,还有我们在上面谈到的单击鼠标所产生的消息也是一种窗口消息。

命令消息,这是一种特殊的窗口消息,它用来处理从一个窗口发送到另一个窗口的用户请求,例如按下一个按钮,它就会向主窗口发送一个命令消息。 控件通知消息,是指这样一种消息,一个窗口内的子控件发生了一些事情,需要通知父窗口。通知消息只适用于标准的窗口控件如按钮、列表框、组合框、编辑框,以及Windows公共控件如树状视图、列表视图等。例如,单击或双击一个控件、在控件中选择部分文本、操作控件的滚动条都会产生通知消息。 它类似于命令消息,当用户与控件窗口交互时,那么控件通知消息就会从控件窗口发送到它的主窗口。但是这种消息的存在并不是为了处理用户命令,而是为了让主窗口能够改变控件,例如加载、显示数据。例如按下一个按钮,它向父窗口发送的消息也可以看作是一个控件通知消息;单击鼠标所产生的消息可以由主窗口直接处理,然后交给控件窗口处理。

其中窗口消息及控件通知消息主要由窗口类即直接或间接由CWND类派生类处理。相对窗口消息及控件通知消息而言,命令消息的处理对象范围就广得多,它不仅可以由窗口类处理,还可以由文档类,文档模板类及应用类所处理。 由于控件通知消息很重要的,人们用的也比较多,下面列出开发系统时使用的常见控件的通知消息的具体含义的: 按扭控件

BN_CLICKED 用户单击了按钮 BN_DISABLE 按钮被禁止

BN_DOUBLECLICKED 用户双击了按钮 BN_HILITE 用户加亮了按钮 BN_PAINT 按钮应当重画

BN_UNHILITE 编辑框控件加亮应当去掉

EN_CHANGE 编辑框中的文本己更新 EN_ERRSPACE 编辑框内存不足

EN_HSCROLL 用户点击了水平滚动条 EN_KILLFOCUS 编辑框正在失去输入焦点 EN_MAXTEXT 插入的内容被截断 EN_SETFOCUS 编辑框获得输入焦点

EN_UPDATE 编辑框中的文本将要更新

EN_VSCROLL 用户点击了垂直滚动条消息含义

ASK数字通信系统的开发过程中使用最多的是按扭控件BN_CLICKED(用户单击了按钮)消息和编辑框控件的EN_CHANGE (编辑框中的文本己更新消息)消息。具体的控件对应的响应函数如表4-3所示:

控件名称 学号 噪声强度 低通滤波器 带通滤波器 基带信号 过低通 调制 噪声 信道 过带通 解调 过低通 恢复判决 汉宁窗 哈名窗 布莱克曼 表4-3 控件对应的响应函数 控件ID 响应的消息 IDC_ID IDC_Intensity IDC_Lpf IDC_Bpf IDC_BaseSignal IDC_PassLpf1 IDC_Modulate IDC_Noise IDC_Channel IDC_PassBpf IDC_Demodulate IDC_PassLpf2 IDC_Adjust IDC_HanNing IDC_HaMing IDC_BuLaiKeMan EN_CHANGE EN_CHANGE BN_CLICKED BN_CLICKED BN_CLICKED BN_CLICKED BN_CLICKED BN_CLICKED BN_CLICKED BN_CLICKED BN_CLICKED BN_CLICKED BN_CLICKED BN_CLICKED BN_CLICKED BN_CLICKED 响应消息的函数 OnChangeId OnChangeIntensity OnLpf OnBpf OnBaseSignal OnPassLpf1 OnModulate OnNoise OnChannel OnPassBpf OnDemodulate OnPassLpf2 OnAdjust OnHanNing OnHaMing OnBuLaiKeMan 4.2 ASK数字通信系统的实现

用Visual C++6.0应用程序向导创建基于MFC的项目文件ASK_Pro,其窗

口界面的设计等已在4.1节中讲述了,下面介绍如何在该应用程序中实现ASK数字通信系统的仿真。

4.2.1 SigTranmit类的生成及功能

在ASK_Pro的主菜单栏中选择插入菜单中的新建类选项,出现一个New Class对话框,在该对话框的Class type中选择Generic Class,在Name中输入类名SigTranmit,单击右边的OK按钮。此时在ASK_Pro项目中生成了一个名为SigTranmit的类,该类用于实现ASK数字通信系统的全过程,包括发送端对信号进行编码、滤波(过低通滤波器)、和调制,信号传输的过程(即过信道),和接收端对信号的滤波(过带通滤波器)、解调、滤波(过低通滤波器)、和恢复判决。

在SigTranmit.h中定义SigTranmit类的两个int类型的私有数据成员myID和myIntensity。它们分别分别为该ASK数字通信系统中将要传输的信号及信道中噪声的强度,需要用户设置,即将它们同对话框中用来接收用户输入的学号信息和噪声强度信息的控件变量nMyID和nIntensity连接起来,将nMyID的值赋給myID,将nIntensity的值赋給myIntensity。

SigTranmit.h中还定义了三个int 类型和十二个float类型的私有数据成员,具体如下所示:

Int c:用来存放窗函数选择结果的变量。

int S0[16]:用来存放在Basesignal函数中对数字信息编码后的信号。 int S1[16]: 用来存放在Adjust函数中对信号抽样取平均后的信号。 float Mod[16*M]:用来存放生成的载波信号。

float Sa[16*M]:用来存放通过系统中每一个环节后的信号。

float Sal[16*M]: 用来存放在 Basesignal函数对信号进行采样后的信号。 float AR[16*M]:用来存放在Dft函数中对传入的数组进行DFT运算后的实部。 float AI[16*M]:用来存放在Dft函数中对传入的数组进行DFT运算后的虚部。 float A[16*M]:用来存放在Dft函数中对传入的数组进行DFT运算后的频域幅值。

float Hl[16*M]:用来存放生成的低通滤波器的单位取样响应。

float H2[16*M]:用来存放在Idft数中对传入的数组进行IDFT运算后的数据。 float No[16*M]:用来存放生成的噪声

float Hb[N]:用来存放带通滤波器的频域单位取样响应。

float P[N]: 用来存放在Idft数中进行IDFT运算所需要的数据。 float Wn[N]:用来存放窗函数的单位取样响应。

在SigTranmit.h中声明SigTranmit类的二十五个公有成员函数,并在SigTranmit.cpp中对它们进行定义。各函数原型及功能如下所示:

CSigTranmit(void):系统自动生成的构造函数,我在函数体内给私有变量c赋值,使得用户没有进行创函数选择时,c有默认值。

void SetDigtal(int ID, int Intensity):该函数用于设置SigTranmit类的共有数据成员myID和myIntensity的初始值。

void Basesignal():该函数用于对学号信息进行编码、采样,生成数字基带信号;接着调用void Dft(float x[],int m)函数对采样后的信号进DFT运算,得到信号的频域特性。

void Lpf():该函数体里首先用窗函数法生成低通滤波器;接着调用函数void Conv(float array1[],float array2[])对低通滤波器和数字基带信号的进行卷积运算,实现信号过低通的模拟;最后调用void Dft(float x[],int m)函数对过低通滤波器后的信号进行DFT运算,得到信号的频域特性。

void modulate():该函数实现对滤波后的信号的振幅调制,并调用void Dft(float x[],int m)函数对过调制后的信号进行DFT运算,得到信号的频域特性。

void Channel():该函数体里首先调用void Noise(float inten)函数生成高斯白噪声;接着将调制后的信号与高斯白噪声相加以模拟信号过信道的过程,最后调用void Dft(float x[],int m)函数对过信道后的信号进行DFT运算,得到信号的频域特性。

void Bpf():该函数体里首先用频率采样法生成带通滤波器,并调用函数void Idft(float h[])得到其时域的特性;接着调用函数void Conv(float array1[],float array2[])对带通滤波器和数字信号的卷积,以模拟接收到的信号过带通;最后调用void Dft(float x[],int m)函数对过带通滤波器后的信号进行DFT运算,得到信号的频域特性。

void Demodulate():该函数首先实现对过带通后的信号进行同步解调;其次调用void Dft(float x[],int m)函数对解调后的信号进行DFT运算,得到信号的频域特性。

void Adjust():该函数首先实现对解调后的信号进行恢复判决,即取平均后再采样;最后调用void Dft(float x[],int m)函数对过带通滤波器后的信号进行DFT运算,得到信号的频域特性。

void Dft(float x[],int m):该函数实现对传入的参数x[]的m点DFT运算,得到信号的频域特性。

void Idft(float h[]):该函数实现对传入的参数h[]的IDFT运算,得到信号的时域特性。

void Conv(float array1[],float array2[]):该函数实现传入的两个参数array1[]和array2[]的卷积运算。

void Noise(float inten):该函数用来生成高斯白噪声。

void SetHl(float H[]):该函数用来设置私有变量Hl[N]的值。 void SetHb(float H[]):该函数用来设置私有变量Hb[N]的值。

void Setc(int Myc):该函数用来设置私有变量c的值。

int GetmyIntensity():该函数用来获取私有变量myIntensity的值。 int Getc():该函数用来获取私有变量c的值。

float* GetSa():该函数用来获取私有变量Sa[16*M]的值。 float* GetA():该函数用来获取私有变量A[16*M]的值。 float* GetHl():该函数用来获取私有变量Hl[N]的值。 float* GetH2():该函数用来获取私有变量H2[N]的值。 float* GetHb():该函数用来获取私有变量Hb[N]的值。 float* GetNo():该函数用来获取私有变量No[16*M]的值。 ~CSigTranmit(void):系统自动生成析构函数,用于执行释放对象时清理工作。

4.2.2 画图函数的定义

该系统在ASK_ProDlg类中定义了两个名字分别为Graph0和Graph的共有成员函数,通过调用它们实现在对话框右边的时域波形和频域波形静态文本框里画图。其中Graph0用来画低通滤波器和带通滤波器的特性图,Graph用来画信号在传输过程中的特性图,即在每个按钮控件的消息响应函数的最后都通过调用画图函数来实现画图功能。它们的代码分别如下。

这两个画图函数的不同点是函数Graph是为信号画图,信号长度为320点,故在计算在静态文本框里画图时的横向步长时是以320点来计算的;而Graph0是为滤波器画图的,低通和带通滤波器的长度均为63,即长度都为63点,所以在计算横向步长时是以63点来计算的。

函数体中在画图前首先调用GetDlgItem函数获取对话框中要画图的静态文本框的地址并赋给一个窗口类指针pWnd,接着调用GetDC获取该区域的设备场景,然后定义一个矩形框类对象rect1,并将该画图区域赋给它,该类对象调用自身的成员函数Width和Height获取画图区域的宽度和高度,我们可以在接下来的程序中根据它们得到画图时横向和纵向步长,并设置画图的起始点。此外还要进行设置画图区域的背景颜色,定义画笔等初始化工作。最后调用函数LineTo和MoveTo实现在静态文本框中画图。

在来两个画图函数中均调用了自定义的函数findmax,它是用来找出传入的数组里的最大值,以便计算画图时的纵向步长。

4.2.3 对话框控件的响应函数代码

上面已经生成了一个SigTranmit类用来实现ASK数字通信系统,下面就介绍如何将窗口里的控件和这个系统连接起来。

我们要实现的功能如下:

(1)对话框里学号和噪声强度编辑框用来接收用户输入并将数据传给SigTranmit类即将SigTranmit类的两个公有数据成员myID和myIntensity和编辑框的控件变量nMyID和nIntensity连接起来,将nMyID的值赋給myID,将nIntensity的值赋給myIntensity。为了使得用户在没有给编辑框输入的情况下系统也能运行,我们需要给编辑框里赋初始值,为实现这个功能我们可以在ASK_ProDlg类的初始化函数OnInitDialog()里写如下代码:

nMyID = 5555; nIntensity = 5;

UpdateData(FALSE);

这里我们设置的初始值分别如上所示,调用UpdateData(FALSE)将控件变量的值传给对话框中相应的编辑框,若用户没有输入,则系统运行时将它们的值分别传给SigTranmit类对象的私有数据成员myID和myIntensity,分别作为ASK数字通信系统要传送的信息和信道中的噪声强度。

(2)当我们单击滤波器特性组合框中低通滤波器按钮时执行低通滤波器

的消息响应函数,即弹出窗函数选择对话框,在窗函数组合框中有汉宁窗、哈明窗、布莱克曼窗三个单选按钮,单击其中的任何一项进行窗函数的选择,接着用窗函数法生成低通滤波器,并调用画图函数Graph0在对话框中右边的时域波形和频域波形静态文本框中画其特性图。其代码如下:

void CASK_ProDlg::OnLpf() {

CChuangHanShu hanshu(&mySignal1); hanshu.DoModal(); int i;

float a=(N-1)/2; float Wn1[N]; float Hl0[N];

switch(mySignal1.Getc()) {

case 0: //生成汉宁窗 {

for(i=0;i

Wn1[i]=0.5*(1.0-cos(2.0*PI*i/(N-1))); } break;

case 1: //生成哈明窗 {

for(i=0;i

Wn1[i]=0.54-0.46*cos(2.0*PI*i/(N-1)); }; break;

case 2: //生成布莱克曼窗 {

for(i=0;i

Wn1[i]=0.42-0.5*cos(2.0*PI*i/(N-1))+0.08*cos(4.0*PI*i/(N-1)); }; }

for(i=0;i

if(i==a)

Hl0 [i]=0.1;

else

Hl0 [i]=sin((2*PI*fh/freq)*(i-a))/(float)(PI*(i-a)); }

for(i=0;i

Hl0[i]=Hl0[i]*Wn1[i];

mySignal1.SetHl(Hl0);

mySignal1.Dft(mySignal1.GetHl(),N);

this->Graph0(mySignal1.GetHl(),mySignal1.GetA());

}

代码的第一条语句是先定义一个CChuangHanShu类对象hanshu,同时调用它的构造函数将mySignal1的地址传给CChuangHanShu类中定义的私有指针变量mySignal,它指向一个SigTranmit类对象。第二条是用来弹出窗函数选择对话框的,选窗函数的同时执行单选按钮的消息相应函数,即给mySignal1的私有变量c赋值。接着由c的值生成相应的窗函数存入变量Wn中,并由此生成低通滤波器并存在变量H1中,并对其进行DFT运算得出其频域的幅值存入变量A中,最后调用画图函数void Graph0(float S[],float Frep[])画出其时域和频域图,并分别显示在右边的时域波形和频域波形静态文本框中。其图如图4-3所示。

图4-3低通滤波器的时域波形和频域波形

进行窗函数选择的三个单选按钮同样也有消息响应函数,它们的功能就是根据用户所选窗给c赋值。这些消息响应函数是在CChuangHanShu.h中声明并在CChuangHanShu.cpp中定义的,其代码分别如下所示:

void CChuangHanShu::OnHanNing() {

mySignal->Setc (0); }

void CChuangHanShu::OnHaMing () { mySignal->Setc (1); }

void CChuangHanShu::OnBuLaiKeMan () {

mySignal->Setc (2); }

mySignal为一个指向SigTranmit类对象的指针,系统运行时,它指向类对象mySignal1。这里的Setc为SigTranmit类的公有成员函数,这里调用它来设置

mySignal的私有变量c的值,以便在低通滤波器的消息函数中进行窗函数的选择。

(3)当我们点击滤波器特性组合框中的带通滤波器的命令按钮时系统执行带通滤波器按钮的消息处理函数,其代码如下:

void CASK_ProDlg::OnBpf () {

int k;

for (k=0; k

for (k=0; k< (N-1)/2; k++) {

if (((float) freq*k/N>700) && ((float) freq*k/N<900)) Hb0 [k] = ((float) freq*k/N-700)/200;

if(((float) freq*k/N>900) && ((float) freq*k/N<1100)) Hb0 [k] =1;

if (((float) freq*k/N>1100) && ((float) freq*k/N<1300)) Hb0 [k] = (1300-(float) freq*k/N)/200; Hb0 [N-k] =Hb0 [k]; }

mySignal1.SetHb (Hb0);

mySignal1.Idft (mySignal1.GetHb ());

this->Graph0 (mySignal1.GetH2 (), mySignal1.GetHb ()); }

图4-4 带通滤波器的时域波形和频域波形

首先用频率采样法生成带通滤波器存入数组Hb0(它是ASK_ProDlg的私有数据成员),接着调用SetHb 将Hb0的值传给Hb,再对Hb进行IDFT运算得出其时域特性存入H2中,最后调用画图函数void Graph0(float S[],float Frep[])

画出其时域和频域图,并分别显示在右边的时域波形和频域波形静态文本框中。如图4-4所示。

图4-5 基带信号的时域波形和频域波形

(4)单击发射机组合框中的基带信号按钮时系统执行基带信号按钮的消息相应函数,其代码如下:

void CASK_ProDlg::OnBaseSignal () {

UpdateData (TRUE);

mySignal1.SetDigtal (nMyID, nIntensity); mySignal1.Basesignal ();

this->Graph (mySignal1.GetSa (), mySignal1.GetA ()); }

首先调用UpdateData(TRUE)将数据从编辑框中传送到对应的控件变量上,因为若用户输入了新的数据则需要更新而不是采用默认值,这样就能使得用户输入的数据能及时传入系统。接着就是mySignal1调用它的成员函数void SetDigtal(int ID, int Intensity)将控件变量的值传给它的私有数据成员myID和myIntensity。其次调用成员函数void Basesignal()对学号编辑框里的数据进行编码、采样以及DFT运算,并将其时域及频域的数值分别存入Sa和A中;最后调用画图函数void Graph(float S[],float Frep[])画出其时域和频域图,并分别显示在右边的时域波形和频域波形静态文本框中。如图4-5所示。

(5)单击发射机组合框中的过低通命令按钮,则系统执行过低通按钮的消息响应函数,其代码如下:

void CASK_ProDlg::OnPassLpf1 () {

mySignal1.Lpf();

this->Graph (mySignal1.GetSa (), mySignal1.GetA ()); }

图4-6 信号过低通后的时域波形和频域波形

首先mySignal1调用它的成员函数void Lpf()进行信号过低通滤波器的一系列运算,并将最后得出的信号的时域数值及其频域的幅值分别存入Sa和A中;最后调用画图函数void Graph (float S[],float Frep[])画出其时域和频域图,并分别显示在右边的时域波形和频域波形静态文本框中。如图4-6所示。

(6)单击发射机组合框中的调制命令按钮,则系统执行调制按钮的消息响应函数,其代码如下:

void CASK_ProDlg::OnModulate () { mySignal1.modulate ();

this->Graph (mySignal1.GetSa (), mySignal1.GetA ()); }

首先mySignal1调用它的成员函数void modulate()实现对信号调制的一系列运算,并将最后得出的信号的时域数值及其频域的幅值分别存入Sa和A中;最后调用画图函数void Graph (float S[],float Frep[])画出其时域和频域图,并分别显示在右边的时域波形和频域波形静态文本框中。如图4-7所示:

图4-7 调制信号的时域波形和频域波形

图4-8 噪声信号的时域波形和频域波形

(7)单击噪声命令按钮,则系统执行噪声按钮的消息响应函数,其代码如下: void CASK_ProDlg::OnNoise() {

mySignal1.Noise (mySignal1.GetmyIntensity ());

this->Graph (mySignal1.GetNo (), mySignal1.GetA ()); }

首先调用mySignal1的成员函数void Noise(float inten)生成高斯白噪声,并将最后得出的噪声信号的时域数值及其频域的幅值分别存入No和A中;最后调用画图函数void Graph (float S[],float Frep[])画出其时域和频域图,并分别显示在右边的时域波形和频域波形静态文本框中。如图4-8所示。

图4-9 过信道后信号的时域波形和频域波形

(8)单击信道命令按钮,则系统执行信道按钮的消息响应函数,其代码如下: void CASK_ProDlg::OnChannel () {

mySignal1.Channel ();

this->Graph (mySignal1.GetSa (), mySignal1.GetA ()); }

首先调用mySignal1的成员函数void Channel()进行信号过信道的一系列运算,并将最后得出的信号的时域数值及其频域的幅值分别存入Sa和A中;最后调用画图函数void Graph (float S[],float Frep[])画出其时域和频域图,并分别显示在右边的时域波形和频域波形静态文本框中。如图4-9所示。

(9)单击接收机组合框中过带通命令按钮,则系统执行过带通按钮的消息响应函数,其代码如下:

void CASK_ProDlg::OnPassBpf () {

mySignal1.Bpf ();

this->Graph (mySignal1.GetSa (), mySignal1.GetA ()); }

首先调用mySignal1的成员函数void Bpf()进行信号过带通的一系列运算,并将最后得出的信号的时域数值及其频域的幅值分别存入Sa和A中;最后调用画图函数void Graph (float S[],float Frep[])画出其时域和频域图,并分别显示在右边的时域波形和频域波形静态文本框中。如图4-10所示。

图4-10 过带通后信号的时域波形和频域波形

(10)单击接收机组合框中的解调命令按钮,则系统执行解调按钮的消息

响应函数,其代码如下:

void CASK_ProDlg::OnDemodulate () {

mySignal1.Demodulate ();

this->Graph (mySignal1.GetSa (), mySignal1.GetA ()); }

首先mySignal1调用它的成员函数void Demodulate()对信号进行解调的一系列运算,并将最后得出的信号的时域数值及其频域的幅值分别存入Sa和A中;最后调用画图函数void Graph (float S[],float Frep[])画出其时域和频域图,并分别显示在右边的时域波形和频域波形静态文本框中。如图4-11所示。

图4-11 解调后信号的时域波形和频域波形

图4-12 过低通后信号的时域波形和频域波形

(11)单击接收机组合框中的过低通命令按钮,则系统执行过低通按钮的消息响应函数,其代码如下:

void CASK_ProDlg::OnPassLpf2 () {

mySignal1.Lpf ();

this->Graph (mySignal1.GetSa (), mySignal1.GetA ()); }

首先mySignal1调用它的成员函数void Lpf()对信号进行过低通的一系列运算,并将最后得出的信号的时域数值及其频域的幅值分别存入Sa和A中;最后

调用画图函数void Graph (float S[],float Frep[])画出其时域和频域图,并分别显示在右边的时域波形和频域波形静态文本框中。图如图4-12所示。

(12)单击接收机组合框中的恢复判决命令按钮,则系统执行恢复判决按钮的消息响应函数,其代码如下:

void CASK_ProDlg::OnAdjust () {

mySignal1.Adjust ();

this->Graph (mySignal1.GetSa (), mySignal1.GetA ()); }

首先mySignal1调用它的成员函数void Adjust()对信号进行抽样判决的一系列运算,并将最后得出的信号的时域数值及其频域的幅值分别存入Sa和A中;最后调用画图函数void Graph (float S[],float Frep[])画出其时域和频域图,并分别显示在右边的时域波形和频域波形静态文本框中。其图分别如4-13所示。

图4-13 判决恢复后信号的时域波形和频域波形

本文来源:https://www.bwwdw.com/article/7f7g.html

Top