Aplikacijski kod

Dependencies:   mbed

U prikazanom primjeru izvedena je remote ModBus TCP/IP komunikacija. Generalni opis konfiguracije: U ovom radu je korištena oprema prizvođača Mikortik te mikrokontroler mbed NXP LPC1768. Libery za ethernet odnosno Modbus TCP/IP sam skino sam stranice mbeda te sam ga modificirao kako bi odgovarao željenoj aplikaciji. (https://os.mbed.com/users/paleskyjp/code/ModbusTCP_Modified/) Preko mrežne opreme izeveo sam SSTP VPN koji spaja lokalne subnete iz uređaja "mbed LOCAL" i uređaja "mbed LAPTOP" u jedan jedinstveni te omogućava nesmetanu komunikaciju između uređaja povezanih u lokalnim subnetima. Moguće se također spojiti direktno preko ethernet kabela u uređaj, ali u ovom primjeru laptop je spojen na WIFI mrežu nazvanzu "MBED TVZ" te preko nje komunicira sa mikrokontrolerom koji je kabelom spojem u mrežni uređaj naziva "mbed LOCAL". Riječ remote u ovom primjeru pokazuje da su dva uređaja "mbed LOCAL" i "mbed LAPTOP" preko WIFI-ja spojeni na 2 različita hosta (mobiteli pored njih) te je otvoren VPN kanal između njih. Na uređajima je također podešen DHCP koji dodijeljuje adrese uređajima koji se pokušavaju spojiti na njih, tako i mikrokontroleru. Lokalni subnet nije pušten na internet te mbed nije direktno izložen internetu, što pridonosi sigurnosnom aspektu komunikacije. Za tesitranje komunikacije dovoljno je koristit osnovne alate koji dolaze sa svakim windows-ima, naredba ping (na videu doljnji desni dio ekrana, dok je mbed bio ugašen vidljivo je da ne prolazi komunikacija, nakon što se upalio i spojio na mrežu komunikacija se uspostavila te je vidljivo kako konstantno vraća odgovor) Alat korišten za upis podataka u registre je Modbus Master koji podržava TCP/IP. Svakako je moguće koristiti i druge aplikacije ili druge uređaje koji podržavaju ovaj tip komunikacije. Primjerice PLC, drugi mbed, neko drugo računalo,... Aplikacija sama po sebi nije nešto pretjerano komplicirana ali put samog paketa od Modbus master-a do samog Modbus slave-a nije tako jednostavan. Aplikacija se odnosi na dio ukoliko na nulti registar bilo koje adresnog polja Modbus master pošalje vrijednost veću od 5 konstantno svijetli LED2 izvedena na samoj ploćici mbeda, te ukoliko dođe vrijednos manja od 5 da ugasi LED2. To je samo demostracija rada komunikacije. U ovoj konfiguraciji moguće je bilo gdje odnjeti mikortik i mbed te ga spojiti na WIFI koji ima propust prema internetu te se sa drugim mikrotikom povezati sa mbed-om i nesmetano komunicirati.

Committer:
lincina
Date:
Thu Nov 14 15:38:42 2019 +0000
Revision:
4:97b3bd92b315
Parent:
0:62be54b8975d
remote komunikacija

Who changed what in which revision?

UserRevisionLine numberNew contents of line
paleskyjp 0:62be54b8975d 1 /*
paleskyjp 0:62be54b8975d 2 * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
paleskyjp 0:62be54b8975d 3 * Copyright (c) 2006 Christian Walter <wolti@sil.at>
paleskyjp 0:62be54b8975d 4 * All rights reserved.
paleskyjp 0:62be54b8975d 5 *
paleskyjp 0:62be54b8975d 6 * Redistribution and use in source and binary forms, with or without
paleskyjp 0:62be54b8975d 7 * modification, are permitted provided that the following conditions
paleskyjp 0:62be54b8975d 8 * are met:
paleskyjp 0:62be54b8975d 9 * 1. Redistributions of source code must retain the above copyright
paleskyjp 0:62be54b8975d 10 * notice, this list of conditions and the following disclaimer.
paleskyjp 0:62be54b8975d 11 * 2. Redistributions in binary form must reproduce the above copyright
paleskyjp 0:62be54b8975d 12 * notice, this list of conditions and the following disclaimer in the
paleskyjp 0:62be54b8975d 13 * documentation and/or other materials provided with the distribution.
paleskyjp 0:62be54b8975d 14 * 3. The name of the author may not be used to endorse or promote products
paleskyjp 0:62be54b8975d 15 * derived from this software without specific prior written permission.
paleskyjp 0:62be54b8975d 16 *
paleskyjp 0:62be54b8975d 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
paleskyjp 0:62be54b8975d 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
paleskyjp 0:62be54b8975d 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
paleskyjp 0:62be54b8975d 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
paleskyjp 0:62be54b8975d 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
paleskyjp 0:62be54b8975d 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
paleskyjp 0:62be54b8975d 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
paleskyjp 0:62be54b8975d 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
paleskyjp 0:62be54b8975d 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
paleskyjp 0:62be54b8975d 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
paleskyjp 0:62be54b8975d 27 *
paleskyjp 0:62be54b8975d 28 * File: $Id: mbfuncholding.c,v 1.12 2007/02/18 23:48:22 wolti Exp $
paleskyjp 0:62be54b8975d 29 */
paleskyjp 0:62be54b8975d 30
paleskyjp 0:62be54b8975d 31 /* ----------------------- System includes ----------------------------------*/
paleskyjp 0:62be54b8975d 32 #include "stdlib.h"
paleskyjp 0:62be54b8975d 33 #include "string.h"
paleskyjp 0:62be54b8975d 34
paleskyjp 0:62be54b8975d 35 /* ----------------------- Platform includes --------------------------------*/
paleskyjp 0:62be54b8975d 36 #include "port.h"
paleskyjp 0:62be54b8975d 37
paleskyjp 0:62be54b8975d 38 /* ----------------------- Modbus includes ----------------------------------*/
paleskyjp 0:62be54b8975d 39 #include "mb.h"
paleskyjp 0:62be54b8975d 40 #include "mbframe.h"
paleskyjp 0:62be54b8975d 41 #include "mbproto.h"
paleskyjp 0:62be54b8975d 42 #include "mbconfig.h"
paleskyjp 0:62be54b8975d 43
paleskyjp 0:62be54b8975d 44 /* ----------------------- Defines ------------------------------------------*/
paleskyjp 0:62be54b8975d 45 #define MB_PDU_FUNC_READ_ADDR_OFF ( MB_PDU_DATA_OFF + 0)
paleskyjp 0:62be54b8975d 46 #define MB_PDU_FUNC_READ_REGCNT_OFF ( MB_PDU_DATA_OFF + 2 )
paleskyjp 0:62be54b8975d 47 #define MB_PDU_FUNC_READ_SIZE ( 4 )
paleskyjp 0:62be54b8975d 48 #define MB_PDU_FUNC_READ_REGCNT_MAX ( 0x007D )
paleskyjp 0:62be54b8975d 49
paleskyjp 0:62be54b8975d 50 #define MB_PDU_FUNC_WRITE_ADDR_OFF ( MB_PDU_DATA_OFF + 0)
paleskyjp 0:62be54b8975d 51 #define MB_PDU_FUNC_WRITE_VALUE_OFF ( MB_PDU_DATA_OFF + 2 )
paleskyjp 0:62be54b8975d 52 #define MB_PDU_FUNC_WRITE_SIZE ( 4 )
paleskyjp 0:62be54b8975d 53
paleskyjp 0:62be54b8975d 54 #define MB_PDU_FUNC_WRITE_MUL_ADDR_OFF ( MB_PDU_DATA_OFF + 0 )
paleskyjp 0:62be54b8975d 55 #define MB_PDU_FUNC_WRITE_MUL_REGCNT_OFF ( MB_PDU_DATA_OFF + 2 )
paleskyjp 0:62be54b8975d 56 #define MB_PDU_FUNC_WRITE_MUL_BYTECNT_OFF ( MB_PDU_DATA_OFF + 4 )
paleskyjp 0:62be54b8975d 57 #define MB_PDU_FUNC_WRITE_MUL_VALUES_OFF ( MB_PDU_DATA_OFF + 5 )
paleskyjp 0:62be54b8975d 58 #define MB_PDU_FUNC_WRITE_MUL_SIZE_MIN ( 5 )
paleskyjp 0:62be54b8975d 59 #define MB_PDU_FUNC_WRITE_MUL_REGCNT_MAX ( 0x0078 )
paleskyjp 0:62be54b8975d 60
paleskyjp 0:62be54b8975d 61 #define MB_PDU_FUNC_READWRITE_READ_ADDR_OFF ( MB_PDU_DATA_OFF + 0 )
paleskyjp 0:62be54b8975d 62 #define MB_PDU_FUNC_READWRITE_READ_REGCNT_OFF ( MB_PDU_DATA_OFF + 2 )
paleskyjp 0:62be54b8975d 63 #define MB_PDU_FUNC_READWRITE_WRITE_ADDR_OFF ( MB_PDU_DATA_OFF + 4 )
paleskyjp 0:62be54b8975d 64 #define MB_PDU_FUNC_READWRITE_WRITE_REGCNT_OFF ( MB_PDU_DATA_OFF + 6 )
paleskyjp 0:62be54b8975d 65 #define MB_PDU_FUNC_READWRITE_BYTECNT_OFF ( MB_PDU_DATA_OFF + 8 )
paleskyjp 0:62be54b8975d 66 #define MB_PDU_FUNC_READWRITE_WRITE_VALUES_OFF ( MB_PDU_DATA_OFF + 9 )
paleskyjp 0:62be54b8975d 67 #define MB_PDU_FUNC_READWRITE_SIZE_MIN ( 9 )
paleskyjp 0:62be54b8975d 68
paleskyjp 0:62be54b8975d 69 /* ----------------------- Static functions ---------------------------------*/
paleskyjp 0:62be54b8975d 70 eMBException prveMBError2Exception( eMBErrorCode eErrorCode );
paleskyjp 0:62be54b8975d 71
paleskyjp 0:62be54b8975d 72 /* ----------------------- Start implementation -----------------------------*/
paleskyjp 0:62be54b8975d 73
paleskyjp 0:62be54b8975d 74 #if MB_FUNC_WRITE_HOLDING_ENABLED > 0
paleskyjp 0:62be54b8975d 75
paleskyjp 0:62be54b8975d 76 eMBException
paleskyjp 0:62be54b8975d 77 eMBFuncWriteHoldingRegister( UCHAR * pucFrame, USHORT * usLen )
paleskyjp 0:62be54b8975d 78 {
paleskyjp 0:62be54b8975d 79 USHORT usRegAddress;
paleskyjp 0:62be54b8975d 80 eMBException eStatus = MB_EX_NONE;
paleskyjp 0:62be54b8975d 81 eMBErrorCode eRegStatus;
paleskyjp 0:62be54b8975d 82
paleskyjp 0:62be54b8975d 83 if( *usLen == ( MB_PDU_FUNC_WRITE_SIZE + MB_PDU_SIZE_MIN ) )
paleskyjp 0:62be54b8975d 84 {
paleskyjp 0:62be54b8975d 85 usRegAddress = ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_ADDR_OFF] << 8 );
paleskyjp 0:62be54b8975d 86 usRegAddress |= ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_ADDR_OFF + 1] );
paleskyjp 0:62be54b8975d 87 usRegAddress++;
paleskyjp 0:62be54b8975d 88
paleskyjp 0:62be54b8975d 89 /* Make callback to update the value. */
paleskyjp 0:62be54b8975d 90 eRegStatus = eMBRegHoldingCB( &pucFrame[MB_PDU_FUNC_WRITE_VALUE_OFF],
paleskyjp 0:62be54b8975d 91 usRegAddress, 1, MB_REG_WRITE );
paleskyjp 0:62be54b8975d 92
paleskyjp 0:62be54b8975d 93 /* If an error occured convert it into a Modbus exception. */
paleskyjp 0:62be54b8975d 94 if( eRegStatus != MB_ENOERR )
paleskyjp 0:62be54b8975d 95 {
paleskyjp 0:62be54b8975d 96 eStatus = prveMBError2Exception( eRegStatus );
paleskyjp 0:62be54b8975d 97 }
paleskyjp 0:62be54b8975d 98 }
paleskyjp 0:62be54b8975d 99 else
paleskyjp 0:62be54b8975d 100 {
paleskyjp 0:62be54b8975d 101 /* Can't be a valid request because the length is incorrect. */
paleskyjp 0:62be54b8975d 102 eStatus = MB_EX_ILLEGAL_DATA_VALUE;
paleskyjp 0:62be54b8975d 103 }
paleskyjp 0:62be54b8975d 104 return eStatus;
paleskyjp 0:62be54b8975d 105 }
paleskyjp 0:62be54b8975d 106 #endif
paleskyjp 0:62be54b8975d 107
paleskyjp 0:62be54b8975d 108 #if MB_FUNC_WRITE_MULTIPLE_HOLDING_ENABLED > 0
paleskyjp 0:62be54b8975d 109 eMBException
paleskyjp 0:62be54b8975d 110 eMBFuncWriteMultipleHoldingRegister( UCHAR * pucFrame, USHORT * usLen )
paleskyjp 0:62be54b8975d 111 {
paleskyjp 0:62be54b8975d 112 USHORT usRegAddress;
paleskyjp 0:62be54b8975d 113 USHORT usRegCount;
paleskyjp 0:62be54b8975d 114 UCHAR ucRegByteCount;
paleskyjp 0:62be54b8975d 115
paleskyjp 0:62be54b8975d 116 eMBException eStatus = MB_EX_NONE;
paleskyjp 0:62be54b8975d 117 eMBErrorCode eRegStatus;
paleskyjp 0:62be54b8975d 118
paleskyjp 0:62be54b8975d 119 if( *usLen >= ( MB_PDU_FUNC_WRITE_MUL_SIZE_MIN + MB_PDU_SIZE_MIN ) )
paleskyjp 0:62be54b8975d 120 {
paleskyjp 0:62be54b8975d 121 usRegAddress = ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_MUL_ADDR_OFF] << 8 );
paleskyjp 0:62be54b8975d 122 usRegAddress |= ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_MUL_ADDR_OFF + 1] );
paleskyjp 0:62be54b8975d 123 usRegAddress++;
paleskyjp 0:62be54b8975d 124
paleskyjp 0:62be54b8975d 125 usRegCount = ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_MUL_REGCNT_OFF] << 8 );
paleskyjp 0:62be54b8975d 126 usRegCount |= ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_MUL_REGCNT_OFF + 1] );
paleskyjp 0:62be54b8975d 127
paleskyjp 0:62be54b8975d 128 ucRegByteCount = pucFrame[MB_PDU_FUNC_WRITE_MUL_BYTECNT_OFF];
paleskyjp 0:62be54b8975d 129
paleskyjp 0:62be54b8975d 130 if( ( usRegCount >= 1 ) &&
paleskyjp 0:62be54b8975d 131 ( usRegCount <= MB_PDU_FUNC_WRITE_MUL_REGCNT_MAX ) &&
paleskyjp 0:62be54b8975d 132 ( ucRegByteCount == ( UCHAR ) ( 2 * usRegCount ) ) )
paleskyjp 0:62be54b8975d 133 {
paleskyjp 0:62be54b8975d 134 /* Make callback to update the register values. */
paleskyjp 0:62be54b8975d 135 eRegStatus =
paleskyjp 0:62be54b8975d 136 eMBRegHoldingCB( &pucFrame[MB_PDU_FUNC_WRITE_MUL_VALUES_OFF],
paleskyjp 0:62be54b8975d 137 usRegAddress, usRegCount, MB_REG_WRITE );
paleskyjp 0:62be54b8975d 138
paleskyjp 0:62be54b8975d 139 /* If an error occured convert it into a Modbus exception. */
paleskyjp 0:62be54b8975d 140 if( eRegStatus != MB_ENOERR )
paleskyjp 0:62be54b8975d 141 {
paleskyjp 0:62be54b8975d 142 eStatus = prveMBError2Exception( eRegStatus );
paleskyjp 0:62be54b8975d 143 }
paleskyjp 0:62be54b8975d 144 else
paleskyjp 0:62be54b8975d 145 {
paleskyjp 0:62be54b8975d 146 /* The response contains the function code, the starting
paleskyjp 0:62be54b8975d 147 * address and the quantity of registers. We reuse the
paleskyjp 0:62be54b8975d 148 * old values in the buffer because they are still valid.
paleskyjp 0:62be54b8975d 149 */
paleskyjp 0:62be54b8975d 150 *usLen = MB_PDU_FUNC_WRITE_MUL_BYTECNT_OFF;
paleskyjp 0:62be54b8975d 151 }
paleskyjp 0:62be54b8975d 152 }
paleskyjp 0:62be54b8975d 153 else
paleskyjp 0:62be54b8975d 154 {
paleskyjp 0:62be54b8975d 155 eStatus = MB_EX_ILLEGAL_DATA_VALUE;
paleskyjp 0:62be54b8975d 156 }
paleskyjp 0:62be54b8975d 157 }
paleskyjp 0:62be54b8975d 158 else
paleskyjp 0:62be54b8975d 159 {
paleskyjp 0:62be54b8975d 160 /* Can't be a valid request because the length is incorrect. */
paleskyjp 0:62be54b8975d 161 eStatus = MB_EX_ILLEGAL_DATA_VALUE;
paleskyjp 0:62be54b8975d 162 }
paleskyjp 0:62be54b8975d 163 return eStatus;
paleskyjp 0:62be54b8975d 164 }
paleskyjp 0:62be54b8975d 165 #endif
paleskyjp 0:62be54b8975d 166
paleskyjp 0:62be54b8975d 167 #if MB_FUNC_READ_HOLDING_ENABLED > 0
paleskyjp 0:62be54b8975d 168
paleskyjp 0:62be54b8975d 169 eMBException
paleskyjp 0:62be54b8975d 170 eMBFuncReadHoldingRegister( UCHAR * pucFrame, USHORT * usLen )
paleskyjp 0:62be54b8975d 171 {
paleskyjp 0:62be54b8975d 172 USHORT usRegAddress;
paleskyjp 0:62be54b8975d 173 USHORT usRegCount;
paleskyjp 0:62be54b8975d 174 UCHAR *pucFrameCur;
paleskyjp 0:62be54b8975d 175
paleskyjp 0:62be54b8975d 176 eMBException eStatus = MB_EX_NONE;
paleskyjp 0:62be54b8975d 177 eMBErrorCode eRegStatus;
paleskyjp 0:62be54b8975d 178
paleskyjp 0:62be54b8975d 179 if( *usLen == ( MB_PDU_FUNC_READ_SIZE + MB_PDU_SIZE_MIN ) )
paleskyjp 0:62be54b8975d 180 {
paleskyjp 0:62be54b8975d 181 usRegAddress = ( USHORT )( pucFrame[MB_PDU_FUNC_READ_ADDR_OFF] << 8 );
paleskyjp 0:62be54b8975d 182 usRegAddress |= ( USHORT )( pucFrame[MB_PDU_FUNC_READ_ADDR_OFF + 1] );
paleskyjp 0:62be54b8975d 183 usRegAddress++;
paleskyjp 0:62be54b8975d 184
paleskyjp 0:62be54b8975d 185 usRegCount = ( USHORT )( pucFrame[MB_PDU_FUNC_READ_REGCNT_OFF] << 8 );
paleskyjp 0:62be54b8975d 186 usRegCount = ( USHORT )( pucFrame[MB_PDU_FUNC_READ_REGCNT_OFF + 1] );
paleskyjp 0:62be54b8975d 187
paleskyjp 0:62be54b8975d 188 /* Check if the number of registers to read is valid. If not
paleskyjp 0:62be54b8975d 189 * return Modbus illegal data value exception.
paleskyjp 0:62be54b8975d 190 */
paleskyjp 0:62be54b8975d 191 if( ( usRegCount >= 1 ) && ( usRegCount <= MB_PDU_FUNC_READ_REGCNT_MAX ) )
paleskyjp 0:62be54b8975d 192 {
paleskyjp 0:62be54b8975d 193 /* Set the current PDU data pointer to the beginning. */
paleskyjp 0:62be54b8975d 194 pucFrameCur = &pucFrame[MB_PDU_FUNC_OFF];
paleskyjp 0:62be54b8975d 195 *usLen = MB_PDU_FUNC_OFF;
paleskyjp 0:62be54b8975d 196
paleskyjp 0:62be54b8975d 197 /* First byte contains the function code. */
paleskyjp 0:62be54b8975d 198 *pucFrameCur++ = MB_FUNC_READ_HOLDING_REGISTER;
paleskyjp 0:62be54b8975d 199 *usLen += 1;
paleskyjp 0:62be54b8975d 200
paleskyjp 0:62be54b8975d 201 /* Second byte in the response contain the number of bytes. */
paleskyjp 0:62be54b8975d 202 *pucFrameCur++ = ( UCHAR ) ( usRegCount * 2 );
paleskyjp 0:62be54b8975d 203 *usLen += 1;
paleskyjp 0:62be54b8975d 204
paleskyjp 0:62be54b8975d 205 /* Make callback to fill the buffer. */
paleskyjp 0:62be54b8975d 206 eRegStatus = eMBRegHoldingCB( pucFrameCur, usRegAddress, usRegCount, MB_REG_READ );
paleskyjp 0:62be54b8975d 207 /* If an error occured convert it into a Modbus exception. */
paleskyjp 0:62be54b8975d 208 if( eRegStatus != MB_ENOERR )
paleskyjp 0:62be54b8975d 209 {
paleskyjp 0:62be54b8975d 210 eStatus = prveMBError2Exception( eRegStatus );
paleskyjp 0:62be54b8975d 211 }
paleskyjp 0:62be54b8975d 212 else
paleskyjp 0:62be54b8975d 213 {
paleskyjp 0:62be54b8975d 214 *usLen += usRegCount * 2;
paleskyjp 0:62be54b8975d 215 }
paleskyjp 0:62be54b8975d 216 }
paleskyjp 0:62be54b8975d 217 else
paleskyjp 0:62be54b8975d 218 {
paleskyjp 0:62be54b8975d 219 eStatus = MB_EX_ILLEGAL_DATA_VALUE;
paleskyjp 0:62be54b8975d 220 }
paleskyjp 0:62be54b8975d 221 }
paleskyjp 0:62be54b8975d 222 else
paleskyjp 0:62be54b8975d 223 {
paleskyjp 0:62be54b8975d 224 /* Can't be a valid request because the length is incorrect. */
paleskyjp 0:62be54b8975d 225 eStatus = MB_EX_ILLEGAL_DATA_VALUE;
paleskyjp 0:62be54b8975d 226 }
paleskyjp 0:62be54b8975d 227 return eStatus;
paleskyjp 0:62be54b8975d 228 }
paleskyjp 0:62be54b8975d 229
paleskyjp 0:62be54b8975d 230 #endif
paleskyjp 0:62be54b8975d 231
paleskyjp 0:62be54b8975d 232 #if MB_FUNC_READWRITE_HOLDING_ENABLED > 0
paleskyjp 0:62be54b8975d 233
paleskyjp 0:62be54b8975d 234 eMBException
paleskyjp 0:62be54b8975d 235 eMBFuncReadWriteMultipleHoldingRegister( UCHAR * pucFrame, USHORT * usLen )
paleskyjp 0:62be54b8975d 236 {
paleskyjp 0:62be54b8975d 237 USHORT usRegReadAddress;
paleskyjp 0:62be54b8975d 238 USHORT usRegReadCount;
paleskyjp 0:62be54b8975d 239 USHORT usRegWriteAddress;
paleskyjp 0:62be54b8975d 240 USHORT usRegWriteCount;
paleskyjp 0:62be54b8975d 241 UCHAR ucRegWriteByteCount;
paleskyjp 0:62be54b8975d 242 UCHAR *pucFrameCur;
paleskyjp 0:62be54b8975d 243
paleskyjp 0:62be54b8975d 244 eMBException eStatus = MB_EX_NONE;
paleskyjp 0:62be54b8975d 245 eMBErrorCode eRegStatus;
paleskyjp 0:62be54b8975d 246
paleskyjp 0:62be54b8975d 247 if( *usLen >= ( MB_PDU_FUNC_READWRITE_SIZE_MIN + MB_PDU_SIZE_MIN ) )
paleskyjp 0:62be54b8975d 248 {
paleskyjp 0:62be54b8975d 249 usRegReadAddress = ( USHORT )( pucFrame[MB_PDU_FUNC_READWRITE_READ_ADDR_OFF] << 8U );
paleskyjp 0:62be54b8975d 250 usRegReadAddress |= ( USHORT )( pucFrame[MB_PDU_FUNC_READWRITE_READ_ADDR_OFF + 1] );
paleskyjp 0:62be54b8975d 251 usRegReadAddress++;
paleskyjp 0:62be54b8975d 252
paleskyjp 0:62be54b8975d 253 usRegReadCount = ( USHORT )( pucFrame[MB_PDU_FUNC_READWRITE_READ_REGCNT_OFF] << 8U );
paleskyjp 0:62be54b8975d 254 usRegReadCount |= ( USHORT )( pucFrame[MB_PDU_FUNC_READWRITE_READ_REGCNT_OFF + 1] );
paleskyjp 0:62be54b8975d 255
paleskyjp 0:62be54b8975d 256 usRegWriteAddress = ( USHORT )( pucFrame[MB_PDU_FUNC_READWRITE_WRITE_ADDR_OFF] << 8U );
paleskyjp 0:62be54b8975d 257 usRegWriteAddress |= ( USHORT )( pucFrame[MB_PDU_FUNC_READWRITE_WRITE_ADDR_OFF + 1] );
paleskyjp 0:62be54b8975d 258 usRegWriteAddress++;
paleskyjp 0:62be54b8975d 259
paleskyjp 0:62be54b8975d 260 usRegWriteCount = ( USHORT )( pucFrame[MB_PDU_FUNC_READWRITE_WRITE_REGCNT_OFF] << 8U );
paleskyjp 0:62be54b8975d 261 usRegWriteCount |= ( USHORT )( pucFrame[MB_PDU_FUNC_READWRITE_WRITE_REGCNT_OFF + 1] );
paleskyjp 0:62be54b8975d 262
paleskyjp 0:62be54b8975d 263 ucRegWriteByteCount = pucFrame[MB_PDU_FUNC_READWRITE_BYTECNT_OFF];
paleskyjp 0:62be54b8975d 264
paleskyjp 0:62be54b8975d 265 if( ( usRegReadCount >= 1 ) && ( usRegReadCount <= 0x7D ) &&
paleskyjp 0:62be54b8975d 266 ( usRegWriteCount >= 1 ) && ( usRegWriteCount <= 0x79 ) &&
paleskyjp 0:62be54b8975d 267 ( ( 2 * usRegWriteCount ) == ucRegWriteByteCount ) )
paleskyjp 0:62be54b8975d 268 {
paleskyjp 0:62be54b8975d 269 /* Make callback to update the register values. */
paleskyjp 0:62be54b8975d 270 eRegStatus = eMBRegHoldingCB( &pucFrame[MB_PDU_FUNC_READWRITE_WRITE_VALUES_OFF],
paleskyjp 0:62be54b8975d 271 usRegWriteAddress, usRegWriteCount, MB_REG_WRITE );
paleskyjp 0:62be54b8975d 272
paleskyjp 0:62be54b8975d 273 if( eRegStatus == MB_ENOERR )
paleskyjp 0:62be54b8975d 274 {
paleskyjp 0:62be54b8975d 275 /* Set the current PDU data pointer to the beginning. */
paleskyjp 0:62be54b8975d 276 pucFrameCur = &pucFrame[MB_PDU_FUNC_OFF];
paleskyjp 0:62be54b8975d 277 *usLen = MB_PDU_FUNC_OFF;
paleskyjp 0:62be54b8975d 278
paleskyjp 0:62be54b8975d 279 /* First byte contains the function code. */
paleskyjp 0:62be54b8975d 280 *pucFrameCur++ = MB_FUNC_READWRITE_MULTIPLE_REGISTERS;
paleskyjp 0:62be54b8975d 281 *usLen += 1;
paleskyjp 0:62be54b8975d 282
paleskyjp 0:62be54b8975d 283 /* Second byte in the response contain the number of bytes. */
paleskyjp 0:62be54b8975d 284 *pucFrameCur++ = ( UCHAR ) ( usRegReadCount * 2 );
paleskyjp 0:62be54b8975d 285 *usLen += 1;
paleskyjp 0:62be54b8975d 286
paleskyjp 0:62be54b8975d 287 /* Make the read callback. */
paleskyjp 0:62be54b8975d 288 eRegStatus =
paleskyjp 0:62be54b8975d 289 eMBRegHoldingCB( pucFrameCur, usRegReadAddress, usRegReadCount, MB_REG_READ );
paleskyjp 0:62be54b8975d 290 if( eRegStatus == MB_ENOERR )
paleskyjp 0:62be54b8975d 291 {
paleskyjp 0:62be54b8975d 292 *usLen += 2 * usRegReadCount;
paleskyjp 0:62be54b8975d 293 }
paleskyjp 0:62be54b8975d 294 }
paleskyjp 0:62be54b8975d 295 if( eRegStatus != MB_ENOERR )
paleskyjp 0:62be54b8975d 296 {
paleskyjp 0:62be54b8975d 297 eStatus = prveMBError2Exception( eRegStatus );
paleskyjp 0:62be54b8975d 298 }
paleskyjp 0:62be54b8975d 299 }
paleskyjp 0:62be54b8975d 300 else
paleskyjp 0:62be54b8975d 301 {
paleskyjp 0:62be54b8975d 302 eStatus = MB_EX_ILLEGAL_DATA_VALUE;
paleskyjp 0:62be54b8975d 303 }
paleskyjp 0:62be54b8975d 304 }
paleskyjp 0:62be54b8975d 305 return eStatus;
paleskyjp 0:62be54b8975d 306 }
paleskyjp 0:62be54b8975d 307
paleskyjp 0:62be54b8975d 308 #endif