Difference between revisions of "Modbus notes"
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
Contents
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.
- https://libmodbus.org/ . . . Ubuntu package is 'libmodbus5' and 'libmodbus-dev'
- 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()? . . .
-
C function pointer syntax:
2019-11-14 Thursday:
^ Modbus tools and resources
- - - top of page - - -