[应用相关]

uC-Modbus-for-RT-Thread-master

[复制链接]
649|5
手机看帖
扫描二维码
随时随地手机跟帖
ADZ2016|  楼主 | 2021-3-23 08:01 | 显示全部楼层 |阅读模式
uC-Modbus-for-RT-Thread-master

uC-Modbus-for-RT-Thread-master.zip

46.28 KB

使用特权

评论回复
ADZ2016|  楼主 | 2021-3-23 08:02 | 显示全部楼层
mb.c
/*
*********************************************************************************************************
*                                              uC/Modbus
*                                       The Embedded Modbus Stack
*
*                    Copyright 2003-2020 Silicon Laboratories Inc. www.silabs.com
*
*                                 SPDX-License-Identifier: APACHE-2.0
*
*               This software is subject to an open source license and is distributed by
*                Silicon Laboratories Inc. pursuant to the terms of the Apache License,
*                    Version 2.0 available at www.apache.org/licenses/LICENSE-2.0.
*
*********************************************************************************************************
*/

/*
*********************************************************************************************************
*                                        uC/MODBUS Source Code
*
* Filename : mb.c
* Version  : V2.14.00
*********************************************************************************************************
*/

/*
*********************************************************************************************************
*                                            INCLUDE FILES
*********************************************************************************************************
*/

#define    MB_MODULE
#include  "mb.h"


/*
*********************************************************************************************************
*                                            LOCAL DEFINES
*********************************************************************************************************
*/


/*
*********************************************************************************************************
*                                           LOCAL CONSTANTS
*********************************************************************************************************
*/


/*
*********************************************************************************************************
*                                          LOCAL DATA TYPES
*********************************************************************************************************
*/


/*
*********************************************************************************************************
*                                            LOCAL TABLES
*********************************************************************************************************
*/


/*
*********************************************************************************************************
*                                       LOCAL GLOBAL VARIABLES
*********************************************************************************************************
*/

                                                                /* RAM Storage Requirements.                            */
#if (MODBUS_CFG_RTU_EN == DEF_ENABLED)
CPU_INT32U  const  MB_TotalRAMSize = sizeof(MB_RTU_Freq)
                                   + sizeof(MB_RTU_TmrCtr)
                                   + sizeof(MB_ChTbl);
#else
CPU_INT32U  const  MB_TotalRAMSize = sizeof(MB_ChTbl);
#endif

CPU_INT16U  const  MB_ChSize       = sizeof(MODBUS_CH);


/*
*********************************************************************************************************
*                                      LOCAL FUNCTION PROTOTYPES
*********************************************************************************************************
*/


/*
*********************************************************************************************************
*                                     LOCAL CONFIGURATION ERRORS
*********************************************************************************************************
*/


/*
*********************************************************************************************************
*                                               MB_Init()
*
* Description : Handle either Modbus ASCII or Modbus RTU received packets.
*
* Argument(s) : freq       Specifies the Modbus RTU timer frequency (in Hz)
*
* Return(s)   : none.
*
* Caller(s)   : Application
*
* Note(s)     : none.
*********************************************************************************************************
*/

void  MB_Init (CPU_INT32U freq)
{
    CPU_INT08U   ch;
    MODBUS_CH   *pch;

#if (MODBUS_CFG_RTU_EN == DEF_ENABLED)
    MB_RTU_Freq = freq;                                         /* Save the RTU frequency                             */
#endif

    pch         = &MB_ChTbl[0];                                 /* Save Modbus channel number in data structure       */
    for (ch = 0; ch < MODBUS_CFG_MAX_CH; ch++) {                /* Initialize default values                          */
        pch->Ch            = ch;
        pch->NodeAddr      = 1;
        pch->MasterSlave   = MODBUS_SLAVE;                      /* Channel defaults to MODBUS_SLAVE mode              */
        pch->Mode          = MODBUS_MODE_ASCII;
        pch->RxBufByteCtr  = 0;
        pch->RxBufPtr      = &pch->RxBuf[0];
        pch->WrEn          = MODBUS_WR_EN;
        pch->WrCtr         = 0;
#if (MODBUS_CFG_RTU_EN == DEF_ENABLED)
        pch->RTU_TimeoutEn = DEF_TRUE;
#endif

#if (MODBUS_CFG_SLAVE_EN == DEF_ENABLED)  && \
    (MODBUS_CFG_FC08_EN  == DEF_ENABLED)
        MBS_StatInit(pch);
#endif
        pch++;
    }

    MB_ChCtr = 0;

    MB_OS_Init();                                               /* Initialize OS interface functions                  */


#if (MODBUS_CFG_RTU_EN == DEF_ENABLED)                         /* MODBUS 'RTU' Initialization                         */
    MB_RTU_TmrInit();
#else
    (void)&freq;
#endif
}

/*
*********************************************************************************************************
*                                               MB_Exit()
*
* Description : This function is called to terminate all Modbus communications
*
* Argument(s) : none.
*
* Return(s)   : none.
*
* Caller(s)   : Application.
*
* Note(s)     : none.
*********************************************************************************************************
*/

void  MB_Exit (void)
{
#if (MODBUS_CFG_RTU_EN == DEF_ENABLED)
    MB_RTU_TmrExit();                                           /* Stop the RTU timer interrupts                      */
#endif

    MB_CommExit();                                              /* Disable all communications                         */

    MB_OS_Exit();                                               /* Stop RTOS services                                 */
}


/*
*********************************************************************************************************
*                                              MB_CfgCh()
*
* Description : This function must be called after calling MB_Init() to initialize each of the Modbus
*               channels in your system.
*
* Argument(s) : node_addr     is the Modbus node address that the channel is assigned to.
*
*               master_slave  specifies whether the channel is a MODBUS_MASTER or a MODBUS_SLAVE
*
*               rx_timeout    amount of time Master will wait for a response from the slave.
*
*               modbus_mode   specifies the type of modbus channel.  The choices are:
*                             MODBUS_MODE_ASCII
*                             MODBUS_MODE_RTU
*
*               port_nbr      is the UART port number associated with the channel
*
*               baud          is the desired baud rate
*
*               parity        is the UART's parity setting:
*                             MODBUS_PARITY_NONE
*                             MODBUS_PARITY_ODD
*                             MODBUS_PARITY_EVEN
*
*               bits          UART's number of bits (7 or 8)
*
*               stops         Number of stops bits (1 or 2)
*
*               wr_en         This argument determines whether a Modbus WRITE request will be accepted.
*                             The choices are:
*                             MODBUS_WR_EN
*                             MODBUS_WR_DIS
*
* Return(s)   : none.
*
* Caller(s)   : Application.
*
* Note(s)     : none.
*********************************************************************************************************
*/

MODBUS_CH  *MB_CfgCh (CPU_INT08U  node_addr,
                      CPU_INT08U  master_slave,
                      CPU_INT32U  rx_timeout,
                      CPU_INT08U  modbus_mode,
                      CPU_INT08U  port_nbr,
                      CPU_INT32U  baud,
                      CPU_INT08U  bits,
                      CPU_INT08U  parity,
                      CPU_INT08U  stops,
                      CPU_INT08U  wr_en)
{
    MODBUS_CH   *pch;
#if (MODBUS_CFG_RTU_EN == DEF_ENABLED)
    CPU_INT16U   cnts;
#endif

    if (MB_ChCtr < MODBUS_CFG_MAX_CH) {
        pch = &MB_ChTbl[MB_ChCtr];
        MB_MasterTimeoutSet(pch, rx_timeout);
        MB_NodeAddrSet(pch, node_addr);
        MB_ModeSet(pch, master_slave, modbus_mode);
        MB_WrEnSet(pch, wr_en);
        MB_ChToPortMap(pch, port_nbr);
        MB_CommPortCfg(pch, port_nbr, baud, bits, parity, stops);
#if (MODBUS_CFG_RTU_EN == DEF_ENABLED)
        if (pch->MasterSlave == MODBUS_MASTER) {
            pch->RTU_TimeoutEn = DEF_FALSE;
        }

        cnts = ((CPU_INT32U)MB_RTU_Freq * 5L * 10L) / baud;     /* Freq * 5 char * 10 bits/char * 1/BaudRate          */
        if (cnts <= 1) {
            cnts = 2;
        }
        pch->RTU_TimeoutCnts = cnts;
        pch->RTU_TimeoutCtr  = cnts;
#endif
        MB_ChCtr++;
        return (pch);
    } else {
        return ((MODBUS_CH *)0);
    }
}

/*
*********************************************************************************************************
*                                         MB_MasterTimeoutSet()
*
* Description : This function is called to change the operating mode of a Modbus channel.
*
* Argument(s) : pch          is a pointer to the Modbus channel to change
*
*               modbus_mode  specifies the type of modbus channel.  The choices are:
*                            MODBUS_MODE_ASCII
*                            MODBUS_MODE_RTU
*
* Return(s)   : none.
*
* Caller(s)   : Application.
*
* Note(s)     : none.
*********************************************************************************************************
*/

void  MB_MasterTimeoutSet (MODBUS_CH  *pch,
                           CPU_INT32U  timeout)
{
    if (pch != (MODBUS_CH *)0) {
        pch->RxTimeout = timeout;
    }
}

/*
*********************************************************************************************************
*                                             MB_ModeSet()
*
* Description : This function is called to change the operating mode of a Modbus channel.
*
* Argument(s) : pch          is a pointer to the Modbus channel to change
*
*               modbus_mode  specifies the type of modbus channel.  The choices are:
*                            MODBUS_MODE_ASCII
*                            MODBUS_MODE_RTU
*
* Return(s)   : none.
*
* Caller(s)   : Application.
*
* Note(s)     : none.
*********************************************************************************************************
*/

void  MB_ModeSet (MODBUS_CH  *pch,
                  CPU_INT08U  master_slave,
                  CPU_INT08U  mode)
{
    if (pch != (MODBUS_CH *)0) {

        switch (master_slave) {
            case MODBUS_MASTER:
                 pch->MasterSlave = MODBUS_MASTER;
                 break;

            case MODBUS_SLAVE:
            default:
                 pch->MasterSlave = MODBUS_SLAVE;
                 break;
        }

        switch (mode) {
#if (MODBUS_CFG_ASCII_EN == DEF_ENABLED)
            case MODBUS_MODE_ASCII:
                 pch->Mode = MODBUS_MODE_ASCII;
                 break;
#endif

#if (MODBUS_CFG_RTU_EN == DEF_ENABLED)
            case MODBUS_MODE_RTU:
                 pch->Mode = MODBUS_MODE_RTU;
                 break;
#endif

            default:
#if (MODBUS_CFG_RTU_EN == DEF_ENABLED)
                 pch->Mode = MODBUS_MODE_RTU;
#else
                 pch->Mode = MODBUS_MODE_ASCII;
#endif
                 break;
        }
    }
}

/*
*********************************************************************************************************
*                                           MB_NodeAddrSet()
*
* Description : This function is called to change the Modbus node address that the channel will respond to.
*
* Argument(s) : pch          is a pointer to the Modbus channel to change
*
*               node_addr    is the Modbus node address that the channel is assigned to.
*
* Return(s)   : none.
*
* Caller(s)   : Application.
*
* Note(s)     : none.
*********************************************************************************************************
*/

void  MB_NodeAddrSet (MODBUS_CH  *pch,
                      CPU_INT08U  node_addr)
{
    if (pch != (MODBUS_CH *)0) {
        pch->NodeAddr = node_addr;
    }
}

/*
*********************************************************************************************************
*                                             MB_WrEnSet()
*
* Description : This function is called to enable or disable write accesses to the data.
*
* Argument(s) : ch           is the Modbus channel to change
*
*               wr_en        This argument determines whether a Modbus WRITE request will be accepted.
*                            The choices are:
*                            MODBUS_WR_EN
*                            MODBUS_WR_DIS
*
* Return(s)   : none.
*
* Caller(s)   : Application.
*
* Note(s)     : none.
*********************************************************************************************************
*/

void  MB_WrEnSet (MODBUS_CH  *pch,
                  CPU_INT08U  wr_en)
{
    if (pch != (MODBUS_CH *)0) {
        pch->WrEn = wr_en;
    }
}


/*
*********************************************************************************************************
*                                           MB_ChToPortMap()
*
* Description : This function is called to change the physical port number of the Modbus channel.
*
* Argument(s) : pch          is a pointer to the Modbus channel to change
*
*               port_nbr     This argument determines the physical port number of the Modbus channel
*
* Return(s)   : none.
*
* Caller(s)   : Application.
*
* Note(s)     : none.
*********************************************************************************************************
*/

void  MB_ChToPortMap (MODBUS_CH  *pch,
                      CPU_INT08U  port_nbr)
{
    if (pch != (MODBUS_CH *)0) {
        pch->PortNbr = port_nbr;
    }
}


/*
*********************************************************************************************************
*                                              MB_RxByte()
*
* Description : A byte has been received from a serial port.  We just store it in the buffer for processing
*               when a complete packet has been received.
*
* Argument(s) : pch         Is a pointer to the Modbus channel's data structure.
*
*               rx_byte     Is the byte received.
*
* Return(s)   : none.
*
* Caller(s)   : MB_CommRxTxISR_Handler().
*
* Note(s)     : none.
*********************************************************************************************************
*/

void  MB_RxByte (MODBUS_CH  *pch,
                 CPU_INT08U  rx_byte)
{
    switch (pch->Mode) {
#if (MODBUS_CFG_ASCII_EN == DEF_ENABLED)
        case MODBUS_MODE_ASCII:
             MB_ASCII_RxByte(pch, rx_byte & 0x7F);
             break;
#endif

#if (MODBUS_CFG_RTU_EN == DEF_ENABLED)
        case MODBUS_MODE_RTU:
             MB_RTU_RxByte(pch, rx_byte);
             break;
#endif

        default:
             break;
    }
}


/*
*********************************************************************************************************
*                                              MB_RxTask()
*
* Description : This function is called when a packet needs to be processed.
*
* Argument(s) : pch         Is a pointer to the Modbus channel's data structure.
*
* Return(s)   : none.
*
* Caller(s)   : MB_OS_RxTask().
*
* Note(s)     : none.
*********************************************************************************************************
*/

void  MB_RxTask (MODBUS_CH *pch)
{
#if (MODBUS_CFG_SLAVE_EN == DEF_ENABLED)
    if (pch != (MODBUS_CH *)0) {
        if (pch->MasterSlave == MODBUS_SLAVE) {
            MBS_RxTask(pch);
        }
    }
#endif
}


/*
*********************************************************************************************************
*                                           MB_ASCII_RxByte()
*
* Description : A byte has been received from a serial port.  We just store it in the buffer for processing
*               when a complete packet has been received.
*
* Argument(s) : pch         Is a pointer to the Modbus channel's data structure.
*
*               rx_byte     Is the byte received.
*
* Return(s)   : none.
*
* Caller(s)   : MB_RxByte().
*
* Return(s)   : none.
*********************************************************************************************************
*/

#if (MODBUS_CFG_ASCII_EN == DEF_ENABLED)
void  MB_ASCII_RxByte (MODBUS_CH  *pch,
                       CPU_INT08U  rx_byte)
{
    CPU_INT08U   node_addr;
    CPU_INT08U  *phex;


    pch->RxCtr++;                                               /* Increment the number of bytes received             */
    if (rx_byte == ':') {                                       /* Is it the start of frame character?                */
        pch->RxBufPtr     = &pch->RxBuf[0];                     /* Yes, Restart a new frame                           */
        pch->RxBufByteCtr = 0;
    }
    if (pch->RxBufByteCtr < MODBUS_CFG_BUF_SIZE) {              /* No, add received byte to buffer                    */
        *pch->RxBufPtr++  = rx_byte;
        pch->RxBufByteCtr++;                                    /* Increment byte counter to see if we have Rx ...    */
                                                                /* ... activity                                       */
    }
    if (rx_byte == MODBUS_ASCII_END_FRAME_CHAR2) {              /* See if we received a complete ASCII frame          */
        phex      = &pch->RxBuf[1];
        node_addr = MB_ASCII_HexToBin(phex);
        if ((node_addr == pch->NodeAddr) ||                     /* Is the address for us?                             */
            (node_addr == 0)) {                                 /* ... or a 'broadcast'?                              */
            MB_OS_RxSignal(pch);                                /* Yes, Let task handle reply                         */
        } else {
            pch->RxBufPtr     = &pch->RxBuf[0];                 /* No,  Wipe out anything, we have to re-synchronize. */
            pch->RxBufByteCtr = 0;
        }
    }
}
#endif


/*
*********************************************************************************************************
*                                             MB_ASCII_Rx()
*
* Description : Parses and converts an ASCII style message into a Modbus frame.  A check is performed
*               to verify that the Modbus packet is valid.
*
* Argument(s) : pch         Is a pointer to the Modbus channel's data structure.
*
* Return(s)   : DEF_TRUE        If all checks pass.
*               DEF_FALSE       If any checks fail.
*
* Caller(s)   : MBM_RxReply().
*
* Note(s)     : none.
*********************************************************************************************************
*/

