?? mm_rab.lib
字號:
/***************************************************************************\
Dynamic C MODBus ASCII/RTU Master
Copyright (c) 2002 Z-World, Inc.
Portions Copyright (c) 1999, CFControls, Inc.
\***************************************************************************/
/*
** MODBus query and response communications have the following default
** (standard or arbitrary) time out limits.
**
** MODBus ASCII query end to response begin is 1000 mS (standard).
**
** MODBus ASCII inter-character is 1000 mS (standard).
**
** MODBus RTU query end to response begin is 100 mS (arbitrary).
**
** MODBus RTU inter-character and transmission end is a 3.5 character
** times gap (standard), which depends on the serial transmission
** format and rate. The default assumes 11 (EG: 1 start, 8 data, 2
** stop) bits per character, and uses the bps rate specified when RTU
** communication is initialized. An extra 1 mS is added to the gap to
** ensure that the calculation's result is always rounded up, not down.
**
** The application can override these MODBus ASCII and RTU defaults by
** defining MM_BRTO (Begin Response Time Out) and/or MM_ERTO (End
** Response Time Out) in milliseconds (long integer).
**
** EG: #define MM_BRTO 2000L // allow long (2 S) query/response delay
** #define MM_ERTO 1L // set short (1 mS) inter-character delay
*/
/*** BeginHeader */
#ifndef __MM_RAB_LIB
#define __MM_RAB_LIB
// User supplied function prototypes (see MMZ_RAB.LIB for examples)
int mmRecv();
int mmSend(unsigned char *pcMess,unsigned wLen);
// Extended MODBus Master Exceptions (NB: always zero or negative)
#define MM_NOBROAD (-9) // Broadcast Not Supported
#define MM_TIMEOUT (-8) // Response Timeout
#define MM_GARBAGE (-7) // Garbage In Response
#define MM_TOOLONG (-6) // Response Exceeds Buffer Length
#define MM_BADXRC (-5) // Bad CRC/LRC
#define MM_BADID (-4) // Unexpected Slave ID in Response
#define MM_BADCODE (-3) // Unexpected Response Code
#define MM_RESCODE (-2) // Reserved Exception Code (zero)
#define MM_OK (-1) // Success
#define MM_BUSY 0 // Master Still Processing
// Supported MODBus Slave Exceptions (NB: always positive)
#define MS_BADFUNC 0x01 // Illegal Function
#define MS_BADADDR 0x02 // Illegal Data Address
#define MS_BADDATA 0x03 // Illegal Data Value
// NB: The following two slave exception names are synonymous.
#define MS_BADRESP 0x04 // Illegal Response Length (unrecoverable error)
#define MS_DEVFAIL 0x04 // Slave Device Failure (unrecoverable error)
#define MS_ACK 0x05 // Acknowledge (long duration program)
#define MS_DEVBUSY 0x06 // Slave Device Busy (long duration program)
#define MS_NACK 0x07 // Negative Acknowledge (reject program)
#define MS_MEMPERR 0x08 // Memory Parity Error (read extended memory)
#define MS_NOGPATH 0x0A // Gateway Path Unavailable (Modbus Plus)
#define MS_NOGRESP 0x0B // Gateway Target Device Failed to Respond
/*** EndHeader */
/* START FUNCTION DESCRIPTION *****************************************
mmRecv <Required by MM_RAB.LIB>
NOTE: MM.LIB functions are generally not reentrant.
SYNTAX: int mmRecv()
DESCRIPTION: Receive one byte from the Modbus Master communication
port. This port-specific function is called by functions in MM.LIB, see
MMZ.LIB for examples.
RETURN VALUE: The current byte (0 to 255), or -1 if none available.
END DESCRIPTION ******************************************************/
/* START FUNCTION DESCRIPTION *****************************************
mmSend <Required by MM_RAB.LIB>
NOTE: MM_RAB.LIB functions are generally not reentrant.
SYNTAX: int mmSend(unsigned char *pcMess, unsigned wLen);
DESCRIPTION: Transmit data out the Modbus Master communication port.
This port-specific function is called by functions in MM_RAB.LIB, see
MMZ.LIB for examples.
PARAMETER1: data buffer pointer
PARAMETER2: length of data in buffer
RETURN VALUE: 0 while busy transmitting data, 1 if successfully done.
END DESCRIPTION ******************************************************/
/***************************************************************************\
MODBus Packet Utilities & ASCII+RTU Globals
\***************************************************************************/
/*** BeginHeader mmRepWord, mmCmdByte, mmCmdWord, mmCmdNew,
acMMCmd, acMMRep, pcMMCmd, pcMMRep */
unsigned mmRepWord(unsigned);
int mmCmdByte(unsigned char);
int mmCmdWord(unsigned);
void mmCmdNew(unsigned,unsigned);
// global variables for Modbus ASCII+RTU
extern unsigned char acMMCmd[256];
extern unsigned char acMMRep[256];
extern shared unsigned char *pcMMCmd;
extern shared unsigned char *pcMMRep;
/*** EndHeader */
unsigned char acMMCmd[256]; // Command Buffer
unsigned char acMMRep[256]; // Reply Buffer
shared unsigned char *pcMMCmd; // Command Pointer
shared unsigned char *pcMMRep; // Reply Pointer
/*=========================================================================*\
Extract Word(MSB First) from Reply Body
\*=========================================================================*/
nodebug
unsigned mmRepWord(unsigned wOff)
{
return((unsigned) acMMRep[wOff] << 8) + acMMRep[wOff + 1];
}
/*=========================================================================*\
Add Byte to Command Body
\*=========================================================================*/
nodebug
int mmCmdByte(unsigned char cByte)
{
if(&acMMCmd[sizeof(acMMCmd) - 1] <= pcMMCmd)
return 0;
*pcMMCmd++ = cByte;
return 1;
}
/*=========================================================================*\
Add Word to Command (MSB First)
\*=========================================================================*/
nodebug
int mmCmdWord(unsigned wWord)
{
return(mmCmdByte((unsigned char) (wWord >> 8)) &&
mmCmdByte((unsigned char) (wWord & 0xFF)));
}
/*=========================================================================*\
Start New Command
\*=========================================================================*/
nodebug
void mmCmdNew(unsigned wAddr, unsigned wCmd)
{
pcMMCmd = acMMCmd; // Reset Reply Pointer
mmCmdByte((unsigned char) (wAddr & 0xFF)); // Slave Address
mmCmdByte((unsigned char) (wCmd & 0xFF)); // Command Opcode
}
/***************************************************************************\
MODBus I/O Utilities
\***************************************************************************/
/*=========================================================================*\
Read Coils (Output or Input)
\*=========================================================================*/
/*** BeginHeader mmCoilRd */
int mmCoilRd(unsigned,unsigned,unsigned,unsigned,void *);
/*** EndHeader */
nodebug
int mmCoilRd(unsigned wAddr, unsigned wCmd, unsigned wCoil,
unsigned wCount, void *pCoils)
{
auto int nErr;
if(!wAddr)
{
nErr = MM_NOBROAD; // Broadcast Not Supported
}
else
{
nErr = MM_BUSY;
costate
{
mmCmdNew(wAddr, wCmd); // Start New Command
mmCmdWord(wCoil); // Coil Address
mmCmdWord(wCount); // Coil Count
waitfor(nErr = mmExec()); // Finish & Process Packet
if(nErr == MM_OK) // Process Reply if Valid
memcpy(pCoils, &acMMRep[3], (size_t) acMMRep[2]);
}
}
return nErr;
}
/*=========================================================================*\
Register Copy Utility
\*=========================================================================*/
/*** BeginHeader mmRegExt */
void mmRegExt(unsigned *);
/*** EndHeader */
nodebug
void mmRegExt(unsigned *pRegs)
{
auto unsigned wCount;
auto unsigned wData;
wCount = acMMRep[2] >> 1; // Register Read Count
for(wData = 3; wCount--; wData += 2) // Store Each Register Word
*pRegs++ = mmRepWord(wData);
}
/*=========================================================================*\
Read Registers (Input or Holding)
\*=========================================================================*/
/*** BeginHeader mmRegRd */
int mmRegRd(unsigned,unsigned,unsigned,unsigned,void *);
/*** EndHeader */
nodebug
int mmRegRd(unsigned wAddr, unsigned wCmd, unsigned wReg,
unsigned wCount, void *pRegs)
{
auto int nErr;
if(!wAddr)
{
nErr = MM_NOBROAD; // Broadcast Not Supported
}
else
{
nErr = MM_BUSY;
costate
{
mmCmdNew(wAddr, wCmd); // Start New Command
mmCmdWord(wReg); // Register Address
mmCmdWord(wCount); // Register Count
waitfor(nErr = mmExec()); // Finish & Process Packet
if(nErr == MM_OK) // Process Reply if Valid
mmRegExt(pRegs);
}
}
return nErr;
}
/*=========================================================================*\
Write Registers (No Reply)
\*=========================================================================*/
/*** BeginHeader mmRegWr */
int mmRegWr(unsigned,unsigned,unsigned *);
/*** EndHeader */
nodebug
int mmRegWr(unsigned wReg, unsigned wCount, unsigned *pRegs)
{
auto int nErr;
nErr = MM_BUSY;
costate
{
mmCmdWord(wReg); // Register Address
mmCmdWord(wCount); // Register Count
mmCmdByte((unsigned char) ((2 * wCount) & 0xFF)); // Data Byte Count
while(wCount--) // Register Data
mmCmdWord(*pRegs++);
waitfor(nErr = mmExec()); // Finish&Exec Packet
}
return nErr;
}
/***************************************************************************\
MODBus Commands
\***************************************************************************/
/*=========================================================================*\
[0x01] Read Coil Status
\*=========================================================================*/
/*** BeginHeader mmOutRd */
int mmOutRd(unsigned,unsigned,unsigned,void *);
/*** EndHeader */
/* START FUNCTION DESCRIPTION *****************************************
mmOutRd <MM_RAB.LIB>
NOTE: MM_RAB.LIB functions are generally not reentrant.
SYNTAX: int mmOutRd(unsigned wAddr, unsigned wCoil, unsigned wCount,
void *pCoils)
DESCRIPTION: Modbus Master query 0x01, Read Coil Status. Reads the
status (ON == 1, OFF == 0) of discrete outputs (coils, 0X references)
in the slave device. Places the present state of the selected output
coils into the buffer pointed to by *pCoils, one coil per bit with the
starting coil number in the least significant bit of the buffer's first
byte. The buffer size should be no less than 'ceil(wCount / 8.0)'
bytes. If wCount is not evenly divisible by eight the unused bits in
the last required byte are cleared to zero.
PARAMETER1: slave address, broadcast (0x00) is not supported.
PARAMETER2: starting 0X coil number (zero based).
PARAMETER3: coils count (one based).
PARAMETER4: coil information buffer pointer.
RETURN VALUE: 0 (MM_BUSY) if busy, -1 (MM_OK) if success, or exception
code (from master if < -1 or from slave if > 0). See the MM_* and MS_*
definitions near the start of MM_RAB.LIB for the complete list.
END DESCRIPTION ******************************************************/
nodebug
int mmOutRd(unsigned wAddr, unsigned wCoil, unsigned wCount,
void *pCoils)
{
return mmCoilRd(wAddr, 0x01, wCoil, wCount, pCoils);
}
/*=========================================================================*\
[0x02] Read Input Status
\*=========================================================================*/
/*** BeginHeader mmIn */
int mmIn(unsigned,unsigned,unsigned,void *);
/*** EndHeader */
/* START FUNCTION DESCRIPTION *****************************************
mmIn <MM_RAB.LIB>
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -