01

Committer:
ascheeren
Date:
Thu Sep 02 14:30:39 2021 +0000
Revision:
3:b8d920737d9e
Parent:
1:35fdc7056f66
01

Who changed what in which revision?

UserRevisionLine numberNew contents of line
ascheeren 3:b8d920737d9e 1 /*
AfdhalAtiffTan 1:35fdc7056f66 2 Modified by Afdhal: arduino library so that it can be used on mbed.
ascheeren 3:b8d920737d9e 3
AfdhalAtiffTan 1:35fdc7056f66 4 Original message:
ascheeren 3:b8d920737d9e 5 Modbus over serial line - RTU Slave Arduino Sketch
ascheeren 3:b8d920737d9e 6
AfdhalAtiffTan 0:6262fc7582a9 7 By Juan Pablo Zometa : jpmzometa@gmail.com
AfdhalAtiffTan 0:6262fc7582a9 8 http://sites.google.com/site/jpmzometa/
AfdhalAtiffTan 0:6262fc7582a9 9 Samuel Marco: sammarcoarmengol@gmail.com
AfdhalAtiffTan 0:6262fc7582a9 10 and Andras Tucsni.
ascheeren 3:b8d920737d9e 11
AfdhalAtiffTan 0:6262fc7582a9 12 These functions implement functions 3, 6, and 16 (read holding registers,
ascheeren 3:b8d920737d9e 13 preset single register and preset multiple registers) of the
AfdhalAtiffTan 0:6262fc7582a9 14 Modbus RTU Protocol, to be used over the Arduino serial connection.
ascheeren 3:b8d920737d9e 15
AfdhalAtiffTan 0:6262fc7582a9 16 This implementation DOES NOT fully comply with the Modbus specifications.
ascheeren 3:b8d920737d9e 17
AfdhalAtiffTan 0:6262fc7582a9 18 This Arduino adaptation is derived from the work
AfdhalAtiffTan 0:6262fc7582a9 19 By P.Costigan email: phil@pcscada.com.au http://pcscada.com.au
ascheeren 3:b8d920737d9e 20
AfdhalAtiffTan 0:6262fc7582a9 21 These library of functions are designed to enable a program send and
AfdhalAtiffTan 0:6262fc7582a9 22 receive data from a device that communicates using the Modbus protocol.
ascheeren 3:b8d920737d9e 23
AfdhalAtiffTan 0:6262fc7582a9 24 Copyright (C) 2000 Philip Costigan P.C. SCADA LINK PTY. LTD.
ascheeren 3:b8d920737d9e 25
AfdhalAtiffTan 0:6262fc7582a9 26 This program is free software; you can redistribute it and/or modify
AfdhalAtiffTan 0:6262fc7582a9 27 it under the terms of the GNU General Public License as published by
AfdhalAtiffTan 0:6262fc7582a9 28 the Free Software Foundation; either version 2 of the License, or
AfdhalAtiffTan 0:6262fc7582a9 29 (at your option) any later version.
ascheeren 3:b8d920737d9e 30
AfdhalAtiffTan 0:6262fc7582a9 31 This program is distributed in the hope that it will be useful,
AfdhalAtiffTan 0:6262fc7582a9 32 but WITHOUT ANY WARRANTY; without even the implied warranty of
AfdhalAtiffTan 0:6262fc7582a9 33 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
AfdhalAtiffTan 0:6262fc7582a9 34 GNU General Public License for more details.
ascheeren 3:b8d920737d9e 35
AfdhalAtiffTan 0:6262fc7582a9 36 You should have received a copy of the GNU General Public License
AfdhalAtiffTan 0:6262fc7582a9 37 along with this program; if not, write to the Free Software
AfdhalAtiffTan 0:6262fc7582a9 38 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
ascheeren 3:b8d920737d9e 39
ascheeren 3:b8d920737d9e 40 The functions included here have been derived from the
AfdhalAtiffTan 0:6262fc7582a9 41 Modicon Modbus Protocol Reference Guide
AfdhalAtiffTan 0:6262fc7582a9 42 which can be obtained from Schneider at www.schneiderautomation.com.
ascheeren 3:b8d920737d9e 43
ascheeren 3:b8d920737d9e 44 This code has its origins with
AfdhalAtiffTan 0:6262fc7582a9 45 paul@pmcrae.freeserve.co.uk (http://www.pmcrae.freeserve.co.uk)
AfdhalAtiffTan 0:6262fc7582a9 46 who wrote a small program to read 100 registers from a modbus slave.
ascheeren 3:b8d920737d9e 47
AfdhalAtiffTan 0:6262fc7582a9 48 I have used his code as a catalist to produce this more functional set
AfdhalAtiffTan 0:6262fc7582a9 49 of functions. Thanks paul.
AfdhalAtiffTan 0:6262fc7582a9 50 */
AfdhalAtiffTan 0:6262fc7582a9 51
AfdhalAtiffTan 0:6262fc7582a9 52
AfdhalAtiffTan 0:6262fc7582a9 53 //#include "Arduino.h" //afdhal
AfdhalAtiffTan 1:35fdc7056f66 54
AfdhalAtiffTan 0:6262fc7582a9 55 #include "millis.h"
AfdhalAtiffTan 0:6262fc7582a9 56 #include "MODSERIAL.h" //afdhal
AfdhalAtiffTan 0:6262fc7582a9 57 MODSERIAL pc(USBTX, USBRX); // tx, rx //afdhal
AfdhalAtiffTan 0:6262fc7582a9 58
AfdhalAtiffTan 0:6262fc7582a9 59 #ifndef ModbusSlave232_h
ascheeren 3:b8d920737d9e 60 #include "ModbusSlave232.h"
AfdhalAtiffTan 0:6262fc7582a9 61 #endif
AfdhalAtiffTan 0:6262fc7582a9 62
AfdhalAtiffTan 0:6262fc7582a9 63
AfdhalAtiffTan 0:6262fc7582a9 64 /****************************************************************************
AfdhalAtiffTan 0:6262fc7582a9 65 * BEGIN MODBUS RTU SLAVE FUNCTIONS
AfdhalAtiffTan 0:6262fc7582a9 66 ****************************************************************************/
AfdhalAtiffTan 0:6262fc7582a9 67
AfdhalAtiffTan 0:6262fc7582a9 68 /* constants */
ascheeren 3:b8d920737d9e 69 enum {
ascheeren 3:b8d920737d9e 70 MAX_READ_REGS = 0x7D,
ascheeren 3:b8d920737d9e 71 MAX_WRITE_REGS = 0x7B,
ascheeren 3:b8d920737d9e 72 MAX_MESSAGE_LENGTH = 256
AfdhalAtiffTan 0:6262fc7582a9 73 };
AfdhalAtiffTan 0:6262fc7582a9 74
AfdhalAtiffTan 0:6262fc7582a9 75
ascheeren 3:b8d920737d9e 76 enum {
ascheeren 3:b8d920737d9e 77 RESPONSE_SIZE = 6,
ascheeren 3:b8d920737d9e 78 EXCEPTION_SIZE = 3,
ascheeren 3:b8d920737d9e 79 CHECKSUM_SIZE = 2
AfdhalAtiffTan 0:6262fc7582a9 80 };
AfdhalAtiffTan 0:6262fc7582a9 81
AfdhalAtiffTan 0:6262fc7582a9 82 /* exceptions code */
ascheeren 3:b8d920737d9e 83 enum {
ascheeren 3:b8d920737d9e 84 NO_REPLY = -1,
ascheeren 3:b8d920737d9e 85 EXC_FUNC_CODE = 1,
ascheeren 3:b8d920737d9e 86 EXC_ADDR_RANGE = 2,
ascheeren 3:b8d920737d9e 87 EXC_REGS_QUANT = 3,
ascheeren 3:b8d920737d9e 88 EXC_EXECUTE = 4
AfdhalAtiffTan 0:6262fc7582a9 89 };
AfdhalAtiffTan 0:6262fc7582a9 90
AfdhalAtiffTan 0:6262fc7582a9 91 /* positions inside the query/response array */
ascheeren 3:b8d920737d9e 92 enum {
ascheeren 3:b8d920737d9e 93 SLAVE = 0,
ascheeren 3:b8d920737d9e 94 FUNC,
ascheeren 3:b8d920737d9e 95 START_H,
ascheeren 3:b8d920737d9e 96 START_L,
ascheeren 3:b8d920737d9e 97 REGS_H,
ascheeren 3:b8d920737d9e 98 REGS_L,
ascheeren 3:b8d920737d9e 99 BYTE_CNT
AfdhalAtiffTan 0:6262fc7582a9 100 };
AfdhalAtiffTan 0:6262fc7582a9 101
AfdhalAtiffTan 0:6262fc7582a9 102
AfdhalAtiffTan 0:6262fc7582a9 103 /* enum of supported modbus function codes. If you implement a new one, put its function code here ! */
ascheeren 3:b8d920737d9e 104 enum {
ascheeren 3:b8d920737d9e 105 FC_READ_REGS = 0x03, //Read contiguous block of holding register
ascheeren 3:b8d920737d9e 106 FC_WRITE_REG = 0x06, //Write single holding register
ascheeren 3:b8d920737d9e 107 FC_WRITE_REGS = 0x10 //Write block of contiguous registers
AfdhalAtiffTan 0:6262fc7582a9 108 };
AfdhalAtiffTan 0:6262fc7582a9 109
AfdhalAtiffTan 0:6262fc7582a9 110 /* supported functions. If you implement a new one, put its function code into this array! */
AfdhalAtiffTan 0:6262fc7582a9 111 const unsigned char fsupported[] = { FC_READ_REGS, FC_WRITE_REG, FC_WRITE_REGS };
AfdhalAtiffTan 0:6262fc7582a9 112
AfdhalAtiffTan 0:6262fc7582a9 113
AfdhalAtiffTan 0:6262fc7582a9 114 /*
AfdhalAtiffTan 0:6262fc7582a9 115 CRC
ascheeren 3:b8d920737d9e 116
AfdhalAtiffTan 0:6262fc7582a9 117 INPUTS:
ascheeren 3:b8d920737d9e 118 buf -> Array containing message to be sent to controller.
AfdhalAtiffTan 0:6262fc7582a9 119 start -> Start of loop in crc counter, usually 0.
AfdhalAtiffTan 0:6262fc7582a9 120 cnt -> Amount of bytes in message being sent to controller/
AfdhalAtiffTan 0:6262fc7582a9 121 OUTPUTS:
AfdhalAtiffTan 0:6262fc7582a9 122 temp -> Returns crc byte for message.
AfdhalAtiffTan 0:6262fc7582a9 123 COMMENTS:
AfdhalAtiffTan 0:6262fc7582a9 124 This routine calculates the crc high and low byte of a message.
ascheeren 3:b8d920737d9e 125 Note that this crc is only used for Modbus, not Modbus+ etc.
AfdhalAtiffTan 0:6262fc7582a9 126 ****************************************************************************/
AfdhalAtiffTan 0:6262fc7582a9 127
AfdhalAtiffTan 0:6262fc7582a9 128 unsigned int ModbusSlave232::crc(unsigned char *buf, unsigned char start,
ascheeren 3:b8d920737d9e 129 unsigned char cnt)
AfdhalAtiffTan 0:6262fc7582a9 130 {
ascheeren 3:b8d920737d9e 131 unsigned char i, j;
ascheeren 3:b8d920737d9e 132 unsigned temp, temp2, flag;
AfdhalAtiffTan 0:6262fc7582a9 133
ascheeren 3:b8d920737d9e 134 temp = 0xFFFF;
AfdhalAtiffTan 0:6262fc7582a9 135
ascheeren 3:b8d920737d9e 136 for (i = start; i < cnt; i++) {
ascheeren 3:b8d920737d9e 137 temp = temp ^ buf[i];
AfdhalAtiffTan 0:6262fc7582a9 138
ascheeren 3:b8d920737d9e 139 for (j = 1; j <= 8; j++) {
ascheeren 3:b8d920737d9e 140 flag = temp & 0x0001;
ascheeren 3:b8d920737d9e 141 temp = temp >> 1;
ascheeren 3:b8d920737d9e 142 if (flag)
ascheeren 3:b8d920737d9e 143 temp = temp ^ 0xA001;
AfdhalAtiffTan 0:6262fc7582a9 144 }
ascheeren 3:b8d920737d9e 145 }
AfdhalAtiffTan 0:6262fc7582a9 146
ascheeren 3:b8d920737d9e 147 /* Reverse byte order. */
ascheeren 3:b8d920737d9e 148 temp2 = temp >> 8;
ascheeren 3:b8d920737d9e 149 temp = (temp << 8) | temp2;
ascheeren 3:b8d920737d9e 150 temp &= 0xFFFF;
AfdhalAtiffTan 0:6262fc7582a9 151
ascheeren 3:b8d920737d9e 152 return (temp);
AfdhalAtiffTan 0:6262fc7582a9 153 }
AfdhalAtiffTan 0:6262fc7582a9 154
AfdhalAtiffTan 0:6262fc7582a9 155
AfdhalAtiffTan 0:6262fc7582a9 156
AfdhalAtiffTan 0:6262fc7582a9 157
AfdhalAtiffTan 0:6262fc7582a9 158 /***********************************************************************
ascheeren 3:b8d920737d9e 159 *
AfdhalAtiffTan 0:6262fc7582a9 160 * The following functions construct the required query into
AfdhalAtiffTan 0:6262fc7582a9 161 * a modbus query packet.
ascheeren 3:b8d920737d9e 162 *
AfdhalAtiffTan 0:6262fc7582a9 163 ***********************************************************************/
AfdhalAtiffTan 0:6262fc7582a9 164
ascheeren 3:b8d920737d9e 165 /*
ascheeren 3:b8d920737d9e 166 * Start of the packet of a read_holding_register response
AfdhalAtiffTan 0:6262fc7582a9 167 */
AfdhalAtiffTan 0:6262fc7582a9 168 void ModbusSlave232::build_read_packet(unsigned char function,
ascheeren 3:b8d920737d9e 169 unsigned char count, unsigned char *packet)
AfdhalAtiffTan 0:6262fc7582a9 170 {
ascheeren 3:b8d920737d9e 171 packet[SLAVE] = slave;
ascheeren 3:b8d920737d9e 172 packet[FUNC] = function;
ascheeren 3:b8d920737d9e 173 packet[2] = count * 2;
ascheeren 3:b8d920737d9e 174 }
AfdhalAtiffTan 0:6262fc7582a9 175
ascheeren 3:b8d920737d9e 176 /*
ascheeren 3:b8d920737d9e 177 * Start of the packet of a preset_multiple_register response
AfdhalAtiffTan 0:6262fc7582a9 178 */
AfdhalAtiffTan 0:6262fc7582a9 179 void ModbusSlave232::build_write_packet(unsigned char function,
ascheeren 3:b8d920737d9e 180 unsigned int start_addr,
ascheeren 3:b8d920737d9e 181 unsigned char count,
ascheeren 3:b8d920737d9e 182 unsigned char *packet)
AfdhalAtiffTan 0:6262fc7582a9 183 {
ascheeren 3:b8d920737d9e 184 packet[SLAVE] = slave;
ascheeren 3:b8d920737d9e 185 packet[FUNC] = function;
ascheeren 3:b8d920737d9e 186 packet[START_H] = start_addr >> 8;
ascheeren 3:b8d920737d9e 187 packet[START_L] = start_addr & 0x00ff;
ascheeren 3:b8d920737d9e 188 packet[REGS_H] = 0x00;
ascheeren 3:b8d920737d9e 189 packet[REGS_L] = count;
ascheeren 3:b8d920737d9e 190 }
AfdhalAtiffTan 0:6262fc7582a9 191
ascheeren 3:b8d920737d9e 192 /*
ascheeren 3:b8d920737d9e 193 * Start of the packet of a write_single_register response
AfdhalAtiffTan 0:6262fc7582a9 194 */
AfdhalAtiffTan 0:6262fc7582a9 195 void ModbusSlave232::build_write_single_packet(unsigned char function,
ascheeren 3:b8d920737d9e 196 unsigned int write_addr, unsigned int reg_val, unsigned char* packet)
AfdhalAtiffTan 0:6262fc7582a9 197 {
ascheeren 3:b8d920737d9e 198 packet[SLAVE] = slave;
ascheeren 3:b8d920737d9e 199 packet[FUNC] = function;
ascheeren 3:b8d920737d9e 200 packet[START_H] = write_addr >> 8;
ascheeren 3:b8d920737d9e 201 packet[START_L] = write_addr & 0x00ff;
ascheeren 3:b8d920737d9e 202 packet[REGS_H] = reg_val >> 8;
ascheeren 3:b8d920737d9e 203 packet[REGS_L] = reg_val & 0x00ff;
ascheeren 3:b8d920737d9e 204 }
AfdhalAtiffTan 0:6262fc7582a9 205
AfdhalAtiffTan 0:6262fc7582a9 206
ascheeren 3:b8d920737d9e 207 /*
ascheeren 3:b8d920737d9e 208 * Start of the packet of an exception response
AfdhalAtiffTan 0:6262fc7582a9 209 */
AfdhalAtiffTan 0:6262fc7582a9 210 void ModbusSlave232::build_error_packet( unsigned char function,
ascheeren 3:b8d920737d9e 211 unsigned char exception, unsigned char *packet)
AfdhalAtiffTan 0:6262fc7582a9 212 {
ascheeren 3:b8d920737d9e 213 packet[SLAVE] = slave;
ascheeren 3:b8d920737d9e 214 packet[FUNC] = function + 0x80;
ascheeren 3:b8d920737d9e 215 packet[2] = exception;
ascheeren 3:b8d920737d9e 216 }
AfdhalAtiffTan 0:6262fc7582a9 217
AfdhalAtiffTan 0:6262fc7582a9 218
AfdhalAtiffTan 0:6262fc7582a9 219 /*************************************************************************
ascheeren 3:b8d920737d9e 220 *
AfdhalAtiffTan 0:6262fc7582a9 221 * modbus_query( packet, length)
ascheeren 3:b8d920737d9e 222 *
AfdhalAtiffTan 0:6262fc7582a9 223 * Function to add a checksum to the end of a packet.
AfdhalAtiffTan 0:6262fc7582a9 224 * Please note that the packet array must be at least 2 fields longer than
AfdhalAtiffTan 0:6262fc7582a9 225 * string_length.
AfdhalAtiffTan 0:6262fc7582a9 226 **************************************************************************/
AfdhalAtiffTan 0:6262fc7582a9 227
ascheeren 3:b8d920737d9e 228 void ModbusSlave232::modbus_reply(unsigned char *packet, unsigned char string_length)
AfdhalAtiffTan 0:6262fc7582a9 229 {
ascheeren 3:b8d920737d9e 230 int temp_crc;
AfdhalAtiffTan 0:6262fc7582a9 231
ascheeren 3:b8d920737d9e 232 temp_crc = crc(packet, 0, string_length);
ascheeren 3:b8d920737d9e 233 packet[string_length] = temp_crc >> 8;
ascheeren 3:b8d920737d9e 234 string_length++;
ascheeren 3:b8d920737d9e 235 packet[string_length] = temp_crc & 0x00FF;
ascheeren 3:b8d920737d9e 236 }
AfdhalAtiffTan 0:6262fc7582a9 237
AfdhalAtiffTan 0:6262fc7582a9 238
AfdhalAtiffTan 0:6262fc7582a9 239
AfdhalAtiffTan 0:6262fc7582a9 240 /***********************************************************************
ascheeren 3:b8d920737d9e 241 *
AfdhalAtiffTan 0:6262fc7582a9 242 * send_reply( query_string, query_length )
ascheeren 3:b8d920737d9e 243 *
AfdhalAtiffTan 0:6262fc7582a9 244 * Function to send a reply to a modbus master.
AfdhalAtiffTan 0:6262fc7582a9 245 * Returns: total number of characters sent
AfdhalAtiffTan 0:6262fc7582a9 246 ************************************************************************/
AfdhalAtiffTan 0:6262fc7582a9 247
ascheeren 3:b8d920737d9e 248 int ModbusSlave232::send_reply(unsigned char *query, unsigned char string_length)
AfdhalAtiffTan 0:6262fc7582a9 249 {
ascheeren 3:b8d920737d9e 250 unsigned char i;
AfdhalAtiffTan 0:6262fc7582a9 251
ascheeren 3:b8d920737d9e 252 /*if (txenpin > 1) { // set MAX485 to speak mode //afdhal
ascheeren 3:b8d920737d9e 253 UCSR0A=UCSR0A |(1 << TXC0);
ascheeren 3:b8d920737d9e 254 digitalWrite( txenpin, HIGH);
ascheeren 3:b8d920737d9e 255 delay(1);
ascheeren 3:b8d920737d9e 256 }*/
AfdhalAtiffTan 0:6262fc7582a9 257
ascheeren 3:b8d920737d9e 258 modbus_reply(query, string_length);
ascheeren 3:b8d920737d9e 259 string_length += 2;
AfdhalAtiffTan 0:6262fc7582a9 260
ascheeren 3:b8d920737d9e 261 for (i = 0; i < string_length; i++) {
ascheeren 3:b8d920737d9e 262 //Serial.print(char(query[i])); //afdhal
ascheeren 3:b8d920737d9e 263 pc.putc(char(query[i])); //afdhal
AfdhalAtiffTan 0:6262fc7582a9 264
ascheeren 3:b8d920737d9e 265 }
ascheeren 3:b8d920737d9e 266
ascheeren 3:b8d920737d9e 267 return i; /* it does not mean that the write was succesful, though */
AfdhalAtiffTan 0:6262fc7582a9 268 }
AfdhalAtiffTan 0:6262fc7582a9 269
AfdhalAtiffTan 0:6262fc7582a9 270 /***********************************************************************
ascheeren 3:b8d920737d9e 271 *
AfdhalAtiffTan 0:6262fc7582a9 272 * receive_request( array_for_data )
ascheeren 3:b8d920737d9e 273 *
AfdhalAtiffTan 0:6262fc7582a9 274 * Function to monitor for a request from the modbus master.
ascheeren 3:b8d920737d9e 275 *
AfdhalAtiffTan 0:6262fc7582a9 276 * Returns: Total number of characters received if OK
ascheeren 3:b8d920737d9e 277 * 0 if there is no request
AfdhalAtiffTan 0:6262fc7582a9 278 * A negative error code on failure
AfdhalAtiffTan 0:6262fc7582a9 279 ***********************************************************************/
AfdhalAtiffTan 0:6262fc7582a9 280
ascheeren 3:b8d920737d9e 281 int ModbusSlave232::receive_request(unsigned char *received_string)
AfdhalAtiffTan 0:6262fc7582a9 282 {
ascheeren 3:b8d920737d9e 283 int bytes_received = 0;
AfdhalAtiffTan 0:6262fc7582a9 284
ascheeren 3:b8d920737d9e 285 /* FIXME: does Serial.available wait 1.5T or 3.5T before exiting the loop? */
ascheeren 3:b8d920737d9e 286 //while (Serial.available()) { //afdhal
ascheeren 3:b8d920737d9e 287 while (pc.readable()) { //afdhal
ascheeren 3:b8d920737d9e 288 received_string[bytes_received] = pc.getc(); //Serial.read(); //afdhal
ascheeren 3:b8d920737d9e 289 //Serial.print(received_string[bytes_received], DEC);
ascheeren 3:b8d920737d9e 290 bytes_received++;
ascheeren 3:b8d920737d9e 291 if (bytes_received >= MAX_MESSAGE_LENGTH)
ascheeren 3:b8d920737d9e 292 return NO_REPLY; /* port error */
ascheeren 3:b8d920737d9e 293 }
AfdhalAtiffTan 0:6262fc7582a9 294
ascheeren 3:b8d920737d9e 295 return (bytes_received);
AfdhalAtiffTan 0:6262fc7582a9 296 }
AfdhalAtiffTan 0:6262fc7582a9 297
AfdhalAtiffTan 0:6262fc7582a9 298
AfdhalAtiffTan 0:6262fc7582a9 299 /*********************************************************************
ascheeren 3:b8d920737d9e 300 *
AfdhalAtiffTan 0:6262fc7582a9 301 * modbus_request(request_data_array)
ascheeren 3:b8d920737d9e 302 *
AfdhalAtiffTan 0:6262fc7582a9 303 * Function to the correct request is returned and that the checksum
AfdhalAtiffTan 0:6262fc7582a9 304 * is correct.
ascheeren 3:b8d920737d9e 305 *
AfdhalAtiffTan 0:6262fc7582a9 306 * Returns: string_length if OK
AfdhalAtiffTan 0:6262fc7582a9 307 * 0 if failed
AfdhalAtiffTan 0:6262fc7582a9 308 * Less than 0 for exception errors
ascheeren 3:b8d920737d9e 309 *
AfdhalAtiffTan 0:6262fc7582a9 310 * Note: All functions used for sending or receiving data via
AfdhalAtiffTan 0:6262fc7582a9 311 * modbus return these return values.
ascheeren 3:b8d920737d9e 312 *
AfdhalAtiffTan 0:6262fc7582a9 313 **********************************************************************/
AfdhalAtiffTan 0:6262fc7582a9 314
ascheeren 3:b8d920737d9e 315 int ModbusSlave232::modbus_request(unsigned char *data)
AfdhalAtiffTan 0:6262fc7582a9 316 {
ascheeren 3:b8d920737d9e 317 int response_length;
ascheeren 3:b8d920737d9e 318 unsigned int crc_calc = 0;
ascheeren 3:b8d920737d9e 319 unsigned int crc_received = 0;
ascheeren 3:b8d920737d9e 320 unsigned char recv_crc_hi;
ascheeren 3:b8d920737d9e 321 unsigned char recv_crc_lo;
AfdhalAtiffTan 0:6262fc7582a9 322
ascheeren 3:b8d920737d9e 323 response_length = receive_request(data);
AfdhalAtiffTan 0:6262fc7582a9 324
ascheeren 3:b8d920737d9e 325 if (response_length > 0) {
ascheeren 3:b8d920737d9e 326 crc_calc = crc(data, 0, response_length - 2);
ascheeren 3:b8d920737d9e 327 recv_crc_hi = (unsigned) data[response_length - 2];
ascheeren 3:b8d920737d9e 328 recv_crc_lo = (unsigned) data[response_length - 1];
ascheeren 3:b8d920737d9e 329 crc_received = data[response_length - 2];
ascheeren 3:b8d920737d9e 330 crc_received = (unsigned) crc_received << 8;
ascheeren 3:b8d920737d9e 331 crc_received =
ascheeren 3:b8d920737d9e 332 crc_received | (unsigned) data[response_length - 1];
AfdhalAtiffTan 0:6262fc7582a9 333
ascheeren 3:b8d920737d9e 334 /*********** check CRC of response ************/
ascheeren 3:b8d920737d9e 335 if (crc_calc != crc_received) {
ascheeren 3:b8d920737d9e 336 return NO_REPLY;
ascheeren 3:b8d920737d9e 337 }
AfdhalAtiffTan 0:6262fc7582a9 338
ascheeren 3:b8d920737d9e 339 /* check for slave id */
ascheeren 3:b8d920737d9e 340 if (slave != data[SLAVE]) {
ascheeren 3:b8d920737d9e 341 return NO_REPLY;
AfdhalAtiffTan 0:6262fc7582a9 342 }
ascheeren 3:b8d920737d9e 343 }
ascheeren 3:b8d920737d9e 344 return (response_length);
AfdhalAtiffTan 0:6262fc7582a9 345 }
AfdhalAtiffTan 0:6262fc7582a9 346
AfdhalAtiffTan 0:6262fc7582a9 347 /*********************************************************************
ascheeren 3:b8d920737d9e 348 *
AfdhalAtiffTan 0:6262fc7582a9 349 * validate_request(request_data_array, request_length, available_regs)
ascheeren 3:b8d920737d9e 350 *
AfdhalAtiffTan 0:6262fc7582a9 351 * Function to check that the request can be processed by the slave.
ascheeren 3:b8d920737d9e 352 *
AfdhalAtiffTan 0:6262fc7582a9 353 * Returns: 0 if OK
AfdhalAtiffTan 0:6262fc7582a9 354 * A negative exception code on error
ascheeren 3:b8d920737d9e 355 *
AfdhalAtiffTan 0:6262fc7582a9 356 **********************************************************************/
AfdhalAtiffTan 0:6262fc7582a9 357
AfdhalAtiffTan 0:6262fc7582a9 358 int ModbusSlave232::validate_request(unsigned char *data, unsigned char length,
ascheeren 3:b8d920737d9e 359 unsigned int regs_size)
AfdhalAtiffTan 0:6262fc7582a9 360 {
ascheeren 3:b8d920737d9e 361 int i, fcnt = 0;
ascheeren 3:b8d920737d9e 362 unsigned int regs_num = 0;
ascheeren 3:b8d920737d9e 363 unsigned int start_addr = 0;
ascheeren 3:b8d920737d9e 364 unsigned char max_regs_num;
AfdhalAtiffTan 0:6262fc7582a9 365
ascheeren 3:b8d920737d9e 366 /* check function code */
ascheeren 3:b8d920737d9e 367 for (i = 0; i < sizeof(fsupported); i++) {
ascheeren 3:b8d920737d9e 368 if (fsupported[i] == data[FUNC]) {
ascheeren 3:b8d920737d9e 369 fcnt = 1;
ascheeren 3:b8d920737d9e 370 break;
AfdhalAtiffTan 0:6262fc7582a9 371 }
ascheeren 3:b8d920737d9e 372 }
ascheeren 3:b8d920737d9e 373 if (0 == fcnt)
ascheeren 3:b8d920737d9e 374 return EXC_FUNC_CODE;
AfdhalAtiffTan 0:6262fc7582a9 375
ascheeren 3:b8d920737d9e 376 if (FC_WRITE_REG == data[FUNC]) {
ascheeren 3:b8d920737d9e 377 /* For function write single reg, this is the target reg.*/
ascheeren 3:b8d920737d9e 378 regs_num = ((int) data[START_H] << 8) + (int) data[START_L];
ascheeren 3:b8d920737d9e 379 if (regs_num >= regs_size)
ascheeren 3:b8d920737d9e 380 return EXC_ADDR_RANGE;
ascheeren 3:b8d920737d9e 381 return 0;
ascheeren 3:b8d920737d9e 382 }
ascheeren 3:b8d920737d9e 383
ascheeren 3:b8d920737d9e 384 /* For functions read/write regs, this is the range. */
ascheeren 3:b8d920737d9e 385 regs_num = ((int) data[REGS_H] << 8) + (int) data[REGS_L];
AfdhalAtiffTan 0:6262fc7582a9 386
ascheeren 3:b8d920737d9e 387 /* check quantity of registers */
ascheeren 3:b8d920737d9e 388 if (FC_READ_REGS == data[FUNC])
ascheeren 3:b8d920737d9e 389 max_regs_num = MAX_READ_REGS;
ascheeren 3:b8d920737d9e 390 else if (FC_WRITE_REGS == data[FUNC])
ascheeren 3:b8d920737d9e 391 max_regs_num = MAX_WRITE_REGS;
AfdhalAtiffTan 0:6262fc7582a9 392
ascheeren 3:b8d920737d9e 393 if ((regs_num < 1) || (regs_num > max_regs_num))
ascheeren 3:b8d920737d9e 394 return EXC_REGS_QUANT;
AfdhalAtiffTan 0:6262fc7582a9 395
ascheeren 3:b8d920737d9e 396 /* check registers range, start address is 0 */
ascheeren 3:b8d920737d9e 397 start_addr = ((int) data[START_H] << 8) + (int) data[START_L];
ascheeren 3:b8d920737d9e 398 if ((start_addr + regs_num) > regs_size)
ascheeren 3:b8d920737d9e 399 return EXC_ADDR_RANGE;
AfdhalAtiffTan 0:6262fc7582a9 400
ascheeren 3:b8d920737d9e 401 return 0; /* OK, no exception */
AfdhalAtiffTan 0:6262fc7582a9 402 }
AfdhalAtiffTan 0:6262fc7582a9 403
AfdhalAtiffTan 0:6262fc7582a9 404
AfdhalAtiffTan 0:6262fc7582a9 405
AfdhalAtiffTan 0:6262fc7582a9 406 /************************************************************************
ascheeren 3:b8d920737d9e 407 *
AfdhalAtiffTan 0:6262fc7582a9 408 * write_regs(first_register, data_array, registers_array)
ascheeren 3:b8d920737d9e 409 *
ascheeren 3:b8d920737d9e 410 * writes into the slave's holding registers the data in query,
AfdhalAtiffTan 0:6262fc7582a9 411 * starting at start_addr.
ascheeren 3:b8d920737d9e 412 *
AfdhalAtiffTan 0:6262fc7582a9 413 * Returns: the number of registers written
AfdhalAtiffTan 0:6262fc7582a9 414 ************************************************************************/
AfdhalAtiffTan 0:6262fc7582a9 415
ascheeren 3:b8d920737d9e 416 int ModbusSlave232::write_regs(unsigned int start_addr, unsigned char *query, int *regs)
AfdhalAtiffTan 0:6262fc7582a9 417 {
ascheeren 3:b8d920737d9e 418 int temp;
ascheeren 3:b8d920737d9e 419 unsigned int i;
AfdhalAtiffTan 0:6262fc7582a9 420
ascheeren 3:b8d920737d9e 421 for (i = 0; i < query[REGS_L]; i++) {
ascheeren 3:b8d920737d9e 422 /* shift reg hi_byte to temp */
ascheeren 3:b8d920737d9e 423 temp = (int) query[(BYTE_CNT + 1) + i * 2] << 8;
ascheeren 3:b8d920737d9e 424 /* OR with lo_byte */
ascheeren 3:b8d920737d9e 425 temp = temp | (int) query[(BYTE_CNT + 2) + i * 2];
AfdhalAtiffTan 0:6262fc7582a9 426
ascheeren 3:b8d920737d9e 427 regs[start_addr + i] = temp;
ascheeren 3:b8d920737d9e 428 }
ascheeren 3:b8d920737d9e 429 return i;
AfdhalAtiffTan 0:6262fc7582a9 430 }
AfdhalAtiffTan 0:6262fc7582a9 431
AfdhalAtiffTan 0:6262fc7582a9 432 /************************************************************************
ascheeren 3:b8d920737d9e 433 *
AfdhalAtiffTan 0:6262fc7582a9 434 * preset_multiple_registers(first_register, number_of_registers,
AfdhalAtiffTan 0:6262fc7582a9 435 * data_array, registers_array)
ascheeren 3:b8d920737d9e 436 *
ascheeren 3:b8d920737d9e 437 * Write the data from an array into the holding registers of the slave.
ascheeren 3:b8d920737d9e 438 *
AfdhalAtiffTan 0:6262fc7582a9 439 *************************************************************************/
AfdhalAtiffTan 0:6262fc7582a9 440
AfdhalAtiffTan 0:6262fc7582a9 441 int ModbusSlave232::preset_multiple_registers(unsigned int start_addr,
ascheeren 3:b8d920737d9e 442 unsigned char count,
ascheeren 3:b8d920737d9e 443 unsigned char *query,
ascheeren 3:b8d920737d9e 444 int *regs)
AfdhalAtiffTan 0:6262fc7582a9 445 {
ascheeren 3:b8d920737d9e 446 unsigned char function = FC_WRITE_REGS; /* Preset Multiple Registers */
ascheeren 3:b8d920737d9e 447 int status = 0;
ascheeren 3:b8d920737d9e 448 unsigned char packet[RESPONSE_SIZE + CHECKSUM_SIZE];
AfdhalAtiffTan 0:6262fc7582a9 449
ascheeren 3:b8d920737d9e 450 build_write_packet(function, start_addr, count, packet);
AfdhalAtiffTan 0:6262fc7582a9 451
ascheeren 3:b8d920737d9e 452 if (write_regs(start_addr, query, regs)) {
ascheeren 3:b8d920737d9e 453 status = send_reply(packet, RESPONSE_SIZE);
ascheeren 3:b8d920737d9e 454 }
AfdhalAtiffTan 0:6262fc7582a9 455
ascheeren 3:b8d920737d9e 456 return (status);
AfdhalAtiffTan 0:6262fc7582a9 457 }
AfdhalAtiffTan 0:6262fc7582a9 458
AfdhalAtiffTan 0:6262fc7582a9 459 /************************************************************************
ascheeren 3:b8d920737d9e 460 *
AfdhalAtiffTan 0:6262fc7582a9 461 * write_single_register(slave_id, write_addr, data_array, registers_array)
ascheeren 3:b8d920737d9e 462 *
ascheeren 3:b8d920737d9e 463 * Write a single int val into a single holding register of the slave.
ascheeren 3:b8d920737d9e 464 *
AfdhalAtiffTan 0:6262fc7582a9 465 *************************************************************************/
AfdhalAtiffTan 0:6262fc7582a9 466
ascheeren 3:b8d920737d9e 467 int ModbusSlave232::write_single_register(unsigned int write_addr, unsigned char *query, int *regs)
AfdhalAtiffTan 0:6262fc7582a9 468 {
ascheeren 3:b8d920737d9e 469 unsigned char function = FC_WRITE_REG; /* Function: Write Single Register */
ascheeren 3:b8d920737d9e 470 int status = 0;
ascheeren 3:b8d920737d9e 471 unsigned int reg_val;
ascheeren 3:b8d920737d9e 472 unsigned char packet[RESPONSE_SIZE + CHECKSUM_SIZE];
AfdhalAtiffTan 0:6262fc7582a9 473
ascheeren 3:b8d920737d9e 474 reg_val = query[REGS_H] << 8 | query[REGS_L];
ascheeren 3:b8d920737d9e 475 build_write_single_packet(function, write_addr, reg_val, packet);
ascheeren 3:b8d920737d9e 476 regs[write_addr] = (int) reg_val;
ascheeren 3:b8d920737d9e 477 /*
ascheeren 3:b8d920737d9e 478 written.start_addr=write_addr;
ascheeren 3:b8d920737d9e 479 written.num_regs=1;
ascheeren 3:b8d920737d9e 480 */
ascheeren 3:b8d920737d9e 481 status = send_reply(packet, RESPONSE_SIZE);
AfdhalAtiffTan 0:6262fc7582a9 482
ascheeren 3:b8d920737d9e 483 return (status);
AfdhalAtiffTan 0:6262fc7582a9 484 }
AfdhalAtiffTan 0:6262fc7582a9 485
AfdhalAtiffTan 0:6262fc7582a9 486 /************************************************************************
ascheeren 3:b8d920737d9e 487 *
AfdhalAtiffTan 0:6262fc7582a9 488 * read_holding_registers(first_register, number_of_registers,
AfdhalAtiffTan 0:6262fc7582a9 489 * registers_array)
ascheeren 3:b8d920737d9e 490 *
AfdhalAtiffTan 0:6262fc7582a9 491 * reads the slave's holdings registers and sends them to the Modbus master
ascheeren 3:b8d920737d9e 492 *
AfdhalAtiffTan 0:6262fc7582a9 493 *************************************************************************/
AfdhalAtiffTan 0:6262fc7582a9 494
AfdhalAtiffTan 0:6262fc7582a9 495 int ModbusSlave232::read_holding_registers( unsigned int start_addr,
AfdhalAtiffTan 0:6262fc7582a9 496
ascheeren 3:b8d920737d9e 497 unsigned char reg_count, int *regs)
AfdhalAtiffTan 0:6262fc7582a9 498 {
ascheeren 3:b8d920737d9e 499 unsigned char function = FC_READ_REGS; /* Read Holding Registers */
ascheeren 3:b8d920737d9e 500 int packet_size = 3;
ascheeren 3:b8d920737d9e 501 int status;
ascheeren 3:b8d920737d9e 502 unsigned int i;
ascheeren 3:b8d920737d9e 503 unsigned char packet[MAX_MESSAGE_LENGTH];
AfdhalAtiffTan 0:6262fc7582a9 504
ascheeren 3:b8d920737d9e 505 build_read_packet(function, reg_count, packet);
AfdhalAtiffTan 0:6262fc7582a9 506
ascheeren 3:b8d920737d9e 507 for (i = start_addr; i < (start_addr + (unsigned int) reg_count);
ascheeren 3:b8d920737d9e 508 i++) {
ascheeren 3:b8d920737d9e 509 packet[packet_size] = regs[i] >> 8;
ascheeren 3:b8d920737d9e 510 packet_size++;
ascheeren 3:b8d920737d9e 511 packet[packet_size] = regs[i] & 0x00FF;
ascheeren 3:b8d920737d9e 512 packet_size++;
ascheeren 3:b8d920737d9e 513 }
AfdhalAtiffTan 0:6262fc7582a9 514
ascheeren 3:b8d920737d9e 515 status = send_reply(packet, packet_size);
AfdhalAtiffTan 0:6262fc7582a9 516
ascheeren 3:b8d920737d9e 517 return (status);
AfdhalAtiffTan 0:6262fc7582a9 518 }
AfdhalAtiffTan 0:6262fc7582a9 519
ascheeren 3:b8d920737d9e 520 /*
AfdhalAtiffTan 0:6262fc7582a9 521 * configure(slave, baud, parity, txenpin)
AfdhalAtiffTan 0:6262fc7582a9 522 *
AfdhalAtiffTan 0:6262fc7582a9 523 * sets the communication parameters for of the serial line.
AfdhalAtiffTan 0:6262fc7582a9 524 *
AfdhalAtiffTan 0:6262fc7582a9 525 * slave: identification number of the slave in the Modbus network (1 to 127)
AfdhalAtiffTan 0:6262fc7582a9 526 * baud: baudrate in bps (typical values 9600, 19200... 115200)
ascheeren 3:b8d920737d9e 527 * parity: a single character sets the parity mode (character frame format):
AfdhalAtiffTan 0:6262fc7582a9 528 * 'n' no parity (8N1); 'e' even parity (8E1), 'o' for odd parity (8O1).
AfdhalAtiffTan 0:6262fc7582a9 529 * txenpin: arduino pin number that controls transmision/reception
AfdhalAtiffTan 0:6262fc7582a9 530 * of an external half-duplex device (e.g. a RS485 interface chip).
AfdhalAtiffTan 0:6262fc7582a9 531 * 0 or 1 disables this function (for a two-device network)
AfdhalAtiffTan 0:6262fc7582a9 532 * >2 for point-to-multipoint topology (e.g. several arduinos)
AfdhalAtiffTan 0:6262fc7582a9 533 */
AfdhalAtiffTan 0:6262fc7582a9 534
AfdhalAtiffTan 0:6262fc7582a9 535 void ModbusSlave232::configure(unsigned char slave, long baud, char parity)
AfdhalAtiffTan 0:6262fc7582a9 536 {
ascheeren 3:b8d920737d9e 537 this->slave = slave;
ascheeren 3:b8d920737d9e 538 //this->txenpin = 2; //afdhal
ascheeren 3:b8d920737d9e 539
AfdhalAtiffTan 0:6262fc7582a9 540
AfdhalAtiffTan 0:6262fc7582a9 541
ascheeren 3:b8d920737d9e 542 //Serial.begin(baud); //afdhal
ascheeren 3:b8d920737d9e 543 pc.baud(baud); //afdhal
AfdhalAtiffTan 0:6262fc7582a9 544
ascheeren 3:b8d920737d9e 545 switch (parity) {
AfdhalAtiffTan 0:6262fc7582a9 546 case 'e': // 8E1
ascheeren 3:b8d920737d9e 547 //UCSR0C |= ((1<<UPM01) | (1<<UCSZ01) | (1<<UCSZ00)); //afdhal
ascheeren 3:b8d920737d9e 548 pc.format(8, SerialBase::Even, 1); //afdhal
ascheeren 3:b8d920737d9e 549 // UCSR0C &= ~((1<<UPM00) | (1<<UCSZ02) | (1<<USBS0));
ascheeren 3:b8d920737d9e 550 break;
AfdhalAtiffTan 0:6262fc7582a9 551 case 'o': // 8O1
ascheeren 3:b8d920737d9e 552 //UCSR0C |= ((1<<UPM01) | (1<<UPM00) | (1<<UCSZ01) | (1<<UCSZ00)); //afdhal
ascheeren 3:b8d920737d9e 553 pc.format(8, SerialBase::Odd, 1); //afdhal
ascheeren 3:b8d920737d9e 554 // UCSR0C &= ~((1<<UCSZ02) | (1<<USBS0));
ascheeren 3:b8d920737d9e 555 break;
AfdhalAtiffTan 0:6262fc7582a9 556 case 'n': // 8N1
ascheeren 3:b8d920737d9e 557 //UCSR0C |= ((1<<UCSZ01) | (1<<UCSZ00)); //afdhal
ascheeren 3:b8d920737d9e 558 pc.format(8, SerialBase::None, 1); //afdhal
ascheeren 3:b8d920737d9e 559 // UCSR0C &= ~((1<<UPM01) | (1<<UPM00) | (1<<UCSZ02) | (1<<USBS0));
ascheeren 3:b8d920737d9e 560 break;
AfdhalAtiffTan 0:6262fc7582a9 561 default:
ascheeren 3:b8d920737d9e 562 break;
ascheeren 3:b8d920737d9e 563 }
AfdhalAtiffTan 0:6262fc7582a9 564
ascheeren 3:b8d920737d9e 565 /*
ascheeren 3:b8d920737d9e 566 if (txenpin > 1) { // pin 0 & pin 1 are reserved for RX/TX
ascheeren 3:b8d920737d9e 567 pinMode(txenpin, OUTPUT);
ascheeren 3:b8d920737d9e 568 digitalWrite(txenpin, LOW);
ascheeren 3:b8d920737d9e 569 }*/
ascheeren 3:b8d920737d9e 570
ascheeren 3:b8d920737d9e 571 return;
ascheeren 3:b8d920737d9e 572 }
AfdhalAtiffTan 0:6262fc7582a9 573
AfdhalAtiffTan 0:6262fc7582a9 574
AfdhalAtiffTan 0:6262fc7582a9 575 /*
AfdhalAtiffTan 0:6262fc7582a9 576 * update(regs, regs_size)
ascheeren 3:b8d920737d9e 577 *
AfdhalAtiffTan 0:6262fc7582a9 578 * checks if there is any valid request from the modbus master. If there is,
AfdhalAtiffTan 0:6262fc7582a9 579 * performs the requested action
ascheeren 3:b8d920737d9e 580 *
AfdhalAtiffTan 0:6262fc7582a9 581 * regs: an array with the holding registers. They start at address 1 (master point of view)
AfdhalAtiffTan 0:6262fc7582a9 582 * regs_size: total number of holding registers.
AfdhalAtiffTan 0:6262fc7582a9 583 * returns: 0 if no request from master,
AfdhalAtiffTan 0:6262fc7582a9 584 * NO_REPLY (-1) if no reply is sent to the master
AfdhalAtiffTan 0:6262fc7582a9 585 * an exception code (1 to 4) in case of a modbus exceptions
AfdhalAtiffTan 0:6262fc7582a9 586 * the number of bytes sent as reply ( > 4) if OK.
AfdhalAtiffTan 0:6262fc7582a9 587 */
AfdhalAtiffTan 0:6262fc7582a9 588 unsigned long Nowdt = 0;
AfdhalAtiffTan 0:6262fc7582a9 589 unsigned int lastBytesReceived;
AfdhalAtiffTan 0:6262fc7582a9 590 const unsigned long T35 = 5;
AfdhalAtiffTan 0:6262fc7582a9 591
AfdhalAtiffTan 0:6262fc7582a9 592 int ModbusSlave232::update(int *regs,
ascheeren 3:b8d920737d9e 593 unsigned int regs_size)
ascheeren 3:b8d920737d9e 594 {
ascheeren 3:b8d920737d9e 595 unsigned char query[MAX_MESSAGE_LENGTH];
ascheeren 3:b8d920737d9e 596 unsigned char errpacket[EXCEPTION_SIZE + CHECKSUM_SIZE];
ascheeren 3:b8d920737d9e 597 unsigned int start_addr;
ascheeren 3:b8d920737d9e 598 int exception;
ascheeren 3:b8d920737d9e 599 int length = pc.rxBufferGetCount(); //Serial.available(); //afdhal
ascheeren 3:b8d920737d9e 600 unsigned long now = millis();
ascheeren 3:b8d920737d9e 601
AfdhalAtiffTan 0:6262fc7582a9 602
AfdhalAtiffTan 0:6262fc7582a9 603
ascheeren 3:b8d920737d9e 604 if (length == 0) {
ascheeren 3:b8d920737d9e 605 lastBytesReceived = 0;
ascheeren 3:b8d920737d9e 606 return 0;
ascheeren 3:b8d920737d9e 607 }
AfdhalAtiffTan 0:6262fc7582a9 608
ascheeren 3:b8d920737d9e 609 if (lastBytesReceived != length) {
ascheeren 3:b8d920737d9e 610 lastBytesReceived = length;
ascheeren 3:b8d920737d9e 611 Nowdt = now + T35;
ascheeren 3:b8d920737d9e 612 return 0;
ascheeren 3:b8d920737d9e 613 }
ascheeren 3:b8d920737d9e 614 if (now < Nowdt)
ascheeren 3:b8d920737d9e 615 return 0;
AfdhalAtiffTan 0:6262fc7582a9 616
ascheeren 3:b8d920737d9e 617 lastBytesReceived = 0;
ascheeren 3:b8d920737d9e 618
ascheeren 3:b8d920737d9e 619 length = modbus_request(query);
ascheeren 3:b8d920737d9e 620 if (length < 1)
ascheeren 3:b8d920737d9e 621 return length;
AfdhalAtiffTan 0:6262fc7582a9 622
ascheeren 3:b8d920737d9e 623 exception = validate_request(query, length, regs_size);
ascheeren 3:b8d920737d9e 624 if (exception) {
ascheeren 3:b8d920737d9e 625 build_error_packet( query[FUNC], exception,
ascheeren 3:b8d920737d9e 626 errpacket);
ascheeren 3:b8d920737d9e 627 send_reply(errpacket, EXCEPTION_SIZE);
ascheeren 3:b8d920737d9e 628 return (exception);
ascheeren 3:b8d920737d9e 629 }
AfdhalAtiffTan 0:6262fc7582a9 630
ascheeren 3:b8d920737d9e 631 start_addr =
ascheeren 3:b8d920737d9e 632 ((int) query[START_H] << 8) +
ascheeren 3:b8d920737d9e 633 (int) query[START_L];
AfdhalAtiffTan 0:6262fc7582a9 634
ascheeren 3:b8d920737d9e 635 switch (query[FUNC]) {
ascheeren 3:b8d920737d9e 636 case FC_READ_REGS:
ascheeren 3:b8d920737d9e 637 return read_holding_registers(
ascheeren 3:b8d920737d9e 638 start_addr,
ascheeren 3:b8d920737d9e 639 query[REGS_L],
ascheeren 3:b8d920737d9e 640 regs);
ascheeren 3:b8d920737d9e 641 break;
ascheeren 3:b8d920737d9e 642 case FC_WRITE_REGS:
ascheeren 3:b8d920737d9e 643 return preset_multiple_registers(
ascheeren 3:b8d920737d9e 644 start_addr,
ascheeren 3:b8d920737d9e 645 query[REGS_L],
ascheeren 3:b8d920737d9e 646 query,
ascheeren 3:b8d920737d9e 647 regs);
ascheeren 3:b8d920737d9e 648 break;
ascheeren 3:b8d920737d9e 649 case FC_WRITE_REG:
ascheeren 3:b8d920737d9e 650 write_single_register(
ascheeren 3:b8d920737d9e 651 start_addr,
ascheeren 3:b8d920737d9e 652 query,
ascheeren 3:b8d920737d9e 653 regs);
ascheeren 3:b8d920737d9e 654 break;
ascheeren 3:b8d920737d9e 655 }
ascheeren 3:b8d920737d9e 656
AfdhalAtiffTan 1:35fdc7056f66 657 }