#if (MODBUS_CFG_ASCII_EN == DEF_ENABLED)
CPU_BOOLEAN  MB_ASCII_Rx (MODBUS_CH  *pch)
{
    CPU_INT08U  *pmsg;
    CPU_INT08U  *prx_data;
    CPU_INT16U   rx_size;


    pmsg      = &pch->RxBuf[0];
    rx_size   =  pch->RxBufByteCtr;
    prx_data  = &pch->RxFrameData[0];
    if ((rx_size & 0x01)                                     &&        /* Message should have an ODD nbr of bytes.        */
        (rx_size            > MODBUS_ASCII_MIN_MSG_SIZE)     &&        /* Check if message is long enough                 */
        (pmsg[0]           == MODBUS_ASCII_START_FRAME_CHAR) &&        /* Check the first char.                           */
        (pmsg[rx_size - 2] == MODBUS_ASCII_END_FRAME_CHAR1)  &&        /* Check the last two.                             */
        (pmsg[rx_size - 1] == MODBUS_ASCII_END_FRAME_CHAR2)) {
        rx_size               -= 3;                                    /* Take away for the ':', CR, and LF               */
        pmsg++;                                                        /* Point past the ':' to the address.              */
        pch->RxFrameNDataBytes = 0;                                    /* Get the data from the message                   */
        while (rx_size > 2) {
            *prx_data++  = MB_ASCII_HexToBin(pmsg);
            pmsg        += 2;
            rx_size     -= 2;
            pch->RxFrameNDataBytes++;                                  /* Increment the number of Modbus packets received */
        }
        pch->RxFrameNDataBytes -= 2;                                   /* Subtract the Address and function code          */
        pch->RxFrameCRC         = (CPU_INT16U)MB_ASCII_HexToBin(pmsg); /* Extract the message's LRC                       */
        return (DEF_TRUE);
    } else {
        return (DEF_FALSE);
    }
}
#endif


/*
*********************************************************************************************************
*                                             MB_ASCII_Tx()
*
* Description : The format of the message is ASCII.  The actual information is taken from the given
*               MODBUS frame.
*
* Argument(s) : pch      Is a pointer to the Modbus channel's data structure.
*
* Return(s)   : none.
*
* Caller(s)   : MBM_TxCmd(),
*               MBS_ASCII_Task().
*
* Note(s)     : none.
*********************************************************************************************************
*/

#if (MODBUS_CFG_ASCII_EN == DEF_ENABLED)
void  MB_ASCII_Tx (MODBUS_CH  *pch)
{
    CPU_INT08U  *ptx_data;
    CPU_INT08U  *pbuf;
    CPU_INT16U   i;
    CPU_INT16U   tx_bytes;
    CPU_INT08U   lrc;


    ptx_data = &pch->TxFrameData[0];
    pbuf     = &pch->TxBuf[0];
    *pbuf++  = MODBUS_ASCII_START_FRAME_CHAR;                   /* Place the start-of-frame character into output buffer  */
    pbuf     = MB_ASCII_BinToHex(*ptx_data++,
                                 pbuf);
    pbuf     = MB_ASCII_BinToHex(*ptx_data++,
                                 pbuf);
    tx_bytes = 5;
    i        = (CPU_INT08U)pch->TxFrameNDataBytes;              /* Transmit the actual data                               */
    while (i > 0) {
        pbuf      = MB_ASCII_BinToHex(*ptx_data++,
                                      pbuf);
        tx_bytes += 2;
        i--;
    }
    lrc               = MB_ASCII_TxCalcLRC(pch,                 /* Compute outbound packet LRC                            */
                                           tx_bytes);
    pbuf              = MB_ASCII_BinToHex(lrc,                  /* Add the LRC checksum in the packet                     */
                                          pbuf);
    *pbuf++           = MODBUS_ASCII_END_FRAME_CHAR1;           /* Add 1st end-of-frame character (0x0D) to output buffer */
    *pbuf++           = MODBUS_ASCII_END_FRAME_CHAR2;           /* Add 2nd end-of-frame character (0x0A) to output buffer */
    tx_bytes         += 4;
    pch->TxFrameCRC   = (CPU_INT16U)lrc;                        /* Save the computed LRC into the channel                 */
    pch->TxBufByteCtr = tx_bytes;                               /* Update the total number of bytes to send               */
    MB_Tx(pch);                                                 /* Send it out the communication driver.                  */
}
#endif


/*
*********************************************************************************************************
*                                            MB_RTU_RxByte()
*
* Description : A byte has been received from a serial port.  We just store it in the buffer for processing
*               when a complete packet has been received.
*
* Argument(s) : pch         Is a pointer to the Modbus channel's data structure.
*
*               rx_byte     Is the byte received.
*
* Return(s)   : none.
*
* Caller(s)   : MB_RxByte().
*
* Note(s)     : none.
*********************************************************************************************************
*/

#if (MODBUS_CFG_RTU_EN == DEF_ENABLED)
void  MB_RTU_RxByte (MODBUS_CH  *pch,
                     CPU_INT08U  rx_byte)
{
    MB_RTU_TmrReset(pch);                                       /* Reset the timeout timer on a new character             */
#if (MODBUS_CFG_MASTER_EN == DEF_ENABLED)
    if (pch->MasterSlave == MODBUS_MASTER) {
        pch->RTU_TimeoutEn = MODBUS_TRUE;
    }
#endif
    if (pch->RxBufByteCtr < MODBUS_CFG_BUF_SIZE) {              /* No, add received byte to buffer                        */
        pch->RxCtr++;                                           /* Increment the number of bytes received                 */
        *pch->RxBufPtr++ = rx_byte;
        pch->RxBufByteCtr++;                                    /* Increment byte counter to see if we have Rx activity   */
    }
}
#endif


/*
*********************************************************************************************************
*                                              MB_RTU_Rx()
*
* Description : Parses a Modbus RTU packet and processes the request if the packet is valid.
*
* Argument(s) : pch         Is a pointer to the Modbus channel's data structure.
*
* Return(s)   : DEF_TRUE    If all checks pass.
*               DEF_FALSE   If any checks fail.
*
* Caller(s)   : MBM_RxReply(),
*               MBS_RTU_Task().
*
* Note(s)     : none.
*********************************************************************************************************
*/

#if (MODBUS_CFG_RTU_EN == DEF_ENABLED)
CPU_BOOLEAN  MB_RTU_Rx (MODBUS_CH  *pch)
{
    CPU_INT08U  *prx_data;
    CPU_INT08U  *pmsg;
    CPU_INT16U   rx_size;
    CPU_INT16U   crc;


    pmsg    = &pch->RxBuf[0];
    rx_size =  pch->RxBufByteCtr;
    if (rx_size >= MODBUS_RTU_MIN_MSG_SIZE) {         /* Is the message long enough?                        */
        if (rx_size <= MODBUS_CFG_BUF_SIZE) {
            prx_data    = &pch->RxFrameData[0];
            *prx_data++ = *pmsg++;                    /* Transfer the node address                          */
            rx_size--;

            *prx_data++ = *pmsg++;                    /* Transfer the function code                         */
            rx_size--;

            pch->RxFrameNDataBytes = 0;               /* Transfer the data                                  */
            while (rx_size > 2) {
                *prx_data++ = *pmsg++;
                pch->RxFrameNDataBytes++;
                rx_size--;
            }

            crc              = (CPU_INT16U)*pmsg++;   /* Transfer the CRC over.  It's LSB first, then MSB.  */
            crc             += (CPU_INT16U)*pmsg << 8;
            pch->RxFrameCRC  = crc;
            return (DEF_TRUE);
        } else {
            return (DEF_FALSE);
        }
    } else {
        return (DEF_FALSE);
    }
}
#endif


/*
*********************************************************************************************************
*                                              MB_RTU_Tx()
*
* Description : A MODBUS message is formed into a buffer and sent to the appropriate communication port.
*               The actual reply is taken from the given MODBUS Frame.
*
* Argument(s) : pch      Is a pointer to the Modbus channel's data structure.
*
* Return(s)   : none.
*
* Caller(s)   : MBM_TxCmd(),
*               MBS_RTU_Task().
*
* Note(s)     : none.
*********************************************************************************************************
*/

#if (MODBUS_CFG_RTU_EN == DEF_ENABLED)
void  MB_RTU_Tx (MODBUS_CH  *pch)
{
    CPU_INT08U  *ptx_data;
    CPU_INT08U  *pbuf;
    CPU_INT08U   i;
    CPU_INT16U   tx_bytes;
    CPU_INT16U   crc;


    tx_bytes  = 0;
    pbuf      = &pch->TxBuf[0];                                    /* Point to the beginning of the output buffer.             */
    ptx_data  = &(pch->TxFrameData[0]);
    i         = (CPU_INT08U)pch->TxFrameNDataBytes + 2;            /* Include the actual data in the buffer                    */
    while (i > 0) {
        *pbuf++ = *ptx_data++;
        tx_bytes++;
        i--;
    }
    crc               = MB_RTU_TxCalcCRC(pch);
    *pbuf++           = (CPU_INT08U)(crc & 0x00FF);                /* Add in the CRC checksum.  Low byte first!                */
    *pbuf             = (CPU_INT08U)(crc >> 8);
    tx_bytes         += 2;
    pch->TxFrameCRC   = crc;                                       /* Save the calculated CRC in the channel                   */
    pch->TxBufByteCtr = tx_bytes;

    MB_Tx(pch);                                                    /* Send it out the communication driver.                    */
}
#endif


/*
*********************************************************************************************************
*                                           MB_RTU_TmrReset()
*
* Description : This function is called when a byte a received and thus, we reset the RTU timeout timer value
*               indicating that we are not done receiving a complete RTU packet.
*
* Argument(s) : none.
*
* Return(s)   : none.
*
* Caller(s)   : MB_RTU_TmrResetAll().
*
* Note(s)     : none.
*********************************************************************************************************
*/

#if (MODBUS_CFG_RTU_EN == DEF_ENABLED)
void  MB_RTU_TmrReset (MODBUS_CH  *pch)
{
    pch->RTU_TimeoutCtr = pch->RTU_TimeoutCnts;
}
#endif


/*
*********************************************************************************************************
*                                           MB_RTU_TmrResetAll()
*
* Description : This function is used to reset all the RTU timers for all Modbus channels.
*
* Argument(s) : none.
*
* Return(s)   : none.
*
* Caller(s)   : MB_RTU_TmrInit().
*
* Note(s)     : none.
*********************************************************************************************************
*/

#if (MODBUS_CFG_RTU_EN == DEF_ENABLED)
void  MB_RTU_TmrResetAll (void)
{
    CPU_INT08U   ch;
    MODBUS_CH   *pch;


    pch = &MB_ChTbl[0];
    for (ch = 0; ch < MODBUS_CFG_MAX_CH; ch++) {
        if (pch->Mode == MODBUS_MODE_RTU) {
            MB_RTU_TmrReset(pch);
        }
        pch++;
    }
}
#endif


/*
*********************************************************************************************************
*                                           MB_RTU_TmrUpdate()
*
* Description : This function is called when the application supplied RTU framing timer expires.
*
* Argument(s) : none.
*
* Return(s)   : none.
*
* Caller(s)   : MB_RTU_TmrISR_Handler().
*
* Note(s)     : none.
*********************************************************************************************************
*/

#if (MODBUS_CFG_RTU_EN == DEF_ENABLED)
void  MB_RTU_TmrUpdate (void)
{
    CPU_INT08U   ch;
    MODBUS_CH   *pch;


    pch = &MB_ChTbl[0];
    for (ch = 0; ch < MODBUS_CFG_MAX_CH; ch++) {
        if (pch->Mode == MODBUS_MODE_RTU) {
            if (pch->RTU_TimeoutEn == DEF_TRUE) {
                if (pch->RTU_TimeoutCtr > 0) {
                    pch->RTU_TimeoutCtr--;
                    if (pch->RTU_TimeoutCtr == 0) {
#if (MODBUS_CFG_RTU_EN == DEF_ENABLED)
                        if (pch->MasterSlave == MODBUS_MASTER) {
                            pch->RTU_TimeoutEn = DEF_FALSE;
                        }
#endif
                        MB_OS_RxSignal(pch);          /* RTU Timer expired for this Modbus channel         */
                    }
                }
            } else {
                pch->RTU_TimeoutCtr = pch->RTU_TimeoutCnts;
            }
        }
        pch++;
    }
}
#endif

使用特权

评论回复
ADZ2016|  楼主 | 2021-3-23 08:03 | 显示全部楼层
/*
*********************************************************************************************************
*                                              uC/Modbus
*                                       The Embedded Modbus Stack
*
*                    Copyright 2003-2020 Silicon Laboratories Inc. www.silabs.com
*
*                                 SPDX-License-Identifier: APACHE-2.0
*
*               This software is subject to an open source license and is distributed by
*                Silicon Laboratories Inc. pursuant to the terms of the Apache License,
*                    Version 2.0 available at www.apache.org/licenses/LICENSE-2.0.
*
*********************************************************************************************************
*/

/*
*********************************************************************************************************
*                                       uC/MODBUS Header File
*
* Filename : mb.h
* Version  : V2.14.00
*********************************************************************************************************
*/


/*
*********************************************************************************************************
*                                               MODULE
*
* Note(s) : (1) This main modbus header file is protected from multiple pre-processor
*               inclusion through use of the modbus module present pre-processor macro definition.
*
*********************************************************************************************************
*/

#ifndef  MODBUS_MODULE_PRESENT                                  /* See Note #1.                                         */
#define  MODBUS_MODULE_PRESENT



/*
*********************************************************************************************************
*                                       MODBUS VERSION NUMBER
*
* Note(s) : (1) (a) The Modbus software version is denoted as follows :
*
*                       Vx.yy.zz
*
*                           where
*                                   V               denotes 'Version' label
*                                   x               denotes major software version revision number
*                                   yy              denotes minor software version revision number
*                                   zz              minor revision
*
*               (b) The software version label #define is formatted as follows :
*
*                       ver = x.yy.zz * 10000
*
*                           where
*                                   ver             denotes software version number scaled as an integer value
*                                   x.yy.zz         denotes software version number
*********************************************************************************************************
*/

#define  MODBUS_VERSION                                  21400u   /* See Note #1.                      */



/*
*********************************************************************************************************
*                                               EXTERNS
*********************************************************************************************************
*/

#ifdef    MB_MODULE
#define   MB_EXT
#else
#define   MB_EXT  extern
#endif



/*
*********************************************************************************************************
*                                        MODBUS PROTOCOL INCLUDE FILES
*
* Note(s) : (1) The modbus protocol suite files are located in the following directories :
*
*               (a) (1) \<Your Product Application>\app_cfg.h
*                   (2)                            \mb_cfg.h
*                   (3)                            \mb_data.c
*
*               (b) \<Modbus Protocol Suite>\Source\mb.h
*                                                  \mb.c
*                                                  \mb_def.c
*                                                  \mb_util.c
*                                                  \mbm_core.c
*                                                  \mbs_core.c
*
*               (c) \<Modbus Protocol Suite>\Ports\<cpu>\mb_bsp.*
*
*               (d) \<Modbus Protocol Suite>\OS\<os>\mb_os.*
*
*                       where
*                               <Your Product Application>      directory path for Your Product's Application
*                               <Modbus Protocol Suite>         directory path for modbus protocol suite
*                               <cpu>                           directory name for specific processor              (CPU)
*                               <compiler>                      directory name for specific compiler
*                               <os>                            directory name for specific operating system       (OS)
*
*           (2) CPU-configuration software files are located in the following directories :
*
*               (a) \<CPU-Compiler Directory>\cpu_def.h
*
*               (b) \<CPU-Compiler Directory>\<cpu>\<compiler>\cpu*.*
*
*                       where
*                               <CPU-Compiler Directory>        directory path for common   CPU-compiler software
*                               <cpu>                           directory name for specific processor (CPU)
*                               <compiler>                      directory name for specific compiler
*
*           (3) NO compiler-supplied standard library functions are used by the modbus protocol suite.
*
*               (a) Standard library functions are implemented in the custom library module(s) :
*
*                       \<Custom Library Directory>\lib*.*
*
*                           where
*                                   <Custom Library Directory>      directory path for custom library software
*
*
*           (4) Compiler MUST be configured to include the '\<Custom Library Directory>\uC-LIB\',
*               '\<CPU-Compiler Directory>\' directory, & the specific CPU-compiler directory as
*               additional include path directories.
**********************************************************************************************************
*/

#include  <cpu.h>
#include  <lib_def.h>

#include  "mb_cfg.h"
#include  "mb_def.h"

#include  "mb_os.h"



/*
*********************************************************************************************************
*                                               DATA TYPES
*********************************************************************************************************
*/

