在我遇到的问题之后,尝试使用 Simulink 从 COM 端口读取,正如我在这个讨论中所写的那样,我想遵循 Phil Goddard 的建议,为此编写一个 C S-function。我的问题是我不会写C代码,所以我希望你能有所帮助。我在网上找到了这两个关于用于串行通信的 C S-Function 的脚本:
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-Function 之间的常见错误是:
'mdlInitializeSizes'
'mdlInitializeSizesFcn'
'mdlInitializeSampleTimes'
'mdlInitializeSampleTimesFcn'
'mdlInitializeSizes'
您对修复这些错误有什么建议吗?
PS:我有 MATLAB 2013b 64 位、64 位 Windows 7、Microsoft Visual C++ 2010(32 位)作为编译器(它在 64 位 matlab 中运行良好以生成 mex 文件)