FreeModbus-RTU-SLAVE程序流程梳理

第一次正儿八经移植程序,整理了2天,终于梳理清楚。
过程曲折&愉快

RTU客端代码梳理
源代码很多,提炼核心,了解程序跳转流程
把握整体框架


modbus-rtu 03数据结构

Slave AddressFunction CodeRegAddRegNumCRC

根据数据结构,就分了3个处理层级

  • 地址 eMBPoll
  • 功能码 eMBFunc…
  • 寄存器 eMBRegHoldingCB

1. 总入口-eMBPoll–<1 设备地址> <mb.c>

层级1 :<设备地址>

主要流程:
  1. 接收事件状态机:case EV_FRAME_RECEIVED / EV_EXECUTE
  2. 提取+判断:设备地址ucRcvAddress
  3. 功能跳转:功能码ucFunctionCode
  4. 回复内容:ucMBFrame
核心代码:
  1. 事件状态机:xMBPortEventGet( &eEvent ) +switch ( eEvent )
  2. 地址提取:peMBFrameReceiveCur( &ucRcvAddress, &ucMBFrame, &usLength )
    地址判断 if( ( ucRcvAddress == ucMBAddress ) || ( ucRcvAddress == MB_ADDRESS_BROADCAST ) )
  3. 功能码跳转关联处理函数:xFuncHandlers[i].pxHandler( ucMBFrame, &usLength )
  4. 回复数据 peMBFrameSendCur( ucMBAddress, ucMBFrame, usLength );
源代码
eMBErrorCode eMBPoll( void )
{
    static UCHAR   *ucMBFrame;
    static UCHAR    ucRcvAddress;
    static UCHAR    ucFunctionCode;
    static USHORT   usLength;
    static eMBException eException;

    int             i;
    eMBErrorCode    eStatus = MB_ENOERR;
    eMBEventType    eEvent;

    /* Check if the protocol stack is ready. */
    if( eMBState != STATE_ENABLED )
    {
        return MB_EILLSTATE;
    }

    /* Check if there is a event available. If not return control to caller.
     * Otherwise we will handle the event. */
    if( xMBPortEventGet( &eEvent ) == TRUE )
    {
        switch ( eEvent )
        {
        case EV_READY:
            break;

        case EV_FRAME_RECEIVED:
            eStatus = peMBFrameReceiveCur( &ucRcvAddress, &ucMBFrame, &usLength );
            if( eStatus == MB_ENOERR )
            {
                /* Check if the frame is for us. If not ignore the frame. */
                if( ( ucRcvAddress == ucMBAddress ) || ( ucRcvAddress == MB_ADDRESS_BROADCAST ) )
                {
                    ( void )xMBPortEventPost( EV_EXECUTE );
                }
            }
            break;

        case EV_EXECUTE:
            ucFunctionCode = ucMBFrame[MB_PDU_FUNC_OFF];
            eException = MB_EX_ILLEGAL_FUNCTION;
            for( i = 0; i < MB_FUNC_HANDLERS_MAX; i++ )
            {
                /* No more function handlers registered. Abort. */
                if( xFuncHandlers[i].ucFunctionCode == 0 )
                {
                    break;
                }
                else if( xFuncHandlers[i].ucFunctionCode == ucFunctionCode )
                {
                    eException = xFuncHandlers[i].pxHandler( ucMBFrame, &usLength );
                    break;
                }
            }

            /* If the request was not sent to the broadcast address we
             * return a reply. */
            if( ucRcvAddress != MB_ADDRESS_BROADCAST )
            {
                if( eException != MB_EX_NONE )
                {
                    /* An exception occured. Build an error frame. */
                    usLength = 0;
                    ucMBFrame[usLength++] = ( UCHAR )( ucFunctionCode | MB_FUNC_ERROR );
                    ucMBFrame[usLength++] = eException;
                }
                eStatus = peMBFrameSendCur( ucMBAddress, ucMBFrame, usLength );
            }
            break;

        case EV_FRAME_SENT:
            break;
        }
    }
    return MB_ENOERR;
}

2. 功能码关联函数-eMBFunc-<2 功能码> <mbfuncholding.c>

层级2: <功能码>

提取:寄存器地址usRegAddress+寄存器数量usRegCount
以eMBFuncReadHoldingRegister为例

主要流程:
  1. 提取:寄存器地址usRegAddress
  2. 提取:寄存器数量usRegCount
  3. 调用寄存器处理函数
核心代码:
  1. 提取寄存器地址+数量
 usRegAddress = ( USHORT )( pucFrame[MB_PDU_FUNC_READ_ADDR_OFF] << 8 );
 usRegAddress |= ( USHORT )( pucFrame[MB_PDU_FUNC_READ_ADDR_OFF + 1] );
 usRegAddress++;

 usRegCount = ( USHORT )( pucFrame[MB_PDU_FUNC_READ_REGCNT_OFF] << 8 );
 usRegCount |= ( USHORT )( pucFrame[MB_PDU_FUNC_READ_REGCNT_OFF + 1] );
  1. 调用寄存器处理函数
    eMBRegHoldingCB( pucFrameCur, usRegAddress, usRegCount, MB_REG_READ );
源代码
eMBException
eMBFuncReadHoldingRegister( UCHAR * pucFrame, USHORT * usLen )
{
    USHORT          usRegAddress;
    USHORT          usRegCount;
    UCHAR          *pucFrameCur;

    eMBException    eStatus = MB_EX_NONE;
    eMBErrorCode    eRegStatus;

    if( *usLen == ( MB_PDU_FUNC_READ_SIZE + MB_PDU_SIZE_MIN ) )
    {
        usRegAddress = ( USHORT )( pucFrame[MB_PDU_FUNC_READ_ADDR_OFF] << 8 );
        usRegAddress |= ( USHORT )( pucFrame[MB_PDU_FUNC_READ_ADDR_OFF + 1] );
        usRegAddress++;

        usRegCount = ( USHORT )( pucFrame[MB_PDU_FUNC_READ_REGCNT_OFF] << 8 );
        usRegCount |= ( USHORT )( pucFrame[MB_PDU_FUNC_READ_REGCNT_OFF + 1] );

        /* Check if the number of registers to read is valid. If not
         * return Modbus illegal data value exception. 
         */
        if( ( usRegCount >= 1 ) && ( usRegCount <= MB_PDU_FUNC_READ_REGCNT_MAX ) )
        {
            /* Set the current PDU data pointer to the beginning. */
            pucFrameCur = &pucFrame[MB_PDU_FUNC_OFF];
            *usLen = MB_PDU_FUNC_OFF;

            /* First byte contains the function code. */
            *pucFrameCur++ = MB_FUNC_READ_HOLDING_REGISTER;
            *usLen += 1;

            /* Second byte in the response contain the number of bytes. */
            *pucFrameCur++ = ( UCHAR ) ( usRegCount * 2 );
            *usLen += 1;

            /* Make callback to fill the buffer. */
            eRegStatus = eMBRegHoldingCB( pucFrameCur, usRegAddress, usRegCount, MB_REG_READ );
            /* If an error occured convert it into a Modbus exception. */
            if( eRegStatus != MB_ENOERR )
            {
                eStatus = prveMBError2Exception( eRegStatus );
            }
            else
            {
                *usLen += usRegCount * 2;
            }
        }
        else
        {
            eStatus = MB_EX_ILLEGAL_DATA_VALUE;
        }
    }
    else
    {
        /* Can't be a valid request because the length is incorrect. */
        eStatus = MB_EX_ILLEGAL_DATA_VALUE;
    }
    return eStatus;
}

3. 寄存器处理回调函数-eMBRegHoldingCB- < 3 寄存器> <user_mb_app.c>

层级3:<寄存器>
回调函数在demo的port->user_mb_app.c
移植时可以参考着修改

主要流程:
  1. 读写判断:eMode
  2. 寄存器地址&数量:usAddress + usNRegs
核心代码:
  1. 读写判断
switch (eMode)
{
	case MB_REG_READ:
	...
	case MB_REG_WRITE:
	...
}
  1. 操作寄存器

 while (usNRegs > 0)
 {
     *pucRegBuffer++ = (UCHAR) (pusRegHoldingBuf[iRegIndex] >> 8);
     *pucRegBuffer++ = (UCHAR) (pusRegHoldingBuf[iRegIndex] & 0xFF);
     iRegIndex++;
     usNRegs--;
 }

while (usNRegs > 0)
{
    pusRegHoldingBuf[iRegIndex] = *pucRegBuffer++ << 8;
    pusRegHoldingBuf[iRegIndex] |= *pucRegBuffer++;
    iRegIndex++;
    usNRegs--;
}
源代码
eMBErrorCode eMBRegHoldingCB(UCHAR * pucRegBuffer, USHORT usAddress,
        USHORT usNRegs, eMBRegisterMode eMode)
{
    eMBErrorCode    eStatus = MB_ENOERR;
    USHORT          iRegIndex;
    USHORT *        pusRegHoldingBuf;
    USHORT          REG_HOLDING_START;
    USHORT          REG_HOLDING_NREGS;
    USHORT          usRegHoldStart;

    pusRegHoldingBuf = usSRegHoldBuf;
    REG_HOLDING_START = S_REG_HOLDING_START;
    REG_HOLDING_NREGS = S_REG_HOLDING_NREGS;
    usRegHoldStart = usSRegHoldStart;

    /* it already plus one in modbus function method. */
    usAddress--;

    if ((usAddress >= REG_HOLDING_START)
            && (usAddress + usNRegs <= REG_HOLDING_START + REG_HOLDING_NREGS))
    {
        iRegIndex = usAddress - usRegHoldStart;
        switch (eMode)
        {
        /* read current register values from the protocol stack. */
        case MB_REG_READ:
            while (usNRegs > 0)
            {
                *pucRegBuffer++ = (UCHAR) (pusRegHoldingBuf[iRegIndex] >> 8);
                *pucRegBuffer++ = (UCHAR) (pusRegHoldingBuf[iRegIndex] & 0xFF);
                iRegIndex++;
                usNRegs--;
            }
            break;

        /* write 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;
}

功能码关联函数清单

static xMBFunctionHandler xFuncHandlers[MB_FUNC_HANDLERS_MAX] = {
17 {MB_FUNC_OTHER_REPORT_SLAVEID, eMBFuncReportSlaveID},
4  {MB_FUNC_READ_INPUT_REGISTER, eMBFuncReadInputRegister},
3  {MB_FUNC_READ_HOLDING_REGISTER, eMBFuncReadHoldingRegister},
16 {MB_FUNC_WRITE_MULTIPLE_REGISTERS, eMBFuncWriteMultipleHoldingRegister},
6  {MB_FUNC_WRITE_REGISTER, eMBFuncWriteHoldingRegister},
23 {MB_FUNC_READWRITE_MULTIPLE_REGISTERS, eMBFuncReadWriteMultipleHoldingRegister},
1  {MB_FUNC_READ_COILS, eMBFuncReadCoils},
5  {MB_FUNC_WRITE_SINGLE_COIL, eMBFuncWriteCoil},
15 {MB_FUNC_WRITE_MULTIPLE_COILS, eMBFuncWriteMultipleCoils},
2  {MB_FUNC_READ_DISCRETE_INPUTS, eMBFuncReadDiscreteInputs},};

寄存器回调函数清单(用户)

//读字
eMBErrorCode eMBRegInputCB(UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs )
//读写字
eMBErrorCode eMBRegHoldingCB(UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs, eMBRegisterMode eMode)
//读写bit
eMBErrorCode eMBRegCoilsCB(UCHAR * pucRegBuffer, USHORT usAddress,USHORT usNCoils, eMBRegisterMode eMode)
//读bit
eMBErrorCode eMBRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNDiscrete )

位操作:01 eMBRegCoilsCB 砍掉写功能=> 02 eMBRegDiscreteCB
字操作:03eMBRegHoldingCB 砍掉写功能=> 04 eMBRegInputCB

在这里插入图片描述

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值