关于MATLAB在信号与系统分析中的应用,本文的写作方法对我来说是新的。
Vc++下如何使用Matlab工具箱进行数字信号处理
本文介绍了如何在Vc环境下使用Matlab工具箱处理数字信号。以Matlab工具箱中的功率谱密度分析函数为例,介绍了如何通过Matlab的引擎、Matlab的编译器和MathTools公司的Matcom调用工具箱函数。
关键词:Matlab M文件引擎编译器Matcom Vc++
Matlab的信号处理工具箱是信号算法文件的集合,它的基本对象是信号和系统。信号处理工具箱位于目录Toolbox\Signal中,工具箱中的文件可以用来实现信号变换、滤波、频谱估计、滤波器设计等。在其他环境下,比如Vc,如果能调用Matlab工具箱中的文件,会大大加快一些算法的实现速度,可靠性也很高。
使用Matlab引擎
Matlab引擎采用客户端和服务器计算方式。在应用中,使用Vc的C语言或C++语言的程序作为前端客户端,向Matlab引擎发送命令和数据信息,并从Matlab引擎接收数据信息。它提供了以下功能:Engopen,Enggetarray,Engputarray,Engevasting,
EngOutputBuffer,engClose与客户端交互。
下面的例程是在Vc下构建一个基于对话框的应用程序,在对话框上设置一个按钮控件,在对话框中添加“engine.h”和“math.h”头文件。cpp文件。以下是部分节目单。
void CtestmatlabDlg::OnMatlabEngine(){
发动机* ep
mxArray* T=NULL,*result=NULL,*mFs=NULL,* mnfft = NULL
double datax[1024];
char缓冲区[1024];
for(int j = 0;j & lt1024;J++)//注意:如果采集卡采集的数据可以放到datax[]数组中,就不需要这个循环了。
{
double samt =(double)(1.0/1024);
datax[j]= sin(2.0 * 63.0 * samt * 3.1415926+1.15 * 3.1415926);
}
双*pPxx,* pFxx
如果(!(EP = eng Open(" \ 0 "){//打开Matlab引擎,与本地Matlab建立连接。
fprintf(stderr," \n无法启动MATLAB引擎\ n ");
退出(-1);
}
双Fs[1]= { 1024 };//因为Matlab运算中涉及到的参数都是矩阵的形式,下面几行会改变参数。
double nfft[1]= { 1024 };//成Matlab可接受的矩阵形式。
T=mxCreateDoubleMatrix(1,1024,MX real);
Mn FFT = mxCreateDoubleMatrix(1,1,MX real);
mFs = mxCreateDoubleMatrix(1,1,MX real);
mxSetName(T," T ");
mxSetName(mnfft,“Mn FFT”);
mxSetName(mFs,“mFs”);
memcpy((char*)mxGetPr(T),(char*)datax,1024 * sizeof(double));
memcpy((char*)mxGetPr(mnfft),(char*)nfft,sizeof(double));
memcpy((char*)mxGetPr(mFs),(char*)Fs,1 * sizeof(double));
engPutArray(ep,T);//将转换后的参数放入引擎中,此时可以在Matlab命令窗口中查看这个参数。
engPutArray(ep,Mn FFT);
engPutArray(ep,mFs);
engEvalString(ep,"[pxx,fo]=psd(T,mnfft,mFs);");//使用引擎执行工具箱中的文件。
engOutputBuffer(ep,Buffer,512);//如果只想看显示的图形,可以去掉返回参数。psd会自动绘制图形,默认不返回参数。
result=engGetArray(ep," pxx ");//从引擎中取出数据,放入指示区域进行后续处理。
pPxx=mxGetPr(结果);
result=engGetArray(ep," fo ");
pFxx=mxGetPr(结果);
engEvalString(ep," plot(fo,10 * log 10(pxx));");//用引擎绘图
EngEvalString(ep,“标题(‘功率谱分析’);”);
engEvalString(ep," xlabel(' Hz ');");
engEvalString(ep," ylable(' db ');");
mxDestroyArray(T);//释放内存
mxDestroyArray(mFs);
mxDestroyArray(Mn FFT);
mxDestroyArray(结果);
engEvalString(ep,“close”);
eng close(EP);
}
在Vc下编译上述程序,需要对libmx.dll和libmx.dll两个动态库使用以下命令:
lib/def:& lt;自带Matlab的安装路径,下同> E: \ MATLAB \ extern \ include \ *。def/machine: ix86/out: *。lib来生成程序需要的静态连接库libeng.lib和libmx.lib。只需将libeng.lib和libmx.lib所在的目录添加到v c++ project/link/object/library modules中即可。
使用Matlab自带的编译器调用工具箱中的函数
Matlab的编译器可以将Matlab的M文件转换成C或C++的源代码,生成完全脱离Matlab运行环境的独立应用程序。但是Matlab本身的数据表明,如果用来建立独立的应用程序,编译器是无法调用Matlab工具箱中的函数的,这对于一些特殊的算法是非常不利的。我研究了一段时间发现,由于工具箱中的函数都是M文件,所以可以用一个编译器编译出来提供调用函数比如Vc,但是编译器只能编译一个独立的M文件,也就是这个M文件不依赖于其他M文件。如果在M文件中调用了其他M文件,被调用的M文件可以复制到调用M文件的相应位置,经过适当的修改就可以用于编译器编译。编译器不支持图形函数,所以如果M文件中有图形函数,就需要把它们注释掉。
当Matlab的编译器mcc添加适当的参数-E(MCC–E *)时。*)或-P(MCC–P *)。*),它可以生成输入的M文件,并将其转换为适合特定应用的C或C++源代码。这样,如果想在Vc下编译,需要连接以下库:libmmfile.dll、libmatlb.dll、libmcc.dll、libmat.dll、libmx.dll、mibut.dll和Matlab C MATH。建议通过上述方法将动态连接改为静态连接。对于C/C++编译环境的设置,运行Matlab命令窗口下的mex -setup并按照提示操作,而对于C/C++连接环境的设置,运行mbuild -setup并按照提示操作。
下面给出一个在Matlab工具箱中使用编译器生成psd.m文件,可以被Vc调用的函数。
将psd.m文件复制到Matlab\bin目录下,重写相应的调用m文件如nargchk.m、hanning.m等。为了生成简洁的代码,在数据采集和处理的输入参数明确的情况下可以进行大量的删除,psd.m最终会成为一个独立的不依赖于其他M文件的M文件。注意不要注释掉画图代码,最后改成下面的形式,由于篇幅有限给出了关键步骤:
函数[Pxx,f]=psd(Fs,nfft,noverlap,x)
window=o,5 *(1-cos(2 * pi *(1:nfft)'/(nffft+1)));//汉宁窗口
dflag =“none”;
window = window(;)
………………………………….
只要你懂Matlab语言,懂信号处理知识,就可以完成这项工作。
假设上面的代码再次保存为testwin.m,设置环境参数,在Matlab命令窗口运行mcc -e testwin,那么Matlab\bin中就可以生成testwin.c,如果运行mcc -p testwin就可以生成testwin.cpp。
在Vc下建立一个基于对话框的文件,然后在ButtonPsd上添加一个按钮控件到对话框中。
添加生成的头文件。c文件添加到。项目的cpp,并添加#ifdef_cplusplus
外部" c"{
#结束if
在Vc的包含文件和生成的包含文件之间添加c代码声明。c.
Will #ifdef_cplusplus
}
#end if添加。cpp文件。
为了简洁和便于处理,对生成的C函数稍作改动,给出部分代码如下:
void ctestpsddwindlg::OnButtonPsd(){
mxArray * x _ rhs _//指向采集数据存储区
fs = 23510;//数据采集频率nfft = 1024;//1024点的fft
Double datax[1024]//收集的数据
x _ RHS _ mxCreateDoubleMatrix(1,1024,MX real);
memcpy(mxGetPr(x_rhs_),datax,1024 * sizeof(double));
nover lap = 512;
……………….
……………….
mccCopy(& amp;pxx & amp;spec);
mccCopy(& amp;f & amp;frevgg _ vector);
for(int j = 0;j & lt(int)(nfft/2+1);j++)
{
datap[j]= mccGetRealVectorElement(& amp;Pxx,(j+1));//功率谱密度存储在datap[]数组中。
dataf[j]= mccGetRealVectorElement(& amp;f,(j+1));//相应的频率存储在数组dataf[]中。
}
mccFreeMatrix(& amp;pxx);
……………….
SendMessageBox(WM_PAINT,0,0);//用Vc中的图形功能绘图
返回;
}
生成的程序可读性不是很好,而生成的c++代码可读性很好。但是一定要注意,只能用Matlab的数学库,不能用c++的数学库,否则编译会出错,空间有限。
3)用Matcom调用工具箱中的函数。
Matcom编译M文件。它首先根据与Matcom的cpp库的对应关系将M文件翻译成cpp源代码,然后用相应版本的C编译器将cpp文件编译成相应的exe或dll文件。所以第一次运行必须指定C编译器的路径,否则无法编译,指定的编译信息写入Matcom\bin\matcom.ini文件。但是,在这一步安装matcom时,它会自动找到编译器,并将其写入matcom.ini文件。Matcom版使用TeeChart3.0 OCX控件,所以支持图形化操作。
我们还是用上面的testwin.m文件,不注释掉图形功能。我们使用Mideva来生成Vc可以调用的信号处理程序。
运行Mideva直接在主界面打开M文件,在菜单中选择编译成dll,进入testwin..可以找到几个类似TestWin的文件。c,TestWin。h,TestWin。CPP,TestWin。Lib,TestWin。DLL,TestWin。Exp等。在Matcom调试目录中。
将上面的testwin.cpp和testwin.h添加到项目中,project/add to project/files,将“stdafx.h”添加到相应的文件中。
添加链接库:Tools\option\directory\,选择include选项,添加e:\matcom45\lib(包括matcom.h)。
库选项,添加e:\matcom45\lib。
4)项目\添加到项目\文件文件类型选项(。lib)将e:\ mat com 45 \ lib \ v 4501 . lib添加到项目中进行编译运行。对应的代码如下:
void CtestmatcomDlg::OnpsdButton(){
双数据p[512],数据f[512];
initM(MATCOM _ VERSION);//初始化matcom库
Mm Fs,nfft,noverlap//创建一个矩阵
Mm x =零(1,1024);
fs = 1024;nfft = 1024;nover lap = 128;
dMm(Pxx _ o);dMm(f _ o);//创建并命名矩阵
datax[];//收集的数据存储在这个数组中。
for(int I = 1;我& lt=1024;i++)
{
x.r(1,I)= datax[I+1];//给X数组赋值
}
testwin(Fs,nfft,noverlap,x,i_o,Pxx,f _ o);//由//matcom生成的函数
for(I = 0;我& lt513;I++){//取出功率谱密度分析结果。
dataf[i]=f_o.r(i+1,1);
datap[i]=Pxx_o.r(i+1,1);}
exit m();
返回;
}
可以看出,使用Matcom转换M文件非常容易,生成的代码可读性非常好。上面的转换还生成了一个动态链接库供Vc调用,作为通用的动态库。同时需要指出的是,Matcom不仅可以转换不依赖于其他M文件的独立M文件,还可以转换调用其他M文件的M文件嵌套。假设这个M文件在同一个目录下,那么上面提到的psd.m就可以通过上面的方法直接转换,生成多个重载的psd函数。
结论:使用Mtlab引擎调用工具箱中的函数,可以节省大量的系统资源,应用程序整体性能良好,但离开Matlab就无法运行。使用Matlab编译器调用工具箱函数时,需要将对应的M文件转换成独立的M文件,不支持图形功能,所以转换后的代码可读性不是很好。用Matcom转换非常方便,生成的代码可读性非常好,支持图形功能,代码执行速度比不转换时快1.5倍以上。上述程序已在VC++6.0、MATLAB 5.2和MATCOM 4.5中调试通过,上述方法在工程实践中得到了很好的应用。
仅供参考,请大家自己学习。
希望对你有帮助。