📄 ms_rab.lib
字号:
;=====================================================================
; msError : Reset Packet Processing
;
; INPUT :
; None
; OUTPUT :
; None
msError::
ld hl, (MS_TIMER+2) ; get lower bytes of MS_TIMER
ld (wMSRLast),hl
ld hl,acMSCmd ; pcMSCmd = acMSCmd
ld (pcMSCmd),hl
ret ; Done
;=====================================================================
; msRecv : Next Byte Received from MODBus
;
; INPUT :
; HL = Byte Received
; OUTPUT :
; None
msRecv:: push de ; Protect DE
ld a,l ; A = Byte Received
ld de,(pcMSCmd) ; DE = Buffer Pointer
ld hl,pcMSCmd-2 ; HL = End of Buffer
or a ; Done if Buffer Full
sbc hl,de
jr c,msR2
ex de,hl ; HL = Buffer Pointer
ld (hl),a ; Store Byte to Buffer
inc hl ; Bump Pointer
ld (pcMSCmd),hl
msR2:
ld hl, (MS_TIMER+2) ; get lower bytes of MS_TIMER
ld (wMSRLast),hl
pop de ; Restore DE
ret ; Done
#endasm
/*=========================================================================*\
Compute Cyclic Redundancy Check
\*=========================================================================*/
const char acMSRHi[] = {
0x00,0xC1,0x81,0x40, 0x01,0xC0,0x80,0x41, 0x01,0xC0,0x80,0x41, 0x00,0xC1,0x81,0x40,
0x01,0xC0,0x80,0x41, 0x00,0xC1,0x81,0x40, 0x00,0xC1,0x81,0x40, 0x01,0xC0,0x80,0x41,
0x01,0xC0,0x80,0x41, 0x00,0xC1,0x81,0x40, 0x00,0xC1,0x81,0x40, 0x01,0xC0,0x80,0x41,
0x00,0xC1,0x81,0x40, 0x01,0xC0,0x80,0x41, 0x01,0xC0,0x80,0x41, 0x00,0xC1,0x81,0x40,
0x01,0xC0,0x80,0x41, 0x00,0xC1,0x81,0x40, 0x00,0xC1,0x81,0x40, 0x01,0xC0,0x80,0x41,
0x00,0xC1,0x81,0x40, 0x01,0xC0,0x80,0x41, 0x01,0xC0,0x80,0x41, 0x00,0xC1,0x81,0x40,
0x00,0xC1,0x81,0x40, 0x01,0xC0,0x80,0x41, 0x01,0xC0,0x80,0x41, 0x00,0xC1,0x81,0x40,
0x01,0xC0,0x80,0x41, 0x00,0xC1,0x81,0x40, 0x00,0xC1,0x81,0x40, 0x01,0xC0,0x80,0x41,
0x01,0xC0,0x80,0x41, 0x00,0xC1,0x81,0x40, 0x00,0xC1,0x81,0x40, 0x01,0xC0,0x80,0x41,
0x00,0xC1,0x81,0x40, 0x01,0xC0,0x80,0x41, 0x01,0xC0,0x80,0x41, 0x00,0xC1,0x81,0x40,
0x00,0xC1,0x81,0x40, 0x01,0xC0,0x80,0x41, 0x01,0xC0,0x80,0x41, 0x00,0xC1,0x81,0x40,
0x01,0xC0,0x80,0x41, 0x00,0xC1,0x81,0x40, 0x00,0xC1,0x81,0x40, 0x01,0xC0,0x80,0x41,
0x00,0xC1,0x81,0x40, 0x01,0xC0,0x80,0x41, 0x01,0xC0,0x80,0x41, 0x00,0xC1,0x81,0x40,
0x01,0xC0,0x80,0x41, 0x00,0xC1,0x81,0x40, 0x00,0xC1,0x81,0x40, 0x01,0xC0,0x80,0x41,
0x01,0xC0,0x80,0x41, 0x00,0xC1,0x81,0x40, 0x00,0xC1,0x81,0x40, 0x01,0xC0,0x80,0x41,
0x00,0xC1,0x81,0x40, 0x01,0xC0,0x80,0x41, 0x01,0xC0,0x80,0x41, 0x00,0xC1,0x81,0x40
};
const char acMSRLo[] = {
0x00,0xC0,0xC1,0x01, 0xC3,0x03,0x02,0xC2, 0xC6,0x06,0x07,0xC7, 0x05,0xC5,0xC4,0x04,
0xCC,0x0C,0x0D,0xCD, 0x0F,0xCF,0xCE,0x0E, 0x0A,0xCA,0xCB,0x0B, 0xC9,0x09,0x08,0xC8,
0xD8,0x18,0x19,0xD9, 0x1B,0xDB,0xDA,0x1A, 0x1E,0xDE,0xDF,0x1F, 0xDD,0x1D,0x1C,0xDC,
0x14,0xD4,0xD5,0x15, 0xD7,0x17,0x16,0xD6, 0xD2,0x12,0x13,0xD3, 0x11,0xD1,0xD0,0x10,
0xF0,0x30,0x31,0xF1, 0x33,0xF3,0xF2,0x32, 0x36,0xF6,0xF7,0x37, 0xF5,0x35,0x34,0xF4,
0x3C,0xFC,0xFD,0x3D, 0xFF,0x3F,0x3E,0xFE, 0xFA,0x3A,0x3B,0xFB, 0x39,0xF9,0xF8,0x38,
0x28,0xE8,0xE9,0x29, 0xEB,0x2B,0x2A,0xEA, 0xEE,0x2E,0x2F,0xEF, 0x2D,0xED,0xEC,0x2C,
0xE4,0x24,0x25,0xE5, 0x27,0xE7,0xE6,0x26, 0x22,0xE2,0xE3,0x23, 0xE1,0x21,0x20,0xE0,
0xA0,0x60,0x61,0xA1, 0x63,0xA3,0xA2,0x62, 0x66,0xA6,0xA7,0x67, 0xA5,0x65,0x64,0xA4,
0x6C,0xAC,0xAD,0x6D, 0xAF,0x6F,0x6E,0xAE, 0xAA,0x6A,0x6B,0xAB, 0x69,0xA9,0xA8,0x68,
0x78,0xB8,0xB9,0x79, 0xBB,0x7B,0x7A,0xBA, 0xBE,0x7E,0x7F,0xBF, 0x7D,0xBD,0xBC,0x7C,
0xB4,0x74,0x75,0xB5, 0x77,0xB7,0xB6,0x76, 0x72,0xB2,0xB3,0x73, 0xB1,0x71,0x70,0xB0,
0x50,0x90,0x91,0x51, 0x93,0x53,0x52,0x92, 0x96,0x56,0x57,0x97, 0x55,0x95,0x94,0x54,
0x9C,0x5C,0x5D,0x9D, 0x5F,0x9F,0x9E,0x5E, 0x5A,0x9A,0x9B,0x5B, 0x99,0x59,0x58,0x98,
0x88,0x48,0x49,0x89, 0x4B,0x8B,0x8A,0x4A, 0x4E,0x8E,0x8F,0x4F, 0x8D,0x4D,0x4C,0x8C,
0x44,0x84,0x85,0x45, 0x87,0x47,0x46,0x86, 0x82,0x42,0x43,0x83, 0x41,0x81,0x80,0x40
};
nodebug
unsigned
msrCRC ( char *pcMess,
unsigned wLen
)
{ char cHi,cLo; // CRC Acc (MSB & LSB)
unsigned w; // CRC Shift In Index
cHi = cLo = 0xFF; // Init CRC
while (wLen--) { // For Each Byte
w = cHi ^ *pcMess++; // Next Table Index
cHi = cLo ^ acMSRHi[w]; // Next CRC
cLo = acMSRLo[w];
}
return (cHi << 8) | cLo; // Return Composite
}
/*=========================================================================*\
Assemble MODBus RTU Packet & Process when Done
\*=========================================================================*/
nodebug
void
msRun ( void
)
{ unsigned wCRC;
unsigned wLen;
char buf[256];
unsigned i;
costate sMSRun always_on {
msError ();
do {
wLen = msXread(buf, 256, wMSRTO);
for (i=0; i<wLen; i++)
msRecv(buf[i]);
} while (!wLen);
wMSRLast = (unsigned)(MS_TIMER & 0x00FFul);
if (4 <= wLen) {
wCRC = msrCRC ( acMSCmd,wLen-2 );
if (wCRC == msCmdWord ( wLen-2 )) {
if (!acMSCmd[0] || (acMSCmd[0] == wMSAddr)) {
if (msExec() && acMSCmd[0]) {
wCRC = msrCRC(acMSRep,pcMSRep-acMSRep);
msRepWord ( wCRC );
waitfor ( wMSRTO < ((unsigned)(MS_TIMER & 0x00FFul)-wMSRLast) );
msSend ( NULL,0 );
waitfor ( msSend ( acMSRep,pcMSRep-acMSRep ) );
}
}
}
}
}
}
/*=========================================================================*\
Initialize MODBus RTU Driver
\*=========================================================================*/
nodebug
void
msrInit ( unsigned wAddr,
unsigned wTO
)
{ wMSRTO = wTO;
msError ();
msInit ( wAddr );
}
/*=========================================================================*\
Stubs for functions that need to be defined in the user's code.
\*=========================================================================*/
/*** BeginHeader */
void msStart();
void msDone();
int msIn(unsigned wCoil, int *pnState);
int msOutRd(unsigned wCoil, int *pnState);
int msOutWr(unsigned wCoil, int bState);
int msInput(unsigned wReg, unsigned *pwValue);
int msRead(unsigned wReg, unsigned *pwValue);
int msWrite(unsigned wReg, unsigned wValue);
/*** EndHeader */
/* START FUNCTION DESCRIPTION *****************************************
msStart <Called by MS_RAB.LIB>
NOTE: MS_RAB.LIB functions are generally not reentrant.
SYNTAX: void msStart()
DESCRIPTION: Called just before a received Modbus packet is processed,
this function is primarily intended to be used to lock resources so
that data returned in one Modbus response packet are atomic. Locking
resources may or may not be required, depending on how the msIn(),
msInput(), msOutRd() and msOutWr() functions are implemented in a
particular Modbus slave application. Note that Modbus command handler
functions in MS_RAB.LIB may make multiple calls to those functions while
responding to a single Modbus command.
RETURN VALUE: None.
END DESCRIPTION ******************************************************/
/* START FUNCTION DESCRIPTION *****************************************
msDone <Called by MS_RAB.LIB>
NOTE: MS_RAB.LIB functions are generally not reentrant.
SYNTAX: void msDone()
DESCRIPTION: Called just after a received Modbus command has been
processed and just before the reply is sent. This function is intended
to be used to unlock resources that were locked by msStart(). Locking
resources may or may not be required, depending on how the msIn(),
msInput(), msOutRd() and msOutWr() functions are implemented in a
particular Modbus slave application. Note that Modbus command handler
functions in MS_RAB.LIB may make multiple calls to those functions while
responding to a single Modbus command.
RETURN VALUE: None.
END DESCRIPTION ******************************************************/
/* START FUNCTION DESCRIPTION *****************************************
msIn <Required by MS_RAB.LIB>
NOTE: MS_RAB.LIB functions are generally not reentrant.
SYNTAX: int msIn(unsigned wCoil, int *pnState)
DESCRIPTION: Places the on (1) or off (0) status of a single discrete
input (coil) into the integer pointed to by *pnState. If the Modbus
slave application is to support discrete inputs (coils, 0X references)
then this function must be implemented in the Modbus slave application.
PARAMETER1: discrete input (coil) number (zero based).
PARAMETER2: input (coil) status information pointer.
RETURN VALUE: 0 if success, or exception code if error. See the MS_*
definitions near the start of MS_RAB.LIB for the complete list.
END DESCRIPTION ******************************************************/
/* START FUNCTION DESCRIPTION *****************************************
msOutRd <Required by MS_RAB.LIB>
NOTE: MS_RAB.LIB functions are generally not reentrant.
SYNTAX: int msOutRd(unsigned wCoil, int *pnState)
DESCRIPTION: Places the on (1) or off (0) status of a single output
coil into the integer pointed to by *pnState. If the Modbus slave
application is to support output coils (1X references) then this
function must be implemented in the Modbus slave application.
PARAMETER1: output coil number (zero based).
PARAMETER2: coil status information pointer.
RETURN VALUE: 0 if success, or exception code if error. See the MS_*
definitions near the start of MS_RAB.LIB for the complete list.
END DESCRIPTION ******************************************************/
/* START FUNCTION DESCRIPTION *****************************************
msOutWr <Required by MS_RAB.LIB>
NOTE: MS_RAB.LIB functions are generally not reentrant.
SYNTAX: int msOutWr(unsigned wCoil, int bState)
DESCRIPTION: Forces the on (1) or off (0) state of a single output
coil according to the logic value in bState. If the Modbus slave
application is to support output coils (1X references) then this
function must be implemented in the Modbus slave application.
PARAMETER1: output coil number (zero based).
PARAMETER2: coil state to be forced.
RETURN VALUE: 0 if success, or exception code if error. See the MS_*
definitions near the start of MS_RAB.LIB for the complete list.
END DESCRIPTION ******************************************************/
/* START FUNCTION DESCRIPTION *****************************************
msInput <Required by MS_RAB.LIB>
NOTE: MS_RAB.LIB functions are generally not reentrant.
SYNTAX: int msInput(unsigned wReg, unsigned *pwValue)
DESCRIPTION: Places the current value of a single input register into
the unsigned integer pointed to by *pwValue. If the Modbus slave
application is to support input registers (3X references) then this
function must be implemented in the Modbus slave application.
PARAMETER1: input register number (zero based).
PARAMETER2: register information pointer.
RETURN VALUE: 0 if success, or exception code if error. See the MS_*
definitions near the start of MS_RAB.LIB for the complete list.
END DESCRIPTION ******************************************************/
/* START FUNCTION DESCRIPTION *****************************************
msRead <Required by MS_RAB.LIB>
NOTE: MS_RAB.LIB functions are generally not reentrant.
SYNTAX: int msRead(unsigned wReg, unsigned *pwValue)
DESCRIPTION: Places the current value of a single holding register into
the unsigned integer pointed to by *pwValue. If the Modbus slave
application is to support holding registers (4X references) then this
function must be implemented in the Modbus slave application.
PARAMETER1: holding register number (zero based).
PARAMETER2: register information pointer.
RETURN VALUE: 0 if success, or exception code if error. See the MS_*
definitions near the start of MS_RAB.LIB for the complete list.
END DESCRIPTION ******************************************************/
/* START FUNCTION DESCRIPTION *****************************************
msWrite <Required by MS_RAB.LIB>
NOTE: MS_RAB.LIB functions are generally not reentrant.
SYNTAX: int msWrite(unsigned wReg, unsigned wValue)
DESCRIPTION: Forces the contents of a single holding register to
the unsigned integer value in wValue. If the Modbus slave application
is to support holding registers (4X references) then this function must
be implemented in the Modbus slave application.
PARAMETER1: holding register number (zero based).
PARAMETER2: register value to be forced.
RETURN VALUE: 0 if success, or exception code if error. See the MS_*
definitions near the start of MS_RAB.LIB for the complete list.
END DESCRIPTION ******************************************************/
/*** BeginHeader */
#endif
/*** EndHeader */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -