← Back to dashboard

File view

VMI_MODBUS_SLAVE.LIB

1
/* START LIBRARY DESCRIPTION *********************************************
2
3
Copyright RabbitSemiconductor November 2005
4
5
Modbus_slave.LIB		Version 1.02
6
7
Modifications: - most reccent at top
8
JLC	1.02 July 2006	fixed bug in mbsWriteRegs to correct byte order
9
JLC	1.01 June 2006	added MODBUS_CRC
10
11
		Copyright (c) 2005 	RabbitSemiconductor, Inc
12
		Copyright (c) 2002 	IAS, Inc.
13
		Copyright (c) 2000 	Z-World, Inc.
14
		Copyright (c) 1997  	CFControls.
15
16
DESCRIPTION:	Dynamic C MODBus Slave functions.
17
The functions in this library are not dependant on the physical media which is
18
being used for ModBus communications.
19
20
None of the functions in this library are meant to be accessed directly by the
21
user program.
22
23
The following functions MUST be defined in the user program or board-specific
24
library:
25
26
mbsStart ( void )	pre-process the packet - usually a null function
27
mbsDone ( void )	post-process the packet - usually a null function
28
29
			Single bit access
30
mbsDigOutRd	( CoilNbr, *nState )		command 0x01 = Read Coil Status
31
mbsDigIn		( InputNbr, *nState ) 	command 0x02 =	Read Input Status
32
mbsDigOut	( wCoil, wData )	  		command 0x05 = Write Single Coil
33
34
			16 bit access
35
mbsRegOutRd	( RegNbr, *wData ) 		command 0x03 =	Read Holding Registers
36
mbsRegIn		( RegNbr, *wData )		command 0x04 =	Read Input Registers
37
mbsRegOut	( wAddr, wData )	  		command 0x06 =	Write Single Register
38
39
command 0x0F =	Write Multiple Coils				uses mbsDigOut
40
command 0x10 =	Write Multiple Registers		uses mbsRegOut
41
command 0x16 =	Mask Write Register				uses mbsRegOut and mbsRegOutRd
42
command 0x17 =	Read/Write Multiple Registers	uses mbsRegOut and mbsRegIn
43
44
45
      Release History.
46
==========================================================================
47
Date		Ver		History
48
Nov 2005	1			initial port from IAS Inc.
49
50
==========================================================================
51
52
END DESCRIPTION **********************************************************/
53
54
/*** BeginHeader */
55
#ifndef __MBSLAVE
56
#define __MBSLAVE
57
58
//	Supported MODBus Exceptions
59
#define 	MB_SUCCESS		0			// success
60
#define	MB_BADFUNC		0x01		//	Illegal Function
61
#define	MB_BADADDR		0x02		//	Illegal Data Address
62
#define	MB_BADDATA		0x03		//	Illegal Data Value
63
#define	MB_SLAVEFAILURE 0x04		// Slave Device Failure
64
#define	MB_BUSY			0x06		//	Target is busy with another request
65
#define	MB_NORESP		0x0B		//	No response from target
66
#define	MB_DEVNOTSET	0x10		// device not properly set up
67
#define	MB_TIMEOUT		-1
68
#define	MB_CRC_ERROR		-5
69
/*** EndHeader */
70
71
72
/*** BeginHeader wMSCmd */
73
74
unsigned _mbsCmdWord		( unsigned wOff );
75
int		_mbsReplyByte	( char cByte );
76
int		_mbsReplyWord	( unsigned wWord );
77
void		_mbsReplyInit	( unsigned wCmd );
78
int		_mbsReplyErr		( unsigned wCode );
79
void		_mbsError			( void );
80
81
extern char				*pcMSCmd, *pcMSReply;
82
extern char				acMSCmd[256], acMSReply[256];
83
extern unsigned 		wMSCmd;				//	Command Opcode
84
extern unsigned		MODBUS_flags0; 	// special flags
85
86
#ifndef MODBUS_SLAVE_DEBUG
87
#define MODBUS_SLAVE_DEBUG nodebug
88
#endif
89
90
#ifndef MODBUS_SLAVE_DEBUG_PRINT
91
#define MODBUS_SLAVE_DEBUG_PRINT 0
92
#endif
93
94
/*** EndHeader */
95
96
unsigned	wMSCmd;
97
unsigned MODBUS_flags0;
98
99
char		acMSCmd[256];			//	Command Buffer
100
char		*pcMSReply;				//	Reply Pointer
101
char		acMSReply[256];		//	Reply Buffer
102
103
104
/************************************************************************/
105
/********************** Utility Functions *******************************/
106
/************************************************************************/
107
108
109
/*=======================================================================*\
110
	Extract Word (MSB First) from Command Body
111
112
	Parameter 1:	byte offset into acMSCmd for MSByte of word - the value
113
   					is Big Endian - most significant byte is at the lowest
114
                  address
115
	return value:	unsigned word value
116
\*=======================================================================*/
117
MODBUS_SLAVE_DEBUG
118
unsigned _mbsCmdWord ( unsigned wOff )
119
{	unsigned CommandWord;
120
	CommandWord = (acMSCmd[wOff] << 8) & 0xFF00;
121
	CommandWord |= acMSCmd[wOff + 1];
122
	return CommandWord;
123
}
124
125
126
/*=======================================================================*\
127
	Add Byte to Reply Body
128
129
   Parameter 1: byte to store at *pcMSReply (pointing to acMSReply)
130
   pcMSReply is  updated
131
   return value:
132
   		1 = pcMSReply pointing beyond acMSReply array
133
         0 = success
134
\*=======================================================================*/
135
MODBUS_SLAVE_DEBUG
136
int _mbsReplyByte (char cByte)
137
{
138
	if ( pcMSReply > &acMSReply[sizeof(acMSReply) - 1] ) return 1;
139
	*pcMSReply++ = cByte;					// store the byte
140
	return MB_SUCCESS;
141
}
142
143
144
/*=======================================================================*\
145
	Add Word to Reply (MSB First)
146
147
   parameter 1: word to store, MSB 1st, at *pcMSReply (pointing to acMSReply)
148
   pcMSReply is  updated
149
   return value:
150
   		1 = pcMSReply pointing beyond acMSReply array
151
         0 = success
152
\*=======================================================================*/
153
MODBUS_SLAVE_DEBUG
154
int _mbsReplyWord(unsigned wWord)
155
{
156
	return _mbsReplyByte(wWord >> 8)  ||  _mbsReplyByte(wWord);
157
}
158
159
160
/*=======================================================================*\
161
	Start New Reply
162
163
   Parameter 1: command byte
164
   Initialize pcMSReply to point to start of acMSReply
165
   Store slave address and command into message
166
167
\*=======================================================================*/
168
MODBUS_SLAVE_DEBUG
169
void _mbsReplyInit(unsigned wCmd)
170
{
171
	pcMSReply = acMSReply;					//	Reset Reply Pointer
172
	_mbsReplyByte ( Config.ModBus.Address ); //	insert Slave Address
173
	_mbsReplyByte ( wCmd );					//		and Command Opcode
174
}
175
176
177
/*=======================================================================*\
178
	Compose Exception Reply
179
180
   Parameter 1: error code
181
	Return value: error code
182
   Start new message with command code and error code in header
183
\*=======================================================================*/
184
MODBUS_SLAVE_DEBUG
185
int _mbsReplyErr(unsigned wCode)
186
{	_mbsReplyInit ( 0x80|wMSCmd );		//	Start Reply (Set Error Flag)
187
	_mbsReplyByte ( wCode );				//	Error Code
188
	return wCode;
189
}
190
191
192
/*=======================================================================*\
193
 Handle Error (Reset Packet Processing)
194
\*=======================================================================*/
195
MODBUS_SLAVE_DEBUG
196
void _mbsError ( void )
197
{
198
}
199
200
201
/*** BeginHeader msExec */
202
void  msExec ( void );
203
/*** EndHeader */
204
205
/*=======================================================================*\
206
	msExec: Process & Execute Command
207
   MODBUS_TCP_tick => ms_Handler => mbPkt => msExec
208
209
This function acts as a dispatcher for the ModBus function.  It uses the
210
function code to determine which ModBus function to execute.  This local
211
function then parses the remaining data to determine the parameters to send
212
to the appropriate function in the board-specific ModBus library.
213
214
Enter with:
215
	acMSCmd = the entire ModBus PDU:
216
		byte 0 = ModBus address
217
   	byte 1 = function code
218
      bytes 2..n = data
219
      bytes n+1, n+2 = CRC (serial only)
220
221
   return value: none
222
223
   Supported MODBUS commands
224
		0x01	Read Coil Status						 1 bit
225
      0x02	Read Input Status						 1 bit
226
      0x03	Read Holding Registers				16 bits
227
      0x04	Read Input Registers			  		16 bits
228
      0x05	Write Single Coil						 1 bit
229
      0x06	Write Single Register				16 bits
230
		0x0F	Write Multiple Coils					 1 bit
231
      0x10	Write Multiple Registers			16 bits
232
      0x16	Mask Write Register					16 bits
233
      0x17	Read/Write Multiple Registers		16 bits
234
235
      For 16 bit ( 2 byte ) data, the MSByte is first ( Big Endian ).
236
237
NOTE: the calling function must calculate the CRC if required.  The number
238
of bytes as well as the data to be used is based on the "current" value
239
of pcMSReply and the reply in acMSReply:
240
		CRCvalue = getcrc ( acMSReply, pcMSReply-acMSReply, 0xFFFF );
241
      _mbsReplyWord (CRCvalue); // append the CRC
242
243
\*=======================================================================*/
244
MODBUS_SLAVE_DEBUG
245
void msExec ( void )
246
{
247
	auto int nErr;
248
249
	wMSCmd = acMSCmd[1];						//	Extract Command Opcode
250
	mbsStart ();								//	Start Packet Processing
251
	_mbsReplyInit ( wMSCmd );				//	new reply: insert 1st 2 bytes
252
	switch ( wMSCmd ) {						//	Dispatch Handler
253
		case	0x01	:							//	Read Coil Status
254
			nErr = mbsCoilRd ( mbsDigOutRd );
255
			break;
256
		case	0x02	:							//	Read Input Status
257
			nErr = mbsCoilRd ( mbsDigIn );
258
			break;
259
		case	0x03	:							//	Read Holding Registers
260
			nErr = mbsRegRd ( mbsRegOutRd );
261
			break;
262
		case	0x04	:							//	Read Input Registers
263
			nErr = mbsRegRd ( mbsRegIn );
264
			break;
265
		case	0x05	:							//	Write Single Coil
266
			nErr = mbsForceCoil ();
267
			break;
268
		case	0x06	:							//	Write Single Register
269
			nErr = mbsWriteReg ();
270
			break;
271
		case	0x0F	:							//	Write Multiple Coils
272
			nErr = mbsForceCoils ();
273
			break;
274
		case	0x10	:							//	Write Multiple Registers
275
			nErr = mbsWriteRegs ();
276
			break;
277
		case	0x16	:							//	Mask Write Register
278
			nErr = mbsRegMask ();
279
			break;
280
		case	0x17	:							//	Read/Write Multiple Registers
281
			nErr = mbsRegRdWr ();
282
			break;
283
284
		// the following are not currently supported by this module
285
		case	0x07	:							//	Read Exception Status
286
		case	0x08	:							//	Diagnostics
287
		case	0x0B	:							//	Fetch Comm Event Counter
288
		case	0x0C	:							//	Fetch Comm Event Log
289
		case	0x11	:							//	Report Slave ID
290
		case	0x14	:							//	Read General Reference
291
		case	0x15	:							//	Write General Reference
292
		case	0x18	:							//	Read FIFO Queue
293
		default		:							//	All Non-MODBus Opcodes
294
			nErr = MB_BADFUNC;
295
         break;
296
	}
297
	mbsDone ();									// Packet Processing Done
298
	if (nErr != MB_SUCCESS) _mbsReplyErr ( nErr );
299
	return;
300
} // msExec
301
302
303
304
/************************************************************************/
305
/*************************************************************************
306
The following utilities call the user defined functions required by the
307
specific ModBus command.
308
*************************************************************************/
309
/************************************************************************/
310
311
312
/*=======================================================================*\
313
	Read Individual Coils: Output [0x01] or Input [0x02]
314
315
   Parameter 1: address of user function msOutRd or msIn,
316
	Requires:
317
  		acMSCmd[2,3] = starting coil number
318
      acMSCmd[4,5] = coil count
319
      wMSCmd = current command
320
   return value:
321
      MB_SUCCESS = success (even if user function fails!)
322
   Reply message
323
		[0] = slave address
324
   	[1] = function code [0x01] or [0x02]
325
      [2] = byte count = nbr of data bytes with 8 coils per byte
326
      [3..n] = data bytes (2 per register) - high byte first
327
\*=======================================================================*/
328
329
/*** BeginHeader mbsCoilRd */
330
int mbsCoilRd(int (*pxRd)());
331
/*** EndHeader */
332
333
MODBUS_SLAVE_DEBUG
334
int mbsCoilRd (int (*pxRd)())
335
{
336
	auto unsigned CoilNbr, CoilCnt;
337
	auto int nState, nErr;
338
	auto char cAcc, cMask;
339
340
	CoilNbr = _mbsCmdWord(2);				//	Starting coil nbr
341
	CoilCnt = _mbsCmdWord(4);				//	Count
342
	_mbsReplyByte( (CoilCnt + 7) >> 3 ); // calculate and insert Byte Count
343
344
	while (CoilCnt) {							// for each coil/input bit
345
		cAcc = 0;								// initialize return value
346
		for (cMask = 0x01; cMask && CoilCnt; cMask <<= 1, CoilCnt--) {
347
			nErr = pxRd (CoilNbr++, &nState); // get state of one coil
348
			if (nErr != MB_SUCCESS) return nErr;
349
			if (nState)	cAcc |= cMask;		// insert state value if state == 1
350
		}
351
		_mbsReplyByte(cAcc);					//	add coil states to reply packet
352
	}
353
	return MB_SUCCESS;						//	Success
354
} // mbsCoilRd
355
356
357
/*=======================================================================*\
358
	Read 8 bit Registers: Input [0x04], [0x17] or Holding [0x03]
359
360
   Parameter 1: address of user function msRead or msInput
361
  		acMSCmd[2,3] = starting register number
362
      acMSCmd[4,5] = register count
363
   return value:
364
      MB_SUCCESS = success
365
   Reply message
366
		[0] = slave address
367
   	[1] = function code [0x03], [0x04] or [0x17]
368
      [2] = byte count = register count * 2
369
      		each register, although only 8 bits each, occupies 2 bytes in
370
            the response
371
      [3..n] = data bytes (2 per register) - high byte first
372
\*=======================================================================*/
373
374
/*** BeginHeader mbsRegRd */
375
int mbsRegRd(int (*pxRd)());
376
/*** EndHeader */
377
378
MODBUS_SLAVE_DEBUG
379
int mbsRegRd(int (*pxRd)())
380
{
381
	auto unsigned RegNbr, RegCnt, wData;
382
	auto int nErr;
383
384
	RegNbr = _mbsCmdWord(2);				//	Starting register nbr
385
	RegCnt = _mbsCmdWord(4);				//	Count
386
	_mbsReplyByte( 2 * RegCnt );			//	calculate and insert Byte Count
387
388
	while (RegCnt--) {						//	for each requested Register
389
		nErr = pxRd(RegNbr++, &wData);	// read it
390
		if (nErr != MB_SUCCESS) return nErr;
391
		_mbsReplyWord(wData);				//	add data to reply packet
392
	}
393
	return MB_SUCCESS;						//	Success
394
} // mbsRegRd
395
396
397
/*=======================================================================*\
398
	Write Registers (No Reply) ( 0x10 and 0x17 )
399
   		acMSCmd[wOff] = starting register number
400
         acMSCmd[wOff+2] = register count
401
         acMSCmd[wOff+5] = byte value for first register - 2 per register
402
\*=======================================================================*/
403
404
/*** BeginHeader mbsRegWr */
405
mbsRegWr(unsigned wOff);
406
/*** EndHeader */
407
408
MODBUS_SLAVE_DEBUG
409
int mbsRegWr(unsigned wOff)
410
{
411
	auto unsigned RegNbr, RegCnt;
412
	auto int nErr;
413
414
	RegNbr = _mbsCmdWord(wOff);			//	starting Register Address
415
	RegCnt = _mbsCmdWord(wOff + 2);		//	Register Count
416
	wOff += 5;									//	point to first data value
417
418
	while (RegCnt--) {						//	Write Registers
419
		nErr = mbsRegOut( RegNbr++, _mbsCmdWord(wOff++) );
420
		if (nErr != MB_SUCCESS) return nErr;
421
	}
422
	return MB_SUCCESS;
423
}
424
425
426
/*=======================================================================*\
427
	[0x05] Force Single Coil
428
  		acMSCmd[2,3] = coil number
429
      acMSCmd[4,5] = coil value
430
   return value:
431
      MB_SUCCESS = success
432
   Reply message
433
		[0] = slave address
434
   	[1] = function code [0x05]
435
      [2,3] = coil number
436
      [4,5] = coil value
437
\*=======================================================================*/
438
439
/*** BeginHeader mbsForceCoil */
440
int mbsForceCoil	(	void );
441
/*** EndHeader */
442
443
MODBUS_SLAVE_DEBUG
444
int mbsForceCoil ( void )
445
{	auto unsigned		wCoil,wData;
446
	auto int			nErr;
447
448
	nErr = MB_BADDATA;
449
	wCoil = _mbsCmdWord ( 2 );				//	get Coil Number
450
	wData = _mbsCmdWord ( 4 );				//	and Coil State
451
	_mbsReplyWord ( wCoil );				//	save Coil Number
452
	_mbsReplyWord ( wData );				//	and Coil State for response
453
454
	nErr = mbsDigOut ( wCoil, wData );
455
	if (nErr != MB_SUCCESS) return nErr;
456
	return MB_SUCCESS;						//	Success
457
} // mbsForceCoil
458
459
460
/*=======================================================================*\
461
	[0x06] Write Single Register
462
  		acMSCmd[2,3] = Register number
463
      acMSCmd[4,5] = Register value
464
   return value:
465
      MB_SUCCESS = success
466
   Reply message
467
		[0] = slave address
468
   	[1] = function code [0x06]
469
      [2,3] = Register number
470
      [4,5] = Register value
471
\*=======================================================================*/
472
473
/*** BeginHeader mbsWriteReg */
474
int mbsWriteReg	(	void );
475
/*** EndHeader */
476
477
MODBUS_SLAVE_DEBUG
478
int mbsWriteReg	(	void )
479
{	auto unsigned wAddr, wData;
480
	auto int	nErr;
481
482
	wAddr = _mbsCmdWord ( 2 );				//	get Register Address
483
	wData = _mbsCmdWord ( 4 );				//	and Register Value
484
	_mbsReplyWord ( wAddr );				//	save Register Address
485
	_mbsReplyWord ( wData );				//	and Register Data for response
486
487
	nErr = mbsRegOut ( wAddr, wData );	//	Write Register
488
	if (nErr != MB_SUCCESS) return nErr;
489
	return MB_SUCCESS;						//	Success
490
}
491
492
493
/*=======================================================================*\
494
	[0x0F] Force Multiple Coils
495
  		acMSCmd[2,3] = starting coil number
496
      acMSCmd[4,5] = coil count
497
		acMSCmd[6] = byte count = coil count/8 + ( rem(coil count/8) != 0 )
498
      acMSCmd[7] = byte value for first 8 coils, bit 0 = 1st coil state
499
   return value:
500
      MB_SUCCESS = success
501
   Reply message
502
		[0] = slave address
503
   	[1] = function code [0x0F]
504
      [2,3] = starting coil number
505
      [4,5] = coil count
506
\*=======================================================================*/
507
508
/*** BeginHeader mbsForceCoils */
509
int mbsForceCoils	(	void );
510
/*** EndHeader */
511
512
MODBUS_SLAVE_DEBUG
513
int mbsForceCoils	(	void )
514
{
515
	auto unsigned CoilNbr, CoilCnt, wState, wBit;
516
	auto char *pcState;
517
	auto int nErr;
518
519
	CoilNbr = _mbsCmdWord ( 2 );			//	get starting Coil Address
520
	CoilCnt = _mbsCmdWord ( 4 );			//	and Coil Count
521
	pcState = &acMSCmd[7];					//	get address of first data byte
522
	_mbsReplyWord ( CoilNbr );				//	save starting Coil number
523
	_mbsReplyWord ( CoilCnt );				//	and Coil Count for reply
524
525
	while (CoilCnt)
526
   {
527
		wState = *pcState++;
528
		for ( wBit=8; wBit-- && CoilCnt; wState>>=1, CoilCnt--)
529
		{	nErr = mbsDigOut ( CoilNbr++, wState&1 );
530
			if (nErr != MB_SUCCESS) return nErr;
531
      }
532
	}
533
	return MB_SUCCESS;						//	Success
534
} // mbsForceCoils
535
536
537
/*=======================================================================*\
538
	[0x10] Write Multiple Registers
539
  		acMSCmd[2,3] = starting register number
540
      acMSCmd[4,5] = register count
541
		acMSCmd[6] = byte count
542
		acMSCmd[7...] = data bytes - 2 per register
543
   return value:
544
      MB_SUCCESS = success
545
   Reply message
546
		[0] = slave address
547
   	[1] = function code [0x10]
548
      [2,3] = starting register number
549
      [4,5] = register count
550
\*=======================================================================*/
551
552
/*** BeginHeader mbsWriteRegs */
553
int mbsWriteRegs	(	void );
554
/*** EndHeader */
555
556
MODBUS_SLAVE_DEBUG
557
int mbsWriteRegs	(	void )
558
{	auto int wAddr, wData;					// register Address and data value
559
	auto int pData;							// index to the data
560
   auto int RegCount;						// nbr of registers
561
   auto int nErr;
562
563
	wAddr = _mbsCmdWord ( 2 );
564
   RegCount = _mbsCmdWord ( 4 );
565
	pData = 7;									// index to first data value
566
	_mbsReplyWord ( wAddr );			//	save starting register
567
	_mbsReplyWord ( RegCount );			//	and register count for response
568
569
   while ( RegCount-- )
570
   {	wData = _mbsCmdWord ( pData );	//	get Register Value
571
   	nErr = mbsRegOut ( wAddr, wData );
572
		if (nErr != MB_SUCCESS) return nErr;
573
		wAddr += 1;								// next register nbr
574
      pData += 2;								// index to next data word
575
	}
576
577
	return MB_SUCCESS;						//	Success
578
} // mbsWriteRegs
579
580
581
/*=======================================================================*\
582
	[0x16] Mask Write Register
583
   		acMSCmd[2,3] = register number
584
         acMSCmd[4,5] = AND mask
585
         acMSCmd[6,7] = OR mask
586
   return value:
587
      MB_SUCCESS = success
588
   Reply message
589
		[0] = slave address
590
   	[1] = function code [0x16]
591
      [2,3] = register number
592
      [4,5] = AND mask
593
      [6,7] = OR mask
594
\*=======================================================================*/
595
596
/*** BeginHeader mbsRegMask */
597
int mbsRegMask		(	void);
598
/*** EndHeader */
599
600
MODBUS_SLAVE_DEBUG
601
int mbsRegMask		(	void)
602
{	auto unsigned wReg, wAnd, wOr, wData;
603
	auto int nErr;
604
605
	wReg = _mbsCmdWord ( 2 );				//	get Register Address,
606
	wAnd = _mbsCmdWord ( 4 );				//	AND Mask
607
	wOr = _mbsCmdWord ( 6 );				//	and OR Mask
608
	_mbsReplyWord ( wReg );					//	save Register Address,
609
	_mbsReplyWord ( wAnd );					//	AND Mask
610
	_mbsReplyWord ( wOr );					//	and OR Mask for response
611
612
	nErr = mbsRegOutRd ( wReg, &wData );
613
	if (nErr != MB_SUCCESS) return nErr;
614
	wData = (wData & wAnd) | (wOr & ~wAnd);
615
	nErr = mbsRegOut ( wReg, wData );
616
	if (nErr != MB_SUCCESS) return nErr;
617
	return MB_SUCCESS;						//	Success
618
} // mbsRegMask
619
620
621
/*=======================================================================*\
622
	[0x17] Read/Write Registers
623
  		acMSCmd[2,3] = starting read register number
624
      acMSCmd[4,5] = read register count
625
  		acMSCmd[6,7] = starting write register number
626
      acMSCmd[8,9] = write register count
627
		acMSCmd[10] = write byte count
628
		acMSCmd[11...] = data bytes - 2 per register
629
   return value:
630
      MB_SUCCESS = success
631
      MB_... if error
632
   Reply message
633
		[0] = slave address
634
   	[1] = function code [0x17]
635
		[2] = read byte count = read register count * 2
636
		[3..n] read register data - 2 bytes per register
637
\*=======================================================================*/
638
639
/*** BeginHeader mbsRegRdWr */
640
int mbsRegRdWr		(	void 	);
641
/*** EndHeader */
642
643
MODBUS_SLAVE_DEBUG
644
int mbsRegRdWr		(	void 	)
645
{	auto int nErr;
646
647
	nErr = mbsRegWr(6);						// Decode & Write Registers
648
	if ( nErr == MB_SUCCESS )
649
		nErr = mbsRegRd ( mbsRegIn );		//	Read Regs & Reply
650
	return nErr;
651
}
652
653
/* START FUNCTION DESCRIPTION ********************************************
654
MODBUS_Serial_tick	<MODBUS_Slave.LIB>
655
656
SYNTAX:			void MODBUS_Serial_tick ( void );
657
658
DESCRIPTION:	Check for a command from a MODBUS master
659
660
PARAMETER1:		none
661
662
RETURN VALUE:	none
663
664
END DESCRIPTION **********************************************************/
665
666
/*** BeginHeader MODBUS_Slave_Serial_tick */
667
void MODBUS_Slave_Serial_tick ( void );
668
/*** EndHeader */
669
670
MODBUS_SLAVE_DEBUG
671
void MODBUS_Slave_Serial_tick ( void )
672
{	auto int ByteCount;
673
	Ms ElapTime;
674
675
   ElapTime = MS_TIMER;
676
	ByteCount = MODBUS_Slave_Serial_Rx (acMSReply);	// check for a message
677
678
#if MODBUS_DEBUG_PRINT & 2
679
	printf ( "ByteCount=%2d  MBaddress=%2d  MBcmd=%2d\n\r",
680
   				ByteCount,    acMSReply[0], acMSReply[1] );
681
#endif
682
683
	if ( ByteCount > 0 )						// if valid byte count
684
   //{	if (acMSReply[0] == MY_MODBUS_ADDRESS ) ** Orginal
685
   {	if (acMSReply[0] == Config.ModBus.Address )
686
   	{
687
      	Config.ModBus.ActivityTimer = SEC_TIMER;
688
	   	memcpy ( acMSCmd, acMSReply, ByteCount ); // copy for msExec
689
         msExec ();							// execute the command
690
         ByteCount = pcMSReply-acMSReply; // byte count of response
691
         MODBUS_Slave_Serial_Tx ( acMSReply, ByteCount );
692
         //printf("MBS: %d\n", MS_TIMER - ElapTime);
693
      }
694
   }
695
696
   return;
697
}
698
699
700
/* START FUNCTION DESCRIPTION ********************************************
701
MODBUS_CRC		<MODBUS_Slave.LIB>
702
703
SYNTAX:        unsigned MODBUS_CRC(unsigned char *pcMess, unsigned wLen)
704
705
DESCRIPTION:	alternate CRC calculation
706
707
PARAMETER1:		address of bytes for CRC calculation
708
709
PARAMETER2:		number of bytes in paraameter1
710
711
RETURN VALUE:	CRC value
712
713
Note: to use this alternate CRC function you must insert
714
#define USE_MODBUS_CRC
715
before the #use directives for the modbus libraries.
716
717
END DESCRIPTION **********************************************************/
718
719
/*** BeginHeader MODBUS_SLAVE_CRC */
720
unsigned MODBUS_SLAVE_CRC(unsigned char *pcMess, unsigned wLen);
721
/*** EndHeader */
722
723
/*=========================================================================*\
724
	Compute Cyclic Redundancy Check
725
\*=========================================================================*/
726
/*
727
const unsigned char MODBUS_CRC_MSB[] ={
728
	0x00,0xC1,0x81,0x40,	0x01,0xC0,0x80,0x41,	0x01,0xC0,0x80,0x41,	0x00,0xC1,0x81,0x40,
729
	0x01,0xC0,0x80,0x41,	0x00,0xC1,0x81,0x40,	0x00,0xC1,0x81,0x40,	0x01,0xC0,0x80,0x41,
730
	0x01,0xC0,0x80,0x41,	0x00,0xC1,0x81,0x40,	0x00,0xC1,0x81,0x40,	0x01,0xC0,0x80,0x41,
731
	0x00,0xC1,0x81,0x40,	0x01,0xC0,0x80,0x41,	0x01,0xC0,0x80,0x41,	0x00,0xC1,0x81,0x40,
732
	0x01,0xC0,0x80,0x41,	0x00,0xC1,0x81,0x40,	0x00,0xC1,0x81,0x40,	0x01,0xC0,0x80,0x41,
733
	0x00,0xC1,0x81,0x40,	0x01,0xC0,0x80,0x41,	0x01,0xC0,0x80,0x41,	0x00,0xC1,0x81,0x40,
734
	0x00,0xC1,0x81,0x40,	0x01,0xC0,0x80,0x41,	0x01,0xC0,0x80,0x41,	0x00,0xC1,0x81,0x40,
735
	0x01,0xC0,0x80,0x41,	0x00,0xC1,0x81,0x40, 0x00,0xC1,0x81,0x40,	0x01,0xC0,0x80,0x41,
736
	0x01,0xC0,0x80,0x41,	0x00,0xC1,0x81,0x40,	0x00,0xC1,0x81,0x40,	0x01,0xC0,0x80,0x41,
737
	0x00,0xC1,0x81,0x40,	0x01,0xC0,0x80,0x41,	0x01,0xC0,0x80,0x41,	0x00,0xC1,0x81,0x40,
738
	0x00,0xC1,0x81,0x40,	0x01,0xC0,0x80,0x41,	0x01,0xC0,0x80,0x41,	0x00,0xC1,0x81,0x40,
739
	0x01,0xC0,0x80,0x41,	0x00,0xC1,0x81,0x40,	0x00,0xC1,0x81,0x40,	0x01,0xC0,0x80,0x41,
740
	0x00,0xC1,0x81,0x40,	0x01,0xC0,0x80,0x41,	0x01,0xC0,0x80,0x41,	0x00,0xC1,0x81,0x40,
741
	0x01,0xC0,0x80,0x41,	0x00,0xC1,0x81,0x40,	0x00,0xC1,0x81,0x40,	0x01,0xC0,0x80,0x41,
742
	0x01,0xC0,0x80,0x41,	0x00,0xC1,0x81,0x40,	0x00,0xC1,0x81,0x40,	0x01,0xC0,0x80,0x41,
743
	0x00,0xC1,0x81,0x40,	0x01,0xC0,0x80,0x41,	0x01,0xC0,0x80,0x41,	0x00,0xC1,0x81,0x40
744
};
745
746
const unsigned char MODBUS_CRC_LSB[] ={
747
   0x00,0xC0,0xC1,0x01, 0xC3,0x03,0x02,0xC2,	0xC6,0x06,0x07,0xC7,	0x05,0xC5,0xC4,0x04,
748
   0xCC,0x0C,0x0D,0xCD,	0x0F,0xCF,0xCE,0x0E, 0x0A,0xCA,0xCB,0x0B,	0xC9,0x09,0x08,0xC8,
749
   0xD8,0x18,0x19,0xD9, 0x1B,0xDB,0xDA,0x1A,	0x1E,0xDE,0xDF,0x1F, 0xDD,0x1D,0x1C,0xDC,
750
   0x14,0xD4,0xD5,0x15,	0xD7,0x17,0x16,0xD6, 0xD2,0x12,0x13,0xD3,	0x11,0xD1,0xD0,0x10,
751
   0xF0,0x30,0x31,0xF1,	0x33,0xF3,0xF2,0x32,	0x36,0xF6,0xF7,0x37,	0xF5,0x35,0x34,0xF4,
752
	0x3C,0xFC,0xFD,0x3D,	0xFF,0x3F,0x3E,0xFE,	0xFA,0x3A,0x3B,0xFB,	0x39,0xF9,0xF8,0x38,
753
	0x28,0xE8,0xE9,0x29,	0xEB,0x2B,0x2A,0xEA,	0xEE,0x2E,0x2F,0xEF,	0x2D,0xED,0xEC,0x2C,
754
	0xE4,0x24,0x25,0xE5,	0x27,0xE7,0xE6,0x26,	0x22,0xE2,0xE3,0x23,	0xE1,0x21,0x20,0xE0,
755
	0xA0,0x60,0x61,0xA1,	0x63,0xA3,0xA2,0x62,	0x66,0xA6,0xA7,0x67,	0xA5,0x65,0x64,0xA4,
756
	0x6C,0xAC,0xAD,0x6D,	0xAF,0x6F,0x6E,0xAE,	0xAA,0x6A,0x6B,0xAB,	0x69,0xA9,0xA8,0x68,
757
	0x78,0xB8,0xB9,0x79,	0xBB,0x7B,0x7A,0xBA,	0xBE,0x7E,0x7F,0xBF,	0x7D,0xBD,0xBC,0x7C,
758
	0xB4,0x74,0x75,0xB5,	0x77,0xB7,0xB6,0x76,	0x72,0xB2,0xB3,0x73,	0xB1,0x71,0x70,0xB0,
759
	0x50,0x90,0x91,0x51,	0x93,0x53,0x52,0x92,	0x96,0x56,0x57,0x97,	0x55,0x95,0x94,0x54,
760
	0x9C,0x5C,0x5D,0x9D,	0x5F,0x9F,0x9E,0x5E,	0x5A,0x9A,0x9B,0x5B,	0x99,0x59,0x58,0x98,
761
	0x88,0x48,0x49,0x89,	0x4B,0x8B,0x8A,0x4A,	0x4E,0x8E,0x8F,0x4F,	0x8D,0x4D,0x4C,0x8C,
762
	0x44,0x84,0x85,0x45,	0x87,0x47,0x46,0x86,	0x82,0x42,0x43,0x83,	0x41,0x81,0x80,0x40
763
};
764
*/
765
MODBUS_SLAVE_DEBUG
766
unsigned MODBUS_SLAVE_CRC(unsigned char *pcMess, unsigned wLen)
767
{
768
	auto unsigned char cHi,cLo;			//	CRC Accumulators (MSB & LSB)
769
	auto unsigned w;							//	CRC Shift In Index
770
771
	cHi = cLo = 0xFF;							//	Init CRC
772
	while(wLen--)
773
	{												//	For Each Byte
774
		w = cHi ^ *pcMess++;					//	Next Table Index
775
		cHi = cLo ^ MODBUS_CRC_MSB[w];	//	Next CRC
776
		cLo = MODBUS_CRC_LSB[w];
777
	}
778
	return ((unsigned) cHi << 8) | cLo;	//	merge the bytes and return
779
}
780
781
/*** BeginHeader */
782
#endif	// __MBSLAVE
783
/*** EndHeader */
784