user_mb_app.c 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. /*
  2. * FreeModbus Libary: user callback functions and buffer define in slave mode
  3. * Copyright (C) 2013 Armink <armink.ztl@gmail.com>
  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.c,v 1.60 2013/11/23 11:49:05 Armink $
  20. */
  21. #include "user_mb_app.h"
  22. /*------------------------Slave mode use these variables----------------------*/
  23. //Slave mode:DiscreteInputs variables
  24. USHORT usSDiscInStart = S_DISCRETE_INPUT_START;
  25. #if S_DISCRETE_INPUT_NDISCRETES%8
  26. UCHAR ucSDiscInBuf[S_DISCRETE_INPUT_NDISCRETES/8+1];
  27. #else
  28. UCHAR ucSDiscInBuf[S_DISCRETE_INPUT_NDISCRETES/8] ;
  29. #endif
  30. //Slave mode:Coils variables
  31. USHORT usSCoilStart = S_COIL_START;
  32. #if S_COIL_NCOILS%8
  33. UCHAR ucSCoilBuf[S_COIL_NCOILS/8+1] ;
  34. #else
  35. UCHAR ucSCoilBuf[S_COIL_NCOILS/8] ;
  36. #endif
  37. //Slave mode:InputRegister variables
  38. USHORT usSRegInStart = S_REG_INPUT_START;
  39. USHORT usSRegInBuf[S_REG_INPUT_NREGS] ;
  40. //Slave mode:HoldingRegister variables
  41. USHORT usSRegHoldStart = S_REG_HOLDING_START;
  42. USHORT usSRegHoldBuf[S_REG_HOLDING_NREGS] ;
  43. /**
  44. * Modbus slave input register callback function.
  45. *
  46. * @param pucRegBuffer input register buffer
  47. * @param usAddress input register address
  48. * @param usNRegs input register number
  49. *
  50. * @return result
  51. */
  52. eMBErrorCode eMBRegInputCB(UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs )
  53. {
  54. eMBErrorCode eStatus = MB_ENOERR;
  55. USHORT iRegIndex;
  56. USHORT * pusRegInputBuf;
  57. USHORT REG_INPUT_START;
  58. USHORT REG_INPUT_NREGS;
  59. USHORT usRegInStart;
  60. pusRegInputBuf = usSRegInBuf;
  61. REG_INPUT_START = S_REG_INPUT_START;
  62. REG_INPUT_NREGS = S_REG_INPUT_NREGS;
  63. usRegInStart = usSRegInStart;
  64. /* it already plus one in modbus function method. */
  65. usAddress--;
  66. if ((usAddress >= REG_INPUT_START)
  67. && (usAddress + usNRegs <= REG_INPUT_START + REG_INPUT_NREGS))
  68. {
  69. iRegIndex = usAddress - usRegInStart;
  70. while (usNRegs > 0)
  71. {
  72. *pucRegBuffer++ = (UCHAR) (pusRegInputBuf[iRegIndex] >> 8);
  73. *pucRegBuffer++ = (UCHAR) (pusRegInputBuf[iRegIndex] & 0xFF);
  74. iRegIndex++;
  75. usNRegs--;
  76. }
  77. }
  78. else
  79. {
  80. eStatus = MB_ENOREG;
  81. }
  82. return eStatus;
  83. }
  84. /**
  85. * Modbus slave holding register callback function.
  86. *
  87. * @param pucRegBuffer holding register buffer
  88. * @param usAddress holding register address
  89. * @param usNRegs holding register number
  90. * @param eMode read or write
  91. *
  92. * @return result
  93. */
  94. eMBErrorCode eMBRegHoldingCB(UCHAR * pucRegBuffer, USHORT usAddress,
  95. USHORT usNRegs, eMBRegisterMode eMode)
  96. {
  97. eMBErrorCode eStatus = MB_ENOERR;
  98. USHORT iRegIndex;
  99. USHORT * pusRegHoldingBuf;
  100. USHORT REG_HOLDING_START;
  101. USHORT REG_HOLDING_NREGS;
  102. USHORT usRegHoldStart;
  103. pusRegHoldingBuf = usSRegHoldBuf;
  104. REG_HOLDING_START = S_REG_HOLDING_START;
  105. REG_HOLDING_NREGS = S_REG_HOLDING_NREGS;
  106. usRegHoldStart = usSRegHoldStart;
  107. /* it already plus one in modbus function method. */
  108. usAddress--;
  109. if ((usAddress >= REG_HOLDING_START)
  110. && (usAddress + usNRegs <= REG_HOLDING_START + REG_HOLDING_NREGS))
  111. {
  112. iRegIndex = usAddress - usRegHoldStart;
  113. switch (eMode)
  114. {
  115. /* read current register values from the protocol stack. */
  116. case MB_REG_READ:
  117. while (usNRegs > 0)
  118. {
  119. *pucRegBuffer++ = (UCHAR) (pusRegHoldingBuf[iRegIndex] >> 8);
  120. *pucRegBuffer++ = (UCHAR) (pusRegHoldingBuf[iRegIndex] & 0xFF);
  121. iRegIndex++;
  122. usNRegs--;
  123. }
  124. break;
  125. /* write current register values with new values from the protocol stack. */
  126. case MB_REG_WRITE:
  127. while (usNRegs > 0)
  128. {
  129. pusRegHoldingBuf[iRegIndex] = *pucRegBuffer++ << 8;
  130. pusRegHoldingBuf[iRegIndex] |= *pucRegBuffer++;
  131. iRegIndex++;
  132. usNRegs--;
  133. }
  134. break;
  135. }
  136. }
  137. else
  138. {
  139. eStatus = MB_ENOREG;
  140. }
  141. return eStatus;
  142. }
  143. /**
  144. * Modbus slave coils callback function.
  145. *
  146. * @param pucRegBuffer coils buffer
  147. * @param usAddress coils address
  148. * @param usNCoils coils number
  149. * @param eMode read or write
  150. *
  151. * @return result
  152. */
  153. eMBErrorCode eMBRegCoilsCB(UCHAR * pucRegBuffer, USHORT usAddress,
  154. USHORT usNCoils, eMBRegisterMode eMode)
  155. {
  156. eMBErrorCode eStatus = MB_ENOERR;
  157. USHORT iRegIndex , iRegBitIndex , iNReg;
  158. UCHAR * pucCoilBuf;
  159. USHORT COIL_START;
  160. USHORT COIL_NCOILS;
  161. USHORT usCoilStart;
  162. iNReg = usNCoils / 8 + 1;
  163. pucCoilBuf = ucSCoilBuf;
  164. COIL_START = S_COIL_START;
  165. COIL_NCOILS = S_COIL_NCOILS;
  166. usCoilStart = usSCoilStart;
  167. /* it already plus one in modbus function method. */
  168. usAddress--;
  169. if( ( usAddress >= COIL_START ) &&
  170. ( usAddress + usNCoils <= COIL_START + COIL_NCOILS ) )
  171. {
  172. iRegIndex = (USHORT) (usAddress - usCoilStart) / 8;
  173. iRegBitIndex = (USHORT) (usAddress - usCoilStart) % 8;
  174. switch ( eMode )
  175. {
  176. /* read current coil values from the protocol stack. */
  177. case MB_REG_READ:
  178. while (iNReg > 0)
  179. {
  180. *pucRegBuffer++ = xMBUtilGetBits(&pucCoilBuf[iRegIndex++],
  181. iRegBitIndex, 8);
  182. iNReg--;
  183. }
  184. pucRegBuffer--;
  185. /* last coils */
  186. usNCoils = usNCoils % 8;
  187. /* filling zero to high bit */
  188. *pucRegBuffer = *pucRegBuffer << (8 - usNCoils);
  189. *pucRegBuffer = *pucRegBuffer >> (8 - usNCoils);
  190. break;
  191. /* write current coil values with new values from the protocol stack. */
  192. case MB_REG_WRITE:
  193. while (iNReg > 1)
  194. {
  195. xMBUtilSetBits(&pucCoilBuf[iRegIndex++], iRegBitIndex, 8,
  196. *pucRegBuffer++);
  197. iNReg--;
  198. }
  199. /* last coils */
  200. usNCoils = usNCoils % 8;
  201. /* xMBUtilSetBits has bug when ucNBits is zero */
  202. if (usNCoils != 0)
  203. {
  204. xMBUtilSetBits(&pucCoilBuf[iRegIndex++], iRegBitIndex, usNCoils,
  205. *pucRegBuffer++);
  206. }
  207. break;
  208. }
  209. }
  210. else
  211. {
  212. eStatus = MB_ENOREG;
  213. }
  214. return eStatus;
  215. }
  216. /**
  217. * Modbus slave discrete callback function.
  218. *
  219. * @param pucRegBuffer discrete buffer
  220. * @param usAddress discrete address
  221. * @param usNDiscrete discrete number
  222. *
  223. * @return result
  224. */
  225. eMBErrorCode eMBRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNDiscrete )
  226. {
  227. eMBErrorCode eStatus = MB_ENOERR;
  228. USHORT iRegIndex , iRegBitIndex , iNReg;
  229. UCHAR * pucDiscreteInputBuf;
  230. USHORT DISCRETE_INPUT_START;
  231. USHORT DISCRETE_INPUT_NDISCRETES;
  232. USHORT usDiscreteInputStart;
  233. iNReg = usNDiscrete / 8 + 1;
  234. pucDiscreteInputBuf = ucSDiscInBuf;
  235. DISCRETE_INPUT_START = S_DISCRETE_INPUT_START;
  236. DISCRETE_INPUT_NDISCRETES = S_DISCRETE_INPUT_NDISCRETES;
  237. usDiscreteInputStart = usSDiscInStart;
  238. /* it already plus one in modbus function method. */
  239. usAddress--;
  240. if ((usAddress >= DISCRETE_INPUT_START)
  241. && (usAddress + usNDiscrete <= DISCRETE_INPUT_START + DISCRETE_INPUT_NDISCRETES))
  242. {
  243. iRegIndex = (USHORT) (usAddress - usDiscreteInputStart) / 8;
  244. iRegBitIndex = (USHORT) (usAddress - usDiscreteInputStart) % 8;
  245. while (iNReg > 0)
  246. {
  247. *pucRegBuffer++ = xMBUtilGetBits(&pucDiscreteInputBuf[iRegIndex++],
  248. iRegBitIndex, 8);
  249. iNReg--;
  250. }
  251. pucRegBuffer--;
  252. /* last discrete */
  253. usNDiscrete = usNDiscrete % 8;
  254. /* filling zero to high bit */
  255. *pucRegBuffer = *pucRegBuffer << (8 - usNDiscrete);
  256. *pucRegBuffer = *pucRegBuffer >> (8 - usNDiscrete);
  257. }
  258. else
  259. {
  260. eStatus = MB_ENOREG;
  261. }
  262. return eStatus;
  263. }