📄 ms_rab.lib
字号:
int nErr;
wCoil = msCmdWord ( 2 ); // Coil Address
wCount = msCmdWord ( 4 ); // Coil Count
pcState = &acMSCmd[7]; // State Field Pointer
while (wCount) { // Force Coils
wState = *pcState++;
for (wBit=8;wBit-- && wCount;wState>>=1,wCount--)
if (nErr = msOutWr ( wCoil++,wState&1 ))
return msRepErr ( nErr );
}
msRepNew ( wMSCmd ); // Start Reply
msRepWord ( msCmdWord(2) ); // Coil Address (Fix 12/7/98 S. Kolega)
msRepWord ( msCmdWord(4) ); // Coil Count
return msRepDone (); // Complete & Send Reply
}
/*=========================================================================*\
[0x10] Preset Multiple Registers
\*=========================================================================*/
nodebug
int
msPresetRegs ( void
)
{
if (msRegWr ( 2 )) { // Decode & Write Registers
msRepNew ( wMSCmd ); // Start Reply
msRepWord ( msCmdWord(2) ); // Register Address
msRepWord ( msCmdWord(4) ); // Register Count
msRepDone (); // Complete & Send Reply
}
return 1;
}
/*=========================================================================*\
[0x16] Mask Write Register
\*=========================================================================*/
nodebug
int
msRegMask ( void
)
{ unsigned wReg,wAnd,wOr,wData;
int nErr;
if (!acMSCmd[0]) // Broadcast Not Supported
return 0;
wReg = msCmdWord ( 2 ); // Register Address
wAnd = msCmdWord ( 4 ); // And Mask
wOr = msCmdWord ( 6 ); // Or Mask
if (nErr = msRead ( wReg,&wData ))
return msRepErr ( nErr );
wData = (wData & wAnd) | (wOr & ~wAnd);
if (nErr = msWrite ( wReg,wData ))
return msRepErr ( nErr );
msRepNew ( wMSCmd ); // Start Reply
msRepWord ( wReg ); // Register Address
msRepWord ( wAnd ); // And Mask
msRepWord ( wOr ); // Or Mask
return msRepDone (); // Complete & Send Reply
}
/*=========================================================================*\
[0x17] Read/Write Registers
\*=========================================================================*/
nodebug
int
msRegRdWr ( void
)
{
if (!acMSCmd[0]) // Broadcast Not Supported
return 0;
if (msRegWr ( 6 )) // Decode & Write Registers
msRegRd ( msRead ); // Read Regs & Reply
return 1;
}
/***************************************************************************\
MODBus High-Level Support Functions
\***************************************************************************/
/*=========================================================================*\
Process & Execute Command
\*=========================================================================*/
nodebug
int
msExec ( void
)
{
int nErr;
wMSCmd = acMSCmd[1]; // Extract Command Opcode
msStart (); // Start Packet Processing
switch ( wMSCmd ) { // Dispatch Handler
case 0x01 : // Read Coil Status
nErr = msCmdOutRd ();
break;
case 0x02 : // Read Input Status
nErr = msCmdIn ();
break;
case 0x03 : // Read Holding Registers
nErr = msCmdRead ();
break;
case 0x04 : // Read Input Registers
nErr = msCmdInput ();
break;
case 0x05 : // Force Single Coil
nErr = msForceCoil ();
break;
case 0x06 : // Preset Single Register
nErr = msPresetReg ();
break;
case 0x0B : // Fetch Comm Event Counter
nErr = msFetchComm ();
break;
case 0x0F : // Force Multiple Coils
nErr = msForceCoils ();
break;
case 0x10 : // Preset Multiple Registers
nErr = msPresetRegs ();
break;
case 0x16 : // Mask Write Register
nErr = msRegMask ();
break;
case 0x17 : // Read/Write Registers
nErr = msRegRdWr ();
break;
case 0x07 : // Read Exception Status
case 0x08 : // Diagnostics
case 0x0C : // Fetch Comm Event Log
case 0x11 : // Report Slave ID
case 0x14 : // Read General Reference
case 0x15 : // Write General Reference
case 0x18 : // Read FIFO Queue
default : // All Non-MODBus Opcodes
nErr = msRepErr ( MS_BADFUNC );
}
msDone (); // Packet Processing Done
return nErr;
}
/*=========================================================================*\
Initialize MODBus Driver
\*=========================================================================*/
nodebug
void
msInit ( unsigned wAddr
)
{
wMSAddr = wAddr;
}
/***************************************************************************\
MODBus ASCII Packet Processing
\***************************************************************************/
/*** BeginHeader msaInit */
void msaInit ( unsigned wAddr );
extern shared char *pcMSAM;
extern char acMSAM[516];
/*** EndHeader */
shared char *pcMSAM; // ASCII Message Pointer
char acMSAM[516]; // ASCII Message Buffer
#asm nodebug root
;=====================================================================
; msError : Handle Serial Error (Reset Packet Processing)
;
; INPUT :
; None
; OUTPUT :
; None
msError:: ld hl,acMSAM ; pcMSAM = acMSAM
ld (pcMSAM),hl
ret ; Done
;=====================================================================
; msRecv : Next Byte Received from MODBus
;
; INPUT :
; HL = Byte Received
; OUTPUT :
; None
msRecv:: ld a,l ; A = Byte (Parity Masked)
and 07Fh
cp a,':' ; A = ':' => Restart & Store ':'
jr z,msR0
cp a,00Dh ; A = <CR> => Store <CR>
jr z,msR1
cp a,00Ah ; A = <LF> => Store <LF>
jr z,msR1
cp a,'0' ; A < '0' => Restart
jr c,msError
cp a,'9'+1 ; A <= '9' => Store '0'..'9'
jr c,msR1
cp a,'A' ; A < 'A' => Restart
jr c,msError
cp a,'F'+1 ; A <= 'F' => Store 'A'..'F'
jr c,msR1
jr msError ; Done (No Legal Character)
msR0: call msError ; Reset Packet Processing
msR1: push de ; Protect DE
ld de,(pcMSAM) ; DE = Buffer Pointer
ld hl,acMSAM+516-1 ; 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 (pcMSAM),hl
msR2: pop de ; Restore DE
ret ; Done
#endasm
/*=========================================================================*\
Compute Longitude Redundancy Check
\*=========================================================================*/
nodebug
unsigned
msaLRC ( char *pcMess,
unsigned wLen
)
{ char cSum;
for (cSum=0;wLen--;cSum+=*pcMess++);
return cSum;
}
/*=========================================================================*\
Assemble MODBus ASCII Packet & Process when Done
\*=========================================================================*/
nodebug
void
msRun ( void
)
{
static char *pcHex;
const static char acHex[] = "0123456789ABCDEF";
static int nDelay;
char *pcCmd,*pcRep;
char *pcM;
unsigned wLRC;
int c;
costate sMSRun always_on {
msError();
do {
c = msXgetc();
if (c != -1) msRecv(c);
} while (c != '\n');
if ((pcMSAM > (acMSAM+2)) && (*(pcMSAM-1) == '\n') &&
(*(pcMSAM-2) == '\r') && (acMSAM[0] == ':')) {
for (pcM=acMSAM+1,pcCmd=acMSCmd;*pcM!='\r';++pcCmd) {
if (!(pcHex = strchr ( acHex,*pcM++ )))
break;
*pcCmd = (pcHex-acHex) << 4;
if (!(pcHex = strchr ( acHex,*pcM++ )))
break;
*pcCmd += (pcHex-acHex);
}
if (!msaLRC ( acMSCmd,pcCmd-acMSCmd )) {
if (!acMSCmd[0] || (acMSCmd[0] == wMSAddr)) {
if (msExec() && acMSCmd[0]) {
wLRC = -msaLRC(acMSRep,pcMSRep-acMSRep) & 0xFF;
pcM = acMSAM;
*pcM++ = ':';
for (pcRep=acMSRep;pcRep<pcMSRep;++pcRep) {
*pcM++ = acHex[*pcRep>>4];
*pcM++ = acHex[*pcRep&15];
}
*pcM++ = acHex[wLRC>>4];
*pcM++ = acHex[wLRC&15];
*pcM++ = '\r';
*pcM++ = '\n';
*pcM = 0;
msSend ( NULL,0 );
waitfor ( msSend ( acMSAM,pcM-acMSAM ) );
}
}
}
}
}
}
/*=========================================================================*\
Initialize MODBus ASCII Driver
\*=========================================================================*/
nodebug
void
msaInit ( unsigned wAddr
)
{
msError ();
msInit ( wAddr );
}
/***************************************************************************\
MODBus RTU Packet Processing
\***************************************************************************/
/*** BeginHeader msrInit */
void msrInit ( unsigned wAddr,unsigned wTO );
/*** EndHeader */
shared
unsigned wMSRLast; // Time Stamp of Last Serial Char
unsigned wMSRTO; // Timeout Period for RTU Sync
#asm nodebug root
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -