饶和昌,赵英俊
(华中科技大学 机械科学与工程学院,湖北 武汉430074)
MATLAB是美国MathWorks公司开发的高性能的科学与工程计算软件,凭借其强大的科学计算和绘图功能、大量稳定可靠的算法库和简洁高效的编程语言,被科技工作者们广泛应用于自动控制、数学运算、信号分析、图像处理等各行各业[1-2]。尽管MATLAB本身是一个完整的、自成体系的编程和数据处理环境,但由于语言的特性使其访问硬件的能力相对较差,这在一定程度上限制了它的使用。对于那些涉及复杂算法同时又需要对硬件资源进行访问的系统,一般的做法是在一个通用的编程平台(如 Visual C++、Visual Basic、Delphi等)上实现对硬件资源的访问,而后调用MATLAB算法对数据进行处理。这种方法优点是通用性好,程序运行效率高,适用大多数场合,但对开发人员编程能力有较高要求,开发周期较长。在一些需要快速的验证模型和算法的场合,为充分发挥MATLAB强大的数值计算能力,以MATLAB作为主开发平台来得更为合适。随着模块化的设计思想在越来越多的产品中得到体现,器件生产厂商们一般都会提供该产品的二次开发函数库,方便了开发者们对硬件操作的同时,也使得MATLAB通过外部程序接口实现对硬件的访问成为可能。
文中具体论述一种基于动态链接库调用实现MATLAB访问一般硬件的方法,并将该方法用于对高精度气压传感器MS5803的数据采集,实现了MATLAB与硬件的无缝结合,极大的方便了数据的后续处理。
在具体阐述MATLAB环境下调用动态链接库函数访问外部硬件之前,有必要对动态链接库做简要介绍。动态链接库英文为Dynamic Linkable Library,缩写DLL,最初是为了解决代码共享的问题而提出的,通俗的理解可以把DLL看成一种仓库,它提供一些可以直接拿来使用的变量、函数或类[3]。动态链接库可以使用不同编程语言来编写,只要符合标准即可。为了加深对动态链接库函数调用的理解,下面以C/C++语言为例简要介绍动态链接库的编写步骤。首先介绍两组关键字:
1)_declspec(dllimport)
这组关键字表示从DLL中导入函数或者数据,一般用在DLL对应的头文件中。
2)_declspec(dllexport)
这组关键字表示从DLL中导出函数或者数据,一般用在DLL对应的工程文件中。
编写动态链接库函数的方法与编写一般函数的方法基本相同,只不过要对库中的可导出函数进行必要的申明。下面以VC环境下一个最简单的DLL工程dll_test进行说明,工程包含dll_test.h和dll_test.cpp两个文件。
//dll_test.h
__declspec(dllexport) int add(int m, int n);
__declspec(dllexport) int sub(int m, int n);
//dll_test.cpp
#include ”dll_test.h”
__declspec(dllexport) int add(int m, int n)
{
return (m+n);
}
__declspec(dllexport) int sub(int m, int n)
{
return (m - n);
}
编译上述dll_test工程即可得到动态链接库dll_test.dll(在Debug或Release目录下),此动态链接库实现了add和sub函数的功能。在解决一些实际问题过程中,有时会遇到只有DLL而没有与之相对应的头文件的情况,而MATLAB在调用DLL文件中的函数之前,必须具备头文件中的函数声明才行,这样根据上述DLL的编写规范可以很容易的编写出与所调用的DLL相对应的头文件。
从Matlab6.5(R13)起,Matlab提供了对动态连接库 DLL文件的接口[1]。利用这个接口,可以在Matlab中调用动态连接库导出的函数。MATLAB加载和使用动态链接库函数仅通过7~8个函数就可以实现,只要掌握这些函数的使用方法,就掌握了加载和应用动态链接的基本方法,从而可以在MATLAB平台下轻松实现对硬件的访问。
利用MATLAB共享库接口实现对外部DLL库的调用主要有以下几个步骤[4]。
1)加载动态链接库文件
在使用动态链接库之前,必须将所需的动态链接库加载到MATLAB工作空间中,之后MATLAB才能调用动态库中的函数。函数lodalibrary用于加载动态链接库,其使用语法如下:
loadlibrary(‘shrlib’, ‘hfile’)
loadlibrary函数有两个输入参数,参数shrlib表示库文件的名称,参数hfile为对应库的C语言头文件,C语言的头文件用于向MATLAB提供基本的函数说明。下面以一示例说明loadlibrary的用法,在命令提示窗口中输入如下命令:
>>loadlibrary(‘dll_test’, ’dll_test.h’) (1)
通过以上命令即将dll_test.dll加载到MATLAB工作空间中。
2)浏览动态库中的函数
成功加载动态链接库后便可调用库中提供的函数。与函数使用类似,在调用函数之前首先要明确函数各输入输出参数的含义及数据类型。一般情况下动态库编写者会提供相应函数的帮助文档,以便用户理解函数的含义并对其进行调用。动态链接库大多使用C或者C++语言编写,然而标准的C或C++数据类型与MATLAB所使用的数据类型不尽相同,因此调用函数前首先要弄清被调用函数参数对应于MATLAB环境下的数据类型。使用函数libfunctions可在MATLAB环境下查看动态库中函数的声明,并将原C函数中参数类型以对应MATLAB参数类型显示,之后便能正确的按照MATLAB语法规则进行调用。libfunctions用法如下:
libfunctions(‘libname’, ‘-full’)
参数libname为已加载到MATLAB工作空间的动态库文件名,-full为可选参数用于输出函数的详细说明。
>>libfunctions(‘dll_test’, ‘-full’) (2)
输入语句(2)后命令行中会显示所有dll_test库中的函数,如下:
Functions in library dll_test:
int32 add(int32, int32)
int32 sub(int32, int32)
3)调用动态库中的导出函数
明确了动态库中函数的参数类型后,便可利用MATLAB提供的calllib接口函数对库中函数进行调用。calllib函数使用方法如下:
[x1, ..., xN]=calllib(‘libname’, ‘funcname’, arg1, ...,argN)
参数libname表示被调用函数所在的库文件名,funcname为被调用的函数名称,arg1,…,argN为函数funcname的输入参数,x1,…,xN为函数funcname的返回值。以下为dll_test.dll中add函数的调用示例:
>> calllib(‘dll_test’, ‘add’, 1, 2)
ans=
3
4)卸载动态链接库
当不再需要对动态库中的函数进行访问后,应及时将动态库从MATLAB工作空间中卸载。与加载动态库类似MATLAB也提供对应的卸载动态库的命令unloadlibrary,例如:
>>unloadlibrary(‘dll_test’)
通过以上4步便可实现在MATLAB环境下对动态链接库导出函数的调用。在实际应用中通过调用硬件商提供的动态链接库或者将其提供的API函数编译为动态链接库,便可实现在MATLAB平台下实现对硬件资源的访问。
MS5803是瑞士Intersema公司生产的一款集成有压阻式压力传感器和ADC接口的SMD混合集成电路,具有体积小(6.2×6.4 mm)、稳定性好、低功耗(1 μA)、高分辨率、高精度等特点,其内置的24位A/D转换器可实现对压力和温度的采样,通过标准I2C和SPI接口与外部设备通信[5]。本设计以MATLAB为软件开发平台,MS5803为目标器件,通过DLL调用方式实现对传感器的数据采集,并对气压高度算法进行快速测试与验证。气压高度计的原型系统结构框图如图1所示[6]。
图1 气压高度计原型系统结构Fig.1 Structure diagram of a barometric altimetry prototype
图 1中GY7502为USB转SPI适配器,一端与笔记本相连,另一端与MS5803连接,MS5803选择工作在SPI接口模式。该原型系统通过一个简单的接口适配器便建立了PC与传感器的连接,之后即可按照一定的通信规则进行编程完成对MS5803数据采集,轻松的实现了数据由目标器件到上位机的传输,后续借助于PC强大的运算功能快速的对算法和模型进行测试。
下面以MATLAB环境下实现对MS5803数据的采集为例,具体介绍前述关于扩展MATLAB硬件访问能力的方法。
GY7502型USB-SPI适配器以动态链接库的方式提供了开发所需的接口函数并提供了各功能函数的头文件定义,开发者只需要熟悉各个接口函数的定义及其功能便能方便的实现对SPI接口器件的操作,而无需关注底层硬件的具体实现。以下为本设计中使用到了库函数声明。
//GY7502.h
DWORD __stdcall GY7502_Open();//打开设备
DWORD __stdcall GY7502_Close();//关闭设备
DWORD __stdcall GY7502_SetConfig(pGY7502_CONFIG_INFO pConfigInfo);
//设置通信频率及SPI总线模式
DWORD __stdcall GY7502_Read(pGY7502_DATA_INFO pDataInfo);//读 SPI总线
DWORD __stdcall
GY7502_Write (pGY7502_DATA_INFO pDataInfo);// 写SPI总线
pGY7502_CONFIG_INFO和pGY7502_DATA_INFO为GY7502.h定义的两种结构体数据类型分别用于配置GY7502适配器工作模式和作为接收或发送数据的缓存。
MS5803在出产的时候生产厂商已经对其进行了初始标定,并将标定系数C1~C6固化在内部的128位PROM中,传感器采样转换输出的原始数据D1和D2需要经过系数C1~C6按照MS5803数据手册提供的模型进行修正,才能计算出真实意义上的压力值和温度值。为此传感器每次上电后系统需要先读取出系数C1~C6,之后才能进行压力和温度的采样,基本工作流程如图2所示。
图2 数据采集基本工作流程Fig.2 Flow chart of data acquisition
下面给出在MATLAB环境下通过调用动态链接库的方法实现传感器数据采集的关键程序段。
%sample.m
%加载GY7502所需的动态链接库
loadlibrary GY7502 GY7502.h
%定义配置参数和读写缓冲
SetConfigInfo=libstruct('GY7502_CONFIG_INFO')
DataInfo=libstruct('GY7502_DATA_INFO')
D1=libstruct('GY7502_DATA_INFO')
D2=libstruct('GY7502_DATA_INFO')
...
%打开设备建立连接
calllib(‘GY7502’, ‘GY7502_Open’)
%配置GY7502工作模式
calllib (‘GY7502’, ‘GY7502_SetConfig’, GY7502_CONFIG_INFO)
%复位传感器,读取标定系数C1~C6
…
%启动一次采样
…
%读取压力和温度转换数值D1、D2
[result, D1]= calllib (‘GY7502’, ‘GY7502_Write’,DataReadD1)
[result, D2]= calllib (‘GY7502’, ‘GY7502_Write’,DataReadD2)
%计算温度T及温度补偿后的压力P
…
%采样结束断开连接
calllib(‘GY7502’, ‘GY7502_Close’)
%卸载动态链接库
unloadlibrary GY7502
完成数据采集之后,便可进行压力与高度换算。由于数据直接引入到MATLAB工作环境,借助于MATLAB强大的数值计算功能,极大地方便了后续算法及模型的测试工作,同时也降低了开发者的工作强度。
MATLAB强大的数值计算能力深受广大科技工作者的喜爱,但其对硬件的支持能力相对较弱。文中通过调用动态链接库的方法,增强了MATLAB对硬件的访问能力,使得开发者可以在MATLAB环境下直接对硬件进行操作,极大地方便了系统算法和模型的测试。
[1]杨波,亓波.精通Matlab7.0混合编程[M].北京:电子工业出版社,2006.
[2]张志涌.精通Matlab6.5版 [M].北京:北京航空航天大学出版社,2003.
[3]任哲.MFC Windows应用程序设计[M].2版.北京:清华大学出版社,2007.
[4]潘大夫,汪博,周志强.Matlab与C/C++混合编程技术研究[J].计算机应用,2009,30(2):465-469.PAN Da-fu,WANG Bo,ZHOU Zhi-qiang.Research on mixed programming technology of Matlab and C/C++[J].Computer Engineering and Design,2009,30(2):465-469.
[5]MEAS Switzerland SA.DS-MS5803-01BA.pdf[EB/OL].(2010-05-11)[2011-04-15].http://www.intersema.ch/index.php?option=com_rubberdoc&view=doc&id=88&format=raw.
[6]赵天成,饶和昌.一种基于MS5803和气象数据的高度测量方法[J].电子设计工程,2011,19(14):44-47.ZHAO Tian-cheng,RAO He-chang.A barometric altimetry method based on MS5803 and meteorological data[J].Electronic Design Engineering,2011,19(14):44-47.