typedef  struct  modbus_ch {
    CPU_INT08U       Ch;                               /* Channel number                                                   */
    CPU_BOOLEAN      WrEn;                             /* Indicates whether MODBUS writes are enabled for the channel      */
    CPU_INT32U       WrCtr;                            /* Incremented each time a write command is performed               */

    CPU_INT08U       NodeAddr;                         /* Modbus node address of the channel                               */

    CPU_INT08U       PortNbr;                          /* UART port number                                                 */
    CPU_INT32U       BaudRate;                         /* Baud Rate                                                        */
    CPU_INT08U       Parity;                           /* UART's parity settings (MODBUS_PARITY_NONE, _ODD or _EVEN)       */
    CPU_INT08U       Bits;                             /* UART's number of bits (7 or 8)                                   */
    CPU_INT08U       Stops;                            /* UART's number of stop bits (1 or 2)                              */

    CPU_INT08U       Mode;                             /* Modbus mode: MODBUS_MODE_ASCII or MODBUS_MODE_RTU                */

    CPU_INT08U       MasterSlave;                      /* Slave when set to MODBUS_SLAVE, Master when set to MODBUS_MASTER */

    CPU_INT16U       Err;                              /* Internal code to indicate the source of MBS_ErrRespSet()         */

#if (MODBUS_CFG_RTU_EN == DEF_ENABLED)
    CPU_INT16U       RTU_TimeoutCnts;                  /* Counts to reload in .RTU_TimeoutCtr when byte received           */
    CPU_INT16U       RTU_TimeoutCtr;                   /* Counts left before RTU timer times out for the channel           */
    CPU_BOOLEAN      RTU_TimeoutEn;                    /* Enable (when TRUE) or Disable (when FALSE) RTU timer             */
#endif

#if (MODBUS_CFG_FC08_EN == DEF_ENABLED)
    CPU_INT16U       StatMsgCtr;                       /* Statistics                                                       */
    CPU_INT16U       StatCRCErrCtr;
    CPU_INT16U       StatExceptCtr;
    CPU_INT16U       StatSlaveMsgCtr;
    CPU_INT16U       StatNoRespCtr;
#endif

    CPU_INT32U       RxTimeout;                        /* Amount of time Master is willing to wait for response from slave */

    CPU_INT32U       RxCtr;                            /* Incremented every time a character is received                   */
    CPU_INT16U       RxBufByteCtr;                     /* Number of bytes received or to send                              */
    CPU_INT08U      *RxBufPtr;                         /* Pointer to current position in buffer                            */
    CPU_INT08U       RxBuf[MODBUS_CFG_BUF_SIZE];       /* Storage of received characters or characters to send             */

    CPU_INT32U       TxCtr;                            /* Incremented every time a character is transmitted                */
    CPU_INT16U       TxBufByteCtr;                     /* Number of bytes received or to send                              */
    CPU_INT08U      *TxBufPtr;                         /* Pointer to current position in buffer                            */
    CPU_INT08U       TxBuf[MODBUS_CFG_BUF_SIZE];       /* Storage of received characters or characters to send             */

    CPU_INT08U       RxFrameData[MODBUS_CFG_BUF_SIZE]; /* Additional data for function requested.                          */
    CPU_INT16U       RxFrameNDataBytes;                /* Number of bytes in the data field.                               */
    CPU_INT16U       RxFrameCRC;                       /* Error check value (LRC or CRC-16).                               */
    CPU_INT16U       RxFrameCRC_Calc;                  /* Error check value computed from packet received                  */

    CPU_INT08U       TxFrameData[MODBUS_CFG_BUF_SIZE]; /* Additional data for function requested.                          */
    CPU_INT16U       TxFrameNDataBytes;                /* Number of bytes in the data field.                               */
    CPU_INT16U       TxFrameCRC;                       /* Error check value (LRC or CRC-16).                               */
} MODBUS_CH;


/*
*********************************************************************************************************
*                                           GLOBAL VARIABLES
*********************************************************************************************************
*/

#if (MODBUS_CFG_RTU_EN == DEF_ENABLED)
MB_EXT   CPU_INT16U      MB_RTU_Freq;                  /* Frequency at which RTU timer is running                          */
MB_EXT   CPU_INT32U      MB_RTU_TmrCtr;                /* Incremented every Modbus RTU timer interrupt                     */
#endif

MB_EXT   CPU_INT08U      MB_ChCtr;                     /* Modbus channel counter (0..MODBUS_MAX_CH)                        */
MB_EXT   MODBUS_CH       MB_ChTbl[MODBUS_CFG_MAX_CH];  /* Modbus channels                                                  */

/*
*********************************************************************************************************
*                                           GLOBAL VARIABLES
*********************************************************************************************************
*/

extern  CPU_INT32U  const  MB_TotalRAMSize;
extern  CPU_INT16U  const  MB_ChSize;

/*
*********************************************************************************************************
*                                  MODBUS INTERFACE FUNCTION PROTOTYPES
*                                               (MB.C)
*********************************************************************************************************
*/

void          MB_Init                   (CPU_INT32U  freq);

void          MB_Exit                   (void);

MODBUS_CH    *MB_CfgCh                  (CPU_INT08U  node_addr,
                                         CPU_INT08U  master_slave,
                                         CPU_INT32U  rx_timeout,
                                         CPU_INT08U  modbus_mode,
                                         CPU_INT08U  port_nbr,
                                         CPU_INT32U  baud,
                                         CPU_INT08U  bits,
                                         CPU_INT08U  parity,
                                         CPU_INT08U  stops,
                                         CPU_INT08U  wr_en);

void          MB_MasterTimeoutSet       (MODBUS_CH  *pch,
                                         CPU_INT32U  timeout);

void          MB_ModeSet                (MODBUS_CH  *pch,
                                         CPU_INT08U  master_slave,
                                         CPU_INT08U  mode);

void          MB_NodeAddrSet            (MODBUS_CH  *pch,
                                         CPU_INT08U  addr);

void          MB_WrEnSet                (MODBUS_CH  *pch,
                                         CPU_INT08U  wr_en);

void          MB_ChToPortMap            (MODBUS_CH  *pch,
                                         CPU_INT08U  port_nbr);

#if (MODBUS_CFG_ASCII_EN == DEF_ENABLED)
void          MB_ASCII_RxByte           (MODBUS_CH   *pch,
                                         CPU_INT08U   rx_byte);
#endif

#if (MODBUS_CFG_RTU_EN == DEF_ENABLED)
void          MB_RTU_RxByte             (MODBUS_CH   *pch,
                                         CPU_INT08U   rx_byte);

void          MB_RTU_TmrReset           (MODBUS_CH   *pch);       /* Resets the Frame Sync timer.                                 */

void          MB_RTU_TmrResetAll        (void);                   /* Resets all the RTU timers                                    */

void          MB_RTU_TmrUpdate          (void);
#endif

void          MB_RxByte                 (MODBUS_CH   *pch,
                                         CPU_INT08U   rx_byte);

void          MB_RxTask                 (MODBUS_CH   *pch);

void          MB_Tx                     (MODBUS_CH   *pch);

void          MB_TxByte                 (MODBUS_CH   *pch);

#if (MODBUS_CFG_ASCII_EN == DEF_ENABLED)
CPU_BOOLEAN  MB_ASCII_Rx                (MODBUS_CH   *pch);
void         MB_ASCII_Tx                (MODBUS_CH   *pch);
#endif


#if (MODBUS_CFG_RTU_EN == DEF_ENABLED)
CPU_BOOLEAN  MB_RTU_Rx                  (MODBUS_CH   *pch);
void         MB_RTU_Tx                  (MODBUS_CH   *pch);
#endif

/*
*********************************************************************************************************
*                                   RTOS INTERFACE FUNCTION PROTOTYPES
*                                         (defined in mb_os.c)
*********************************************************************************************************
*/

void          MB_OS_Init                (void);

void          MB_OS_Exit                (void);

void          MB_OS_RxSignal            (MODBUS_CH   *pch);

void          MB_OS_RxWait              (MODBUS_CH   *pch,
                                         CPU_INT16U  *perr);

/*
*********************************************************************************************************
*                            COMMON MODBUS ASCII INTERFACE FUNCTION PROTOTYPES
*                                       (defined in mb_util.c)
*********************************************************************************************************
*/

#if (MODBUS_CFG_ASCII_EN == DEF_ENABLED)
CPU_INT08U   *MB_ASCII_BinToHex         (CPU_INT08U   value,
                                         CPU_INT08U  *pbuf);

CPU_INT08U    MB_ASCII_HexToBin         (CPU_INT08U  *phex);

CPU_INT08U    MB_ASCII_RxCalcLRC        (MODBUS_CH   *pch);

CPU_INT08U    MB_ASCII_TxCalcLRC        (MODBUS_CH   *pch,
                                         CPU_INT16U   tx_bytes);
#endif

/*
*********************************************************************************************************
*                             COMMON MODBUS RTU INTERFACE FUNCTION PROTOTYPES
*                                       (defined in mb_util.C)
*********************************************************************************************************
*/

#if (MODBUS_CFG_RTU_EN == DEF_ENABLED)
CPU_INT16U   MB_RTU_CalcCRC             (MODBUS_CH  *pch);

CPU_INT16U   MB_RTU_TxCalcCRC           (MODBUS_CH  *pch);

CPU_INT16U   MB_RTU_RxCalcCRC           (MODBUS_CH  *pch);
#endif

/*
*********************************************************************************************************
*                                    INTERFACE TO APPLICATION DATA
*                                       (defined in mb_data.C)
*********************************************************************************************************
*/

#if (MODBUS_CFG_FC01_EN == DEF_ENABLED)
CPU_BOOLEAN  MB_CoilRd                  (CPU_INT16U   coil,
                                         CPU_INT16U  *perr);
#endif

#if (MODBUS_CFG_FC05_EN == DEF_ENABLED)
void         MB_CoilWr                  (CPU_INT16U   coil,
                                         CPU_BOOLEAN  coil_val,
                                         CPU_INT16U  *perr);
#endif

#if (MODBUS_CFG_FC02_EN == DEF_ENABLED)
CPU_BOOLEAN  MB_DIRd                    (CPU_INT16U   di,
                                         CPU_INT16U  *perr);
#endif

#if (MODBUS_CFG_FC04_EN == DEF_ENABLED)
CPU_INT16U   MB_InRegRd                 (CPU_INT16U   reg,
                                         CPU_INT16U  *perr);

CPU_FP32     MB_InRegRdFP               (CPU_INT16U   reg,
                                         CPU_INT16U  *perr);
#endif

#if (MODBUS_CFG_FC03_EN == DEF_ENABLED)
CPU_INT16U   MB_HoldingRegRd            (CPU_INT16U   reg,
                                         CPU_INT16U  *perr);

CPU_FP32     MB_HoldingRegRdFP          (CPU_INT16U   reg,
                                         CPU_INT16U  *perr);
#endif

#if (MODBUS_CFG_FC06_EN == DEF_ENABLED) || \
    (MODBUS_CFG_FC16_EN == DEF_ENABLED)
void         MB_HoldingRegWr            (CPU_INT16U   reg,
                                         CPU_INT16U   reg_val_16,
                                         CPU_INT16U  *perr);

void         MB_HoldingRegWrFP          (CPU_INT16U   reg,
                                         CPU_FP32     reg_val_fp,
                                         CPU_INT16U  *perr);
#endif

#if (MODBUS_CFG_FC20_EN == DEF_ENABLED)
CPU_INT16U   MB_FileRd                  (CPU_INT16U   file_nbr,
                                         CPU_INT16U   record_nbr,
                                         CPU_INT16U   ix,
                                         CPU_INT08U   record_len,
                                         CPU_INT16U  *perr);
#endif

#if (MODBUS_CFG_FC21_EN == DEF_ENABLED)
void         MB_FileWr                  (CPU_INT16U   file_nbr,
                                         CPU_INT16U   record_nbr,
                                         CPU_INT16U   ix,
                                         CPU_INT08U   record_len,
                                         CPU_INT16U   value,
                                         CPU_INT16U  *perr);
#endif

/*
*********************************************************************************************************
*                                        BSP FUNCTION PROTOTYPES
*********************************************************************************************************
*/

void         MB_CommExit                (void);                   /* Exit       Modbus Communications                             */

void         MB_CommPortCfg             (MODBUS_CH   *pch,
                                         CPU_INT08U   port_nbr,
                                         CPU_INT32U   baud,
                                         CPU_INT08U   bits,
                                         CPU_INT08U   parity,
                                         CPU_INT08U   stops);

#if (MODBUS_CFG_RTU_EN == DEF_ENABLED)
void         MB_RTU_TmrInit             (void);                       /* Initialize the timer used for RTU framing                    */

void         MB_RTU_TmrExit             (void);

void         MB_RTU_TmrISR_Handler      (void);
#endif

/*
*********************************************************************************************************
*                                            MODBUS SLAVE
*                                      GLOBAL FUNCTION PROTOTYPES
*********************************************************************************************************
*/

#if (MODBUS_CFG_SLAVE_EN == DEF_ENABLED)
CPU_BOOLEAN  MBS_FCxx_Handler           (MODBUS_CH   *pch);

void         MBS_RxTask                 (MODBUS_CH   *pch);

#if (MODBUS_CFG_FC08_EN == DEF_ENABLED)
void         MBS_StatInit               (MODBUS_CH   *pch);
#endif
#endif

/*
*********************************************************************************************************
*                                            MODBUS MASTER
*                                      GLOBAL FUNCTION PROTOTYPES
*********************************************************************************************************
*/

#if (MODBUS_CFG_MASTER_EN == DEF_ENABLED)

#if (MODBUS_CFG_FC01_EN == DEF_ENABLED)
CPU_INT16U  MBM_FC01_CoilRd          (MODBUS_CH   *pch,
                                      CPU_INT08U   slave_addr,
                                      CPU_INT16U   start_addr,
                                      CPU_INT08U  *p_coil_tbl,
                                      CPU_INT16U   nbr_coils);
#endif

#if (MODBUS_CFG_FC02_EN == DEF_ENABLED)
CPU_INT16U  MBM_FC02_DIRd            (MODBUS_CH   *pch,
                                      CPU_INT08U   slave_node,
                                      CPU_INT16U   slave_addr,
                                      CPU_INT08U  *p_di_tbl,
                                      CPU_INT16U   nbr_di);
#endif

#if (MODBUS_CFG_FC03_EN == DEF_ENABLED)
CPU_INT16U  MBM_FC03_HoldingRegRd    (MODBUS_CH   *pch,
                                      CPU_INT08U   slave_node,
                                      CPU_INT16U   slave_addr,
                                      CPU_INT16U  *p_reg_tbl,
                                      CPU_INT16U   nbr_regs);
#endif

#if (MODBUS_CFG_FC03_EN == DEF_ENABLED) && \
    (MODBUS_CFG_FP_EN   == DEF_ENABLED)
CPU_INT16U  MBM_FC03_HoldingRegRdFP  (MODBUS_CH   *pch,
                                      CPU_INT08U   slave_node,
                                      CPU_INT16U   slave_addr,
                                      CPU_FP32    *p_reg_tbl,
                                      CPU_INT16U   nbr_regs);
#endif

#if (MODBUS_CFG_FC04_EN == DEF_ENABLED)
CPU_INT16U  MBM_FC04_InRegRd         (MODBUS_CH   *pch,
                                      CPU_INT08U   slave_node,
                                      CPU_INT16U   slave_addr,
                                      CPU_INT16U  *p_reg_tbl,
                                      CPU_INT16U   nbr_regs);
#endif

#if (MODBUS_CFG_FC05_EN == DEF_ENABLED)
CPU_INT16U  MBM_FC05_CoilWr          (MODBUS_CH   *pch,
                                      CPU_INT08U   slave_node,
                                      CPU_INT16U   slave_addr,
                                      CPU_BOOLEAN  coil_val);
#endif

#if (MODBUS_CFG_FC06_EN == DEF_ENABLED)
CPU_INT16U  MBM_FC06_HoldingRegWr    (MODBUS_CH   *pch,
                                      CPU_INT08U   slave_node,
                                      CPU_INT16U   slave_addr,
                                      CPU_INT16U   reg_val);
#endif

#if (MODBUS_CFG_FC06_EN == DEF_ENABLED) && \
    (MODBUS_CFG_FP_EN   == DEF_ENABLED)
CPU_INT16U  MBM_FC06_HoldingRegWrFP  (MODBUS_CH   *pch,
                                      CPU_INT08U   slave_node,
                                      CPU_INT16U   slave_addr,
                                      CPU_FP32     reg_val_fp);
#endif

#if (MODBUS_CFG_FC08_EN == DEF_ENABLED)
CPU_INT16U  MBM_FC08_Diag            (MODBUS_CH   *pch,
                                      CPU_INT08U   slave_node,
                                      CPU_INT16U   fnct,
                                      CPU_INT16U   fnct_data,
                                      CPU_INT16U  *pval);
#endif

#if (MODBUS_CFG_FC15_EN == DEF_ENABLED)
CPU_INT16U  MBM_FC15_CoilWr          (MODBUS_CH   *pch,
                                      CPU_INT08U   slave_node,
                                      CPU_INT16U   slave_addr,
                                      CPU_INT08U  *p_coil_tbl,
                                      CPU_INT16U   nbr_coils);
#endif

#if (MODBUS_CFG_FC16_EN == DEF_ENABLED)
CPU_INT16U  MBM_FC16_HoldingRegWrN   (MODBUS_CH   *pch,
                                      CPU_INT08U   slave_node,
                                      CPU_INT16U   slave_addr,
                                      CPU_INT16U  *p_reg_tbl,
                                      CPU_INT16U   nbr_regs);
#endif

#if (MODBUS_CFG_FC16_EN == DEF_ENABLED) && \
    (MODBUS_CFG_FP_EN   == DEF_ENABLED)
CPU_INT16U  MBM_FC16_HoldingRegWrNFP (MODBUS_CH   *pch,
                                      CPU_INT08U   slave_node,
                                      CPU_INT16U   slave_addr,
                                      CPU_FP32    *p_reg_tbl,
                                      CPU_INT16U   nbr_regs);
#endif

#endif
/*
*********************************************************************************************************
*                                            SYMBOL ERRORS
*********************************************************************************************************
*/

#ifndef  MODBUS_CFG_MASTER_EN
#error  "MODBUS_CFG_MASTER_EN                   not #defined                                           "
#error  "... Defines wheteher your product will support Modbus Master                                  "
#endif

#ifndef  MODBUS_CFG_SLAVE_EN
#error  "MODBUS_CFG_SLAVE_EN                   not #defined                                             "
#error  "... Defines wheteher your product will support Modbus Slave                                    "
#endif

#ifndef  MODBUS_CFG_MAX_CH
#error  "MODBUS_CFG_MAX_CH                       not #defined                                           "
#error  "... Defines the number of Modbus ports supported.  Should be 1 to N.                           "
#endif

#ifndef  MODBUS_CFG_MAX_CH
#error  "MODBUS_CFG_MAX_CH                       not #defined                                           "
#error  "... Defines the number of Modbus ports supported.  Should be 1 to N.                           "
#endif


#ifndef  MODBUS_CFG_MAX_CH
#error  "MODBUS_CFG_MAX_CH                       not #defined                                           "
#error  "... Defines the number of Modbus ports supported.  Should be 1 to N.                           "
#endif

#ifndef  MODBUS_CFG_ASCII_EN
#error  "MODBUS_CFG_ASCII_EN                     not #defined                                           "
#error  "... Defines whether your product will support Modbus ASCII.                                    "
#endif

#ifndef  MODBUS_CFG_RTU_EN
#error  "MODBUS_CFG_RTU_EN                       not #defined                                           "
#error  "... Defines whether your product will support Modbus RTU.                                      "
#endif

#ifndef  MODBUS_CFG_FP_EN
#error  "MODBUS_CFG_FP_EN                        not #defined                                           "
#error  "... Defines whether your product will support Daniels Flow Meter Floating-Point extensions.    "
#endif

#ifndef  MODBUS_CFG_FP_START_IX
#error  "MODBUS_CFG_FP_START_IX                  not #defined                                           "
#error  "... Defines the starting register number for floating-point registers.                         "
#endif

#ifndef  MODBUS_CFG_FC01_EN
#error  "MODBUS_CFG_FC01_EN                      not #defined                                           "
#endif

#ifndef  MODBUS_CFG_FC02_EN
#error  "MODBUS_CFG_FC02_EN                      not #defined                                           "
#endif

#ifndef  MODBUS_CFG_FC03_EN
#error  "MODBUS_CFG_FC03_EN                      not #defined                                           "
#endif

#ifndef  MODBUS_CFG_FC04_EN
#error  "MODBUS_CFG_FC04_EN                      not #defined                                           "
#endif

#ifndef  MODBUS_CFG_FC05_EN
#error  "MODBUS_CFG_FC05_EN                      not #defined                                           "
#endif

#ifndef  MODBUS_CFG_FC06_EN
#error  "MODBUS_CFG_FC06_EN                      not #defined                                           "
#endif

#ifndef  MODBUS_CFG_FC08_EN
#error  "MODBUS_CFG_FC08_EN                      not #defined                                            "
#endif

#ifndef  MODBUS_CFG_FC15_EN
#error  "MODBUS_CFG_FC15_EN                      not #defined                                            "
#endif

#ifndef  MODBUS_CFG_FC16_EN
#error  "MODBUS_CFG_FC16_EN                      not #defined                                            "
#endif

#ifndef  MODBUS_CFG_FC20_EN
#error  "MODBUS_CFG_FC20_EN                      not #defined                                            "
#endif

#ifndef  MODBUS_CFG_FC21_EN
#error  "MODBUS_CFG_FC21_EN                      not #defined                                            "
#endif



/*
*********************************************************************************************************
*                                             MODULE END
*********************************************************************************************************
*/

#endif                                                          /* End of modbus module include.                             */

使用特权

评论回复
ADZ2016|  楼主 | 2021-3-23 08:04 | 显示全部楼层
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date           Author       Notes
* 2020-11-21     Meco Man     the first verion
*/
/*
*********************************************************************************************************
*                                              uC/Modbus
*                                       The Embedded Modbus Stack
*
*                    Copyright 2003-2020 Silicon Laboratories Inc. www.silabs.com
*
*                                 SPDX-License-Identifier: APACHE-2.0
*
*               This software is subject to an open source license and is distributed by
*                Silicon Laboratories Inc. pursuant to the terms of the Apache License,
*                    Version 2.0 available at www.apache.org/licenses/LICENSE-2.0.
*
*********************************************************************************************************
*/

/*
*********************************************************************************************************
*
*                                              uC/Modbus
*
*                                     MODBUS BOARD SUPPORT PACKAGE
*                                        RT-Thread UART Device
*
*
* Filename : mb_bsp.c
* Version  : V2.14.00
*********************************************************************************************************
*/

/*
*********************************************************************************************************
*                                            INCLUDE FILES
*********************************************************************************************************
*/

#include "mb.h"
#include <os.h>
#include <rtdevice.h>
#include <stdlib.h>

/*
*********************************************************************************************************
*                                               GLOBALS
*********************************************************************************************************
*/     



/*
*********************************************************************************************************
*                                             MB_CommExit()
*
* Description : This function is called to terminate Modbus communications.  All Modbus channels are close.
*
* Argument(s) : none
*
* Return(s)   : none.
*
* Caller(s)   : MB_Exit()
*
* Note(s)     : none.
*********************************************************************************************************
*/

CPU_VOID  MB_CommExit (CPU_VOID)
{
    CPU_INT08U   ch;
    MODBUS_CH   *pch;
    char uart_dev_name[RT_NAME_MAX]={0};
    rt_device_t uart_dev;

    pch = &MB_ChTbl[0];
    for (ch = 0; ch < MODBUS_CFG_MAX_CH; ch++) {
        if(pch == RT_NULL){
            pch++;
            continue;
        }

        rt_snprintf(uart_dev_name, RT_NAME_MAX, "uart%d", pch->PortNbr);   
        uart_dev = rt_device_find(uart_dev_name);
        if(uart_dev == (rt_device_t)0){
            pch++;
            continue;
        }

        rt_device_set_rx_indicate(uart_dev, RT_NULL);
        rt_device_close(uart_dev);
        pch++;
    }
}

static rt_err_t mb_rx_handler(rt_device_t dev, rt_size_t size)
{
    CPU_INT08U byte;
    CPU_INT08U   ch;
    MODBUS_CH  *pch;
    char dev_id_name[RT_NAME_MAX] = {0};
    CPU_INT08U id;
   
    rt_strncpy(dev_id_name, &dev->parent.name[4], 2); /* "uart1" -> "1"*/
    id = atoi(dev_id_name); /* "1" -> 1 */
   
    pch = &MB_ChTbl[0];
    for (ch = 0; ch < MODBUS_CFG_MAX_CH; ch++) {
        if(pch->PortNbr == id){
            break;
        }
        pch++;
    }

    for(ch=size; ch>0; ch--)
    {
        if(rt_device_read(dev, -1, &byte, 1) == 1) /* read one byte from uart */
        {
            MB_RxByte(pch, byte); /* invoke MB_RxByte() */
        }
    }

    return RT_EOK;
}

/*
*********************************************************************************************************
*                                           MB_CommPortCfg()
*
* Description : This function initializes the serial port to the desired baud rate and the UART will be
*               configured for N, 8, 1 (No parity, 8 bits, 1 stop).
*
* Argument(s) : pch        is a pointer to the Modbus channel
*               port_nbr   is the desired serial port number.  This argument allows you to assign a
*                          specific serial port to a sepcific Modbus channel.
*               baud       is the desired baud rate for the serial port.
*               parity     is the desired parity and can be either:
*
*                          MODBUS_PARITY_NONE
*                          MODBUS_PARITY_ODD
*                          MODBUS_PARITY_EVEN
*
*               bits       specifies the number of bit and can be either 7 or 8.
*               stops      specifies the number of stop bits and can either be 1 or 2
*
* Return(s)   : none.
*
* Caller(s)   : MB_CfgCh()
*
* Note(s)     : none.
*********************************************************************************************************
*/

CPU_VOID  MB_CommPortCfg (MODBUS_CH  *pch,
                          CPU_INT08U  port_nbr,
                          CPU_INT32U  baud,
                          CPU_INT08U  bits,
                          CPU_INT08U  parity,
                          CPU_INT08U  stops)
{
    char uart_dev_name[RT_NAME_MAX]={0};
    rt_device_t uart_dev;                                           /* uart device handler */
    struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;

    if (pch == (MODBUS_CH *)0){
        return;
    }
    pch->PortNbr        = port_nbr;                                 /* Store configuration in channel              */
    pch->BaudRate       = baud;
    pch->Parity         = parity;
    pch->Bits           = bits;
    pch->Stops          = stops;        

    rt_snprintf(uart_dev_name, RT_NAME_MAX, "uart%d", port_nbr);   
    uart_dev = rt_device_find(uart_dev_name);
    if(uart_dev == (rt_device_t)0){
        return;
    }

    switch(baud)
    {
        case 2400:
            config.baud_rate = BAUD_RATE_2400; break;
        case 4800:
            config.baud_rate = BAUD_RATE_4800; break;
        case 9600:
            config.baud_rate = BAUD_RATE_9600; break;
        case 19200:
            config.baud_rate = BAUD_RATE_19200; break;
        case 38400:
            config.baud_rate = BAUD_RATE_38400; break;
        case 57600:
            config.baud_rate = BAUD_RATE_57600; break;
        case 115200:
            config.baud_rate = BAUD_RATE_115200; break;
        case 230400:
            config.baud_rate = BAUD_RATE_230400; break;
        case 460800:
            config.baud_rate = BAUD_RATE_460800; break;
        case 921600:
            config.baud_rate = BAUD_RATE_921600; break;
        case 2000000:
            config.baud_rate = BAUD_RATE_2000000; break;
        case 3000000:
            config.baud_rate = BAUD_RATE_3000000; break;
        default:
            config.baud_rate = BAUD_RATE_115200; break;
    }
   
    switch(bits)
    {
        case 7:
           config.data_bits = DATA_BITS_7; break;
        case 8:
        default:
           config.data_bits = DATA_BITS_8; break;        
    }
   
    switch(stops)
    {
        case 2:
            config.stop_bits = STOP_BITS_2; break;
        case 1:
        default:
            config.stop_bits = STOP_BITS_1; break;
    }
   
    switch(parity)
    {
        case MODBUS_PARITY_ODD:
            config.parity = PARITY_ODD; break;
        case MODBUS_PARITY_EVEN:
            config.parity = PARITY_EVEN; break;
        case MODBUS_PARITY_NONE:
        default:
            config.parity = PARITY_NONE; break;
    }

    config.bufsz     = 128;
   
    rt_device_contr**, RT_DEVICE_CTRL_CONFIG, &config);
    if(rt_device_open(uart_dev, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_DMA_RX) == RT_EOK)
    {
        rt_device_set_rx_indicate(uart_dev, mb_rx_handler);
    }
}

