freemodbus多从机支持

 MODBUS文件包含 callback、modbus、port。

文件框架

callback文件下有回调函数文件夹 mbcallback.c

 

#include "mb.h"

#include "includes.h"
/* ----------------------- Defines ------------------------------------------*/
#define REG_INPUT_START 1000
#define REG_INPUT_NREGS 4

/* ----------------------- Static variables ---------------------------------*/
static USHORT   usRegInputStart = REG_INPUT_START;
static USHORT   usRegInputBuf[REG_INPUT_NREGS];
/* ----------------------- Defines --自保持寄存器-------------------------------*/
#define REG_HOLDING_START   ( 0x3000	 )  //起始地址,16位字宽,对应VB区
#define REG_HOLDING_NREGS   ( 20 )
/* ----------------------- Static variables ---自保持寄存器---------------------*/
static USHORT usRegHoldingBuf[REG_HOLDING_NREGS];
//*! 
extern HOLD_REG_t Hold_Reg;				//保持寄存器


eMBErrorCode
eMBRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs )
{
    eMBErrorCode    eStatus = MB_ENOERR;
    int             iRegIndex;

    if( ( usAddress >= REG_INPUT_START )
        && ( usAddress + usNRegs <= REG_INPUT_START + REG_INPUT_NREGS ) )
    {
        iRegIndex = ( int )( usAddress - usRegInputStart );
        while( usNRegs > 0 )
        {
            *pucRegBuffer++ = ( unsigned char )( usRegInputBuf[iRegIndex] >> 8 );
            *pucRegBuffer++ = ( unsigned char )( usRegInputBuf[iRegIndex] & 0xFF );
            iRegIndex++;
            usNRegs--;
        }
    }
    else
    {
        eStatus = MB_ENOREG;
    }

    return eStatus;
}

eMBErrorCode
eMBRegHoldingCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs, eMBRegisterMode eMode )
{
    eMBErrorCode    eStatus = MB_ENOERR;
    int             iRegIndex;
		/* Number of reception */
		u16 MultiWriteNum = usNRegs;
		/* 是否更新数据 holdreg 或者 */
		
		USHORT *StartAddr;
	
//		if(eMode == MB_REG_READ)
//		{
//			UpdataHoldReg();
//			StartAddr = (USHORT *)&Hold_Reg;
//		}
//		
//		if(eMode == MB_REG_WRITE)
//		{
//			StartAddr = (USHORT *)&Hold_Reg;
//		}		
		
    if( ( usAddress >= REG_HOLDING_START )
        && ( usAddress + usNRegs <= REG_HOLDING_START + REG_HOLDING_NREGS ) )
    {
        iRegIndex = ( int )( usAddress - REG_HOLDING_START );
        while( usNRegs > 0 )
        {
					
					if(MB_REG_READ == eMode){
						*pucRegBuffer++ = ( unsigned char )( usRegHoldingBuf[iRegIndex] >> 8 );
						*pucRegBuffer++ = ( unsigned char )( usRegHoldingBuf[iRegIndex] & 0xFF );
						
//						*pucRegBuffer++ = ( unsigned char )( StartAddr[iRegIndex] >> 8 );
//						*pucRegBuffer++ = ( unsigned char )( StartAddr[iRegIndex] & 0xFF );				
						
						iRegIndex++;
						usNRegs--;
					}
					else
					{
		                usRegHoldingBuf[iRegIndex] = *pucRegBuffer++ << 8;
		                usRegHoldingBuf[iRegIndex] |= *pucRegBuffer++;
						
//										StartAddr[iRegIndex] = *pucRegBuffer++ << 8;
//										StartAddr[iRegIndex] |= *pucRegBuffer++;				
						iRegIndex++;
						usNRegs--;				
					}
        }
/*				if(MB_REG_WRITE == eMode)
					eStatus = Set_num(usAddress);*/
					if(MB_REG_WRITE == eMode)
          {
            
          }
//						eStatus = Set_num(usAddress - 1,MultiWriteNum);
    }
    else
    {
        eStatus = MB_ENOREG;
    }

    return eStatus;
}


