?? utitech.c
字號(hào):
len = ReadSimComm(lpPort->mbCid, (LPSTR) lpPort->mbRspBuffer, 1024);
#endif
if (len < 0) {
/* error received on COM port, log error message and continue */
UdprotCheckErrors(lpPort);
}
/* indicate whether port is quiet */
return (len == 0);
} /* WaitForQuietPort */
/***********************************************************************/
/** Write message to indicated port,
return 1 if successful,
0 if not successful,
-1 if serious error **/
int
WINAPI
WritePortMsg (LPPORT lpPort, LPUDMSG lpMsg)
{
int len;
int status;
/* initialize return status */
status = 1;
/* write message to serial port, get status */
#ifndef SIMULATING
len = WriteComm(lpPort->mbCid, (LPSTR) lpMsg->mmData, lpMsg->mmSize);
#else
len = WriteSimComm(lpPort->mbCid, (LPSTR) lpMsg->mmData, lpMsg->mmSize);
#endif
if ((len < 0) || (len != lpMsg->mmSize)) {
/* error occurred on write, identify and display if appropriate */
if (UdprotCheckErrors(lpPort))
status = -1;
else status = 0;
}
/* indicate success or failure */
return (status);
} /* WritePortMsg */
/***********************************************************************/
/** get response from port,
return 1 if successful,
0 if not successful,
-1 if serious error **/
int
WINAPI
ReadPortMsg (LPPORT lpPort)
{
int len;
int status;
/* initialize return status */
status = 0;
/* attempt to read data from COM port */
len = 0;
#ifndef SIMULATING
len = Utitech_ReadComm(lpPort);
/*len = ReadComm(lpPort->mbCid,
(LPSTR) &lpPort->mbRspBuffer[lpPort->mbRspIndex],
INQSIZE - lpPort->mbRspIndex);*/
#else
len = ReadSimComm(lpPort->mbCid,
(LPSTR) &lpPort->mbRspBuffer[lpPort->mbRspIndex],
INQSIZE - lpPort->mbRspIndex);
#endif
if (len <= 0) {
/* if ReadComm() result < 0, it is -count and an error has occurred */
len = -len; /* get actual length count */
/* check for serious errors, print debug messages showing problem */
if (UdprotCheckErrors(lpPort)) {
/* serious error encountered, indicate problem */
status = -1;
return (status);
}
} else {
/* indicate data received OK */
status = 1;
}
/* check length of message received, if any */
if (len > 0) {
/* update length of message received so far */
//lpPort->mbRspIndex += len;
}
/* indicate whether data was received OK */
return (status);
} /* ReadPortMsg */
/***********************************************************************/
/** indicate whether port has data in receive buffer **/
BOOL
WINAPI
PortHasData (LPPORT lpPort)
{
/* always indicate port has data -- at least, potentially */
return (TRUE);
} /* PortHasData */
/***********************************************************************
***********************************************************************
* PLC SIMULATION ROUTINES *
***********************************************************************
***********************************************************************/
#ifndef SIMULATING
BOOL WINAPI IsSimulatorEnabled (void)
{
return (FALSE);
} /* IsSimulatorEnabled */
#else
BOOL WINAPI IsSimulatorEnabled (void)
{
return (TRUE);
} /* IsSimulatorEnabled */
/** The following routines simulate a simple PLC-type device for testing
purposes.
One simulated PLC is implemented for each of COM ports 1..4.
The simulation has two memory segments:
NAME ADDRESS RANGE DESCRIPTION FUNCTION
V 1..512 variable memory holds value steady
C 1..512 counter memory increments each time read
Addressing wraps around, so V814 = V((814-1) mod 512)+1 = V302
Messages are limited to no more than 100 characters, including the
leading colon, checksum, and trailing semicolon.
Read messages and write messages can access up to 22 consecutive
locations (i.e. 44 bytes) within a memory type:
Write to V :81AAAANN[CCCC]....[CCCC]XX;
return value is :81AAAANNXX;
Write to C :82AAAANN[CCCC]....[CCCC]XX;
return value is :82AAAANNXX;
Read from V :01AAAANNXX;
return value is :01AAAANN[CCCC]...[CCCC]XX;
Read from C :02AAAANNXX;
return value is :02AAAANN[CCCC]...[CCCC]XX;
where AAAA represents a 4-character hex ASCII address
NN represents a 2-character hex ASCII count
CCCC represents a 4-character hex ASCII value
XX represents a 2-character hex ASCII checksum
Any command which contains invalid hex ASCII characters, an odd number
of bytes, or an invalid checksum will receive an error response
:000000000000FF;
Any command BB besides 01, 02, 81, or 82 will receive an error response
:00BBAAAANN00XX;
which echos back the first part of the bad command.
Any valid command that has a bad address or a bad length (i.e. not
enough characters, count = 0, or number of write values does not match
the count) will receive an error response
:00BBAAAANNDDXX;
where for a write, DD represents the number of good values received,
and for a read, DD represents the number of values that will fit.
Only if the message is valid will the read or write be performed.
**/
/* data storage for simulated PLC */
typedef struct tagSIM_PLC {
WORD V[512];
WORD C[512];
} SIM_PLC;
SIM_PLC sim_plc [4];
/* communications buffers for simulated I/O channels */
typedef struct tagSIM_BUF {
char read[100+1];
char write[100+1];
} SIM_BUF;
SIM_BUF sim_buf [4];
BOOL sim_buf_first = TRUE;
extern BOOL SimulatorWritePaused;
extern BOOL SimulatorReadPaused;
static VOID WINAPI InitializeSimulator (void);
/***********************************************************************/
/* initialize PLC simulator */
static
VOID
WINAPI
InitializeSimulator (void)
{
int portID;
sim_buf_first = FALSE;
for (portID = 0; portID < 4; portID++)
sim_buf[portID].read[0] = 0;
debug ("Simulated I/O -- for test purposes only!");
} /* InitializeSimulator */
/***********************************************************************/
/** simulate start-up of communication with COM port **/
BOOL
WINAPI
OpenPort(LPPORT lpPort)
{
char st [81];
/* set COM port ID */
lstrcpy (st, &lpPort->mbPortName[3]);
lpPort->mbCid = atoi (st) - 1;
/* check whether valid for simulator */
if ((lpPort->mbCid < 0) || (3 < lpPort->mbCid)) {
/* indicate selected COM port cannot be opened */
lpPort->mbCid = IE_BADID;
UdprotReportOpenErrorCode(lpPort);
/* indicate error */
return (FALSE);
}
/* indicate success */
return (TRUE);
} /* OpenPort */
/***********************************************************************/
/** simulate shut-down of communication with COM port **/
void
WINAPI
ClosePort(LPPORT lpPort)
{
} /* ClosePort */
/***********************************************************************/
/** simulate COM port read from PLC **/
static
int ReadSimComm(int idComDev, void FAR *lpvBuf, int cbRead)
{
int portID;
int len;
LPSTR read_buf;
/* ensure readbacks are clear the first time */
if (sim_buf_first) {
InitializeSimulator ();
}
/* indicate nothing read if simulator is paused */
if (SimulatorReadPaused)
return (0);
/* force COM port number to 0..3 */
portID = idComDev & 0x03;
/* select appropriate read buffer, get length */
read_buf = (LPSTR) sim_buf[portID].read;
len = lstrlen (read_buf);
/* ensure length is within limits */
if (len > cbRead)
len = cbRead;
if (cbRead > len)
cbRead = len;
/* copy read buffer to destination */
_fstrncpy ((LPSTR) lpvBuf, read_buf, len);
/* clear read buffer */
read_buf[0] = '\0';
/* return length of string */
return (len);
} /* ReadSimComm */
/***********************************************************************/
/** simulate COM port write to PLC
prepare read response, return written length **/
static
int WriteSimComm(int idComDev, const void FAR *lpvBuf, int cbWrite)
{
int portID;
int len;
LPSTR write_buf, read_buf, ptr, rsp;
int cks, cmd;
WORD addr, count;
WORD num_val;
int errflg;
BOOL bad_cmd;
SIM_PLC *plc;
/* ensure readbacks are clear the first time */
if (sim_buf_first) {
InitializeSimulator ();
}
/* indicate nothing written if simulator is paused */
if (SimulatorWritePaused)
return (0);
/* force COM port number to 0..3 */
portID = idComDev & 0x03;
/* select appropriate write, read buffers */
write_buf = (LPSTR) sim_buf[portID].write;
read_buf = (LPSTR) sim_buf[portID].read;
/* select appropriate simulated PLC memory */
plc = &sim_plc[portID];
/* clear response */
read_buf[0] = 0;
/* get length of string, ensure within limits */
if (cbWrite > 100)
cbWrite = 100;
len = cbWrite;
/* copy source to write buffer, append terminating zero */
_fstrncpy (write_buf, (LPSTR) lpvBuf, len);
write_buf[len] = 0;
/* check whether command has valid length, delimiters, checksum */
if (!IsCommandValid (write_buf, len)) {
/* bad or corrupt message, return error indicator */
lstrcpy (read_buf, (LPSTR) ":0000000000FF;");
/* return length written to simulator */
return (cbWrite);
}
/* initialize pointer, scan length */
ptr = write_buf+1;
len -= 4;
/* initialize flag */
bad_cmd = FALSE;
/* get command, update pointer and length, check for error */
cmd = (int) GetHexVal (ptr, 2, &errflg);
if ((cmd != 0x01) && (cmd != 0x02) && (cmd != 0x81) && (cmd != 0x82)) {
/* indicate bad command */
bad_cmd = TRUE;
}
ptr += 2; len -= 2;
/* get address, update pointer and length, check for error */
if (len < 4) {
/* indicate bad command */
bad_cmd = TRUE;
/* pad the end with zeros */
while (len < 4) {
ptr[len++] = '0';
}
}
addr = (WORD) GetHexVal (ptr, 4, &errflg);
ptr += 4; len -= 4;
/* get count, update pointer and length, check for error */
if (len < 2) {
/* indicate bad command */
bad_cmd = TRUE;
/* pad the end with zeros */
while (len < 2) {
ptr[len++] = '0';
}
}
count = (WORD) GetHexVal (ptr, 2, &errflg);
if (count == 0)
/* indicate bad command */
bad_cmd = TRUE;
ptr += 2; len -= 2;
/* check whether command is a read or a write */
num_val = 0;
if ((cmd == 0x81) || (cmd == 0x82)) {
/* write, check count vs. number of values */
if (count * 4 != (WORD) len) {
/* indicate bad command */
bad_cmd = TRUE;
/* determine number of complete values supplied */
num_val = (WORD) (len / 4);
}
}
if ((cmd == 0x01) || (cmd == 0x02)) {
/* read, check count vs. available length */
if (count * 4 > 88) {
/* indicate bad command */
bad_cmd = TRUE;
/* determine max number of values that will fit */
num_val = 88 / 4;
}
}
/* check whether command is invalid */
if (bad_cmd) {
/* construct and return error message */
rsp = read_buf;
*(rsp++) = ':';
rsp = put_hex_byte (rsp, 0x00);
rsp = put_hex_byte (rsp, (BYTE) cmd);
rsp = put_hex_word (rsp, addr);
rsp = put_hex_byte (rsp, (BYTE) count);
rsp = put_hex_byte (rsp, (BYTE) num_val);
len = (int) (rsp - read_buf);
cks = BldCks (read_buf+1, len-1, &errflg);
rsp = put_hex_byte (rsp, (BYTE) cks);
*(rsp++) = ';';
*rsp = 0;
/* return length written to simulator */
return (cbWrite);
}
/* command is valid, prepare beginnings of response */
rsp = read_buf;
*(rsp++) = ':';
rsp = put_hex_byte (rsp, (BYTE) cmd);
rsp = put_hex_word (rsp, addr);
rsp = put_hex_byte (rsp, (BYTE) count);
/* get (address - 1) mod 512 */
addr = (WORD) ((addr - 1) & 0x01FF);
/* determine whether to handle read or write */
if ((cmd & 0x80) == 0) {
/* command is a read */
while (count > 0) {
/* get appropriate value */
if (cmd == 0x01) {
num_val = plc->V[addr];
} else {
(plc->C[addr])++;
num_val = plc->C[addr];
}
/* place value in return message */
rsp = put_hex_word (rsp, num_val);
/* advance address and decrement count */
addr = (WORD) ((addr + 1) & 0x01FF);
count--;
}
} else {
/* command is a write */
while (count > 0) {
/* acquire value from write message */
num_val = (WORD) GetHexVal (ptr, 4, &errflg);
ptr += 4; len -= 4;
/* store appropriate value */
if (cmd == 0x81) {
plc->V[addr] = num_val;
} else {
plc->C[addr] = num_val;
}
/* advance address and decrement count */
addr = (WORD) ((addr + 1) & 0x01FF);
count--;
}
}
/* command complete, fill in remainder of response */
len = (int) (rsp - read_buf);
cks = BldCks (read_buf+1, len-1, &errflg);
rsp = put_hex_byte (rsp, (BYTE) cks);
*(rsp++) = ';';
*rsp = 0;
/* return length written to simulator */
return (cbWrite);
} /* WriteSimComm */
#endif
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -