?? udbldmsg.c
字號:
/* starting address, number of items to read */
ptr = put_bin_word (ptr, addr1); len+=2;
ptr = put_bin_word (ptr, (BYTE) numRd); len+=2;
/* get length, allowing for checksum */
// len = (WORD) ((unsigned long)(ptr - (LPSTR) msg) + 1);
/* checksum */
// 2/29/2000 modify by Chen jun
cks = CRC16((LPSTR)msg,len); // Checksum
//cks = BldCks ((LPSTR) &msg[0], len-1, &errflg);
*ptr++ = cks%256; len += 1;
*ptr++ = cks/256; len += 1;
/* return the address and the length of the message built */
*plpMsg = (LPSTR) msg;
if (Verbose)
ShowBldMsg ((LPSTR) &msg[0], len);
return (len);
}
/* BldRead */
/***********************************************************************/
/** build message to write data to a point in the PLC,
return length of message **/
/************************************************************************\
Note: The last four arguments to this routine are protocol-dependent.
Modify them as required.
\************************************************************************/
WORD
WINAPI
BldWrite(BYTE plcAddr, /* 2/28/2000 Modify by Chen jun local PLC address */
LPSTR *plpMsg, /* pointer to where the message is stored */
BYTE FAR *pData, /* pointer to data values to be sent */
BYTE plcDataType,/* type of device data to generate */
BYTE DDEType, /* type of data to transfer */
WORD addr1, /* address of point(s) to be accessed */
WORD numWrt) /* number of items to write */
{
LPSTR ptr;
BYTE msgCmd;
WORD len;
WORD cks;
WORD i;
int b;
int errflg;
len = 0;
/* determine message command */
// 3/1/2000 modify by chen jun
//msgCmd = (BYTE) (plcDataType | 0x80);
switch (plcDataType){
case ITEM_HOLDING_COIL:
msgCmd = 15;
break;
case ITEM_HOLDING_REG:
msgCmd = 16;
break;
}
/* initialize message buffer pointer */
ptr = (LPSTR) msg;
/* message type */
//ptr = put_bin_byte (ptr, msgCmd);
ptr = put_bin_byte (ptr, plcAddr); len+=1;
ptr = put_bin_byte (ptr, msgCmd); len+=1;
/* starting address, number of items to write */
ptr = put_bin_word (ptr, addr1); len+=2;
/* number of byte to write */
b = numWrt;
if(plcDataType == ITEM_HOLDING_COIL)
{
ptr = put_bin_word (ptr, (WORD) numWrt); len+=2;
ptr = put_bin_byte (ptr, (BYTE)(b/8+1)); len+=1;
/* data for each item */
for( i=0; i<(numWrt/8+1); i++ ) {
ptr = put_bin_byte (ptr, (BYTE) (*(INTG FAR *)pData));
pData += 1;
len += 1;
}
}
else{
ptr = put_bin_word (ptr, (WORD) numWrt); len+=2;
ptr = put_bin_byte (ptr, (BYTE)(b*2)); len+=1;
/* data for each item */
for( i=0; i<numWrt; i++ ) {
ptr = put_bin_word (ptr, (WORD) (*(INTG FAR *)pData));
pData += 2;
len += 2;
}
}
/* get length, allowing for checksum */
//len = (WORD) ((unsigned long)(ptr - (LPSTR) msg) + 1);
/* checksum */
//cks = BldCks ((LPSTR) &msg[0], len-1, &errflg);
// ptr = put_bin_byte (ptr, cks);
cks = CRC16((LPSTR)msg,len);
//cks = BldCks ((LPSTR) &msg[0], len-1, &errflg);
*ptr++ = cks%256; len += 1;
*ptr++ = cks/256; len += 1;
//Modify end
/* return the address and the length of the message built */
*plpMsg = (LPSTR) msg;
if (Verbose)
ShowBldMsg ((LPSTR) &msg[0], len);
return (len);
} /* BldWrite */
/***********************************************************************/
/* display built message for tracing purposes */
static
VOID
WINAPI
ShowBldMsg (LPSTR lpStr, WORD len)
{
BYTE FAR *rd;
int i, n, L;
int max_str, max_msg;
/* get message length and pointer */
n = (int) len;
rd = (BYTE FAR *) lpStr;
/* get number of characters that can be stored in display string */
max_str = DBG_BUF_SIZE - 1;
/* format message for display */
sprintf (dbgBuf, "BldMsg (%d) -- ", n);
/****************************************************************\
Format the rest of the message and append it to dbgBuf.
Depending on the protocol, it may be appropriate to
convert bytes to hex ASCII, or simply copy an ASCII string.
\****************************************************************/
L = strlen (dbgBuf);
if (n == 0) {
sprintf (&dbgBuf[L], "<nothing>");
} else {
if (bBldSendMsgInBinary) {
/* convert characters to hex ASCII */
max_msg = (max_str - L) / 2;
if (n > max_msg)
/* make sure message doesn't overflow buffer */
n = max_msg;
if (n > 0) {
for (i = 1; i <= n; i++) {
sprintf (&dbgBuf[L], "%02X", *(rd++));
L += strlen (&dbgBuf[L]);
}
}
} else {
/* take characters just as they are */
max_msg = max_str - L;
if (n > max_msg)
/* make sure message doesn't overflow buffer */
n = max_msg;
f_lstrncpy (&dbgBuf[L], (LPSTR) rd, n);
dbgBuf[L+n] = '\0';
}
}
/* output display string to logger */
debug (dbgBuf);
} /* ShowBldMsg */
/***********************************************************************/
/** verify that the command header format is valid,
return the expected total length of the message **/
BOOL
WINAPI
IsHeaderValid (LPSTR lpStr, int len, int *total_len)
{
/*******************************************************************\
The contents of this routine are protocol dependent.
This routine is called at the point when we have received
enough bytes to pick the length out of the message header.
Validate the message header and calculate the total length
of the message. Then return the new expected length.
The example code below assumes a header of the form
:BBAAAANN
where response to a write will be of the form
:BBAAAANNXX;
and the response to a read will be of the form
:BBAAAANN[CCCC]....[CCCC]XX;
where BB is a command in hex ASCII
AAAA is an address in hex ASCII
NN is a number of words in hex ASCII
CCCC is a word value in hex ASCII
XX is a checksum in hex ASCII
Alternatively, an error message may be received, which will
have one of the following forms:
:000000000000FF;
for a garbled message
:00BBAAAANN00XX;
for an invalid command BB
:00BBAAAANNDDXX;
for an invalid number of "cells" to read or write
So by the ninth character, we know how many are coming.
\*******************************************************************/
int num_words, errflg;
BYTE cmd;
BOOL valid;
/* initialize return status, length */
valid = TRUE;
*total_len = len;
/* check start of message */
if (lpStr[0] != ':')
valid = FALSE;
/* get command */
if (valid) {
cmd = (BYTE) GetHexVal (lpStr+1, 2, &errflg);
if (errflg)
valid = FALSE;
}
/* check for error message */
if (valid) {
if (cmd == 0x00) {
/* error message, set up for response length */
*total_len = 16;
} else {
/* get number of words handled by message */
num_words = (int) GetHexVal (lpStr+7, 2, &errflg);
if (errflg) {
valid = FALSE;
} else {
/* check whether read or write */
if ((cmd & 0x80) != 0) {
/* command is a write, response is fixed length */
*total_len = 12;
} else {
/* command is a read, response is based on count */
*total_len = 12 + num_words * 4;
}
}
}
}
/* indicate whether message header is valid */
return (valid);
} /* IsHeaderValid */
/***********************************************************************/
/** verify that the command format is valid **/
BOOL
WINAPI
IsCommandValid (LPSTR lpStr, int len)
{
/*******************************************************************\
The contents of this routine are protocol dependent.
The following example assumes that the received message is in
the format
:AABBCCDDEE...ZZ;
where AA, BB, ..., ZZ are pairs of hexadecimal digits,
and ZZ is the checksum for the message.
\*******************************************************************/
int cks, byteval, err1, err2;
BOOL ok;
/* initialize return value */
ok = TRUE;
/* check length of command */
if ((len < 6) || ((len & 0x01) != 0)) {
/* too short, or odd number of bytes */
ok = FALSE;
} else {
/* check beginning, ending characters */
if ((lpStr[0] != ':') || (lpStr[len-1] != ';')) {
/* invalid delimiters */
ok = FALSE;
} else {
/* calculate checksum */
cks = BldCks (lpStr+1, len-4, &err1);
/* compare to checksum in message */
byteval = (int) GetHexVal (lpStr+(len-3), 2, &err2);
if (err1 || err2 || (cks != byteval))
/* invalid characters or mismatched checksum */
ok = FALSE;
}
}
/* indicate success or failure */
return (ok);
} /* IsCommandValid */
/***********************************************************************/
/** convert indicated message to binary,
return TRUE if resulting string is valid binary data **/
BOOL
WINAPI
GetMsgAsBinary (LPSTR lpStr, int *len)
{
/*******************************************************************\
The contents of this routine are protocol dependent.
The following example assumes that the received message is in
the format
:AABBCCDDEE...ZZ;
where AA, BB, ..., ZZ are pairs of hexadecimal digits,
and ZZ is the checksum for the message.
The checksum, leading ':' and trailing ';' characters are ignored.
\*******************************************************************/
BYTE FAR *rsp;
LPSTR cp;
int i;
BOOL valid, ok;
/* initialize return value */
valid = TRUE;
/* convert string from ASCII to binary */
rsp = (BYTE FAR *) lpStr; /* pointer to binary string */
cp = lpStr + 1; /* pointer to ASCII string */
i = *len; /* length of ASCII string */
if (i >= 4) /* check length */
i = i - 4; /* drop head, tail, checksum */
else i = 0;
i = i / 2; /* length of the response */
*len = i; /* return length of binary */
while (i--) { /* for each ASCII pair */
*(rsp++) = ah_to_bin (cp, &ok); /* convert it and save byte */
valid = (valid && ok); /* identify if non-hex char */
cp += 2; /* point to next ASCII pair */
}
/* indicate whether binary message is valid */
return (valid);
} /* GetMsgAsBinary */
/***********************************************************************/
/** determine size of block needed for message to read data
returns size for a new block of data
and size for extending an existing block of data **/
/************************************************************************\
Note: The last four arguments to this routine are protocol-dependent.
Modify them as required.
\************************************************************************/
VOID
WINAPI
GetBldMsgReadBlockSizes (WORD *blockSize,
WORD *extSize,
BYTE msgType,
BYTE plcDataType,
WORD addr1,
WORD count)
{
WORD len;
WORD bytesToWrite;
/* determine length of data */
bytesToWrite = (WORD) (count * 2);
/* length of characters needed to specify data */
len = 0;
/* return length of data extension */
*extSize = len;
/** allow for type, address prefix, length count: TT AAAA NN **/
len += 8;
/** allow for leading ':', checksum XX, and trailing ';' */
len += 4;
/* return length of block */
*blockSize = len;
} /* GetBldMsgReadBlockSizes */
/***********************************************************************/
/** determine size of block needed for message to write data
returns size for a new block of data
and size for extending an existing block of data **/
/************************************************************************\
Note: The last four arguments to this routine are protocol-dependent.
Modify them as required.
\************************************************************************/
VOID
WINAPI
GetBldMsgWriteBlockSizes (WORD *blockSize,
WORD *extSize,
BYTE msgType,
BYTE plcDataType,
WORD addr1,
WORD count)
{
WORD len;
WORD bytesToWrite;
/* determine length of data */
bytesToWrite = (WORD) (count * 2);
/* length of characters needed to specify data */
len = (WORD) (bytesToWrite * 2);
/* return length of data extension */
*extSize = len;
/** allow for type, address prefix, length count: TT AAAA NN **/
len += 8;
/** allow for leading ':', checksum XX, and trailing ';' */
len += 4;
/* return length of block */
*blockSize = len;
} /* GetBldMsgWriteBlockSizes */
#else
/* >>>>>>>> USE_ASCII_HEX_MESSAGES not defined <<<<<<<< */
/***********************************************************************/
/** calculate checksum of message **/
/*************************************************************\
The content of this routine is protocol dependent.
Modify it as required.
\*************************************************************/
BYTE
WINAPI
BldCks(LPSTR lpBuf, /* pointer to buffer containing message */
int len, /* length of message */
int *errflg) /* nonzero if invalid characters */
{
int cks, byteval;
char ch;
/* initialize checksum, error flag */
cks = 0;
*errflg = 0;
/************************************************\
include byte lpBuf[i] in the checksum
Example:
\************************************************/
/* get byte values */
while (len > 0) {
/* get byte from message buffer */
ch = *(lpBuf++); len--;
byteval = (int) ((BYTE) ch);
/* update checksum */
cks = (cks + byteval) & 0xFF;
}
/* invert checksum and return it */
cks = 0xFF - cks;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -