C S-function to read data from serial

1.9k Views Asked by At

After issues I met, trying to read from COM port with Simulink, as I wrote in this discussion, I would like to follow Phil Goddard's suggestion on writing a C S-function for that. My problem is that I am not able to write C-code, so I hope in some help from you. I have found this two scripts on the net about C S-function for serial communication:

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

But when I try to compile it by mex sfun_comport.c it returns following errors:

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

This produces:

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. 

As you can notice common errors between two S-function are about:

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

Do you have some suggestion to fix those errors ?

PS: I have MATLAB 2013b 64-bit, 64-bit Windows 7, Microsoft Visual C++ 2010 (32-bit) as compiler (it has worked fine in 64-bit matlab to produce mex files)

1

There are 1 best solutions below

0
On

You still have to write those functions by yourself. As you can see from their names, they define the sizes and sample time of the S-Function. They are required components of a complete and functional S-Function.

For example:

static void mdlInitializeSizes(SimStruct *S) describes the sizes information that is used by Simulink to determine the S-function block's characteristics (number of inputs, outputs, states, etc.).

static void mdlInitializeSampleTimes(SimStruct *S) is used to specify the sample time(s) for your S-function.

See also:

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