FreeModbus_Slave-Master-RTT.../FreeModbus/port/user_mb_app.c

276 lines
11 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* FreeModbus Libary: user callback functions and buffer define in slave mode
* Copyright (C) 2013 Armink <armink.ztl@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* File: $Id: user_mb_app.c,v 1.60 2013/11/23 11:49:05 Armink $
*/
#include "user_mb_app.h"
/*------------------------Slave mode use these variables----------------------*/
//Slave mode:DiscreteInputs variables
USHORT usSDiscInStart = S_DISCRETE_INPUT_START;
#if S_DISCRETE_INPUT_NDISCRETES%8
UCHAR ucSDiscInBuf[S_DISCRETE_INPUT_NDISCRETES/8+1];
#else
UCHAR ucSDiscInBuf[S_DISCRETE_INPUT_NDISCRETES/8] ;
#endif
//Slave mode:Coils variables
USHORT usSCoilStart = S_COIL_START;
#if S_COIL_NCOILS%8
UCHAR ucSCoilBuf[S_COIL_NCOILS/8+1] ;
#else
UCHAR ucSCoilBuf[S_COIL_NCOILS/8] ;
#endif
//Slave mode:InputRegister variables
USHORT usSRegInStart = S_REG_INPUT_START;
USHORT usSRegInBuf[S_REG_INPUT_NREGS] ;
//Slave mode:HoldingRegister variables
USHORT usSRegHoldStart = S_REG_HOLDING_START;
USHORT usSRegHoldBuf[S_REG_HOLDING_NREGS] ;
//******************************输入寄存器回调函数**********************************
//函数定义: eMBErrorCode eMBRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs )
//描 述:输入寄存器相关的功能(读、连续读)
//入口参数pucRegBuffer : 回调函数将Modbus寄存器的当前值写入的缓冲区
// usAddress : 寄存器的起始地址输入寄存器的地址范围是1-65535。
// usNRegs : 寄存器数量
//出口参数eMBErrorCode : 这个函数将返回的错误码
//备 注EditorArmink 2010-10-31 Company: BXXJS
//**********************************************************************************
eMBErrorCode
eMBRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs )
{
eMBErrorCode eStatus = MB_ENOERR;
USHORT iRegIndex;
USHORT * pusRegInputBuf;
UCHAR REG_INPUT_START;
UCHAR REG_INPUT_NREGS;
UCHAR usRegInStart;
pusRegInputBuf = usSRegInBuf;
REG_INPUT_START = S_REG_INPUT_START;
REG_INPUT_NREGS = S_REG_INPUT_NREGS;
usRegInStart = usSRegInStart;
usAddress--;//FreeModbus功能函数中已经加1为保证与缓冲区首地址一致故减1
if( ( usAddress >= REG_INPUT_START )
&& ( usAddress + usNRegs <= REG_INPUT_START + REG_INPUT_NREGS ) )
{
iRegIndex = usAddress - usRegInStart;
while( usNRegs > 0 )
{
*pucRegBuffer++ = (unsigned char) (pusRegInputBuf[iRegIndex] >> 8);
*pucRegBuffer++ = ( unsigned char )( pusRegInputBuf[iRegIndex] & 0xFF );
iRegIndex++;
usNRegs--;
}
}
else
{
eStatus = MB_ENOREG;
}
return eStatus;
}
//******************************保持寄存器回调函数**********************************
//函数定义: eMBErrorCode eMBRegHoldingCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs, eMBRegisterMode eMode )
//描 述:保持寄存器相关的功能(读、连续读、写、连续写)
//入口参数pucRegBuffer : 如果需要更新用户寄存器数值,这个缓冲区必须指向新的寄存器数值。
// 如果协议栈想知道当前的数值,回调函数必须将当前值写入这个缓冲区
// usAddress : 寄存器的起始地址。
// usNRegs : 寄存器数量
// eMode : 如果该参数为eMBRegisterMode::MB_REG_WRITE用户的应用数值将从pucRegBuffer中得到更新。
// 如果该参数为eMBRegisterMode::MB_REG_READ用户需要将当前的应用数据存储在pucRegBuffer中
//出口参数eMBErrorCode : 这个函数将返回的错误码
//备 注EditorArmink 2010-10-31 Company: BXXJS
//**********************************************************************************
eMBErrorCode
eMBRegHoldingCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs, eMBRegisterMode eMode )
{
eMBErrorCode eStatus = MB_ENOERR;
USHORT iRegIndex;
USHORT * pusRegHoldingBuf;
UCHAR REG_HOLDING_START;
UCHAR REG_HOLDING_NREGS;
UCHAR usRegHoldStart;
pusRegHoldingBuf = usSRegHoldBuf;
REG_HOLDING_START = S_REG_HOLDING_START;
REG_HOLDING_NREGS = S_REG_HOLDING_NREGS;
usRegHoldStart = usSRegHoldStart;
usAddress--;//FreeModbus功能函数中已经加1为保证与缓冲区首地址一致故减1
if( ( usAddress >= REG_HOLDING_START ) &&
( usAddress + usNRegs <= REG_HOLDING_START + REG_HOLDING_NREGS ) )
{
iRegIndex = usAddress - usRegHoldStart;
switch ( eMode )
{
/* Pass current register values to the protocol stack. */
case MB_REG_READ:
while( usNRegs > 0 )
{
*pucRegBuffer++ = ( unsigned char )( pusRegHoldingBuf[iRegIndex] >> 8 );
*pucRegBuffer++ = ( unsigned char )( pusRegHoldingBuf[iRegIndex] & 0xFF );
iRegIndex++;
usNRegs--;
}
break;
/* Update current register values with new values from the
* protocol stack. */
case MB_REG_WRITE:
while( usNRegs > 0 )
{
pusRegHoldingBuf[iRegIndex] = *pucRegBuffer++ << 8;
pusRegHoldingBuf[iRegIndex] |= *pucRegBuffer++;
iRegIndex++;
usNRegs--;
}
break;
}
}
else
{
eStatus = MB_ENOREG;
}
return eStatus;
}
//****************************线圈状态寄存器回调函数********************************
//函数定义: eMBErrorCode eMBRegCoilsCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNCoils, eMBRegisterMode eMode )
//描 述:线圈状态寄存器相关的功能(读、连续读、写、连续写)
//入口参数pucRegBuffer : 位组成一个字节起始寄存器对应的位处于该字节pucRegBuffer的最低位LSB。
// 如果回调函数要写这个缓冲区没有用到的线圈例如不是8个一组的线圈状态对应的位的数值必须设置位0。
// usAddress : 第一个线圈地址。
// usNCoils : 请求的线圈个数
// eMode 如果该参数为eMBRegisterMode::MB_REG_WRITE用户的应用数值将从pucRegBuffer中得到更新。
// 如果该参数为eMBRegisterMode::MB_REG_READ用户需要将当前的应用数据存储在pucRegBuffer中
//出口参数eMBErrorCode : 这个函数将返回的错误码
//备 注EditorArmink 2010-10-31 Company: BXXJS
//**********************************************************************************
eMBErrorCode
eMBRegCoilsCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNCoils, eMBRegisterMode eMode )
{
eMBErrorCode eStatus = MB_ENOERR;
USHORT iRegIndex , iRegBitIndex , iNReg;
UCHAR * pucCoilBuf;
UCHAR COIL_START;
UCHAR COIL_NCOILS;
UCHAR usCoilStart;
iNReg = usNCoils / 8 + 1; //占用寄存器数量
pucCoilBuf = ucSCoilBuf;
COIL_START = S_COIL_START;
COIL_NCOILS = S_COIL_NCOILS;
usCoilStart = usSCoilStart;
usAddress--;//FreeModbus功能函数中已经加1为保证与缓冲区首地址一致故减1
if( ( usAddress >= COIL_START ) &&
( usAddress + usNCoils <= COIL_START + COIL_NCOILS ) )
{
iRegIndex = ( int )( usAddress - usCoilStart ) / 8 ; //每个寄存器存8个
iRegBitIndex = ( int )( usAddress - usCoilStart ) % 8 ; //相对于寄存器内部的位地址
switch ( eMode )
{
/* Pass current coil values to the protocol stack. */
case MB_REG_READ:
while( iNReg > 0 )
{
*pucRegBuffer++ = xMBUtilGetBits(&pucCoilBuf[iRegIndex++] , iRegBitIndex , 8);
iNReg --;
}
pucRegBuffer --;
usNCoils = usNCoils % 8; //余下的线圈数
*pucRegBuffer = *pucRegBuffer <<(8 - usNCoils); //高位补零
*pucRegBuffer = *pucRegBuffer >>(8 - usNCoils);
break;
/* Update current coil values with new values from the
* protocol stack. */
case MB_REG_WRITE:
while(iNReg > 1) //最后面余下来的数单独算
{
xMBUtilSetBits(&pucCoilBuf[iRegIndex++] , iRegBitIndex , 8 , *pucRegBuffer++);
iNReg--;
}
usNCoils = usNCoils % 8; //余下的线圈数
if (usNCoils != 0) //xMBUtilSetBits方法 在操作位数量为0时存在bug
{
xMBUtilSetBits(&pucCoilBuf[iRegIndex++], iRegBitIndex, usNCoils,
*pucRegBuffer++);
}
break;
}
}
else
{
eStatus = MB_ENOREG;
}
return eStatus;
}
//****************************离散输入寄存器回调函数********************************
//函数定义: eMBErrorCode eMBRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNDiscrete )
//描 述:离散输入寄存器相关的功能(读、连续读)
//入口参数pucRegBuffer : 用当前的线圈数据更新这个寄存器起始寄存器对应的位处于该字节pucRegBuffer的最低位LSB。
// 如果回调函数要写这个缓冲区没有用到的线圈例如不是8个一组的线圈状态对应的位的数值必须设置为0。
// usAddress : 离散输入的起始地址
// usNDiscrete : 离散输入点数量
//出口参数eMBErrorCode : 这个函数将返回的错误码
//备 注EditorArmink 2010-10-31 Company: BXXJS
//**********************************************************************************
eMBErrorCode
eMBRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNDiscrete )
{
eMBErrorCode eStatus = MB_ENOERR;
USHORT iRegIndex , iRegBitIndex , iNReg;
UCHAR * pucDiscreteInputBuf;
UCHAR DISCRETE_INPUT_START;
UCHAR DISCRETE_INPUT_NDISCRETES;
UCHAR usDiscreteInputStart;
iNReg = usNDiscrete / 8 + 1; //占用寄存器数量
pucDiscreteInputBuf = ucSDiscInBuf;
DISCRETE_INPUT_START = S_DISCRETE_INPUT_START;
DISCRETE_INPUT_NDISCRETES = S_DISCRETE_INPUT_NDISCRETES;
usDiscreteInputStart = usSDiscInStart;
usAddress--;//FreeModbus功能函数中已经加1为保证与缓冲区首地址一致故减1
if( ( usAddress >= DISCRETE_INPUT_START )
&& ( usAddress + usNDiscrete <= DISCRETE_INPUT_START + DISCRETE_INPUT_NDISCRETES ) )
{
iRegIndex = ( int )( usAddress - usDiscreteInputStart ) / 8 ; //每个寄存器存8个
iRegBitIndex = ( int )( usAddress - usDiscreteInputStart ) % 8 ; //相对于寄存器内部的位地址
while (iNReg > 0)
{
*pucRegBuffer++ = xMBUtilGetBits(&pucDiscreteInputBuf[iRegIndex++],
iRegBitIndex, 8);
iNReg--;
}
pucRegBuffer--;
usNDiscrete = usNDiscrete % 8; //余下的线圈数
*pucRegBuffer = *pucRegBuffer << (8 - usNDiscrete); //高位补零
*pucRegBuffer = *pucRegBuffer >>(8 - usNDiscrete);
}
else
{
eStatus = MB_ENOREG;
}
return eStatus;
}