MEX-файл для вывода импульса в петле на плату DAQ - PullRequest
0 голосов
/ 26 апреля 2010

Я решил, что должен использовать MEX-файл для вывода цифровых импульсов в цикле (40 кГц) из Matlab на мою DAQ-плату. У меня есть несколько API от поставщика DAQ-Board, но я действительно не знаю, являются ли они полезно. Это большая документация на веб-сайте Mathworks о MEX-файле и API, которые просто запутывают меня. Поэтому я спрашиваю здесь, может ли кто-нибудь сориентировать меня или показывает пример кода, чтобы понять это !!

1 Ответ

0 голосов
/ 10 февраля 2011

Некоторое время назад я написал небольшой пакет winsock, использующий функции mex, потому что у tcpip в Matlab были проблемы с отправкой больших объемов данных (например, изображений). Я мало что знаю о мекс-функциях, кроме того, что я узнал, чтобы заставить этот пакет работать, и даже это было довольно давно. Но вот некоторые из моих предыдущих заметок и одна из функций, которые я написал в качестве примера, которые, надеюсь, могут вам помочь.

Прежде чем писать какие-либо мекс-функции, вам необходимо настроить Matlab для возможности их компиляции. Это можно сделать, введя mex -setup в командной строке matlab и следуя инструкциям, которые он дает. Я настроил его на использование компилятора Visual Studio (обратите внимание, что для этого параметра необходимо установить Visual Studio).

После настройки компилятора вы скомпилируете свои mex-функции, введя «mex filename.cpp» в командной строке Matlab. Это создает файл .mexw32 (в предположении 32-разрядного), который Matlab использует при вызове вашей функции mex.

Чтобы написать саму функцию mex, вы пишете m-файл, чтобы объявить ее и предоставить комментарии, а также файл cpp с фактической реализацией.

Например, вот один из m-файлов, которые я написал:

function sendColorImage( socketHandle, colorImage ) %#ok<*INUSD>
%SENDCOLORIMAGE Sends a color image over the given socket
%   This function sends a color image over the socket provided.  The image
%   is really just an MxNx3 matrix.  Note that this function sends the
%   image data in the order in which Matlab stores it (non-interlaced
%   column major order), which is different from most other languages.
%   This means the red values for every pixel will be sent first, then the
%   green values, then the blue values.  Furthermore, the scanlines read
%   from the top of the image to the bottom, starting at the left side of
%   the image.
%
%   socketHande - A handle to the socket over which the image should be
%   sent.  This handle is returned by the openSocket function when the
%   socket is first created.
%
%   colorImage - An MxNx3 matrix containing the image data.  This matrix
%   should be in the same format as a matrix loaded using Matlabs imread
%   function.
%
%   This is a mex function and is defined in its corresponding .cpp file.

А вот соответствующий файл cpp. Обратите внимание, что я только что создал свой собственный формат сообщения и имел соответствующий код C #, который анализировал его обратно из потока байтов.

// Instruct the compiler to link with wsock32.lib (in case it isn't specified on the command line)
#pragma comment(lib,"wsock32.lib")

#include "mex.h"
#include <winsock2.h>
#include <cstdio>
#include "protocol.h"

// See the corresponding .m file for documentation on this mex function.
void mexFunction(int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[]){

    char errorMessage[100];

    // Validate input and output arguments
    if(nlhs != 0)
        mexErrMsgTxt("There are no output arguments for this function.");
    if(nrhs != 2)
        mexErrMsgTxt("Must have 2 input parameters: the socket handle and the MxNx3 image matrix");
    if(!mxIsClass(prhs[0], "uint32"))
        mexErrMsgTxt("The first input parameter should be a uint32 containing the socket handle");
    if(!mxIsClass(prhs[1], "uint8") || mxGetNumberOfDimensions(prhs[1]) != 3 || mxGetDimensions(prhs[1])[2] != 3)
        mexErrMsgTxt("The 2nd input parameter should be an MxNx3 uint8 matrix containing the image");

    // Get the socket handle
    SOCKET socketHandle = (int)(mxGetPr(prhs[0])[0]);

    // Set up the header
    int frameWidth = mxGetDimensions(prhs[1])[1];
    int frameHeight = mxGetDimensions(prhs[1])[0];
    int header[3];
    header[0] = COLOR_IMAGE;
    header[1] = frameWidth;
    header[2] = frameHeight;

    // Send the header
    int bytesSent;
    int totalBytesSent = 0;
    while(totalBytesSent < 3*sizeof(int)){
        bytesSent = send(socketHandle, ((char*)header) + totalBytesSent, 3*sizeof(int) - totalBytesSent, 0);
        if(bytesSent == SOCKET_ERROR){
            sprintf(errorMessage, "Error sending image header over the socket: %d", WSAGetLastError());
            mexErrMsgTxt(errorMessage);
        }
        totalBytesSent += bytesSent;
    }

    // Send the image
    totalBytesSent = 0;
    int totalBytesToSend = frameWidth * frameHeight * 3;
    char* dataPointer = (char*)mxGetData(prhs[1]);
    while(totalBytesSent < totalBytesToSend){
        bytesSent = send(socketHandle, dataPointer + totalBytesSent, totalBytesToSend - totalBytesSent, 0);
        if(bytesSent == SOCKET_ERROR){
            sprintf(errorMessage, "Error sending image over the socket: %d", WSAGetLastError());
            mexErrMsgTxt(errorMessage);
        }
        totalBytesSent += bytesSent;
    }
}
...