← Back to dashboard

File view

VMI_MODBUS_MASTER.LIB

1
/* MODBUS_master.c			Copyright January 2006, RabbitSemiconductor
2
3
Modifications:
4
JLC	June 2006	added MODBUS_CRC
5
6
This library supports the following MODBUS commands:
7
8
	0x01 Read Coils
9
   0x03 Read Holding Registers
10
   0x05 Write Single Coil
11
   0x06 Write Single Register
12
	0x0F Write multiple Coils
13
14
It is independant of the communications method in use.  It is equally
15
compatible with TCP and serial interfaces.  Its primary function is to
16
develop the MODBUS APU.  It requires the following functions from the
17
appropriate interface library/program:
18
	MBM_Send_ADU ( *ADUaddress, ADUlength )
19
   	This function must send the ADU to the defined slave device and return
20
      an appropriate success/failure status value.  It must also insert
21
      the response ADU from the slave into the same ADU buffer.
22
*/
23
24
/*** BeginHeader */
25
#ifndef __MBMASTER
26
#define __MBMASTER
27
28
#define 	MB_SUCCESS		0
29
#define	MB_BADFUNC		0x01		//	Illegal Function
30
#define	MB_BADADDR		0x02		//	Illegal Data Address
31
#define	MB_BADDATA		0x03		//	Illegal Data Value
32
#define	MB_SLAVEFAILURE 0x04		// Slave Device Failure
33
#define	MB_BUSY			0x06		//	Target is busy with another request
34
#define	MB_NORESP		0x0B		//	No response from target
35
#define	MB_DEVNOTSET	0x10		// device not properly set up
36
37
#define	MBM_INVALID_PARAMETER -1
38
#define	MBM_PACKET_ERROR	-2
39
#define	MBM_BAD_ADDRESS	-3
40
#define	MBM_BAD_BYTECOUNT -4
41
#define	MB_CRC_ERROR		-5
42
43
// Rx message offsets
44
#define	ADU_OFF_ADDRESS	0
45
#define	ADU_OFF_FUNCTION	1
46
#define	ADU_OFF_EXCEPTION	2
47
#define	ADU_OFF_BYTECOUNT	2
48
49
#ifndef MODBUS_DEBUG
50
#define MODBUS_DEBUG nodebug
51
#endif
52
/*** EndHeader */
53
54
55
/*** BeginHeader _initADU, _insertWord */
56
57
void _initADU ( int MB_address, int FunctionCode, int PDUbyteCount );
58
void _insertWord	( int Value );
59
void _insertByte	( int Value );
60
int  _getADUword	( int Offset );
61
62
extern char mbADU[255];		// MODBUS packet
63
extern char *pmbADU;			//pointer to mbPacket
64
65
/*** EndHeader */
66
67
char mbADU[255];		// MODBUS packet
68
char *pmbADU;			//pointer to mbPacket
69
70
/* START FUNCTION DESCRIPTION ********************************************
71
_initADU											<Modbus_Master.LIB>
72
73
SYNTAX:			_initADU ( int MB_address, int FunctionCode, int PDUbyteCount )
74
75
DESCRIPTION:	Initialize the MODBUS ADU
76
77
PARAMETER1:		Modbus target address
78
79
PARAMETER2:		Modbus function
80
81
PARAMETER3:		nbr of data bytes in the PDU
82
83
RETURN VALUE:	none
84
85
The format of a MODBUS Protocol Data Unit (PDU) is: Function Code + Data
86
87
END DESCRIPTION **********************************************************/
88
89
MODBUS_DEBUG
90
void _initADU ( int MB_address, int FunctionCode, int PDUbyteCount )
91
{
92
	pmbADU = mbADU;							// init pointer
93
  	//_initMBMpacket ( PDUbyteCount+1 );	//  include Function code byte
94
   *pmbADU++ = MB_address;					// insert target address
95
	*pmbADU++ = FunctionCode;				// and Function Code
96
	return;
97
}
98
99
100
// insert a word - MSByte first - into the transmit ADU
101
MODBUS_DEBUG
102
void _insertWord ( int Value )
103
{	*pmbADU++ = Value >> 8;					// insert high byte
104
	*pmbADU++ = Value;						// and low byte
105
   return;
106
}
107
108
// insert a byte into the transmit ADU
109
MODBUS_DEBUG
110
void _insertByte ( int Value )
111
{	*pmbADU++ = Value;
112
   return;
113
}
114
115
// retrieve a word - MSByte first - from the received ADU
116
MODBUS_DEBUG
117
int _getADUword ( int Offset )
118
{	auto ADUword;
119
	ADUword = mbADU[Offset]<<8;			// get MSByte
120
   ADUword |= mbADU[Offset+1];				// and LSByte
121
   return ADUword;
122
}
123
124
/* START FUNCTION DESCRIPTION ********************************************
125
MBM_ReadCoils 0x01
126
127
SYNTAX:			int MBM_ReadCoils ( int MB_address, int* Result,
128
						int Starting_Coil, int Nbr_of-Coils );
129
130
DESCRIPTION:	Read the state of the specified coils.  The function will
131
					create the MODBUS ADU, in mbADU, with the target address
132
               pre-pended.
133
134
PARAMETER1:		MODBUS addresss of the target device
135
136
PARAMETER2:		Address to put the result
137
					The state of the coils: 1 = on, 0 = off
138
					Each coil state will occupy one bit of the result with
139
					the first coil in bit 0, the next in bit 1, etc
140
141
PARAMETER3:    Starting coil number, 1 relative, to read
142
143
PARAMETER4:		Number of coils to read - max of 16
144
145
RETURN VALUE:	MB_SUCCESS
146
					MBM_INVALID_PARAMETER
147
               MBM_PACKET_ERROR
148
               MBM_BAD_ADDRESS
149
150
END DESCRIPTION **********************************************************/
151
152
/*** BeginHeader MBM_ReadCoils */
153
int MBM_ReadCoils ( int MB_address, int* Result, int Starting_Coil,
154
	int Nbr_of_Coils );
155
/*** EndHeader */
156
157
MODBUS_DEBUG
158
int MBM_ReadCoils ( int MB_address, int* Result, int Starting_Coil,
159
	int Nbr_of_Coils )
160
{
161
	auto int ADUStatus;
162
	auto int CoilStatus;
163
164
	if ( Starting_Coil < 0 ) return MBM_INVALID_PARAMETER;
165
	if ( Nbr_of_Coils > 16  ||  Nbr_of_Coils < 0 ) return MBM_INVALID_PARAMETER;
166
167
	_initADU( MB_address, 0x01, 4 );
168
   _insertWord ( Starting_Coil );
169
   _insertWord ( Nbr_of_Coils );
170
171
   ADUStatus = MBM_Send_ADU ( mbADU, pmbADU - mbADU );
172
173
   if ( ADUStatus != MB_SUCCESS ) return ADUStatus;
174
   if ( mbADU[ADU_OFF_ADDRESS] != MB_address ) return MBM_BAD_ADDRESS;
175
   if ( mbADU[ADU_OFF_FUNCTION] & 0x80 ) return (int)mbADU[ADU_OFF_EXCEPTION];
176
   if ( mbADU[ADU_OFF_BYTECOUNT] > 2 ) return MBM_BAD_BYTECOUNT;
177
178
	if ( Nbr_of_Coils > 8 ) CoilStatus = _getADUword (3);
179
   else CoilStatus = (int)mbADU[3] & 0xFF;
180
181
	*Result = CoilStatus;
182
	return MB_SUCCESS;
183
} // MBM_ReadCoils
184
185
186
/* START FUNCTION DESCRIPTION ********************************************
187
MBM_ReadRegs 0x03
188
189
SYNTAX:			int MBM_ReadRegs ( int MB_address, int* Result,
190
						int Starting_Reg, int Nbr_of_Regs );
191
192
DESCRIPTION:	Read the specified registers.  The function will
193
					create the MODBUS ADU, in mbADU, with the target address
194
               pre-pended.
195
196
PARAMETER1:		MODBUS addresss of the target device
197
198
PARAMETER2:		Starting address to put the results
199
200
PARAMETER3:    Starting register number, 1 relative, to read
201
202
PARAMETER4:		Number of registers to read
203
204
RETURN VALUE:	MB_SUCCESS
205
					MBM_INVALID_PARAMETER
206
               MBM_PACKET_ERROR
207
               MBM_BAD_ADDRESS
208
209
END DESCRIPTION **********************************************************/
210
211
/*** BeginHeader MBM_ReadRegs */
212
int MBM_ReadRegs ( int MB_address, int* Result, int Starting_Reg,
213
	int Nbr_of_Regs );
214
/*** EndHeader */
215
216
MODBUS_DEBUG
217
int MBM_ReadRegs ( int MB_address, int* Result, int Starting_Reg,
218
	int Nbr_of_Regs )
219
{
220
	auto int ADUStatus;
221
	auto int RegValue;
222
   auto int Count;
223
224
	if ( Starting_Reg < 0 ) return MBM_INVALID_PARAMETER;
225
	if ( Nbr_of_Regs <= 0  ||  Nbr_of_Regs > 125 ) return MBM_INVALID_PARAMETER;
226
227
	_initADU( MB_address, 0x03, 4 );
228
   _insertWord ( Starting_Reg );
229
   _insertWord ( Nbr_of_Regs );
230
231
   ADUStatus = MBM_Send_ADU ( mbADU, pmbADU - mbADU );
232
233
   if ( ADUStatus != MB_SUCCESS ) return ADUStatus;
234
   if ( mbADU[ADU_OFF_ADDRESS] != MB_address ) return MBM_BAD_ADDRESS;
235
   if ( mbADU[ADU_OFF_FUNCTION] & 0x80 ) return (int)mbADU[ADU_OFF_EXCEPTION];
236
237
   Result+= Starting_Reg;
238
   for ( Count=0; Count<Nbr_of_Regs; Count+=1 )
239
   	*Result++ = _getADUword(3+(Count*2));
240
241
	return MB_SUCCESS;
242
} // MBM_ReadRegs
243
244
245
/* START FUNCTION DESCRIPTION ********************************************
246
MBM_ReadInRegs 0x04
247
248
SYNTAX:			int MBM_ReadInRegs ( int MB_address, int* Result,
249
						int Starting_Reg, int Nbr_of_Regs );
250
251
DESCRIPTION:	Read the specified input registers.  The function will
252
					create the MODBUS ADU, in mbADU, with the target address
253
               pre-pended.
254
255
PARAMETER1:		MODBUS addresss of the target device
256
257
PARAMETER2:		Starting address to put the results
258
259
PARAMETER3:    Starting input register number, 1 relative, to read
260
261
PARAMETER4:		Number of registers to read
262
263
RETURN VALUE:	MB_SUCCESS
264
					MBM_INVALID_PARAMETER
265
               MBM_PACKET_ERROR
266
               MBM_BAD_ADDRESS
267
268
END DESCRIPTION **********************************************************/
269
270
/*** BeginHeader MBM_ReadInRegs */
271
int MBM_ReadInRegs ( int MB_address, int* Result, int Starting_Reg,
272
	int Nbr_of_Regs );
273
/*** EndHeader */
274
275
MODBUS_DEBUG
276
int MBM_ReadInRegs ( int MB_address, int* Result, int Starting_Reg,
277
	int Nbr_of_Regs )