eMBErrorCode
eMBRegCoilsCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNCoils, eMBRegisterMode eMode )
{
    ( void )pucRegBuffer;
    ( void )usAddress;
    ( void )usNCoils;
    ( void )eMode;
    return MB_ENOREG;
}

eMBErrorCode
eMBRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNDiscrete )
{
    ( void )pucRegBuffer;
    ( void )usAddress;
    ( void )usNDiscrete;
    return MB_ENOREG;
}

modbus下文件夹有 ascii、functions、include、rtu、tcp文件夹

mbrtu.c代码如下:

/* ----------------------- Platform includes --------------------------------*/
#include "port.h"

/* ----------------------- Modbus includes ----------------------------------*/
#include "mb.h"
#include "mbrtu.h"
#include "mbframe.h"

#include "mbport.h"
#include "mbcrc.h"

#include <includes.h>

/* !!! 满足RTU 多从机 2018/9/20 15:59:14  */
void xMBPortEventInit_new(MB_RTU_DCB *const pMBRTU)
{
	pMBRTU->xEventInQueue = FALSE;
}
void xMBPortEventPost_new(MB_RTU_DCB *const pMBRTU,eMBEventType eEvent )
{
    pMBRTU->xEventInQueue = TRUE;
    pMBRTU->eQueuedEvent = eEvent;	
}
BOOL xMBPortEventGet_new(MB_RTU_DCB  *const pMBRTU,eMBEventType * eEvent)
{
    if(pMBRTU->xEventInQueue){
		*eEvent = pMBRTU->eQueuedEvent;
        pMBRTU->xEventInQueue = FALSE;
		return TRUE;
    }
    else
		return FALSE;	
}



void xMBRTUReceiveFSM(MB_RTU_DCB *const pMBRTU)
{
    UCHAR           ucByte;

    /* Always read the character. */
    pMBRTU->ucPort->pvMBPortSerialGetByte( ( UCHAR * ) & ucByte );

    switch ( pMBRTU->eRcvState )
    {
        /* If we have received a character in the init state we have to
         * wait until the frame is finished.
         */
    case STATE_RX_INIT:
		pMBRTU->ucPort->pvMBPortTimersEnable(T3_5);
        break;

        /* In the error state we wait until all characters in the
         * damaged frame are transmitted.
         */
    case STATE_RX_ERROR:
		pMBRTU->ucPort->pvMBPortTimersEnable(T3_5);
        break;

        /* In the idle state we wait for a new character. If a character
         * is received the t1.5 and t3.5 timers are started and the
         * receiver is in the state STATE_RX_RECEIVCE.
         */
    case STATE_RX_IDLE:
        pMBRTU->ucBufferCount = 0;
        pMBRTU->ucBuffer[pMBRTU->ucBufferCount++] = ucByte;
        pMBRTU->eRcvState = STATE_RX_RCV;

        /* Enable t3.5 timers. */
		pMBRTU->ucPort->pvMBPortTimersEnable(T3_5);
        break;

        /* We are currently receiving a frame. Reset the timer after
         * every character received. If more than the maximum possible
         * number of bytes in a modbus frame is received the frame is
         * ignored.
         */
    case STATE_RX_RCV:
        if( pMBRTU->ucBufferCount < MB_SER_PDU_SIZE_MAX )
        {
            pMBRTU->ucBuffer[pMBRTU->ucBufferCount++] = ucByte;
        }
        else
        {
            pMBRTU->eRcvState = STATE_RX_ERROR;
        }
		pMBRTU->ucPort->pvMBPortTimersEnable(T3_5);
        break;
    }
}

void xMBRTUTransmitFSM(MB_RTU_DCB *const pMBRTU)
{
    switch ( pMBRTU->eSndState )
    {
        /* We should not get a transmitter event if the transmitter is in
         * idle state.  */
    case STATE_TX_IDLE:
        /* enable receiver/disable transmitter. */
		pMBRTU->ucPort->pvMBPortSerialEnable( TRUE, FALSE );
        break;

    case STATE_TX_XMIT:
        /* check if we are finished. */
        if( pMBRTU->ucBufferCount != 0 )
        {
			pMBRTU->ucPort->pvMBPortSerialPutByte( ( CHAR )*pMBRTU->pucBuffer );
            pMBRTU->pucBuffer++;  /* next byte in sendbuffer. */
            pMBRTU->ucBufferCount--;
        }
        else
        {
			xMBPortEventPost_new(pMBRTU,EV_FRAME_SENT );
            /* Disable transmitter. This prevents another transmit buffer
             * empty interrupt. */
			pMBRTU->ucPort->pvMBPortSerialEnable( TRUE, FALSE );
            pMBRTU->eSndState = STATE_TX_IDLE;
        }
        break;
    }
}

eMBErrorCode 
eMBRTUReceive(MB_RTU_DCB *const pMBRTU, UCHAR * pucRcvAddress, UCHAR ** pucFrame, USHORT * pusLength )
{
	eMBErrorCode    eStatus= MB_ENOERR;
    pMBRTU->ucPort->pvMBEnterCriticalSection();
    /* Length and CRC check */
    if( ( pMBRTU->ucBufferCount >= MB_SER_PDU_SIZE_MIN )
        && ( usMBCRC16( ( UCHAR * )pMBRTU->ucBuffer, pMBRTU->ucBufferCount ) == 0 ) )
    {
        /* Save the address field. All frames are passed to the upper layed
         * and the decision if a frame is used is done there.
         */
        *pucRcvAddress = pMBRTU->ucBuffer[MB_SER_PDU_ADDR_OFF];

//         /* Total length of Modbus-PDU is Modbus-Serial-Line-PDU minus
//          * size of address field and CRC checksum.
//          */
//         *pusLength = ( USHORT )( pMBRTU->ucBufferCount - MB_SER_PDU_PDU_OFF - MB_SER_PDU_SIZE_CRC );

//         /* Return the start of the Modbus PDU to the caller. */
//         *pucFrame = ( UCHAR * ) & pMBRTU->ucBuffer[MB_SER_PDU_PDU_OFF];
    }
    else
    {
        eStatus = MB_EIO;
    }

    pMBRTU->ucPort->pvMBExitCriticalSection();
    return eStatus;
}

eMBErrorCode
eMBRTUSend(MB_RTU_DCB *const pMBRTU,const UCHAR * pucFrame, USHORT usLength )
{
    eMBErrorCode    eStatus = MB_ENOERR;
    USHORT          usCRC16;

    pMBRTU->ucPort->pvMBEnterCriticalSection();

    /* Check if the receiver is still in idle state. If not we where to
     * slow with processing the received frame and the master sent another
     * frame on the network. We have to abort sending the frame.
     */
    if( pMBRTU->eRcvState == STATE_RX_IDLE )
    {
        /* First byte before the Modbus-PDU is the slave address. */
        pMBRTU->pucBuffer = ( UCHAR * ) pucFrame - 1;
        pMBRTU->ucBufferCount = 1;

        /* Now copy the Modbus-PDU into the Modbus-Serial-Line-PDU. */
        pMBRTU->pucBuffer[MB_SER_PDU_ADDR_OFF] = pMBRTU->ucMBAddress;
        pMBRTU->ucBufferCount += usLength;

        /* Calculate CRC16 checksum for Modbus-Serial-Line-PDU. */
        usCRC16 = usMBCRC16( ( UCHAR * ) pMBRTU->pucBuffer, pMBRTU->ucBufferCount );
        pMBRTU->ucBuffer[pMBRTU->ucBufferCount++] = 
  • 3
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值