收集整理了一份《2024年最新物联网嵌入式全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升的朋友。
需要这些体系化资料的朋友,可以加我V获取:vip1024c (备注嵌入式)
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人
都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
由于CVI有一定年头了,很多书籍介绍混合编程时使用的都是较早的版本,加载函数仅有两个参数,故运行在新版本CVI软件中时可能出现“过多输入”的错误,此时需要使用新版的MLApp_NewDIMLApp函数。
该函数在ActiveX服务配置后生成的最底层MLApp.c文件中被定义(再次说明了在本机上第一次使用ActiveX服务时需要对其进行配置的重要性),其在头文件中的声明和使用如下所示。
//声明
HRESULT CVIFUNC MLApp_NewDIMLApp (const char *server, int supportMultithreading,
LCID locale, int reserved,
CAObjHandle *objectHandle);
//使用
stat = MLApp_NewDIMLApp(NULL,1,LOCALE_NEUTRAL,0,&hMatlab); //加载Matlab
if(result != SUCCESS)
{
MessagePopup("警告","Matlab加载出错!");
return 0;
}
函数末尾的hMatlab为全局的Matlab句柄,需提前定义(尤其当你想在其他地方也调用Matlab时)
不仅是该函数,大多数函数均会返回一个状态变量,故一般使用上面这种形式进行编程,以对软件的运行进行更好的控制,当加载错误时,能有效报错,防止软件无故崩溃
2.改变窗口大小:MinMaxMatlab
该函数在maltbutil.c文件中被定义,在最底层的MLApp之上进行进一步封装得到,0表示最小化窗口,1表示最大化窗口。
int MinMaxMatlab(CAObjHandle hMatlab, int minmaxFlag)
MinMaxMatlab(hMatlab,0);
3.退出Matlab脚本:MLApp_DIMLAppQuit
该函数在MLApp.c文件中被定义,也可以对其进行进一步的封装。
HRESULT CVIFUNC MLApp_DIMLAppQuit (CAObjHandle objectHandle,
ERRORINFO *errorInfo);
stat = MLApp_DIMLAppQuit (*hMatlab, NULL);
4.运行Matlab命令:RunMatlabCommand
该函数在maltbutil.c文件中被定义,仅可执行Matlab内部函数相关的命令,无法执行自定义函数命令,否则会报“undefined function or method”错误。
int RunMatlabCommand(CAObjHandle hMatlab, char *command)
result = RunMatlabCommand(hMatlab,"mMatrix=inv(cMatrix);");
if (result != SUCCESS)
{
MessagePopup ("ERROR", "Error in sending command to MATLAB");
return 0;
}
涉及的变量mMatrix与cMatrix无需在CVI中进行声明。
5.发送/接收字符串:SendString/GetString
该函数在maltbutil.c文件中被定义,由于Matlab不支持BSTRs,故发送接收过程中需要使用Fmt函数进行字符串与双精度浮点数的转换。
Fmt函数示例如下:
Fmt(CVIString,"%s<Hello MATLAB");
Fmt(command,"%s<%s=transpose(%s)",matStringName,matStringName);
Fmt(command,"%s<%s=char(%s)",matStringName,matStringName);
发送接收函数如下所示
int SendString(CAObjHandle hMatlab, char *matStringName, char *CVIString)
int GetString(CAObjHandle hMatlab, char *matStringName, char **cString)
result = SendString(hMatlab, "matStr", CVIString);
result = GetString(hMatlab,"matStr",&cStr);
demo给出的例子是,将“Hello MATLAB”字符串转换为双精度浮点数,变量名为CVIString,传输到Matlab中,在Matlab中的名称为matStr,而后从Matlab中获得这个字符串,变量名为cStr。
在CVI程序中,matStr无需声明,然而CVIString与cStr是需要声明的,形式是一维数组。
6.发送/接收矩阵
同5,demo矩阵的传输演示是将一个2x2的矩阵传入Matlab,进行转置运算后接收回来。
int SendMatrix(CAObjHandle hMatlab, char *matlabName, double *matrixReal,
double *matrixImag, size_t dim1, size_t dim2)
int GetMatrix(CAObjHandle hMatlab, char *matlabName, double **matrixReal,
double **matrixImag, size_t *dim1, size_t *dim2)
result = SendMatrix(hMatlab,"cMatrix",(double*)matrix_r,(double*)matrix_i,2,2);
result = GetMatrix(hMatlab,"mMatrix",&matrixReal,&matrixImag,&dim1,&dim2);
传输变量包括Matlab句柄,在Matlab中的名称,矩阵实部数值(也是矩阵),矩阵虚部数值(也是矩阵),行数,列数。其中没有虚部或者实部时可以用NULL表示。
同4,mMatrix与cMatrix无需在CVI中进行声明。但发送矩阵的实部数值matrix_r与虚部数值matrix_i需要在CVI中声明,形式是二维数组。接收矩阵的实部数值matrixReal和虚部数值matrixImag为初始化为NULL的指针,也需要提前声明,行数列数也需要提前确定。
7.运行M文件脚本:RunMatlabScript
该函数在matlabutil中定义。
int RunMatlabScript(CAObjHandle hMatlab, char *mFilePath)
result = RunMatlabScript(hMatlab,"G:\\sig\_gen\\demo\_0728\\create\_chaffsig.m");
在设定路径时,Windows下的分隔符需使用\以强制转义,否则会使得路径解析出错,另外由于函数中对路径长度以及文件名长度最大值仅设为256,故运M文件脚本不可设置过深,以防止无法解析。
另外还可利用FileSelectPopupEx等系统相关的函数,实现选择m文件运行的操作,这里不再赘述。
调用自定义函数
若要调用自定义函数,建议采用以下两种方式:
1.不足5行的函数,直接使用RunMatlabCommand,拆分为多个语句进行代替。
2.程序较长,但不存在额外调用自定义函数的情况(额外调用自定义函数指:例如本打算调用自定义函数A,A函数中又使用了自定义函数B),则在Matlab中充分测试A函数后,去掉首行的声明(即function [输出变量] = 函数名(输入变量))以及末尾的”end”,将所需要的输入变量提前构成数组,直接传入Matlab,再在Matlab中还原为各参数变量。如下所示:
在CVI中将变量构成数组
m_out_data[0] = fc;
m_out_data[1] = fs;
m_out_data[2] = (double)m;
m_out_data[3] = TotalTime*(1e-6);
在M文件头部还原
f0 = m_out_data(1);
fs = m_out_data(2);
m = m_out_data(3);
T = m_out_data(4);
完成运算后再将所需要的数据导出,由于一般调用Matlab的原因是C语言计算信号的各种变换较慢,所以所需数据一般也为行向量,可以用1xN的矩阵表示。
小结
调用Matlab时,需要在CVI代码中首先加载Matlab,其次具有一定的技巧地使用自定义函数,最后调用完成后需关闭Matlab避免拖累系统。
三、测试结果
在同一计算机上进行相同计算任务,
按上文的思路,CVI使用原方法完成50*245000个循环,耗时100s左右。
Matlab环境下运行(也是两重循环),耗时60s
Matlab改为单循环时,耗时0.0648s
CVI与Matlab进行混合编程后,耗时不足2s。
由上可知,混合编程成功地优化了功能,体现了混合编程的优越性。
收集整理了一份《2024年最新物联网嵌入式全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升的朋友。
需要这些体系化资料的朋友,可以加我V获取:vip1024c (备注嵌入式)
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人
都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
1715886325872)]
需要这些体系化资料的朋友,可以加我V获取:vip1024c (备注嵌入式)
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人
都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!