Difference between revisions of "Modbus notes"

From Wiki at Neela Nurseries
Jump to: navigation, search
m (^ Modbus frames and framing handling)
m (^ Modbus frames and framing handling)
Line 117: Line 117:
  
 
Variable <code>usRegInputBuf</code> is in source file simple2.c a static array of bytes, which hold values that a Modbus function returns,
 
Variable <code>usRegInputBuf</code> is in source file simple2.c a static array of bytes, which hold values that a Modbus function returns,
 +
 +
<pre>
 +
<./simple2.c:42:static unsigned short usRegInputBuf[REG_INPUT_NREGS];
 +
./simple2.c:76:        usRegInputBuf[0]++;
 +
./simple2.c:79:        usRegInputBuf[1] = ( unsigned portSHORT )( xLastWakeTime >> 16UL );
 +
./simple2.c:80:        usRegInputBuf[2] = ( unsigned portSHORT )( xLastWakeTime & 0xFFFFUL );
 +
./simple2.c:82:        usRegInputBuf[3] = 33;
 +
./simple2.c:99:                ( unsigned char )( usRegInputBuf[iRegIndex] >> 8 );
 +
./simple2.c:101:                ( unsigned char )( usRegInputBuf[iRegIndex] & 0xFF );
 +
/pre>
 +
 +
We look then at <code>pucRegBuffer</code> because of the following assignments in a callback routine of this demo:
 +
 +
<pre>
 +
86 eMBErrorCode
 +
87 eMBRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs )
 +
88 {
 +
89    eMBErrorCode    eStatus = MB_ENOERR;
 +
90    int            iRegIndex;
 +
91
 +
92    if( ( usAddress >= REG_INPUT_START )
 +
93        && ( usAddress + usNRegs <= REG_INPUT_START + REG_INPUT_NREGS ) )
 +
94    {
 +
95        iRegIndex = ( int )( usAddress - usRegInputStart );
 +
96        while( usNRegs > 0 )
 +
97        {
 +
98            *pucRegBuffer++ =
 +
99                ( unsigned char )( usRegInputBuf[iRegIndex] >> 8 );
 +
100            *pucRegBuffer++ =
 +
101                ( unsigned char )( usRegInputBuf[iRegIndex] & 0xFF );
 +
102            iRegIndex++;
 +
103            usNRegs--;
 +
104        }
 +
105    }
 +
106    else
 +
107    {
 +
108        eStatus = MB_ENOREG;
 +
109    }
 +
110
 +
111    return eStatus;
 +
112 }
 +
</pre>
 +
 +
Now the question is, which code calls the routine <code>eMBErrorCode eMBRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs )</code>?  This routine is not called by any code in this specific demo:
 +
 +
<pre>
 +
$ grep -nr -A 1 eMBRegInputCB ./*
 +
./excoils.c:130:eMBRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs )
 +
./excoils.c-131-{
 +
--
 +
./exdisc.c:118:eMBRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs )
 +
./exdisc.c-119-{
 +
--
 +
./exholding.c:86:eMBRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs )
 +
./exholding.c-87-{
 +
--
 +
./simple2.c:87:eMBRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs )
 +
./simple2.c-88-{
 +
--
 +
./simple.c:94:eMBRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs )
 +
./simple.c-95-{
 +
</pre>
 +
 +
 +
Looking now a level or two up and at the FreeModbus library sources . . .
  
 
<pre>
 
<pre>
 
...
 
...
 
</pre>
 
</pre>
 +
 +
 +
  
  

Revision as of 02:04, 15 November 2019



This wiki article contains some notes and references on FreeModbus, an opensource C library to support a Modbus protocol stack in stand-alone applications as well as operating system and scheduler based systems. This article also contains a number of links to more general C language references, which discuss function pointers in C, and the type defining of function pointers.



- 2019-11-08 FRI -

When working with FreeModbus, be sure to pay attention to the versions of protocol available, and likely, we only want to enable one of these. See Modbus/include/mbconfig.h. See also Modbus/include/mb.h for instructions on how to initialize and begin to use an instance of FreeModbus stack in given program. Also mention that eMBPoll() routine may be set up as a task in an RTOS, to realize the periodic polling which is part of the stack's runtime manifestation . . .

Looks like also this function to register callbacks for end-user-device-specific Modbus registers will be important:

  eMBErrorCode eMBRegisterCB ( UCHAR ucFunctionCode,
    pxMBFunctionHandler pxHandler
  )

This function signature part of documentation found at https://www.embedded-solutions.at/en/freemodbus/api-documentation/, which gives Doxygen generated API help in an embedded pane in the browser window on which it is visited.


2019-11-12 Tuesday - trying to figure out how pxMBFunctionHandler is defined . . . from http://www.teamfdi.com/uez/docs/mbproto_8h.html:

 Typedefs
 typedef eMBException(* pxMBFunctionHandler )(UCHAR *pucFrame, USHORT *pusLength)

...from this typedef looks like Modbus routines implemented by the end user/end designer must have parameter lists which match "unsigned char pointer, unsigned integer pointer".


2019-11-13 Further search for FreeModbus callback registering code"

downloads/freemodbus/freemodbus-v1.5.0$ grep -nr pxMBFunctionHandler ./*
./modbus/mb.c:226:eMBRegisterCB( UCHAR ucFunctionCode, pxMBFunctionHandler pxHandler )
./modbus/include/mbproto.h:72:typedef         eMBException( *pxMBFunctionHandler ) ( UCHAR * pucFrame, USHORT * pusLength );
./modbus/include/mbproto.h:77:    pxMBFunctionHandler pxHandler;
./modbus/include/mb.h:266:                               pxMBFunctionHandler pxHandler )

And the entire section of typedefs from mbproto.h:

/* ----------------------- Type definitions ---------------------------------*/
    typedef enum
{
    MB_EX_NONE = 0x00,
    MB_EX_ILLEGAL_FUNCTION = 0x01,
    MB_EX_ILLEGAL_DATA_ADDRESS = 0x02,
    MB_EX_ILLEGAL_DATA_VALUE = 0x03,
    MB_EX_SLAVE_DEVICE_FAILURE = 0x04,
    MB_EX_ACKNOWLEDGE = 0x05,
    MB_EX_SLAVE_BUSY = 0x06,
    MB_EX_MEMORY_PARITY_ERROR = 0x08,
    MB_EX_GATEWAY_PATH_FAILED = 0x0A,
    MB_EX_GATEWAY_TGT_FAILED = 0x0B
} eMBException;

typedef         eMBException( *pxMBFunctionHandler ) ( UCHAR * pucFrame, USHORT * pusLength );

typedef struct
{
    UCHAR           ucFunctionCode;
    pxMBFunctionHandler pxHandler;
} xMBFunctionHandler;



^ Obscurely defined FreeModbus variables

Where is the following demo/LPC214X/port/port.c variable defined? Does not appear defined in any file of FreeModbus 1.5.0 download. Note however that this may be an LPC microcontroller register name:

  VICIntEnable

See http://www.keil.com/dd/vtr/3880/9794.htm for a brief mention of this term. - TMH



^ Modbus frames and framing handling

This search result may not be directly useful to getting a first modbus routine running and testable:

./modbus/include/mbport.h:109:extern          BOOL( *pxMBFrameCBByteReceived ) ( void );
Binary file ./modbus/include/.mbport.h.swp matches
./modbus/mb.c:85:BOOL( *pxMBFrameCBByteReceived ) ( void );
./modbus/mb.c:153:            pxMBFrameCBByteReceived = xMBRTUReceiveFSM;
./modbus/mb.c:167:            pxMBFrameCBByteReceived = xMBASCIIReceiveFSM;


Here is a search history, some searches run in the STR71X demo. These variables and routines look more promising in terms of telling us how to implement a routine of our own which properly ties in with FreeModbus library code:

 1004  grep -nr usRegInputBuf ./*
 1005  grep -n pucRegBuffer ./*
 1006  # eMBRegInputCB, third token for which to search


Variable usRegInputBuf is in source file simple2.c a static array of bytes, which hold values that a Modbus function returns,

<./simple2.c:42:static unsigned short usRegInputBuf[REG_INPUT_NREGS];
./simple2.c:76:        usRegInputBuf[0]++;
./simple2.c:79:        usRegInputBuf[1] = ( unsigned portSHORT )( xLastWakeTime >> 16UL );
./simple2.c:80:        usRegInputBuf[2] = ( unsigned portSHORT )( xLastWakeTime & 0xFFFFUL );
./simple2.c:82:        usRegInputBuf[3] = 33;
./simple2.c:99:                ( unsigned char )( usRegInputBuf[iRegIndex] >> 8 );
./simple2.c:101:                ( unsigned char )( usRegInputBuf[iRegIndex] & 0xFF );
/pre>

We look then at <code>pucRegBuffer</code> because of the following assignments in a callback routine of this demo:

<pre>
 86 eMBErrorCode
 87 eMBRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs )
 88 {
 89     eMBErrorCode    eStatus = MB_ENOERR;
 90     int             iRegIndex;
 91 
 92     if( ( usAddress >= REG_INPUT_START )
 93         && ( usAddress + usNRegs <= REG_INPUT_START + REG_INPUT_NREGS ) )
 94     {
 95         iRegIndex = ( int )( usAddress - usRegInputStart );
 96         while( usNRegs > 0 )
 97         {
 98             *pucRegBuffer++ =
 99                 ( unsigned char )( usRegInputBuf[iRegIndex] >> 8 );
100             *pucRegBuffer++ =
101                 ( unsigned char )( usRegInputBuf[iRegIndex] & 0xFF );
102             iRegIndex++;
103             usNRegs--;
104         }
105     }
106     else
107     {
108         eStatus = MB_ENOREG;
109     }
110 
111     return eStatus;
112 }

Now the question is, which code calls the routine eMBErrorCode eMBRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs )? This routine is not called by any code in this specific demo:

$ grep -nr -A 1 eMBRegInputCB ./*
./excoils.c:130:eMBRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs )
./excoils.c-131-{
--
./exdisc.c:118:eMBRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs )
./exdisc.c-119-{
--
./exholding.c:86:eMBRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs )
./exholding.c-87-{
--
./simple2.c:87:eMBRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs )
./simple2.c-88-{
--
./simple.c:94:eMBRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs )
./simple.c-95-{


Looking now a level or two up and at the FreeModbus library sources . . .

...




^ C function pointers and further references

What do we need to pass to eMBRegisterCB()? . . .

2019-11-14 Thursday:



^ Modbus tools and resources


- - - top of page - - -