codi pic c compiler (llibreria modbus)

23
1 E:\modbus.c ////////////////////////////////////////////////////////////////////////////////////////// //// modbus . c //// //// //// //// MODBUS protocol driver for serial communications . //// //// //// //// Refer to documentation at http :// www . modbus . org for more information on MODBUS . //// //// //// ////////////////////////////////////////////////////////////////////////////////////////// //// //// //// DEFINES : //// //// //// //// MODBUS _ TYPE MODBUS _ TYPE _ MASTER or MODBUS _ TYPE _ SLAVE //// //// MODBUS _ SERIAL _ INT _ SOURCE Source of interrupts //// //// ( MODBUS _ INT _ EXT , MODBUS _ INT _ RDA , MODBUS _ INT _ RDA 2 ) //// //// MODBUS _ SERIAL _ BAUD Valid baud rate for serial //// //// MODBUS _ SERIAL _ RX _ PIN Valid pin for serial receive //// //// MODBUS _ SERIAL _ TX _ PIN Valid pin for serial transmit //// //// MODBUS _ SERIAL _ ENABLE _ PIN Valid pin for serial enable , rs 485 only //// //// MODBUS _ SERIAL _ RX _ ENABLE Valid pin for serial rcv enable , rs 485 only //// //// MODBUS _ SERAIL _ RX _ BUFFER _ SIZE Size of the receive buffer //// //// //// //// //// //// SHARED API : //// //// //// //// modbus _ init () //// //// - Initialize modbus serial communication system //// //// //// //// modbus _ serial _ send _ start ( address , func ) //// //// - Setup serial line to begin sending . Once this is called , you can send data //// //// using modbus _ serial _ putc (). Should only be used for custom commands . //// //// //// //// modbus _ serial _ send _ stop () //// //// - Must be called to finalize the send when modbus _ serial _ send _ start is used . //// //// //// //// modbus _ kbhit () //// //// - Used to check if a packet has been received . //// //// //// //// MASTER API : //// //// All master API functions return 0 on success . //// //// //// //// exception modbus _ read _ coils ( address , start _ address , quantity ) //// //// - Wrapper for function 0 x 01 ( read coils ) in the MODBUS specification . //// //// //// //// exception modbus _ read _ discrete _ input ( address , start _ address , quantity ) //// //// - Wrapper for function 0 x 02 ( read discret input ) in the MODBUS specification . //// //// //// //// exception modbus _ read _ holding _ registers ( address , start _ address , quantity ) //// //// - Wrapper for function 0 x 03 ( read holding regs ) in the MODBUS specification . //// //// //// //// exception modbus _ read _ input _ registers ( address , start _ address , quantity ) //// //// - Wrapper for function 0 x 04 ( read input regs ) in the MODBUS specification . //// //// //// //// exception modbus _ write _ single _ coil ( address , output _ address , on ) //// //// - Wrapper for function 0 x 05 ( write single coil ) in the MODBUS specification . //// //// //// //// exception modbus _ write _ single _ register ( address , reg _ address , reg _ value ) //// //// - Wrapper for function 0 x 06 ( write single reg ) in the MODBUS specification . //// //// //// //// exception modbus _ read _ exception _ status ( address ) //// //// - Wrapper for function 0 x 07 ( read void status ) in the MODBUS specification . //// //// //// //// exception modbus _ diagnostics ( address , sub _ func , data ) //// //// - Wrapper for function 0 x 08 ( diagnostics ) in the MODBUS specification . //// //// //// //// exception modbus _ get _ comm _ event _ counter ( address ) //// //// - Wrapper for function 0 x 0 B ( get comm event count ) in the MODBUS specification .//// //// //// //// exception modbus _ get _ comm _ event _ log ( address ) //// //// - Wrapper for function 0 x 0 C ( get comm event log ) in the MODBUS specification . //// //// //// //// exception modbus _ write _ multiple _ coils ( address , start _ address , quantity , * values ) //// //// - Wrapper for function 0 x 0 F ( write multiple coils ) in the MODBUS specification .//// //// - Special Note : values is a pointer to an int 8 array , each byte represents 8 //// //// coils . ////

Upload: francisco-carreiro

Post on 26-Oct-2015

88 views

Category:

Documents


16 download

TRANSCRIPT

Page 1: Codi PIC C COMPILER (Llibreria Modbus)

1E:\modbus.c

/////////////////////////////////////////////////// /////////////////////////////////////////// modbus. c //////// //////// MODBUS protocol driver for serial communications . //////// //////// Refer to documentation at http :// www. modbus. org for more information on MODBUS . //////// /////////////////////////////////////////////////////// /////////////////////////////////////////// //////// DEFINES: //////// //////// MODBUS_TYPE MODBUS _TYPE_MASTER or MODBUS_TYPE_SLAVE //////// MODBUS_SERIAL_INT _SOURCE Source of interrupts //////// ( MODBUS_INT _EXT, MODBUS_INT _RDA, MODBUS_INT _RDA2) //////// MODBUS_SERIAL_BAUD Valid baud rate for serial //////// MODBUS_SERIAL_RX_PIN Valid pin for serial receive //////// MODBUS_SERIAL_TX_PIN Valid pin for serial transmit //////// MODBUS_SERIAL_ENABLE_PIN Valid pin for serial enable , rs 485 only //////// MODBUS_SERIAL_RX_ENABLE Valid pin for serial rcv enable , rs 485 only //////// MODBUS_SERAIL_RX_BUFFER_SIZE Size of the receive buffer //////// //////// //////// SHARED API: //////// //////// modbus_init () //////// - Initialize modbus serial communication system //////// //////// modbus_serial _send _start ( address , func ) //////// - Setup serial line to begin sending . Once this is called , you can send data //////// using modbus _serial _putc (). Should only be used for custom commands . //////// //////// modbus_serial _send _stop () //////// - Must be called to finalize the send when modbus _serial _send _start is used . //////// //////// modbus_kbhit () //////// - Used to check if a packet has been received . //////// //////// MASTER API: //////// All master API functions return 0 on success . //////// //////// exception modbus _read _coils ( address , start _address , quantity ) //////// - Wrapper for function 0x 01( read coils ) in the MODBUS specification . //////// //////// exception modbus _read _discrete _input ( address , start _address , quantity ) //////// - Wrapper for function 0x 02( read discret input ) in the MODBUS specification . //////// //////// exception modbus _read _holding _registers ( address , start _address , quantity ) //////// - Wrapper for function 0x 03( read holding regs ) in the MODBUS specification . //////// //////// exception modbus _read _input _registers ( address , start _address , quantity ) //////// - Wrapper for function 0x 04( read input regs ) in the MODBUS specification . //////// //////// exception modbus _write _single _coil ( address , output _address , on ) //////// - Wrapper for function 0x 05( write single coil ) in the MODBUS specification . //////// //////// exception modbus _write _single _register ( address , reg _address , reg _value ) //////// - Wrapper for function 0x 06( write single reg ) in the MODBUS specification . //////// //////// exception modbus _read _exception _status ( address ) //////// - Wrapper for function 0x 07( read void status ) in the MODBUS specification . //////// //////// exception modbus _diagnostics ( address , sub _func , data ) //////// - Wrapper for function 0x 08( diagnostics ) in the MODBUS specification . //////// //////// exception modbus _get _comm_event _counter ( address ) //////// - Wrapper for function 0x 0B( get comm event count ) in the MODBUS specification .//////// //////// exception modbus _get _comm_event _log ( address ) //////// - Wrapper for function 0x 0C( get comm event log ) in the MODBUS specification . //////// //////// exception modbus _write _multiple _coils ( address , start _address , quantity , * values ) //////// - Wrapper for function 0x 0F( write multiple coils ) in the MODBUS specification .//////// - Special Note : values is a pointer to an int 8 array , each byte represents 8 //////// coils . ////

Page 2: Codi PIC C COMPILER (Llibreria Modbus)

2E:\modbus.c

//// //////// exception modbus _write _multiple _registers ( address , start _address , quantity , * values )/////// - Wrapper for function 0x 10( write multiple regs ) in the MODBUS specification . //////// - Special Note : values is a pointer to an int 8 array //////// //////// exception modbus _report _slave _id ( address ) //////// - Wrapper for function 0x 11( report slave id ) in the MODBUS specification . //////// //////// exception modbus _read _file _record ( address , byte _count , * request ) //////// - Wrapper for function 0x 14( read file record ) in the MODBUS specification . //////// //////// exception modbus _write _file _record ( address , byte _count , * request ) //////// - Wrapper for function 0x 15( write file record ) in the MODBUS specification . //////// //////// exception modbus _mask_write _register ( address , reference _address , AND_mask, OR_mask)//////// - Wrapper for function 0x 16( read coils ) in the MODBUS specification . //////// //////// exception modbus _read _write _multiple _registers ( address , read _start , read _quantity , //////// write _start , write _quantity , * write _registers _value ) //////// - Wrapper for function 0x 17( read write mult regs ) in the MODBUS specification .//////// //////// exception modbus _read _FIFO _queue ( address , FIFO _address ) //////// - Wrapper for function 0x 18( read FIFO queue ) in the MODBUS specification . //////// //////// //////// Slave API : //////// //////// void modbus _read _coils _rsp ( address , byte _count , * coil _data ) //////// - Wrapper to respond to 0x 01( read coils ) in the MODBUS specification . //////// //////// void modbus _read _discrete _input _rsp ( address , byte _count , * input _data ) //////// - Wrapper to respond to 0x 02( read discret input ) in the MODBUS specification . //////// //////// void modbus _read _holding _registers _rsp ( address , byte _count , * reg _data ) //////// - Wrapper to respond to 0x 03( read holding regs ) in the MODBUS specification . //////// //////// void modbus _read _input _registers _rsp ( address , byte _count , * input _data ) //////// - Wrapper to respond to 0x 04( read input regs ) in the MODBUS specification . //////// //////// void modbus _write _single _coil _rsp ( address , output _address , output _value ) //////// - Wrapper to respond to 0x 05( write single coil ) in the MODBUS specification . //////// //////// void modbus _write _single _register _rsp ( address , reg _address , reg _value ) //////// - Wrapper to respond to 0x 06( write single reg ) in the MODBUS specification . //////// //////// void modbus _read _exception _status _rsp ( address , data ) //////// - Wrapper to respond to 0x 07( read void status ) in the MODBUS specification . //////// //////// void modbus _diagnostics _rsp ( address , sub _func , data ) //////// - Wrapper to respond to 0x 08( diagnostics ) in the MODBUS specification . //////// //////// void modbus _get _comm_event _counter _rsp ( address , status , event _count ) //////// - Wrapper to respond to 0x 0B( get comm event count ) in the MODBUS specification //////// //////// void modbus _get _comm_event _log _rsp ( address , status , event _count , message _count , //////// * events , events _len ) //////// - Wrapper to respond to 0x 0C( get comm event log ) in the MODBUS specification . //////// //////// void modbus _write _multiple _coils _rsp ( address , start _address , quantity ) //////// - Wrapper to respond to 0x 0F( write multiple coils ) in the MODBUS specification //////// //////// void modbus _write _multiple _registers _rsp ( address , start _address , quantity ) //////// - Wrapper to respond to 0x 10( write multiple regs ) in the MODBUS specification .//////// //////// void modbus _report _slave _id _rsp ( address , slave _id , run _status , * data , data _len ) //////// - Wrapper to respond to 0x 11( report slave id ) in the MODBUS specification . //////// //////// void modbus _read _file _record _rsp ( address , byte _count , * request ) //////// - Wrapper to respond to 0x 14( read file record ) in the MODBUS specification . //////// //////// void modbus _write _file _record _rsp ( address , byte _count , * request ) //////// - Wrapper to respond to 0x 15( write file record ) in the MODBUS specification . //////// //////// void modbus _mask_write _register _rsp ( address , reference _address , AND_mask, OR_mask) ////

Page 3: Codi PIC C COMPILER (Llibreria Modbus)

3E:\modbus.c

//// - Wrapper to respond to 0x 16( read coils ) in the MODBUS specification . //////// //////// void modbus _read _write _multiple _registers _rsp ( address , * data , data _len ) //////// - Wrapper to respond to 0x 17( read write mult regs ) in the MODBUS specification //////// //////// void modbus _read _FIFO _queue _rsp ( address , FIFO _len , * data ) //////// - Wrapper to respond to 0x 18( read FIFO queue ) in the MODBUS specification . //////// //////// void modbus _exception _rsp ( int 8 address , int 16 func , exception error ) //////// - Wrapper to send an exception response . See exception list below . //////// //////// Exception List : //////// ILLEGAL _FUNCTION, ILLEGAL _DATA_ADDRESS, ILLEGAL _DATA_VALUE, //////// SLAVE_DEVICE_FAILURE, ACKNOWLEDGE, SLAVE_DEVICE_BUSY, MEMORY_PARITY_ERROR, //////// GATEWAY_PATH_UNAVAILABLE, GATEWAY_TARGET_NO_RESPONSE //////// /////////////////////////////////////////////////////// /////////////////////////////////////////// ( C) Copyright 1996 , 2006 Custom Computer Services //////// This source code may only be used by licensed users of the CCS //////// C compiler . This source code may only be distributed to other //////// licensed users of the CCS C compiler . No other use , //////// reproduction or distribution is permitted without w ritten //////// permission . Derivative programs created using this software //////// in object code form are not restricted in any way . /////////////////////////////////////////////////////// ///////////////////////////////////////

/* Some defines so we can use identifiers to set thing s up */#define MODBUS_TYPE_MASTER 99999#define MODBUS_TYPE_SLAVE 88888#define MODBUS_INT _RDA 77777#define MODBUS_INT _RDA2 66666#define MODBUS_INT _EXT 55555#define MODBUS_SERIAL COM1#ifndef MODBUS_TYPE#define MODBUS_TYPE MODBUS_TYPE_MASTER#endif

#ifndef MODBUS_SERIAL_INT _SOURCE#define MODBUS_SERIAL_INT _SOURCE MODBUS_INT _EXT // Seleccionar entre una interrupció

externa#endif // o una interrupció sèrie assíncrona

#ifndef MODBUS_SERIAL_BAUD#define MODBUS_SERIAL_BAUD 19200#endif

#ifndef MODBUS_SERIAL_RX_PIN#define MODBUS_SERIAL_RX_PIN PIN _C7 // Pin de rebre dades #endif

#ifndef MODBUS_SERIAL_TX_PIN#define MODBUS_SERIAL_TX_PIN PIN _C6 // Pin de transmetre dades #endif

#ifndef MODBUS_SERIAL_ENABLE_PIN#define MODBUS_SERIAL_ENABLE_PIN T _CS // Pin DE de control . RX low , TX high .#endif

#ifndef MODBUS_SERIAL_RX_ENABLE#define MODBUS_SERIAL_RX_ENABLE 0 // Controls RE pin . Should keep low .#endif

#ifndef MODBUS_SERIAL_TIMEOUT#define MODBUS_SERIAL_TIMEOUT 10000 // in us#endif

#if ( MODBUS_SERIAL_INT _SOURCE == MODBUS_INT _RDA ) #use rs 232 ( baud =MODBUS_SERIAL_BAUD, UART1, parity =N, stream =MODBUS_SERIAL, errors ) #define RCV_OFF() { disable _interrupts ( INT _RDA) ;}#elif ( MODBUS_SERIAL_INT _SOURCE == MODBUS_INT _RDA2 ) #use rs 232 ( baud =MODBUS_SERIAL_BAUD, UART2, parity =N, stream =MODBUS_SERIAL, error ) #define RCV_OFF() { disable _interrupts ( INT _RDA2) ;}#elif ( MODBUS_SERIAL_INT _SOURCE == MODBUS_INT _EXT ) #use rs 232 ( baud =MODBUS_SERIAL_BAUD, xmit =MODBUS_SERIAL_TX_PIN , rcv =MODBUS_SERIAL_RX_PIN

Page 4: Codi PIC C COMPILER (Llibreria Modbus)

4E:\modbus.c

, parity =N, stream =MODBUS_SERIAL, disable _ints ) #define RCV_OFF() { disable _interrupts ( INT _EXT) ;}#else #error Please define a correct interrupt source#endif

#ifndef MODBUS_SERIAL_RX_BUFFER_SIZE#define MODBUS_SERIAL_RX_BUFFER_SIZE 64 // tamany de enviar / rebre buffer#endif

#if ( MODBUS_TYPE == MODBUS_TYPE_MASTER) int 32 modbus_serial _wait =MODBUS_SERIAL_TIMEOUT;

#define MODBUS_SERIAL_WAIT_FOR_RESPONSE() \{\ if ( address ) \ {\ while (! modbus_kbhit () && -- modbus_serial _wait ) \ delay _us ( 1) ;\ if (! modbus_serial _wait ) \ modbus_rx . error =TIMEOUT;\ }\ modbus_serial _wait = MODBUS_SERIAL_TIMEOUT;\}#endif

#if ( MODBUS_SERIAL_INT _SOURCE != MODBUS_INT _EXT)#byte TXSTA =getenv ( " sfr : TXSTA" )#bit TRMT =TXSTA. 1

#define WAIT _FOR_HW_BUFFER() \{\ while (! TRMT) ;\} #endif

int 1 modbus_serial _new=0;

/************************************************** ******************Les següents excepcions estan definides en el proto col de MODBUS . Són perquè l ' esclau pugui comunicar els problemes de comunicació ambel mestre . La excepció de Timeout , es retorna quan no hi ha cap esclauque respongui as màster durant aquest temps .

TYPEDEF DEFINEIX UN TIPUS . DEFINEIX CADENES DE TEXT , CADA CADENA DE TXTQUEDA ASSOCIADA A UN NÚMERO*************************************************** *****************/typedef enum _exception { ILLEGAL _FUNCTION=1, ILLEGAL _DATA_ADDRESS=2, ILLEGAL _DATA_VALUE=3, SLAVE_DEVICE_FAILURE=4, ACKNOWLEDGE=5, SLAVE_DEVICE_BUSY=6, MEMORY_PARITY_ERROR=8, GATEWAY_PATH_UNAVAILABLE=10 , GATEWAY_TARGET_NO_RESPONSE=11 ,TIMEOUT=12} exception ;

/************************************************** ******************Aquestes funcions estan definides en el protocol MO DBUS. Poden ser utilitzades per l ' esclau per comprobar la funció d ' entrada*************************************************** *****************/typedef enum _function { FUNC_READ_COILS=0x 01 , FUNC_READ_DISCRETE_INPUT=0x 02 ,FUNC_READ_HOLDING_REGISTERS=0x 03 , FUNC_READ_INPUT_REGISTERS=0x 04 ,FUNC_WRITE_SINGLE_COIL=0x 05 , FUNC_WRITE_SINGLE_REGISTER=0x 06 ,FUNC_READ_EXCEPTION_STATUS=0x 07 , FUNC_DIAGNOSTICS=0x 08 ,FUNC_GET_COMM_EVENT_COUNTER=0x 0B, FUNC_GET_COMM_EVENT_LOG=0x 0C,FUNC_WRITE_MULTIPLE_COILS=0x 0F, FUNC_WRITE_MULTIPLE_REGISTERS=0x 10 ,FUNC_REPORT_SLAVE_ID =0x 11 , FUNC_READ_FILE _RECORD=0x 14 ,FUNC_WRITE_FILE _RECORD=0x 15 , FUNC_MASK_WRITE_REGISTER=0x 16 ,FUNC_READ_WRITE_MULTIPLE_REGISTERS=0x 17 , FUNC_READ_FIFO _QUEUE=0x 18} function ;

// Estats de la recepció de trames MODBUS// 1r Adreçament// 2n Codi de funció// 2r Dades

Page 5: Codi PIC C COMPILER (Llibreria Modbus)

5E:\modbus.c

enum { MODBUS_GETADDY=0, MODBUS_GETFUNC=1, MODBUS_GETDATA=2} modbus_serial _state = 0;

union{ int 8 b[ 2] ; // queden definits 2 bytes b 0 i b 1 int 16 d; // Defineix un Word de 16 bits} modbus_serial _crc ;

/************************************************** ******************Aquest struct és un conjunt de bytes que modifiquem en la recepció

La funció struct ens serveix per tenir variables or denades per grups *************************************************** *****************/struct{ int 8 address ;

int 8 len ; // number of bytes in the message received function func ; // the function of the message received exception error ; // error recieved , if any int 8 data [ MODBUS_SERIAL_RX_BUFFER_SIZE ] ; // data of the message received} modbus_rx ;

/* Taula del càlcul del CRC _high - order byte */const unsigned char modbus _auchCRCHi [] = {0x 00 , 0xC1, 0x 81 , 0x 40 , 0x 01 , 0xC0, 0x 80 , 0x 41 , 0x 01 , 0xC0, 0x 80 , 0x 41 , 0x 00 , 0xC1, 0x 81 ,0x 40 , 0x 01 , 0xC0, 0x 80 , 0x 41 , 0x 00 , 0xC1, 0x 81 , 0x 40 , 0x 00 , 0xC1, 0x 81 , 0x 40 , 0x 01 , 0xC0,0x 80 , 0x 41 , 0x 01 , 0xC0, 0x 80 , 0x 41 , 0x 00 , 0xC1, 0x 81 , 0x 40 , 0x 00 , 0xC1, 0x 81 , 0x 40 , 0x 01 ,0xC0, 0x 80 , 0x 41 , 0x 00 , 0xC1, 0x 81 , 0x 40 , 0x 01 , 0xC0, 0x 80 , 0x 41 , 0x 01 , 0xC0, 0x 80 , 0x 41 ,0x 00 , 0xC1, 0x 81 , 0x 40 , 0x 01 , 0xC0, 0x 80 , 0x 41 , 0x 00 , 0xC1, 0x 81 , 0x 40 , 0x 00 , 0xC1, 0x 81 ,0x 40 , 0x 01 , 0xC0, 0x 80 , 0x 41 , 0x 00 , 0xC1, 0x 81 , 0x 40 , 0x 01 , 0xC0, 0x 80 , 0x 41 , 0x 01 , 0xC0,0x 80 , 0x 41 , 0x 00 , 0xC1, 0x 81 , 0x 40 , 0x 00 , 0xC1, 0x 81 , 0x 40 , 0x 01 , 0xC0, 0x 80 , 0x 41 , 0x 01 ,0xC0, 0x 80 , 0x 41 , 0x 00 , 0xC1, 0x 81 , 0x 40 , 0x 01 , 0xC0, 0x 80 , 0x 41 , 0x 00 , 0xC1, 0x 81 , 0x 40 ,0x 00 , 0xC1, 0x 81 , 0x 40 , 0x 01 , 0xC0, 0x 80 , 0x 41 , 0x 01 , 0xC0, 0x 80 , 0x 41 , 0x 00 , 0xC1, 0x 81 ,0x 40 , 0x 00 , 0xC1, 0x 81 , 0x 40 , 0x 01 , 0xC0, 0x 80 , 0x 41 , 0x 00 , 0xC1, 0x 81 , 0x 40 , 0x 01 , 0xC0,0x 80 , 0x 41 , 0x 01 , 0xC0, 0x 80 , 0x 41 , 0x 00 , 0xC1, 0x 81 , 0x 40 , 0x 00 , 0xC1, 0x 81 , 0x 40 , 0x 01 ,0xC0, 0x 80 , 0x 41 , 0x 01 , 0xC0, 0x 80 , 0x 41 , 0x 00 , 0xC1, 0x 81 , 0x 40 , 0x 01 , 0xC0, 0x 80 , 0x 41 ,0x 00 , 0xC1, 0x 81 , 0x 40 , 0x 00 , 0xC1, 0x 81 , 0x 40 , 0x 01 , 0xC0, 0x 80 , 0x 41 , 0x 00 , 0xC1, 0x 81 ,0x 40 , 0x 01 , 0xC0, 0x 80 , 0x 41 , 0x 01 , 0xC0, 0x 80 , 0x 41 , 0x 00 , 0xC1, 0x 81 , 0x 40 , 0x 01 , 0xC0,0x 80 , 0x 41 , 0x 00 , 0xC1, 0x 81 , 0x 40 , 0x 00 , 0xC1, 0x 81 , 0x 40 , 0x 01 , 0xC0, 0x 80 , 0x 41 , 0x 01 ,0xC0, 0x 80 , 0x 41 , 0x 00 , 0xC1, 0x 81 , 0x 40 , 0x 00 , 0xC1, 0x 81 , 0x 40 , 0x 01 , 0xC0, 0x 80 , 0x 41 ,0x 00 , 0xC1, 0x 81 , 0x 40 , 0x 01 , 0xC0, 0x 80 , 0x 41 , 0x 01 , 0xC0, 0x 80 , 0x 41 , 0x 00 , 0xC1, 0x 81 ,0x 40};

/* Taula del càlcul del CRC _low–order byte */const char modbus _auchCRCLo[] = {0x 00 , 0xC0, 0xC1, 0x 01 , 0xC3, 0x 03 , 0x 02 , 0xC2, 0xC6, 0x 06 , 0x 07 , 0xC7, 0x 05 , 0xC5, 0xC4,0x 04 , 0xCC, 0x 0C, 0x 0D, 0xCD, 0x 0F, 0xCF, 0xCE, 0x 0E, 0x 0A, 0xCA, 0xCB, 0x 0B, 0xC9, 0x 09 ,0x 08 , 0xC8, 0xD8, 0x 18 , 0x 19 , 0xD9, 0x 1B, 0xDB, 0xDA, 0x 1A, 0x 1E, 0xDE, 0xDF, 0x 1F, 0xDD,0x 1D, 0x 1C, 0xDC, 0x 14 , 0xD4, 0xD5, 0x 15 , 0xD7, 0x 17 , 0x 16 , 0xD6, 0xD2, 0x 12 , 0x 13 , 0xD3,0x 11 , 0xD1, 0xD0, 0x 10 , 0xF0, 0x 30 , 0x 31 , 0xF1, 0x 33 , 0xF3, 0xF2, 0x 32 , 0x 36 , 0xF6, 0xF7,0x 37 , 0xF5, 0x 35 , 0x 34 , 0xF4, 0x 3C, 0xFC, 0xFD, 0x 3D, 0xFF, 0x 3F, 0x 3E, 0xFE, 0xFA, 0x 3A,0x 3B, 0xFB, 0x 39 , 0xF9, 0xF8, 0x 38 , 0x 28 , 0xE8, 0xE9, 0x 29 , 0xEB, 0x 2B, 0x 2A, 0xEA, 0xEE,0x 2E, 0x 2F, 0xEF, 0x 2D, 0xED, 0xEC, 0x 2C, 0xE4, 0x 24 , 0x 25 , 0xE5, 0x 27 , 0xE7, 0xE6, 0x 26 ,0x 22 , 0xE2, 0xE3, 0x 23 , 0xE1, 0x 21 , 0x 20 , 0xE0, 0xA0, 0x 60 , 0x 61 , 0xA1, 0x 63 , 0xA3, 0xA2,0x 62 , 0x 66 , 0xA6, 0xA7, 0x 67 , 0xA5, 0x 65 , 0x 64 , 0xA4, 0x 6C, 0xAC, 0xAD, 0x 6D, 0xAF, 0x 6F,0x 6E, 0xAE, 0xAA, 0x 6A, 0x 6B, 0xAB, 0x 69 , 0xA9, 0xA8, 0x 68 , 0x 78 , 0xB8, 0xB9, 0x 79 , 0xBB,0x 7B, 0x 7A, 0xBA, 0xBE, 0x 7E, 0x 7F, 0xBF, 0x 7D, 0xBD, 0xBC, 0x 7C, 0xB4, 0x 74 , 0x 75 , 0xB5,0x 77 , 0xB7, 0xB6, 0x 76 , 0x 72 , 0xB2, 0xB3, 0x 73 , 0xB1, 0x 71 , 0x 70 , 0xB0, 0x 50 , 0x 90 , 0x 91 ,0x 51 , 0x 93 , 0x 53 , 0x 52 , 0x 92 , 0x 96 , 0x 56 , 0x 57 , 0x 97 , 0x 55 , 0x 95 , 0x 94 , 0x 54 , 0x 9C, 0x 5C,0x 5D, 0x 9D, 0x 5F, 0x 9F, 0x 9E, 0x 5E, 0x 5A, 0x 9A, 0x 9B, 0x 5B, 0x 99 , 0x 59 , 0x 58 , 0x 98 , 0x 88 ,0x 48 , 0x 49 , 0x 89 , 0x 4B, 0x 8B, 0x 8A, 0x 4A, 0x 4E, 0x 8E, 0x 8F, 0x 4F, 0x 8D, 0x 4D, 0x 4C, 0x 8C,0x 44 , 0x 84 , 0x 85 , 0x 45 , 0x 87 , 0x 47 , 0x 46 , 0x 86 , 0x 82 , 0x 42 , 0x 43 , 0x 83 , 0x 41 , 0x 81 , 0x 80 ,0x 40};

// Objectiu : Permet la recepció de dades// Entrades : Cap// Sortides : Capvoid RCV_ON( void ){ #if ( MODBUS_SERIAL_INT _SOURCE!= MODBUS_INT _EXT) while ( kbhit ( MODBUS_SERIAL)) { getc () ;} // Borra RX buffer . Borra interrupció RDA .

Borra el flag del overrun error flag .

Page 6: Codi PIC C COMPILER (Llibreria Modbus)

6E:\modbus.c

#if ( MODBUS_SERIAL_INT _SOURCE==MODBUS_INT _RDA) clear _interrupt ( INT _RDA) ; // Neteja interrupció RDA #else clear _interrupt ( INT _RDA2) ; #endif

#if ( MODBUS_SERIAL_RX_ENABLE!= 0) output _low ( MODBUS_SERIAL_RX_ENABLE) ; #endif

#if ( MODBUS_SERIAL_INT _SOURCE==MODBUS_INT _RDA) enable _interrupts ( INT _RDA) ; #else enable _interrupts ( INT _RDA2) ; #endif #else clear _interrupt ( INT _EXT) ; ext _int _edge ( H_TO_L) ;

#if ( MODBUS_SERIAL_RX_ENABLE!= 0) output _low ( MODBUS_SERIAL_RX_ENABLE) ; #endif

enable _interrupts ( INT _EXT) ; #endif}

// Objectiu : Inicialitza comunicació RS - 485 . Cridem aquesta funció abans// d' utilitzar qualsevol funció RS - 485 // Entrades : Cap// Sortides : Capvoid modbus _init () { output _low ( MODBUS_SERIAL_ENABLE_PIN ) ; // Possem a zero el Tcs del transreceptor

RCV_ON() ; // crida aquesta funció per activar la recepció

setup _timer _2( T2_DIV _BY_16 , 249 , 5) ; // Configuració del Timer 2 per interrupció ~4ms

enable _interrupts ( GLOBAL) ; // Permet les interrupcions globals}

// Objectiu : Inicia el Timer de Timeout alhora d ' enviar o rebre trames// Entrades : Enable , s ' utilitza per canviar l ' estat on / off// Sortides : cap// El Timeout s ' haurà d ' activar quan el següent byte tardi més de 4ms// a 1 = càrrega Timeout // a 0 = Parat// Per enviar trama activem el Timeoutvoid modbus _enable _timeout ( int 1 enable ){ disable _interrupts ( INT _TIMER2) ; // Desabilita la interrupció del Timer 2 if ( enable ) { set _timer 2( 0) ; // Posa a 0 el Timer clear _interrupt ( INT _TIMER2) ; // Neteja la interrupció enable _interrupts ( INT _TIMER2) ; // Torna a habilitar la int del timer }}

// Objectiu : Quan s ' ha disparat la interrupció 2 el programa se situa a int timer 2// Entrades : Cap// Sortides : Cap#int _timer 2void modbus _timeout _now( void ) // EL MODBUS- GETDATA és l ' estat 2 definit a enum// Si el programa es troba en l ' Estat 2 i el Crc ha arribat a 0 ( trama correcta ) i tenim

nova trama : { if (( modbus_serial _state == MODBUS_GETDATA) && ( modbus_serial _crc . d == 0x 0000 ) && (!

modbus_serial _new)) { modbus_rx . len -= 2; modbus_serial _new=TRUE; // Marcador que indica que hi ha una nova trama a proc essar }

Page 7: Codi PIC C COMPILER (Llibreria Modbus)

7E:\modbus.c

else modbus_serial _new=FALSE; // prepara microcontrolador per la següent trama modbus_serial _crc . d=0xFFFF; // Inicialitza el CRC ( sempre inicialitzat a 0xFFFF) modbus_serial _state =MODBUS_GETADDY; modbus_enable _timeout ( FALSE) ; // Para temporitzador de timeout}

// Objectiu : Calcula el CRC de l ' últim byte que se li passa per la variable Data// ( Data = C de Modbus _serial _putc ) i actualitza el CRC global // Entrades : Caràcter// Sortides : Capvoid modbus _calc _crc ( char data ){ int 8 uIndex ; // És l ' índex per adreçar - nos a les taules de CRC ( lookup table )

// Càlcul del CRC uIndex = ( modbus_serial _crc . b[ 1]) ^ data ;

modbus_serial _crc . b[ 1] = ( modbus_serial _crc . b[ 0]) ^ modbus_auchCRCHi [ uIndex ] ; // byte major pes

modbus_serial _crc . b[ 0] = modbus_auchCRCLo[ uIndex ] ; // byte menor pes

}

// Objectiu : Posa un byte a la UART per poder enviar trames// Entrades : Caràcter// Sortides : Capvoid modbus _serial _putc ( int 8 c ){ fputc ( c , MODBUS_SERIAL) ; // Enviem el byte C a la UART modbus_calc _crc ( c ) ; // Enviem el byte C a la funció per calcular el CRC ( data ) delay _us ( 1000000 / MODBUS_SERIAL_BAUD) ; // Retard perquè el receptor tingui temps de

calcular el CRC}

// Objectiu : Interrumpeix la rutina de servei per tractar dades d' entrada// Entrades : Cap// Sortides : Cap#if ( MODBUS_SERIAL_INT _SOURCE==MODBUS_INT _RDA)#int _rda // Quan tenim buffer sèrie ple es dispara una interrup ció #elif ( MODBUS_SERIAL_INT _SOURCE==MODBUS_INT _RDA2)#int _rda 2#elif ( MODBUS_SERIAL_INT _SOURCE==MODBUS_INT _EXT)#int _ext#else#error Please define a correct interrupt source#endifvoid incomming _modbus_serial () { char c ;

c =fgetc ( MODBUS_SERIAL) ; // MODBUS SERIAL és el nom que hem donat a la UART // Agafa sempre tota la trama encara que no sigui per nosaltres

if (! modbus_serial _new) // Mira en quin estat ens trobem ADR , FUN, DAD { if ( modbus_serial _state == MODBUS_GETADDY) { modbus_serial _crc . d = 0xFFFF; // Inicialitzar CRC per rebre modbus_rx . address = c; // Guarda adreça que arriba modbus_serial _state ++; // Incrementa Estat modbus_rx . len = 0; // Inicia byte llargada modbus_rx . error =0; // Inicia byte d ' error } else if ( modbus_serial _state == MODBUS_GETFUNC) { modbus_rx . func = c; // Guarda codi de funció modbus_serial _state ++; // Incrementa l ' estat del sistema } else if ( modbus_serial _state == MODBUS_GETDATA) // el rx buffer size és el màxim de memòria que hem do nat ( definit a programa Main ) { if ( modbus_rx . len >=MODBUS_SERIAL_RX_BUFFER_SIZE ) { modbus_rx . len =

MODBUS_SERIAL_RX_BUFFER_SIZE - 1;} modbus_rx . data [ modbus_rx . len ]= c; // Guarda la C a rx . data

Page 8: Codi PIC C COMPILER (Llibreria Modbus)

8E:\modbus.c

modbus_rx . len ++; // Incrementa la posició }

modbus_calc _crc ( c ) ; // Calcula el CRC del valor agafat de la UART modbus_enable _timeout ( TRUE) ; // Activem el temps de Timeout i el següent

byte // Té 4 ms de Timeout per arribar }}

// Objectiu : Enviar missastge pel bus RS 485// Entrades : 1) L' adreçament del receptor ( to )// 2) Nombre de bytes de dades a enviar// 3) Un punter per les dades a enviar// 4) La llargada de les dades// Sortides : TRUE és correcte// FALSE si hi ha fallida// Nota : Format : font | destinació | llargada - dades | dades | checksumvoid modbus _serial _send _start ( int 8 to , int 8 func ){ modbus_serial _crc . d=0xFFFF; // Inicialitza el CRC modbus_serial _new=FALSE; // re - inicialitzem el bit de nova trama RCV_OFF() ; // Parem la Recepció ( off ) #if ( MODBUS_SERIAL_ENABLE_PIN != 0) output _high ( MODBUS_SERIAL_ENABLE_PIN ) ;#endif

delay _us ( 3500000 / MODBUS_SERIAL_BAUD) ; // 3. 5 character delay ( caràcters de retràs

modbus_serial _putc ( to ) ; // Envia les dades a la UART modbus_serial _putc ( func ) ;}

void modbus _serial _send _stop (){ int 8 crc _low , crc _high ;

crc _high =modbus_serial _crc . b[ 1] ; // Guardem el valor del Checksum MSB crc _low =modbus_serial _crc . b[ 0] ; // Guardem el valor del checksum LSB // Per defecte es calcula el CRC d ' aquests dos valors però enviarem a la UART // directement el valor CRC high i low . modbus_serial _putc ( crc _high ) ; // Enviem aquests valors a la UART modbus_serial _putc ( crc _low ) ;

#if ( MODBUS_SERIAL_INT _SOURCE!= MODBUS_INT _EXT) WAIT_FOR_HW_BUFFER() ;

#endif delay _us ( 3500000 / MODBUS_SERIAL_BAUD) ; // 3. 5 character delay

RCV_ON() ; // Activa la recepció

#if ( MODBUS_SERIAL_ENABLE_PIN != 0) output _low ( MODBUS_SERIAL_ENABLE_PIN ) ;#endif

modbus_serial _crc . d=0xFFFF;}

// Objectiu : Guarda missatge del bus en un buffer// Entrades : Cap// Sortides : TRUE si el missatge s ' ha rebut// FALSE si no s ' ha rebut// Nota : Les dades seran omplertes en el modbus _rx structint 1 modbus_kbhit (){ if (! modbus_serial _new) // si no tenim nova trama Kbhit =0 return FALSE ;

else if ( modbus_rx . func & 0x 80) // sinó si la funció té error {

Page 9: Codi PIC C COMPILER (Llibreria Modbus)

9E:\modbus.c

modbus_rx . error = modbus_rx . data [ 0] ; // guarda l ' error modbus_rx . len = 1; // es modifica la trama a enviar } modbus_serial _new=FALSE; // Inicia l ' indicador de trama nova return TRUE; // Kbhit =1 TENIM NOVA TRAMA}

#if ( MODBUS_TYPE==MODBUS_TYPE_MASTER)/* MODBUS Master Functions */

//**************************** FUNCIONS DE L ' ESCLAU MODBUS******************************/************************************************** ************************************Els següents structs , s ' utilitzen per fer peticions o respostes de lectura o escriptura*************************************************** ************************************/typedef struct _modbus_read _sub _request{ int 8 reference _type ;

int 16 file _number ; int 16 record _number ; int 16 record _length ;

} modbus_read _sub _request ;

typedef struct _modbus_write _sub _request{ int 8 reference _type ;

int 16 file _number ; int 16 record _number ; int 16 record _length ;

int 16 data [ MODBUS_SERIAL_RX_BUFFER_SIZE - 8] ;} modbus_write _sub _request ;

/************************************************** **********************************Els següents functions de l ' esclau , estan definides en el protocol Modbus .Aquest protocol es pot trobar a la web http :// www. modbus. orgTotes les funcions envien primer l ' adreçament de l ' esclau a qui va dirigida la funció*************************************************** ***********************************/

/*read _coilsInput : int 8 address Slave Address int 16 start _address Address to start reading from int 16 quantity Amount of addresses to readOutput : exception 0 if no error , else the exception*/exception modbus _read _coils ( int 8 address , int 16 start _address , int 16 quantity ){ modbus_serial _send _start ( address , FUNC_READ_COILS) ;

modbus_serial _putc ( make8( start _address , 1)) ;

modbus_serial _putc ( make8( start _address , 0)) ;

modbus_serial _putc ( make8( quantity , 1)) ;

modbus_serial _putc ( make8( quantity , 0)) ;

modbus_serial _send _stop () ;

MODBUS_SERIAL_WAIT_FOR_RESPONSE() ;

return modbus _rx . error ;

}

/*read _discrete _inputInput : int 8 address Slave Address int 16 start _address Address to start reading from int 16 quantity Amount of addresses to readOutput : exception 0 if no error , else the exception*/exception modbus _read _discrete _input ( int 8 address , int 16 start _address , int 16 quantity ){ modbus_serial _send _start ( address , FUNC_READ_DISCRETE_INPUT) ;

Page 10: Codi PIC C COMPILER (Llibreria Modbus)

10E:\modbus.c

modbus_serial _putc ( make8( start _address , 1)) ;

modbus_serial _putc ( make8( start _address , 0)) ;

modbus_serial _putc ( make8( quantity , 1)) ;

modbus_serial _putc ( make8( quantity , 0)) ;

modbus_serial _send _stop () ;

MODBUS_SERIAL_WAIT_FOR_RESPONSE() ;

return modbus _rx . error ;

}

/*read _holding _registersInput : int 8 address Slave Address int 16 start _address Address to start reading from int 16 quantity Amount of addresses to readOutput : exception 0 if no error , else the exception*/exception modbus _read _holding _registers ( int 8 address , int 16 start _address , int 16 quantity ){ modbus_serial _send _start ( address , FUNC_READ_HOLDING_REGISTERS) ;

modbus_serial _putc ( make8( start _address , 1)) ;

modbus_serial _putc ( make8( start _address , 0)) ;

modbus_serial _putc ( make8( quantity , 1)) ;

modbus_serial _putc ( make8( quantity , 0)) ;

modbus_serial _send _stop () ;

MODBUS_SERIAL_WAIT_FOR_RESPONSE() ;

return modbus _rx . error ;

}

/*read _input _registersInput : int 8 address Slave Address int 16 start _address Address to start reading from int 16 quantity Amount of addresses to readOutput : exception 0 if no error , else the exception*/exception modbus _read _input _registers ( int 8 address , int 16 start _address , int 16 quantity ){ modbus_serial _send _start ( address , FUNC_READ_INPUT_REGISTERS) ;

modbus_serial _putc ( make8( start _address , 1)) ;

modbus_serial _putc ( make8( start _address , 0)) ;

modbus_serial _putc ( make8( quantity , 1)) ;

modbus_serial _putc ( make8( quantity , 0)) ;

modbus_serial _send _stop () ;

MODBUS_SERIAL_WAIT_FOR_RESPONSE() ;

return modbus _rx . error ;

}

/*write _single _coilInput : int 8 address Slave Address int 16 output _address Address to write into int 1 on true for on , false for offOutput : exception 0 if no error , else the exception*/exception modbus _write _single _coil ( int 8 address , int 16 output _address , int 1 on ){ modbus_serial _send _start ( address , FUNC_WRITE_SINGLE_COIL) ;

modbus_serial _putc ( make8( output _address , 1)) ;

modbus_serial _putc ( make8( output _address , 0)) ;

Page 11: Codi PIC C COMPILER (Llibreria Modbus)

11E:\modbus.c

if ( on ) modbus_serial _putc ( 0xFF) ; else modbus_serial _putc ( 0x 00) ; modbus_serial _putc ( 0x 00) ;

modbus_serial _send _stop () ;

MODBUS_SERIAL_WAIT_FOR_RESPONSE() ;

return modbus _rx . error ;

}

/*write _single _registerInput : int 8 address Slave Address int 16 reg _address Address to write into int 16 reg _value Value to writeOutput : exception 0 if no error , else the exception*/exception modbus _write _single _register ( int 8 address , int 16 reg _address , int 16 reg _value ){ modbus_serial _send _start ( address , FUNC_WRITE_SINGLE_REGISTER) ;

modbus_serial _putc ( make8( reg _address , 1)) ;

modbus_serial _putc ( make8( reg _address , 0)) ;

modbus_serial _putc ( make8( reg _value , 1)) ;

modbus_serial _putc ( make8( reg _value , 0)) ;

modbus_serial _send _stop () ;

MODBUS_SERIAL_WAIT_FOR_RESPONSE() ;

return modbus _rx . error ;

}

/*read _exception _statusInput : int 8 address Slave AddressOutput : exception 0 if no error , else the exception*/exception modbus _read _exception _status ( int 8 address ){ modbus_serial _send _start ( address , FUNC_READ_EXCEPTION_STATUS) ; modbus_serial _send _stop () ;

MODBUS_SERIAL_WAIT_FOR_RESPONSE() ;

return modbus _rx . error ;

}

/*diagnosticsInput : int 8 address Slave Address int 16 sub _func Subfunction to send int 16 data Data to send , changes based on subfunctionOutput : exception 0 if no error , else the exception*/exception modbus _diagnostics ( int 8 address , int 16 sub _func , int 16 data ){ modbus_serial _send _start ( address , FUNC_DIAGNOSTICS) ;

modbus_serial _putc ( make8( sub _func , 1)) ;

modbus_serial _putc ( make8( sub _func , 0)) ;

modbus_serial _putc ( make8( data , 1)) ;

modbus_serial _putc ( make8( data , 0)) ;

modbus_serial _send _stop () ;

MODBUS_SERIAL_WAIT_FOR_RESPONSE() ;

Page 12: Codi PIC C COMPILER (Llibreria Modbus)

12E:\modbus.c

return modbus _rx . error ;

}

/*get _comm_event _couterInput : int 8 address Slave AddressOutput : exception 0 if no error , else the exception*/exception modbus _get _comm_event _counter ( int 8 address ){ modbus_serial _send _start ( address , FUNC_GET_COMM_EVENT_COUNTER) ; modbus_serial _send _stop () ;

MODBUS_SERIAL_WAIT_FOR_RESPONSE() ;

return modbus _rx . error ;

}

/*get _comm_event _logInput : int 8 address Slave AddressOutput : exception 0 if no error , else the exception*/exception modbus _get _comm_event _log ( int 8 address ){ modbus_serial _send _start ( address , FUNC_GET_COMM_EVENT_LOG) ; modbus_serial _send _stop () ;

MODBUS_SERIAL_WAIT_FOR_RESPONSE() ;

return modbus _rx . error ;

}

/*write _multiple _coilsInput : int 8 address Slave Address int 16 start _address Address to start at int 16 quantity Amount of coils to write to int 1* values A pointer to an array holding th e values to writeOutput : exception 0 if no error , else the exception*/exception modbus _write _multiple _coils ( int 8 address , int 16 start _address , int 16 quantity , int 8 * values ){ int 8 i , count ;

count = ( int 8)(( quantity / 8)) ;

if ( quantity %8) count ++;

modbus_serial _send _start ( address , FUNC_WRITE_MULTIPLE_COILS) ;

modbus_serial _putc ( make8( start _address , 1)) ;

modbus_serial _putc ( make8( start _address , 0)) ;

modbus_serial _putc ( make8( quantity , 1)) ;

modbus_serial _putc ( make8( quantity , 0)) ;

modbus_serial _putc ( count ) ;

for ( i =0; i < count ; ++i ) modbus_serial _putc ( values [ i ]) ;

modbus_serial _send _stop () ;

MODBUS_SERIAL_WAIT_FOR_RESPONSE() ;

return modbus _rx . error ;

}

/*write _multiple _registers

Page 13: Codi PIC C COMPILER (Llibreria Modbus)

13E:\modbus.c

Input : int 8 address Slave Address int 16 start _address Address to start at int 16 quantity Amount of coils to write to int 16* values A pointer to an array holding th e data to writeOutput : exception 0 if no error , else the exception*/exception modbus _write _multiple _registers ( int 8 address , int 16 start _address , int 16

quantity , int 16 * values ){ int 8 i , count ;

count = quantity * 2;

modbus_serial _send _start ( address , FUNC_WRITE_MULTIPLE_REGISTERS) ;

modbus_serial _putc ( make8( start _address , 1)) ;

modbus_serial _putc ( make8( start _address , 0)) ;

modbus_serial _putc ( make8( quantity , 1)) ;

modbus_serial _putc ( make8( quantity , 0)) ;

modbus_serial _putc ( count ) ;

for ( i =0; i < quantity ; ++i ) { modbus_serial _putc ( make8( values [ i ] , 1)) ;

modbus_serial _putc ( make8( values [ i ] , 0)) ;

}

modbus_serial _send _stop () ;

MODBUS_SERIAL_WAIT_FOR_RESPONSE() ;

return modbus _rx . error ;

}

/*report _slave _idInput : int 8 address Slave AddressOutput : exception 0 if no error , else the exception*/exception modbus _report _slave _id ( int 8 address ){ modbus_serial _send _start ( address , FUNC_REPORT_SLAVE_ID ) ; modbus_serial _send _stop () ;

MODBUS_SERIAL_WAIT_FOR_RESPONSE() ;

return modbus _rx . error ;

}

/*read _file _recordInput : int 8 address Slave Address int 8 byte _count Number of bytes to read read _sub _request * request Structure holding record informa tionOutput : exception 0 if no error , else the exception*/exception modbus _read _file _record ( int 8 address , int 8 byte _count , modbus_read _sub _request * request ){ int 8 i ;

modbus_serial _send _start ( address , FUNC_READ_FILE _RECORD) ;

modbus_serial _putc ( byte _count ) ;

for ( i =0; i < ( byte _count / 7) ; i +=7) { modbus_serial _putc ( request - >reference _type ) ; modbus_serial _putc ( make8( request - >file _number , 1)) ;

modbus_serial _putc ( make8( request - >file _number , 0)) ;

modbus_serial _putc ( make8( request - >record _number , 1)) ;

Page 14: Codi PIC C COMPILER (Llibreria Modbus)

14E:\modbus.c

modbus_serial _putc ( make8( request - >record _number , 0)) ;

modbus_serial _putc ( make8( request - >record _length , 1)) ;

modbus_serial _putc ( make8( request - >record _length , 0)) ;

request ++; }

modbus_serial _send _stop () ;

MODBUS_SERIAL_WAIT_FOR_RESPONSE() ;

return modbus _rx . error ;

}

/*write _file _recordInput : int 8 address Slave Address int 8 byte _count Number of bytes to read read _sub _request * request Structure holding record / data

informationOutput : exception 0 if no error , else the exception*/exception modbus _write _file _record ( int 8 address , int 8 byte _count , modbus_write _sub _request * request ){ int 8 i , j =0;

modbus_serial _send _start ( address , FUNC_WRITE_FILE _RECORD) ;

modbus_serial _putc ( byte _count ) ;

for ( i =0; i < byte _count ; i +=( 7+( j * 2))) { modbus_serial _putc ( request - >reference _type ) ; modbus_serial _putc ( make8( request - >file _number , 1)) ;

modbus_serial _putc ( make8( request - >file _number , 0)) ;

modbus_serial _putc ( make8( request - >record _number , 1)) ;

modbus_serial _putc ( make8( request - >record _number , 0)) ;

modbus_serial _putc ( make8( request - >record _length , 1)) ;

modbus_serial _putc ( make8( request - >record _length , 0)) ;

for ( j =0; ( j < request - >record _length ) && ( j < MODBUS_SERIAL_RX_BUFFER_SIZE - 8) ; j +=2) { modbus_serial _putc ( make8( request - >data [ j ] , 1)) ;

modbus_serial _putc ( make8( request - >data [ j ] , 0)) ;

} request ++; }

modbus_serial _send _stop () ;

MODBUS_SERIAL_WAIT_FOR_RESPONSE() ;

return modbus _rx . error ;

}

/*mask_write _registerInput : int 8 address Slave Address int 16 reference _address Address to mask int 16 AND_mask A mask to AND with the data at refer ence _address int 16 OR_mask A mask to OR with the data at refer ence _addressOutput : exception 0 if no error , else the exception*/exception modbus _mask_write _register ( int 8 address , int 16 reference _address , int 16 AND_mask, int 16 OR_mask){ modbus_serial _send _start ( address , FUNC_MASK_WRITE_REGISTER) ;

modbus_serial _putc ( make8( reference _address , 1)) ;

modbus_serial _putc ( make8( reference _address , 0)) ;

modbus_serial _putc ( make8( AND_mask, 1)) ;

modbus_serial _putc ( make8( AND_mask, 0)) ;

Page 15: Codi PIC C COMPILER (Llibreria Modbus)

15E:\modbus.c

modbus_serial _putc ( make8( OR_mask, 1)) ;

modbus_serial _putc ( make8( OR_mask, 0)) ;

modbus_serial _send _stop () ;

MODBUS_SERIAL_WAIT_FOR_RESPONSE() ;

return modbus _rx . error ;

}

/*read _write _multiple _registersInput : int 8 address Slave Address int 16 read _start Address to start reading int 16 read _quantity Amount of registers to read int 16 write _start Address to start writing int 16 write _quantity Amount of registers to write int 16* write _registers _value Pointer to an aray us to writeOutput : exception 0 if no error , else the exception*/exception modbus _read _write _multiple _registers ( int 8 address , int 16 read _start , int 16 read _quantity , int 16 write _start , int 16 write _quantity , int 16 * write _registers _value ){ int 8 i ;

modbus_serial _send _start ( address , FUNC_READ_WRITE_MULTIPLE_REGISTERS) ;

modbus_serial _putc ( make8( read _start , 1)) ;

modbus_serial _putc ( make8( read _start , 0)) ;

modbus_serial _putc ( make8( read _quantity , 1)) ;

modbus_serial _putc ( make8( read _quantity , 0)) ;

modbus_serial _putc ( make8( write _start , 1)) ;

modbus_serial _putc ( make8( write _start , 0)) ;

modbus_serial _putc ( make8( write _quantity , 1)) ;

modbus_serial _putc ( make8( write _quantity , 0)) ;

modbus_serial _putc (( int 8)( 2* write _quantity )) ;

for ( i =0; i < write _quantity ; i +=2) { modbus_serial _putc ( make8( write _registers _value [ i ] , 1)) ;

modbus_serial _putc ( make8( write _registers _value [ i +1] , 0)) ;

}

modbus_serial _send _stop () ;

MODBUS_SERIAL_WAIT_FOR_RESPONSE() ;

return modbus _rx . error ;

}

/*read _FIFO _queueInput : int 8 address Slave Address int 16 FIFO _address FIFO addressOutput : exception 0 if no error , else the exception*/exception modbus _read _FIFO _queue ( int 8 address , int 16 FIFO _address ){ modbus_serial _send _start ( address , FUNC_READ_FIFO _QUEUE) ;

modbus_serial _putc ( make8( FIFO _address , 1)) ;

modbus_serial _putc ( make8( FIFO _address , 0)) ;

modbus_serial _send _stop () ;

MODBUS_SERIAL_WAIT_FOR_RESPONSE() ;

Page 16: Codi PIC C COMPILER (Llibreria Modbus)

16E:\modbus.c

return modbus _rx . error ;

}

#else/* MODBUS Slave Functions */

/************************************************** ******************The following structs are used for read / write _sub _request _rsp . Thesefunctions take in one of these structs . Please refer to the MODBUSprotocol specification if you do not understand the members of thestructure .*************************************************** *****************/typedef struct _modbus_read _sub _request _rsp{ int 8 record _length ;

int 8 reference _type ;

int 16 data [(( MODBUS_SERIAL_RX_BUFFER_SIZE )/ 2)- 3] ;} modbus_read _sub _request _rsp ;

typedef struct _modbus_write _sub _request _rsp{ int 8 reference _type ;

int 16 file _number ; int 16 record _number ; int 16 record _length ;

int 16 data [(( MODBUS_SERIAL_RX_BUFFER_SIZE )/ 2)- 8] ;} modbus_write _sub _request _rsp ;

/************************************************** ******************The following slave functions are defined in the MO DBUS protocol .Please refer to http :// www. modbus. org for the purpose of each ofthese . All functions take the slaves address as their firs tparameter .*************************************************** *****************///**************************** CODI 1****************************************/*read _coils _rspInput : int 8 address Slave Address int 8 byte _count Number of bytes being sent int 8* coil _data Pointer to an array of data to sendOutput : void*/void modbus _read _coils _rsp ( int 8 address , int 8 byte _count , int 8* coil _data ){ int 8 i ;

modbus_serial _send _start ( address , FUNC_READ_COILS) ;

modbus_serial _putc ( byte _count ) ;

for ( i =0; i < byte _count ; ++i ) { modbus_serial _putc (* coil _data ) ; coil _data ++; }

modbus_serial _send _stop () ;

}

//************************* CODI 2********************************************/*read _discrete _input _rspInput : int 8 address Slave Address int 8 byte _count Number of bytes being sent int 8* input _data Pointer to an array of data to sendOutput : void*/void modbus _read _discrete _input _rsp ( int 8 address , int 8 byte _count , int 8 * input _data ){ int 8 i ;

modbus_serial _send _start ( address , FUNC_READ_DISCRETE_INPUT) ;

Page 17: Codi PIC C COMPILER (Llibreria Modbus)

17E:\modbus.c

modbus_serial _putc ( byte _count ) ;

for ( i =0; i < byte _count ; ++i ) { modbus_serial _putc (* input _data ) ; input _data ++; }

modbus_serial _send _stop () ;

}

//*********************** CODI 3 LLEGIR*************************************/*read _holding _registers _rsp // Màster vol llegir de l ' esclauInput : int 8 address Adreça de l ' esclau int 8 byte _count Nombre de bytes que s ' envien int 8* reg _data Punter en un vector de dades a envia r Punter de READ HOLDING REGISTERSOutput : void */void modbus _read _holding _registers _rsp ( int 8 address , int 8 byte _count , int 8 * reg _data ){ int 8 i ;

modbus_serial _send _start ( address , FUNC_READ_HOLDING_REGISTERS) ;// Send Start

modbus_serial _putc ( byte _count ) ;

for ( i =0; i < byte _count ; ++i ) { modbus_serial _putc (* reg _data ) ; // Amb * es refereix al contingut reg _data ++; // Sense * a la posició // Incrementem posició } modbus_serial _send _stop () ; // Send Stop}

//****************************** CODI 4******************************************/*read _input _registers _rspEntrada : int 8 address Adreça de l ' esclau int 8 byte _count Nombre de bytes que s ' envien int 8* input _data Punter en un vector de dades a enviarSortida : void*/void modbus _read _input _registers _rsp ( int 8 address , int 8 byte _count , int 8 * input _data ){ int 8 i ;

modbus_serial _send _start ( address , FUNC_READ_INPUT_REGISTERS) ;

modbus_serial _putc ( byte _count ) ;

for ( i =0; i < byte _count ; ++i ) { modbus_serial _putc (* input _data ) ; input _data ++; }

modbus_serial _send _stop () ;

}//************************ CODI 5****************************************/*write _single _coil _rspEntrades : int 8 address Slave Address int 16 output _address Echo of output address received int 16 output _value Echo of output value receivedSortida : void*/void modbus _write _single _coil _rsp ( int 8 address , int 16 output _address , int 16 output _value )

Page 18: Codi PIC C COMPILER (Llibreria Modbus)

18E:\modbus.c

{ modbus_serial _send _start ( address , FUNC_WRITE_SINGLE_COIL) ;

modbus_serial _putc ( make8( output _address , 1)) ;

modbus_serial _putc ( make8( output _address , 0)) ;

modbus_serial _putc ( make8( output _value , 1)) ;

modbus_serial _putc ( make8( output _value , 0)) ;

modbus_serial _send _stop () ;

}

//************************** CODI 6****************************************/*write _single _register _rsp // Escriure un sol registreEntrada : int 8 address Adreça de l ' esclau int 16 reg _address Echo of register address received int 16 reg _value Echo of register value receivedSortida : void*/void modbus _write _single _register _rsp ( int 8 address , int 16 reg _address , int 16 reg _value ){ modbus_serial _send _start ( address , FUNC_WRITE_SINGLE_REGISTER) ;// Send Start

modbus_serial _putc ( make8( reg _address , 1)) ; // Posició Inici d ' escriptura modbus_serial _putc ( make8( reg _address , 0)) ;

modbus_serial _putc ( make8( reg _value , 1)) ; // nombre de registres modbus_serial _putc ( make8( reg _value , 0)) ;

modbus_serial _send _stop () ; // Send Stop}

//****************************** CODI 7****************************************/*read _exception _status _rspEntrada : int 8 address Slave AddressSortida : void*/void modbus _read _exception _status _rsp ( int 8 address , int 8 data ){ modbus_serial _send _start ( address , FUNC_READ_EXCEPTION_STATUS) ; modbus_serial _send _stop () ;

}

//*************************** CODI 8******************************************/*diagnostics _rspInput : int 8 address Slave Address int 16 sub _func Echo of sub function received int 16 data Echo of data receivedOutput : void*/void modbus _diagnostics _rsp ( int 8 address , int 16 sub _func , int 16 data ){ modbus_serial _send _start ( address , FUNC_DIAGNOSTICS) ;

modbus_serial _putc ( make8( sub _func , 1)) ;

modbus_serial _putc ( make8( sub _func , 0)) ;

modbus_serial _putc ( make8( data , 1)) ;

modbus_serial _putc ( make8( data , 0)) ;

modbus_serial _send _stop () ;

}//************************+ CODI 0B*******************************************

/*get _comm_event _counter _rspInput : int 8 address Slave Address int 16 status Status , refer to MODBUS documentation int 16 event _count Count of eventsOutput : void

Page 19: Codi PIC C COMPILER (Llibreria Modbus)

19E:\modbus.c

*/void modbus _get _comm_event _counter _rsp ( int 8 address , int 16 status , int 16 event _count ){ modbus_serial _send _start ( address , FUNC_GET_COMM_EVENT_COUNTER) ;

modbus_serial _putc ( make8( status , 1)) ;

modbus_serial _putc ( make8( status , 0)) ;

modbus_serial _putc ( make8( event _count , 1)) ;

modbus_serial _putc ( make8( event _count , 0)) ;

modbus_serial _send _stop () ;

}

//******************* CODI 0C*************************************************/*get _comm_event _counter _rspInput : int 8 address Slave Address int 16 status Status , refer to MODBUS documentation int 16 event _count Count of events int 16 message _count Count of messages int 8* events Pointer to event data int 8 events _len Length of event data in bytesOutput : void*/void modbus _get _comm_event _log _rsp ( int 8 address , int 16 status , int 16 event _count , int 16 message _count , int 8 * events , int 8 events _len ){ int 8 i ; modbus_serial _send _start ( address , FUNC_GET_COMM_EVENT_LOG) ;

modbus_serial _putc ( events _len +6) ;

modbus_serial _putc ( make8( status , 1)) ;

modbus_serial _putc ( make8( status , 0)) ;

modbus_serial _putc ( make8( event _count , 1)) ;

modbus_serial _putc ( make8( event _count , 0)) ;

modbus_serial _putc ( make8( message _count , 1)) ;

modbus_serial _putc ( make8( message _count , 0)) ;

for ( i =0; i < events _len ; ++i ) { modbus_serial _putc (* events ) ; events ++; }

modbus_serial _send _stop () ;

}

//************************* CODI 0F******************************************/*write _multiple _coils _rspInput : int 8 address Slave Address int 16 start _address Echo of address to start at int 16 quantity Echo of amount of coils written toOutput : void*/void modbus _write _multiple _coils _rsp ( int 8 address , int 16 start _address , int 16 quantity ){ modbus_serial _send _start ( address , FUNC_WRITE_MULTIPLE_COILS) ;

modbus_serial _putc ( make8( start _address , 1)) ;

modbus_serial _putc ( make8( start _address , 0)) ;

modbus_serial _putc ( make8( quantity , 1)) ;

modbus_serial _putc ( make8( quantity , 0)) ;

modbus_serial _send _stop () ;

Page 20: Codi PIC C COMPILER (Llibreria Modbus)

20E:\modbus.c

}

//****************************** CODI 10****************************************/*write _multiple _registers _rspInput : int 8 address Slave Address int 16 start _address Echo of address to start at int 16 quantity Echo of amount of registers writ ten toOutput : void*/void modbus _write _multiple _registers _rsp ( int 8 address , int 16 start _address , int 16 quantity ){ modbus_serial _send _start ( address , FUNC_WRITE_MULTIPLE_REGISTERS) ;

modbus_serial _putc ( make8( start _address , 1)) ;

modbus_serial _putc ( make8( start _address , 0)) ;

modbus_serial _putc ( make8( quantity , 1)) ;

modbus_serial _putc ( make8( quantity , 0)) ;

modbus_serial _send _stop () ;

}

//************************ CODI 11*********************************************/*report _slave _id _rspInput : int 8 address Slave Address int 8 slave _id Slave Address int 8 run _status Are we running ? int 8* data Pointer to an array holding the data int 8 data _len Length of data in bytesOutput : void*/void modbus _report _slave _id _rsp ( int 8 address , int 8 slave _id , int 1 run _status , int 8 * data , int 8 data _len ){ int 8 i ;

modbus_serial _send _start ( address , FUNC_REPORT_SLAVE_ID ) ;

modbus_serial _putc ( data _len +2) ; modbus_serial _putc ( slave _id ) ;

if ( run _status ) modbus_serial _putc ( 0xFF) ; else modbus_serial _putc ( 0x 00) ;

for ( i =0; i < data _len ; ++i ) { modbus_serial _putc (* data ) ; data ++; }

modbus_serial _send _stop () ;

}

//******************************** CODI 14******************************************************

/*read _file _record _rspInput : int 8 address Slave Address int 8 byte _count Number of bytes to send read _sub _request _rsp * request Structure holding record / data

informationOutput : void*/void modbus _read _file _record _rsp ( int 8 address , int 8 byte _count , modbus_read _sub _request _rsp * request ){ int 8 i =0, j ;

modbus_serial _send _start ( address , FUNC_READ_FILE _RECORD) ;

Page 21: Codi PIC C COMPILER (Llibreria Modbus)

21E:\modbus.c

modbus_serial _putc ( byte _count ) ;

while ( i < byte _count ) ; { modbus_serial _putc ( request - >record _length ) ; modbus_serial _putc ( request - >reference _type ) ;

for ( j =0; ( j < request - >record _length ) ; j +=2) { modbus_serial _putc ( make8( request - >data [ j ] , 1)) ;

modbus_serial _putc ( make8( request - >data [ j ] , 0)) ;

}

i += ( request - >record _length )+ 1; request ++; }

modbus_serial _send _stop () ;

}

//********************************* CODI 15*********************************************************

/*write _file _record _rspInput : int 8 address Slave Address int 8 byte _count Echo of number of bytes sent write _sub _request _rsp * request Echo of Structure holding record

informationOutput : void*/void modbus _write _file _record _rsp ( int 8 address , int 8 byte _count , modbus_write _sub _request _rsp * request ){ int 8 i , j =0;

modbus_serial _send _start ( address , FUNC_WRITE_FILE _RECORD) ;

modbus_serial _putc ( byte _count ) ;

for ( i =0; i < byte _count ; i +=( 7+( j * 2))) { modbus_serial _putc ( request - >reference _type ) ; modbus_serial _putc ( make8( request - >file _number , 1)) ;

modbus_serial _putc ( make8( request - >file _number , 0)) ;

modbus_serial _putc ( make8( request - >record _number , 1)) ;

modbus_serial _putc ( make8( request - >record _number , 0)) ;

modbus_serial _putc ( make8( request - >record _length , 1)) ;

modbus_serial _putc ( make8( request - >record _length , 0)) ;

for ( j =0; ( j < request - >record _length ) ; j +=2) { modbus_serial _putc ( make8( request - >data [ j ] , 1)) ;

modbus_serial _putc ( make8( request - >data [ j ] , 0)) ;

} }

modbus_serial _send _stop () ;

}

//******************************* CODI 16***********************************/*mask_write _register _rspInput : int 8 address Slave Address int 16 reference _address Echo of reference address int 16 AND_mask Echo of AND mask int 16 OR_mask Echo or OR maskOutput : void*/void modbus _mask_write _register _rsp ( int 8 address , int 16 reference _address , int 16 AND_mask, int 16 OR_mask){ modbus_serial _send _start ( address , FUNC_MASK_WRITE_REGISTER) ;

Page 22: Codi PIC C COMPILER (Llibreria Modbus)

22E:\modbus.c

modbus_serial _putc ( make8( reference _address , 1)) ;

modbus_serial _putc ( make8( reference _address , 0)) ;

modbus_serial _putc ( make8( AND_mask, 1)) ;

modbus_serial _putc ( make8( AND_mask, 0)) ;

modbus_serial _putc ( make8( OR_mask, 1)) ;

modbus_serial _putc ( make8( OR_mask, 0)) ;

modbus_serial _send _stop () ;

}

//*********************** CODI 17*****************************************/*read _write _multiple _registers _rspInput : int 8 address Slave Address int 16* data Pointer to an array of data int 8 data _len Length of data in bytesOutput : void*/void modbus _read _write _multiple _registers _rsp ( int 8 address , int 8 data _len , int 16 * data ){ int 8 i ;

modbus_serial _send _start ( address , FUNC_READ_WRITE_MULTIPLE_REGISTERS) ;

modbus_serial _putc ( data _len * 2) ;

for ( i =0; i < data _len * 2; i +=2) { modbus_serial _putc ( make8( data [ i ] , 1)) ;

modbus_serial _putc ( make8( data [ i ] , 0)) ;

}

modbus_serial _send _stop () ;

}

//**************************** CODI 18************************************/*read _FIFO _queue _rspInput : int 8 address Slave Address int 16 FIFO _len Length of FIFO in bytes int 16* data Pointer to an array of dataOutput : void*/void modbus _read _FIFO _queue _rsp ( int 8 address , int 16 FIFO _len , int 16 * data ){ int 8 i ; int 16 byte _count ;

byte _count = (( FIFO _len * 2)+ 2) ;

modbus_serial _send _start ( address , FUNC_READ_FIFO _QUEUE) ;

modbus_serial _putc ( make8( byte _count , 1)) ;

modbus_serial _putc ( make8( byte _count , 0)) ;

modbus_serial _putc ( make8( FIFO _len , 1)) ;

modbus_serial _putc ( make8( FIFO _len , 0)) ;

for ( i =0; i < FIFO _len ; i +=2) { modbus_serial _putc ( make8( data [ i ] , 1)) ;

modbus_serial _putc ( make8( data [ i ] , 0)) ;

}

modbus_serial _send _stop () ;

}

//****************************** EXCEPCIONS*****************************

void modbus _exception _rsp ( int 8 address , int 16 func , exception error ){

Page 23: Codi PIC C COMPILER (Llibreria Modbus)

23E:\modbus.c

modbus_serial _send _start ( address , func | 0x 80) ; modbus_serial _putc ( error ) ; modbus_serial _send _stop () ;

}

#endif