1 /*
2 * FreeModbus Libary: user callback functions and buffer define in master mode
3 * Copyright (C) 2013 Armink <[email protected]>
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 *
19 * File: $Id: user_mb_app_m.c,v 1.60 2013/11/23 11:49:05 Armink $
20 */
21 #include "user_mb_app.h"
22
23 /*-----------------------Master mode use these variables----------------------*/
24 #if MB_MASTER_RTU_ENABLED > 0 || MB_MASTER_ASCII_ENABLED > 0
25 //Master mode:DiscreteInputs variables
26 USHORT usMDiscInStart = M_DISCRETE_INPUT_START;
27 #if M_DISCRETE_INPUT_NDISCRETES%8
28 UCHAR ucMDiscInBuf[MB_MASTER_TOTAL_SLAVE_NUM][M_DISCRETE_INPUT_NDISCRETES/8+1];
29 #else
30 UCHAR ucMDiscInBuf[MB_MASTER_TOTAL_SLAVE_NUM][M_DISCRETE_INPUT_NDISCRETES/8];
31 #endif
32 //Master mode:Coils variables
33 USHORT usMCoilStart = M_COIL_START;
34 #if M_COIL_NCOILS%8
35 UCHAR ucMCoilBuf[MB_MASTER_TOTAL_SLAVE_NUM][M_COIL_NCOILS/8+1];
36 #else
37 UCHAR ucMCoilBuf[MB_MASTER_TOTAL_SLAVE_NUM][M_COIL_NCOILS/8];
38 #endif
39 //Master mode:InputRegister variables
40 USHORT usMRegInStart = M_REG_INPUT_START;
41 USHORT usMRegInBuf[MB_MASTER_TOTAL_SLAVE_NUM][M_REG_INPUT_NREGS];
42 //Master mode:HoldingRegister variables
43 USHORT usMRegHoldStart = M_REG_HOLDING_START;
44 USHORT usMRegHoldBuf[MB_MASTER_TOTAL_SLAVE_NUM][M_REG_HOLDING_NREGS];
45
46 /**
47 * Modbus master input register callback function.
48 *
49 * @param pucRegBuffer input register buffer
50 * @param usAddress input register address
51 * @param usNRegs input register number
52 *
53 * @return result
54 */
eMBMasterRegInputCB(UCHAR * pucRegBuffer,USHORT usAddress,USHORT usNRegs)55 eMBErrorCode eMBMasterRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs )
56 {
57 eMBErrorCode eStatus = MB_ENOERR;
58 USHORT iRegIndex;
59 USHORT * pusRegInputBuf;
60 USHORT REG_INPUT_START;
61 USHORT REG_INPUT_NREGS;
62 USHORT usRegInStart;
63
64 pusRegInputBuf = usMRegInBuf[ucMBMasterGetDestAddress() - 1];
65 REG_INPUT_START = M_REG_INPUT_START;
66 REG_INPUT_NREGS = M_REG_INPUT_NREGS;
67 usRegInStart = usMRegInStart;
68
69 /* it already plus one in modbus function method. */
70 usAddress--;
71
72 if ((usAddress >= REG_INPUT_START)
73 && (usAddress + usNRegs <= REG_INPUT_START + REG_INPUT_NREGS))
74 {
75 iRegIndex = usAddress - usRegInStart;
76 while (usNRegs > 0)
77 {
78 pusRegInputBuf[iRegIndex] = *pucRegBuffer++ << 8;
79 pusRegInputBuf[iRegIndex] |= *pucRegBuffer++;
80 iRegIndex++;
81 usNRegs--;
82 }
83 }
84 else
85 {
86 eStatus = MB_ENOREG;
87 }
88
89 return eStatus;
90 }
91
92 /**
93 * Modbus master holding register callback function.
94 *
95 * @param pucRegBuffer holding register buffer
96 * @param usAddress holding register address
97 * @param usNRegs holding register number
98 * @param eMode read or write
99 *
100 * @return result
101 */
eMBMasterRegHoldingCB(UCHAR * pucRegBuffer,USHORT usAddress,USHORT usNRegs,eMBRegisterMode eMode)102 eMBErrorCode eMBMasterRegHoldingCB(UCHAR * pucRegBuffer, USHORT usAddress,
103 USHORT usNRegs, eMBRegisterMode eMode)
104 {
105 eMBErrorCode eStatus = MB_ENOERR;
106 USHORT iRegIndex;
107 USHORT * pusRegHoldingBuf;
108 USHORT REG_HOLDING_START;
109 USHORT REG_HOLDING_NREGS;
110 USHORT usRegHoldStart;
111
112 pusRegHoldingBuf = usMRegHoldBuf[ucMBMasterGetDestAddress() - 1];
113 REG_HOLDING_START = M_REG_HOLDING_START;
114 REG_HOLDING_NREGS = M_REG_HOLDING_NREGS;
115 usRegHoldStart = usMRegHoldStart;
116 /* if mode is read, the master will write the received date to buffer. */
117 eMode = MB_REG_WRITE;
118
119 /* it already plus one in modbus function method. */
120 usAddress--;
121
122 if ((usAddress >= REG_HOLDING_START)
123 && (usAddress + usNRegs <= REG_HOLDING_START + REG_HOLDING_NREGS))
124 {
125 iRegIndex = usAddress - usRegHoldStart;
126 switch (eMode)
127 {
128 /* read current register values from the protocol stack. */
129 case MB_REG_READ:
130 while (usNRegs > 0)
131 {
132 *pucRegBuffer++ = (UCHAR) (pusRegHoldingBuf[iRegIndex] >> 8);
133 *pucRegBuffer++ = (UCHAR) (pusRegHoldingBuf[iRegIndex] & 0xFF);
134 iRegIndex++;
135 usNRegs--;
136 }
137 break;
138 /* write current register values with new values from the protocol stack. */
139 case MB_REG_WRITE:
140 while (usNRegs > 0)
141 {
142 pusRegHoldingBuf[iRegIndex] = *pucRegBuffer++ << 8;
143 pusRegHoldingBuf[iRegIndex] |= *pucRegBuffer++;
144 iRegIndex++;
145 usNRegs--;
146 }
147 break;
148 }
149 }
150 else
151 {
152 eStatus = MB_ENOREG;
153 }
154 return eStatus;
155 }
156
157 /**
158 * Modbus master coils callback function.
159 *
160 * @param pucRegBuffer coils buffer
161 * @param usAddress coils address
162 * @param usNCoils coils number
163 * @param eMode read or write
164 *
165 * @return result
166 */
eMBMasterRegCoilsCB(UCHAR * pucRegBuffer,USHORT usAddress,USHORT usNCoils,eMBRegisterMode eMode)167 eMBErrorCode eMBMasterRegCoilsCB(UCHAR * pucRegBuffer, USHORT usAddress,
168 USHORT usNCoils, eMBRegisterMode eMode)
169 {
170 eMBErrorCode eStatus = MB_ENOERR;
171 USHORT iRegIndex , iRegBitIndex , iNReg;
172 UCHAR * pucCoilBuf;
173 USHORT COIL_START;
174 USHORT COIL_NCOILS;
175 USHORT usCoilStart;
176 iNReg = usNCoils / 8 + 1;
177
178 pucCoilBuf = ucMCoilBuf[ucMBMasterGetDestAddress() - 1];
179 COIL_START = M_COIL_START;
180 COIL_NCOILS = M_COIL_NCOILS;
181 usCoilStart = usMCoilStart;
182
183 /* if mode is read,the master will write the received date to buffer. */
184 eMode = MB_REG_WRITE;
185
186 /* it already plus one in modbus function method. */
187 usAddress--;
188
189 if ((usAddress >= COIL_START)
190 && (usAddress + usNCoils <= COIL_START + COIL_NCOILS))
191 {
192 iRegIndex = (USHORT) (usAddress - usCoilStart) / 8;
193 iRegBitIndex = (USHORT) (usAddress - usCoilStart) % 8;
194 switch (eMode)
195 {
196 /* read current coil values from the protocol stack. */
197 case MB_REG_READ:
198 while (iNReg > 0)
199 {
200 *pucRegBuffer++ = xMBUtilGetBits(&pucCoilBuf[iRegIndex++],
201 iRegBitIndex, 8);
202 iNReg--;
203 }
204 pucRegBuffer--;
205 /* last coils */
206 usNCoils = usNCoils % 8;
207 /* filling zero to high bit */
208 *pucRegBuffer = *pucRegBuffer << (8 - usNCoils);
209 *pucRegBuffer = *pucRegBuffer >> (8 - usNCoils);
210 break;
211
212 /* write current coil values with new values from the protocol stack. */
213 case MB_REG_WRITE:
214 while (iNReg > 1)
215 {
216 xMBUtilSetBits(&pucCoilBuf[iRegIndex++], iRegBitIndex, 8,
217 *pucRegBuffer++);
218 iNReg--;
219 }
220 /* last coils */
221 usNCoils = usNCoils % 8;
222 /* xMBUtilSetBits has bug when ucNBits is zero */
223 if (usNCoils != 0)
224 {
225 xMBUtilSetBits(&pucCoilBuf[iRegIndex++], iRegBitIndex, usNCoils,
226 *pucRegBuffer++);
227 }
228 break;
229 }
230 }
231 else
232 {
233 eStatus = MB_ENOREG;
234 }
235 return eStatus;
236 }
237
238 /**
239 * Modbus master discrete callback function.
240 *
241 * @param pucRegBuffer discrete buffer
242 * @param usAddress discrete address
243 * @param usNDiscrete discrete number
244 *
245 * @return result
246 */
eMBMasterRegDiscreteCB(UCHAR * pucRegBuffer,USHORT usAddress,USHORT usNDiscrete)247 eMBErrorCode eMBMasterRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNDiscrete )
248 {
249 eMBErrorCode eStatus = MB_ENOERR;
250 USHORT iRegIndex , iRegBitIndex , iNReg;
251 UCHAR * pucDiscreteInputBuf;
252 USHORT DISCRETE_INPUT_START;
253 USHORT DISCRETE_INPUT_NDISCRETES;
254 USHORT usDiscreteInputStart;
255 iNReg = usNDiscrete / 8 + 1;
256
257 pucDiscreteInputBuf = ucMDiscInBuf[ucMBMasterGetDestAddress() - 1];
258 DISCRETE_INPUT_START = M_DISCRETE_INPUT_START;
259 DISCRETE_INPUT_NDISCRETES = M_DISCRETE_INPUT_NDISCRETES;
260 usDiscreteInputStart = usMDiscInStart;
261
262 /* it already plus one in modbus function method. */
263 usAddress--;
264
265 if ((usAddress >= DISCRETE_INPUT_START)
266 && (usAddress + usNDiscrete <= DISCRETE_INPUT_START + DISCRETE_INPUT_NDISCRETES))
267 {
268 iRegIndex = (USHORT) (usAddress - usDiscreteInputStart) / 8;
269 iRegBitIndex = (USHORT) (usAddress - usDiscreteInputStart) % 8;
270
271 /* write current discrete values with new values from the protocol stack. */
272 while (iNReg > 1)
273 {
274 xMBUtilSetBits(&pucDiscreteInputBuf[iRegIndex++], iRegBitIndex, 8,
275 *pucRegBuffer++);
276 iNReg--;
277 }
278 /* last discrete */
279 usNDiscrete = usNDiscrete % 8;
280 /* xMBUtilSetBits has bug when ucNBits is zero */
281 if (usNDiscrete != 0)
282 {
283 xMBUtilSetBits(&pucDiscreteInputBuf[iRegIndex++], iRegBitIndex,
284 usNDiscrete, *pucRegBuffer++);
285 }
286 }
287 else
288 {
289 eStatus = MB_ENOREG;
290 }
291
292 return eStatus;
293 }
294 #endif
295