C S函数从串行读取数据

时间:2014-12-20 14:04:44

标签: matlab serial-port simulink s-function

在我遇到的问题之后,尝试使用Simulink从COM端口读取,正如我在this discussion中所写,我想跟随Phil Goddard关于为此编写C S函数的建议。我的问题是我无法编写C代码,所以我希望得到一些帮助。 我在网上找到了关于用于串行通信的C S函数的这两个脚本:

1)

#define S_FUNCTION_NAME sfun_comport

#define S_FUNCTION_LEVEL 2

#include "simstruc.h"

#include "windows.h"

#include "Strsafe.h"

#define MDL_START

#if defined(MDL_START)

/* Function: mdlStart =================================================*/
static void mdlStart(SimStruct *S)
{
    HANDLE hCom;
    DCB dcb;
    COMMTIMEOUTS uCtm;
    char pcCommPort[10];
    uint8_T comport = 4;
      //-------------------------------------------------------------------
      StringCbPrintfA((STRSAFE_LPSTR)&pcCommPort,
                      sizeof(pcCommPort),
                      "COM%d",
                      comport);
      //-------------------------------------------------------------------
      hCom = CreateFileA (pcCommPort,
                          GENERIC_READ | GENERIC_WRITE,
                          0,
                          NULL,
                          OPEN_EXISTING,
                          0,
                          NULL);
      if (hCom == INVALID_HANDLE_VALUE)
      {
          ssSetErrorStatus(S,"COM-Port konnte nicht geoeffnet werden!");
          return;
      }
      //-------------------------------------------------------------------
      SecureZeroMemory(&dcb, sizeof(dcb));
      memset(&dcb, 0, sizeof(dcb));
      dcb.DCBlength = sizeof(dcb);
      dcb.BaudRate  = (uint16_T)9600;
      dcb.ByteSize  = 8;
      dcb.Parity    = NOPARITY;
      dcb.StopBits  = ONESTOPBIT;
      //-------------------------------------------------------------------
      uCtm.ReadIntervalTimeout         = MAXDWORD;
      uCtm.ReadTotalTimeoutMultiplier  = 0;
      uCtm.ReadTotalTimeoutConstant    = 0;
      uCtm.WriteTotalTimeoutMultiplier = 0;
      uCtm.WriteTotalTimeoutConstant   = 0;
      //-------------------------------------------------------------------
      if ((!SetCommState(hCom, &dcb)) | (!SetCommTimeouts(hCom, &uCtm)))
      {
          CloseHandle(hCom);
          ssSetErrorStatus(S,"Konfigurationsfehler des COM-Ports!");
          return;
      }
      //-------------------------------------------------------------------
      ssSetPWorkValue(S, 0, hCom);
  }
#endif
/* Function: mdlOutputs =================================================*/

static void mdlOutputs(SimStruct *S, int_T tid) {

    const real_T *u0 = (const real_T*) ssGetInputPortSignal(S,0);
    real_T       *y0 = ssGetOutputPortSignal(S,0);
    HANDLE hCom = (HANDLE*)ssGetPWorkValue(S, 0);
    uint32_T read_cnt;
    uint32_T write_cnt;
    char getbuffer[] = "test";
    char putbuffer[] = "Dies ist ein Test\r";
    //int i;
    //---------------------------------------------------------------------
    read_cnt = sizeof(putbuffer)-1;
    ReadFile(hCom, putbuffer, read_cnt, &read_cnt, NULL);
    //---------------------------------------------------------------------    
    write_cnt = sizeof(putbuffer)-1;
    WriteFile(hCom, putbuffer, write_cnt, &write_cnt, NULL);
    //---------------------------------------------------------------------
    Sleep(3000);
}
#define MDL_UPDATE

#if defined(MDL_UPDATE)

/* Function: mdlUpdate ================================================*/
static void mdlUpdate(SimStruct *S, int_T tid)
{
}
#endif
/* Function: mdlTerminate ===============================================*/

