参考资料MFC编程(2)

2019-05-17 14:51

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());


参考资料MFC编程(2).doc 将本文的Word文档下载到电脑 下载失败或者文档不完整,请联系客服人员解决!

下一篇:马原案例分析资料(半期考试)

相关阅读
本类排行
× 注册会员免费下载(下载后可以自由复制和排版)

马上注册会员

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: