饒和昌,趙英俊
(華中科技大學 機械科學與工程學院,湖北 武漢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.