static void mdlTerminate(SimStruct *S) {

    CloseHandle((HANDLE*)ssGetPWorkValue(S, 0));
}



#ifdef  MATLAB_MEX_FILE    /* Is this file being compiled as a MEX-file? */
#include "simulink.c"      /* MEX-file interface mechanism */
#else
#include "cg_sfun.h"       /* Code generation registration function */
#endif

但是当我尝试按mex sfun_comport.c编译它时,它会返回以下错误:

C:\Program Files\MATLAB\R2013b\simulink\include\simulink.c(449) : warning C4995: 'sprintf': name was marked as #pragma deprecated 
C:\Program Files\MATLAB\R2013b\simulink\include\simulink.c(1692) : warning C4995: 'sprintf': name was marked as #pragma deprecated 
C:\Program Files\MATLAB\R2013b\simulink\include\simulink.c(1701) : warning C4995: 'sprintf': name was marked as #pragma deprecated 
C:\Program Files\MATLAB\R2013b\simulink\include\simulink.c(1724) : warning C4995: 'sprintf': name was marked as #pragma deprecated 
C:\Program Files\MATLAB\R2013b\simulink\include\simulink.c(2373) : warning C4995: 'sprintf': name was marked as #pragma deprecated 
C:\Program Files\MATLAB\R2013b\simulink\include\simulink.c(2380) : warning C4995: 'sprintf': name was marked as #pragma deprecated 
C:\Program Files\MATLAB\R2013b\simulink\include\simulink.c(2393) : warning C4995: 'sprintf': name was marked as #pragma deprecated 
C:\Program Files\MATLAB\R2013b\simulink\include\simulink.c(2402) : warning C4995: 'sprintf': name was marked as #pragma deprecated 
C:\Program Files\MATLAB\R2013b\simulink\include\simulink.c(2408) : warning C4995: 'sprintf': name was marked as #pragma deprecated 
C:\Program Files\MATLAB\R2013b\simulink\include\simulink.c(2448) : warning C4995: 'sprintf': name was marked as #pragma deprecated 
C:\Program Files\MATLAB\R2013b\simulink\include\simulink.c(2459) : error C2065: 'mdlInitializeSizes' : undeclared identifier 
C:\Program Files\MATLAB\R2013b\simulink\include\simulink.c(2459) : warning C4047: '=' : 'mdlInitializeSizesFcn' differs in levels of indirection from 'int' 
C:\Program Files\MATLAB\R2013b\simulink\include\simulink.c(2548) : error C2065: 'mdlInitializeSampleTimes' : undeclared identifier 
C:\Program Files\MATLAB\R2013b\simulink\include\simulink.c(2548) : warning C4047: '=' : 'mdlInitializeSampleTimesFcn' differs in levels of indirection from 'int' 
C:\Program Files\MATLAB\R2013b\simulink\include\simulink.c(2679) : warning C4013: 'mdlInitializeSizes' undefined; assuming extern returning int 
C:\Program Files\MATLAB\R2013b\simulink\include\simulink.c(2948) : warning C4013: 'mdlInitializeSampleTimes' undefined; assuming extern returning int 

  C:\PROGRA~1\MATLAB\R2013B\BIN\MEX.PL: Error: Compile of 'sfun_comport.c' failed. 

2)

#define S_FUNCTION_NAME  sfun_tryserial
#define S_FUNCTION_LEVEL 2


#include "simstruc.h" 
#include "windows.h" 
#include "strsafe.h" 
#include "stdio.h" 
#include "string.h" 
#include "stdlib.h" 


static void mdlStart(SimStruct *S) 
{ 
    HANDLE hCom; 
    DCB dcb; 
    COMMTIMEOUTS uCtm;     
    char pcCommPort[12]; 
    //char pcCommPort[10]="COM4"; 
    uint8_T comport = mxGetScalar(ssGetSFcnParam(S, 0)); 

    StringCbPrintfA((STRSAFE_LPSTR)&pcCommPort, sizeof(pcCommPort), "COM%d:", comport); 
    //--------------------------------------------------------------- 
    hCom = CreateFileA (pcCommPort, 
               GENERIC_READ | GENERIC_WRITE, 
               0, 
               NULL, 
               OPEN_EXISTING, 
               0, 
               NULL); 

    if (hCom == INVALID_HANDLE_VALUE) 
    { 
   ssSetErrorStatus(S,"COM-Port konnte nicht geoeffnet werden!"); 
        return; 
    } 
    //--------------------------------------------------------------- 
    SecureZeroMemory(&dcb, sizeof(dcb)); 
    memset(&dcb, 0, sizeof(dcb)); 
    dcb.DCBlength = sizeof(dcb); 
    dcb.BaudRate = (uint16_T)9600; 
    dcb.ByteSize = 8; 
    dcb.Parity = NOPARITY; 
    dcb.StopBits = ONESTOPBIT; 
    //dcb.fDtrControl = 0X01; //ENABLE 
    //dcb.fRtsControl = 0x01; //ENABLE 
    //---------------------------------------------------------------   
    uCtm.ReadIntervalTimeout = MAXDWORD; 
    uCtm.ReadTotalTimeoutMultiplier = 0; 
    uCtm.ReadTotalTimeoutConstant = 0; 
    uCtm.WriteTotalTimeoutMultiplier = 0; 
    uCtm.WriteTotalTimeoutConstant = 0; 
    //--------------------------------------------------------------- 
    if ((!SetCommState(hCom, &dcb)) | (!SetCommTimeouts(hCom, &uCtm))) 
    { 
        CloseHandle(hCom); 
        ssSetErrorStatus(S,"Konfigurationsfehler des COM-Ports!"); 
        return; 
    } 
    //--------------------------------------------------------------- 
    ssSetErrorStatus(S,"Konfigurationsfehler des COM-Ports!"); 
    ssSetPWorkValue(S, 0, &hCom); 
} 


static void mdlOutputs(SimStruct *S, int_T tid) 
{ 
    const real_T   *u0 = (const real_T*)ssGetInputPortSignal(S, 0); 
    real_T           *y0 = (real_T *)ssGetOutputPortRealSignal(S, 0); 

    uint32_T read_cnt; 
    uint32_T write_cnt; 
    char getbuffer[255] = {0}; 
    char putbuffer[255] = {0}; 

    HANDLE hCom = (HANDLE*)ssGetPWorkValue(S, 0); 

    //++++++++++++++++++++++++++++++++++++++++++++++ 
    if (ReadFile(hCom, getbuffer, sizeof(getbuffer), &read_cnt, NULL)) 
    { 
        // Daten auswerten, read_cnt enthält die Anzahl gelesener Bytes 
    } 
    else 
    { 
        // keine Daten empfangen 
        // z.B. Fehlermeldung oder nix machen 
    }     
     //++++++++++++++++++++++++++++++++++++++++++++++ 
    if (!WriteFile(hCom, putbuffer, write_cnt, &read_cnt, NULL)); 
    { 
        // Fehlermeldung, weil die Daten nicht verschickt werden konnten 
    } 
    //++++++++++++++++++++++++++++++++++++++++++++++ 
} 

static void mdlTerminate(SimStruct *S) 
{ 
    CloseHandle((HANDLE*)ssGetPWorkValue(S, 0)); 
} 

#ifdef  MATLAB_MEX_FILE    /* Is this file being compiled as a MEX-file? */
#include "simulink.c"      /* MEX-file interface mechanism */
#else
#include "cg_sfun.h"       /* Code generation registration function */
#endif

这会产生:

sfun_tryserial.c(20) : warning C4244: 'initializing' : conversion from 'double' to 'uint8_T', possible loss of data 
C:\Program Files\MATLAB\R2013b\simulink\include\simulink.c(449) : warning C4995: 'sprintf': name was marked as #pragma deprecated 
C:\Program Files\MATLAB\R2013b\simulink\include\simulink.c(1692) : warning C4995: 'sprintf': name was marked as #pragma deprecated 
C:\Program Files\MATLAB\R2013b\simulink\include\simulink.c(1701) : warning C4995: 'sprintf': name was marked as #pragma deprecated 
C:\Program Files\MATLAB\R2013b\simulink\include\simulink.c(1724) : warning C4995: 'sprintf': name was marked as #pragma deprecated 
C:\Program Files\MATLAB\R2013b\simulink\include\simulink.c(2373) : warning C4995: 'sprintf': name was marked as #pragma deprecated 
C:\Program Files\MATLAB\R2013b\simulink\include\simulink.c(2380) : warning C4995: 'sprintf': name was marked as #pragma deprecated 
C:\Program Files\MATLAB\R2013b\simulink\include\simulink.c(2393) : warning C4995: 'sprintf': name was marked as #pragma deprecated 
C:\Program Files\MATLAB\R2013b\simulink\include\simulink.c(2402) : warning C4995: 'sprintf': name was marked as #pragma deprecated 
C:\Program Files\MATLAB\R2013b\simulink\include\simulink.c(2408) : warning C4995: 'sprintf': name was marked as #pragma deprecated 
C:\Program Files\MATLAB\R2013b\simulink\include\simulink.c(2448) : warning C4995: 'sprintf': name was marked as #pragma deprecated 
C:\Program Files\MATLAB\R2013b\simulink\include\simulink.c(2459) : error C2065: 'mdlInitializeSizes' : undeclared identifier 
C:\Program Files\MATLAB\R2013b\simulink\include\simulink.c(2459) : warning C4047: '=' : 'mdlInitializeSizesFcn' differs in levels of indirection from 'int' 
C:\Program Files\MATLAB\R2013b\simulink\include\simulink.c(2548) : error C2065: 'mdlInitializeSampleTimes' : undeclared identifier 
C:\Program Files\MATLAB\R2013b\simulink\include\simulink.c(2548) : warning C4047: '=' : 'mdlInitializeSampleTimesFcn' differs in levels of indirection from 'int' 
C:\Program Files\MATLAB\R2013b\simulink\include\simulink.c(2679) : warning C4013: 'mdlInitializeSizes' undefined; assuming extern returning int 
C:\Program Files\MATLAB\R2013b\simulink\include\simulink.c(2948) : warning C4013: 'mdlInitializeSampleTimes' undefined; assuming extern returning int 

  C:\PROGRA~1\MATLAB\R2013B\BIN\MEX.PL: Error: Compile of 'sfun_provaseriale2.c' failed. 

你可以注意到两个S函数之间的常见错误是:

'mdlInitializeSizes'
'mdlInitializeSizesFcn'
'mdlInitializeSampleTimes'
'mdlInitializeSampleTimesFcn'
'mdlInitializeSizes'

你有什么建议来解决这些错误吗?

PS:我有MATLAB 2013b 64位,64位Windows 7,Microsoft Visual C ++ 2010(32位)作为编译器(它在64位matlab中运行良好,可生成mex文件)

1 个答案:

答案 0 :(得分:0)

您仍然需要自己编写这些功能。从名称中可以看出,它们定义了S-Function的大小和采样时间。它们是完整且功能齐全的S-Function的必需组件。

例如:

static void mdlInitializeSizes(SimStruct *S)描述了Simulink用于确定S函数块特征(输入,输出,状态等的数量)的大小信息。

static void mdlInitializeSampleTimes(SimStruct *S)用于指定S函数的采样时间。

另见:

http://de.mathworks.com/help/simulink/sfg/mdlinitializesizes.html http://de.mathworks.com/help/simulink/sfg/mdlinitializesampletimes.html