/*
*********************************************************************************************************
*                                                MB_Tx()
*
* Description : This function is called to start transmitting a packet to a modbus channel.
*
* Argument(s) : pch      Is a pointer to the Modbus channel's data structure.
*
* Return(s)   : none.
*
* Caller(s)   : MB_ASCII_Tx(),
*               MB_RTU_Tx().
*
* Note(s)     : none.
*********************************************************************************************************
*/
/* combine MB_Tx() and MB_TxByte() */
void  MB_Tx (MODBUS_CH  *pch)
{
    char uart_dev_name[RT_NAME_MAX]={0};
    rt_device_t uart_dev;
   
    pch->TxBufPtr = &pch->TxBuf[0];
    if (pch->TxBufByteCtr > 0) {
#if (MODBUS_CFG_MASTER_EN == DEF_ENABLED)
        if (pch->MasterSlave == MODBUS_MASTER) {
#if (MODBUS_CFG_RTU_EN == DEF_ENABLED)
            pch->RTU_TimeoutEn = MODBUS_FALSE;                  /* Disable RTU timeout timer until we start receiving */
#endif
            pch->RxBufByteCtr  = 0;                             /* Flush Rx buffer                                    */
        }
#endif
        rt_snprintf(uart_dev_name, RT_NAME_MAX, "uart%d", pch->PortNbr);   
        uart_dev = rt_device_find(uart_dev_name);
        if(uart_dev == (rt_device_t)0){
            return;
        }
        
        rt_device_write(uart_dev,0,pch->TxBufPtr,pch->TxBufByteCtr); /* send a message */
        
        /* end of transmission */
        pch->TxCtr = pch->TxBufByteCtr;
        pch->TxBufByteCtr = 0;
    }
}


/*
*********************************************************************************************************
*                                           MB_RTU_TmrInit()
*
* Description : This function is called to initialize the RTU timeout timer.
*
* Argument(s) : freq          Is the frequency of the modbus RTU timer interrupt.
*
* Return(s)   : none.
*
* Caller(s)   : MB_Init().
*
* Note(s)     : none.
*********************************************************************************************************
*/

#if (MODBUS_CFG_RTU_EN == DEF_ENABLED)
CPU_VOID  MB_RTU_TmrInit (void)
{
}
#endif


/*
*********************************************************************************************************
*                                           MB_RTU_TmrExit()
*
* Description : This function is called to disable the RTU timeout timer.
*
* Argument(s) : none.
*
* Return(s)   : none.
*
* Caller(s)   : MB_Exit()
*
* Note(s)     : none.
*********************************************************************************************************
*/

#if (MODBUS_CFG_RTU_EN == DEF_ENABLED)
CPU_VOID  MB_RTU_TmrExit (CPU_VOID)
{   
}
#endif



/*
*********************************************************************************************************
*                                       MB_RTU_TmrISR_Handler()
*
* Description : This function handles the case when the RTU timeout timer expires.
*
* Arguments   : none.
*
* Returns     : none.
*
* Caller(s)   : This is a ISR.
*
* Note(s)     : none.
*********************************************************************************************************
*/

#if (MODBUS_CFG_RTU_EN == DEF_ENABLED)
CPU_VOID  MB_RTU_Tmr_Timeout (CPU_VOID)
{
}
#endif

使用特权

评论回复
ADZ2016|  楼主 | 2021-3-23 08:10 | 显示全部楼层
/*
*********************************************************************************************************
*                                              uC/Modbus
*                                       The Embedded Modbus Stack
*
*                    Copyright 2003-2020 Silicon Laboratories Inc. www.silabs.com
*
*                                 SPDX-License-Identifier: APACHE-2.0
*
*               This software is subject to an open source license and is distributed by
*                Silicon Laboratories Inc. pursuant to the terms of the Apache License,
*                    Version 2.0 available at www.apache.org/licenses/LICENSE-2.0.
*
*********************************************************************************************************
*/

/*
*********************************************************************************************************
*                                      MODBUS CONFIGURATION
*
* Filename : mb_cfg.h
* Version  : V2.14.00
*********************************************************************************************************
* Note(s)  : (1) This file contains configuration constants for uC/Modbus
*********************************************************************************************************
*/

#include <rtconfig.h>

/*
*********************************************************************************************************
*                                           OS Configuration
*
*********************************************************************************************************
*/

#ifdef PKG_USING_UC_MODBUS_TASK_PRIO
#define  MB_OS_CFG_RX_TASK_PRIO           PKG_USING_UC_MODBUS_TASK_PRIO
#else
#define  MB_OS_CFG_RX_TASK_PRIO           10
#endif

#ifdef PKG_USING_UC_MODBUS_TASK_STK_SIZE
#define  MB_OS_CFG_RX_TASK_STK_SIZE       PKG_USING_UC_MODBUS_TASK_STK_SIZE
#else
#define  MB_OS_CFG_RX_TASK_STK_SIZE       512
#endif


/*
*********************************************************************************************************
*                                  MODBUS MODULES CONFIGURATION
*********************************************************************************************************
*/

#define  MODBUS_CFG_SLAVE_EN              DEF_ENABLED           /* Enable or Disable  Modbus Slave                    */
#define  MODBUS_CFG_MASTER_EN             DEF_DISABLED          /* Enable or Disable  Modbus Master                   */

/*
*********************************************************************************************************
*                                  MODBUS MODES CONFIGURATION
*********************************************************************************************************
*/

#define  MODBUS_CFG_ASCII_EN               DEF_ENABLED          /* Modbus ASCII is supported when DEF_ENABLED         */
#define  MODBUS_CFG_RTU_EN                 DEF_ENABLED          /* Modbus RTU   is supported when DEF_ENABLED         */

/*
*********************************************************************************************************
*                               MODBUS COMMUNICATION CONFIGURATION
*********************************************************************************************************
*/

#define  MODBUS_CFG_MAX_CH                          10           /* Maximum number of Modbus channels.                 */

#define  MODBUS_CFG_BUF_SIZE                       255           /* Maximum outgoing message size.                     */

/*
*********************************************************************************************************
*                                  MODBUS FLOATING POINT SUPPORT
*********************************************************************************************************
*/

#define  MODBUS_CFG_FP_EN                  DEF_ENABLED          /* Enable Floating-Point support.                     */

#if     (MODBUS_CFG_FP_EN == DEF_ENABLED)
#define  MODBUS_CFG_FP_START_IX                  5000           /* Start address of Floating-Point registers          */
#else
#define  MODBUS_CFG_FP_START_IX                 65500           /* Floating point is disabled, set start of ...       */
                                                                /*   ...FP very high                                  */
#endif


/*
*********************************************************************************************************
*                                   MODBUS FUNCTIONS CONFIGURATION
*********************************************************************************************************
*/

#define  MODBUS_CFG_FC01_EN                DEF_ENABLED          /* Enable or Disable support for Modbus functions     */
#define  MODBUS_CFG_FC02_EN                DEF_ENABLED
#define  MODBUS_CFG_FC03_EN                DEF_ENABLED
#define  MODBUS_CFG_FC04_EN                DEF_ENABLED
#define  MODBUS_CFG_FC05_EN                DEF_ENABLED
#define  MODBUS_CFG_FC06_EN                DEF_ENABLED
#define  MODBUS_CFG_FC08_EN                DEF_ENABLED
#define  MODBUS_CFG_FC15_EN                DEF_ENABLED
#define  MODBUS_CFG_FC16_EN                DEF_ENABLED
#define  MODBUS_CFG_FC20_EN                DEF_DISABLED
#define  MODBUS_CFG_FC21_EN                DEF_DISABLED

使用特权

评论回复
aozima| | 2021-3-23 10:19 | 显示全部楼层
有没说明啊。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

61

主题

1209

帖子

7

粉丝