278
{
279
	auto int ADUStatus;
280
	auto int RegValue;
281
   auto int Count;
282
283
	if ( Starting_Reg < 0 ) return MBM_INVALID_PARAMETER;
284
	if ( Nbr_of_Regs <= 0  ||  Nbr_of_Regs > 125 ) return MBM_INVALID_PARAMETER;
285
286
	_initADU( MB_address, 0x04, 4 );
287
   _insertWord ( Starting_Reg );
288
   _insertWord ( Nbr_of_Regs );
289
290
   ADUStatus = MBM_Send_ADU ( mbADU, pmbADU - mbADU );
291
292
   if ( ADUStatus != MB_SUCCESS ) return ADUStatus;
293
   if ( mbADU[ADU_OFF_ADDRESS] != MB_address ) return MBM_BAD_ADDRESS;
294
   if ( mbADU[ADU_OFF_FUNCTION] & 0x80 ) return (int)mbADU[ADU_OFF_EXCEPTION];
295
296
   for ( Count=0; Count<Nbr_of_Regs; Count+=1 )
297
   	*Result++ = _getADUword(3+(Count*2));
298
299
	return MB_SUCCESS;
300
} // MBM_ReadInRegs
301
302
303
/* START FUNCTION DESCRIPTION ********************************************
304
MBM_WriteCoil 0x05
305
306
SYNTAX:        int MBM_WriteCoil ( int MB_address, int CoilNbr,
307
						int CoilState );
308
309
DESCRIPTION:	write a value to a single coil
310
311
PARAMETER1:		MODBUS addresss of the target device
312
313
PARAMETER2:		Coil number
314
315
PARAMETER3:		Coil state
316
317
RETURN VALUE:	MB_SUCCESS
318
					MBM_INVALID_PARAMETER
319
               MBM_PACKET_ERROR
320
               MBM_BAD_ADDRESS
321
322
END DESCRIPTION **********************************************************/
323
324
/*** BeginHeader MBM_WriteCoil */
325
int MBM_WriteCoil ( int MB_address, int CoilNbr, int CoilState );
326
/*** EndHeader */
327
328
MODBUS_DEBUG
329
int MBM_WriteCoil ( int MB_address, int CoilNbr, int CoilState )
330
{
331
	auto int ADUStatus;
332
333
	if ( CoilState & 0xFFFE ) return MBM_INVALID_PARAMETER;
334
	_initADU( MB_address, 0x05, 4 );
335
   _insertWord ( CoilNbr );
336
   _insertWord ( CoilState );
337
338
   ADUStatus = MBM_Send_ADU ( mbADU, pmbADU - mbADU );
339
340
   if ( ADUStatus != MB_SUCCESS ) return MBM_PACKET_ERROR;
341
   if ( mbADU[ADU_OFF_ADDRESS] != MB_address ) return MBM_BAD_ADDRESS;
342
   if ( mbADU[ADU_OFF_FUNCTION] & 0x80 ) return (int)mbADU[ADU_OFF_EXCEPTION];
343
344
	return MB_SUCCESS;
345
} // MBM_WriteCoil
346
347
348
/* START FUNCTION DESCRIPTION ********************************************
349
MBM_WriteReg 0x06
350
351
SYNTAX:        int MBM_WriteReg ( int MB_address, int RegNbr, int RegData );
352
353
DESCRIPTION:	write a value to a single register
354
355
PARAMETER1:		MODBUS addresss of the target device
356
357
PARAMETER2:		Register number
358
359
PARAMETER3:		Regester Data
360
361
RETURN VALUE:	MB_SUCCESS
362
					MBM_INVALID_PARAMETER
363
               MBM_PACKET_ERROR
364
               MBM_BAD_ADDRESS
365
366
END DESCRIPTION **********************************************************/
367
368
/*** BeginHeader MBM_WriteReg */
369
int MBM_WriteReg ( int MB_address, int RegNbr, int RegData );
370
/*** EndHeader */
371
372
MODBUS_DEBUG
373
int MBM_WriteReg ( int MB_address, int RegNbr, int RegData )
374
{
375
	auto int ADUStatus;
376
377
	_initADU( MB_address, 0x06, 4 );
378
   _insertWord ( RegNbr );
379
   _insertWord ( RegData );
380
381
   ADUStatus = MBM_Send_ADU ( mbADU, pmbADU - mbADU );
382
383
   if ( ADUStatus != MB_SUCCESS ) return MBM_PACKET_ERROR;
384
   if ( mbADU[ADU_OFF_ADDRESS] != MB_address ) return MBM_BAD_ADDRESS;
385
   if ( mbADU[ADU_OFF_FUNCTION] & 0x80 ) return (int)mbADU[ADU_OFF_EXCEPTION];
386
387
	return MB_SUCCESS;
388
} // MBM_WriteReg
389
390
391
/* START FUNCTION DESCRIPTION ********************************************
392
MBM_WriteCoils 0x0F
393
394
SYNTAX:        int MBM_WriteCoils ( int MB_address, int StartCoilNbr,
395
						int NbrCoils, int CoilStates );
396
397
DESCRIPTION:	write a values to coils
398
399
PARAMETER1:		MODBUS addresss of the target device
400
401
PARAMETER2:		Starting Coil number
402
403
PARAMETER3:		Number of Coils
404
405
PARAMETER4:		Coil states - max of 16 with lowest coil nbr value in bit 0
406
407
RETURN VALUE:	MB_SUCCESS
408
					MBM_INVALID_PARAMETER
409
               MBM_PACKET_ERROR
410
               MBM_BAD_ADDRESS
411
412
END DESCRIPTION **********************************************************/
413
414
/*** BeginHeader MBM_WriteCoils */
415
int MBM_WriteCoils ( int MB_address, int StartCoilNbr, int NbrCoils, int CoilStates );
416
/*** EndHeader */
417
418
MODBUS_DEBUG
419
int MBM_WriteCoils ( int MB_address, int StartCoilNbr, int NbrCoils, int CoilStates )
420
{
421
	auto int ADUStatus;
422
423
	if ( CoilState & 0xFFFE ) return MBM_INVALID_PARAMETER;
424
425
	_initADU( MB_address, 0x0F, 8 );
426
   _insertWord ( StartCoilNbr );
427
   _insertWord ( NbrCoils );
428
	_insertWord ( 2 );						// byte count for up to 16 coils
429
   _insertWord ( CoilStates );
430
431
   ADUStatus = MBM_Send_ADU ( mbADU, pmbADU - mbADU );
432
433
   if ( ADUStatus != MB_SUCCESS ) return MBM_PACKET_ERROR;
434
   if ( mbADU[MBM_OFF_ADDRESS] != MB_address ) return MBM_BAD_ADDRESS;
435
   if ( mbADU[MBM_OFF_FUNCTION] & 0x80 ) return (int)mbADU[ADU_OFF_EXCEPTION];
436
437
	return MB_SUCCESS;
438
}
439
440
/* START FUNCTION DESCRIPTION ********************************************
441
MODBUS_CRC		<MODBUS_Slave.LIB>
442
443
SYNTAX:        unsigned MODBUS_CRC(unsigned char *pcMess, unsigned wLen)
444
445
DESCRIPTION:	alternate CRC calculation
446
447
PARAMETER1:		address of bytes for CRC calculation
448
449
PARAMETER2:		number of bytes in paraameter1
450
451
RETURN VALUE:	CRC value
452
453
Note: to use this alternate CRC function you must insert
454
#define USE_MODBUS_CRC
455
before the #use directives for the modbus libraries.
456
457
END DESCRIPTION **********************************************************/
458
459
/*** BeginHeader MODBUS_CRC */
460
unsigned MODBUS_CRC(unsigned char *pcMess, unsigned wLen);
461
/*** EndHeader */
462
463
/*=========================================================================*\
464
	Compute Cyclic Redundancy Check
465
\*=========================================================================*/
466
467
const unsigned char MODBUS_CRC_MSB[] ={
468
	0x00,0xC1,0x81,0x40,	0x01,0xC0,0x80,0x41,	0x01,0xC0,0x80,0x41,	0x00,0xC1,0x81,0x40,
469
	0x01,0xC0,0x80,0x41,	0x00,0xC1,0x81,0x40,	0x00,0xC1,0x81,0x40,	0x01,0xC0,0x80,0x41,
470
	0x01,0xC0,0x80,0x41,	0x00,0xC1,0x81,0x40,	0x00,0xC1,0x81,0x40,	0x01,0xC0,0x80,0x41,
471
	0x00,0xC1,0x81,0x40,	0x01,0xC0,0x80,0x41,	0x01,0xC0,0x80,0x41,	0x00,0xC1,0x81,0x40,
472
	0x01,0xC0,0x80,0x41,	0x00,0xC1,0x81,0x40,	0x00,0xC1,0x81,0x40,	0x01,0xC0,0x80,0x41,
473
	0x00,0xC1,0x81,0x40,	0x01,0xC0,0x80,0x41,	0x01,0xC0,0x80,0x41,	0x00,0xC1,0x81,0x40,
474
	0x00,0xC1,0x81,0x40,	0x01,0xC0,0x80,0x41,	0x01,0xC0,0x80,0x41,	0x00,0xC1,0x81,0x40,
475
	0x01,0xC0,0x80,0x41,	0x00,0xC1,0x81,0x40, 0x00,0xC1,0x81,0x40,	0x01,0xC0,0x80,0x41,
476
	0x01,0xC0,0x80,0x41,	0x00,0xC1,0x81,0x40,	0x00,0xC1,0x81,0x40,	0x01,0xC0,0x80,0x41,
477
	0x00,0xC1,0x81,0x40,	0x01,0xC0,0x80,0x41,	0x01,0xC0,0x80,0x41,	0x00,0xC1,0x81,0x40,
478
	0x00,0xC1,0x81,0x40,	0x01,0xC0,0x80,0x41,	0x01,0xC0,0x80,0x41,	0x00,0xC1,0x81,0x40,
479
	0x01,0xC0,0x80,0x41,	0x00,0xC1,0x81,0x40,	0x00,0xC1,0x81,0x40,	0x01,0xC0,0x80,0x41,
480
	0x00,0xC1,0x81,0x40,	0x01,0xC0,0x80,0x41,	0x01,0xC0,0x80,0x41,	0x00,0xC1,0x81,0x40,
481
	0x01,0xC0,0x80,0x41,	0x00,0xC1,0x81,0x40,	0x00,0xC1,0x81,0x40,	0x01,0xC0,0x80,0x41,
482
	0x01,0xC0,0x80,0x41,	0x00,0xC1,0x81,0x40,	0x00,0xC1,0x81,0x40,	0x01,0xC0,0x80,0x41,
483
	0x00,0xC1,0x81,0x40,	0x01,0xC0,0x80,0x41,	0x01,0xC0,0x80,0x41,	0x00,0xC1,0x81,0x40
484
};
485
486
const unsigned char MODBUS_CRC_LSB[] ={
487
   0x00,0xC0,0xC1,0x01, 0xC3,0x03,0x02,0xC2,	0xC6,0x06,0x07,0xC7,	0x05,0xC5,0xC4,0x04,
488
   0xCC,0x0C,0x0D,0xCD,	0x0F,0xCF,0xCE,0x0E, 0x0A,0xCA,0xCB,0x0B,	0xC9,0x09,0x08,0xC8,
489
   0xD8,0x18,0x19,0xD9, 0x1B,0xDB,0xDA,0x1A,	0x1E,0xDE,0xDF,0x1F, 0xDD,0x1D,0x1C,0xDC,
490
   0x14,0xD4,0xD5,0x15,	0xD7,0x17,0x16,0xD6, 0xD2,0x12,0x13,0xD3,	0x11,0xD1,0xD0,0x10,
491
   0xF0,0x30,0x31,0xF1,	0x33,0xF3,0xF2,0x32,	0x36,0xF6,0xF7,0x37,	0xF5,0x35,0x34,0xF4,
492
	0x3C,0xFC,0xFD,0x3D,	0xFF,0x3F,0x3E,0xFE,	0xFA,0x3A,0x3B,0xFB,	0x39,0xF9,0xF8,0x38,
493
	0x28,0xE8,0xE9,0x29,	0xEB,0x2B,0x2A,0xEA,	0xEE,0x2E,0x2F,0xEF,	0x2D,0xED,0xEC,0x2C,
494
	0xE4,0x24,0x25,0xE5,	0x27,0xE7,0xE6,0x26,	0x22,0xE2,0xE3,0x23,	0xE1,0x21,0x20,0xE0,
495
	0xA0,0x60,0x61,0xA1,	0x63,0xA3,0xA2,0x62,	0x66,0xA6,0xA7,0x67,	0xA5,0x65,0x64,0xA4,
496
	0x6C,0xAC,0xAD,0x6D,	0xAF,0x6F,0x6E,0xAE,	0xAA,0x6A,0x6B,0xAB,	0x69,0xA9,0xA8,0x68,
497
	0x78,0xB8,0xB9,0x79,	0xBB,0x7B,0x7A,0xBA,	0xBE,0x7E,0x7F,0xBF,	0x7D,0xBD,0xBC,0x7C,
498
	0xB4,0x74,0x75,0xB5,	0x77,0xB7,0xB6,0x76,	0x72,0xB2,0xB3,0x73,	0xB1,0x71,0x70,0xB0,
499
	0x50,0x90,0x91,0x51,	0x93,0x53,0x52,0x92,	0x96,0x56,0x57,0x97,	0x55,0x95,0x94,0x54,
500
	0x9C,0x5C,0x5D,0x9D,	0x5F,0x9F,0x9E,0x5E,	0x5A,0x9A,0x9B,0x5B,	0x99,0x59,0x58,0x98,
501
	0x88,0x48,0x49,0x89,	0x4B,0x8B,0x8A,0x4A,	0x4E,0x8E,0x8F,0x4F,	0x8D,0x4D,0x4C,0x8C,
502
	0x44,0x84,0x85,0x45,	0x87,0x47,0x46,0x86,	0x82,0x42,0x43,0x83,	0x41,0x81,0x80,0x40
503
};
504
505
MODBUS_DEBUG
506
unsigned MODBUS_CRC(unsigned char *pcMess, unsigned wLen)
507
{
508
	auto unsigned char cHi,cLo;			//	CRC Accumulators (MSB & LSB)
509
	auto unsigned w;							//	CRC Shift In Index
510
511
	cHi = cLo = 0xFF;							//	Init CRC
512
	while(wLen--)
513
	{												//	For Each Byte
514
		w = cHi ^ *pcMess++;					//	Next Table Index
515
		cHi = cLo ^ MODBUS_CRC_MSB[w];	//	Next CRC
516
		cLo = MODBUS_CRC_LSB[w];
517
	}
518
	return ((unsigned) cHi << 8) | cLo;	//	merge the bytes and return
519
}
520
521
/*** BeginHeader */
522
#endif // __MBMASTER
523
/*** EndHeader */
524