The structure of the needed H-file
Neuron Power Engineer will automatically create the implementation stubs within the H-file, if you follow the best practice instruction specified within the article "Details: Creating a vendor block". Nevertheless it is useful, if you know the basic structure of a H-file.
The basic structure of the H-file must be as follows:
-
include of the required types
If the vendor block is to support generic data types, all of the relevant elementary data types must be declared in this section – if not otherwise defined. -
type definition for the data type of the new vendor block
-
initialization macro for the type definition (=
INIT
macro) -
only required for function blocks:
-
initialization macro for warm boot (=
WINIT
macro) -
name server data structure
-
-
implementation of the functionality
The contents of the type definition incl. the macros as well as of the implementation is influenced by:
-
the statement
{ ImplementationProperties ( ) }
and some of its definitions (see article "Properties for implementing vendor blocks" for details) – for instance, the definitionuseUntypedTypeStructure
. -
the fact whether the vendor block is using generic data types or not
The following examples illustrate the required contents of the H-file for a vendor block with elementary data types only:
If your vendor block is to support more complex data types (e.g. structures, arrays, references, strings), please contact Neuron.
Example 1: MUL_01 function with a concrete data type
The following interface declares a function with 2 inputs of data type INT
.
Example 1 for interface |
---|
|
The application Test_01
is calling the specified vendor block MUL_01
and assigning its return value to the variable Var2
.
Example 1 for application using the vendor block |
---|
|
The following lines are required within the H-file lcfu___MUL_01.h
so that Neuron Power Engineer is able to build the application for Test_01
. The lines /* ... */
are just comments that have been added to explain the structure.
Example 1 for H-file |
---|
|
Here some basic explanations for this contents:
-
The default header file must be included because the default data type
INT
is used. -
The type definition must declare the following elements of the POU and its data type:
Function blocks
Functions
→input variable of the POU
–
→in-out variable of the POU
ENO
output (its data type is alwaysBOOL
)→output variable of the POU
local →variable of the POU
–
return value of the function
–
auxiliary variables that are not visible to the user
These auxiliary variables are necessary to keep its values from one execution of the application to the next one.–
The data type of the variables and return value depends on the specified interface. For the above example, the data type
INT
must be specified for the return valueLC_VD_MUL_01
.
Declare the variables in the order as specified in the table. The order might become relevant when an application is updated by using the resource manager (= reloaded).
This means:-
The required order for variables in a vendor function is:
VAR_IN_OUT
–ENO
–VAR_OUTPUT
– return value -
The required order for variables in a vendor function block is:
VAR_INPUT
–VAR_IN_OUT
–ENO
–VAR_OUTPUT
–VAR
– auxiliary variables that are not visible to the user
-
-
The initialization macro is required for each element declared within the type definition but not for the
ENO
output. The initialization macro is a type-specific initialization. -
The implementation specifies a "C-function" telling what the POU should do when it is called. For the above example,
MUL_01
calculates2*IN1*IN2
and assigns its result to the return valueLC_VD_MUL_01
.
As an alternative, the implementation can be done by using a C-file. In this case, the definitionfunctionHasCFile
within the statement{ ImplementationProperties ( ) }
is required within the vendor block. For information on the structure of a C-file, please contact Neuron.
If you are building the application for Test_01
, Neuron Power Engineer automatically generates the following lines within the file lcpu___test_01.c
for the line Var2:=MUL_01(IN1:=2, IN2:=Var1);
:
(This file is located within the sub-folder src-gen
of the project. This sub-folder is not visible by default.)
Example 1 for generated C-code |
---|
|
Here are some basic explanations for this code (if you are interested in details, please contact Neuron):
-
Line
LC_TD_Function_MUL_01 lFunction_MUL_01;
= usage of the type definition (specified in the H-file); Also, the variablelFunction_MUL_01
is created. -
Line
LC_INIT_Function_MUL_01(&lFunction_MUL_01);
= initialization of the created variable with the initialization macro (specified in the H-file) -
Line
lcfu___MUL_01(&lFunction_MUL_01, (LC_TD_INT)2, LC_this->LC_VD_VAR1, pEPDB);
= calling the functionMUL_01
with assigned parameters; At first, a variable is assigned to the return value, then the values or variables are assigned to the input variables (here: literal2
and variableVAR1
are assigned. At last, the internal parameterpEPDB
is always listed.
If input variables of the function would have been omitted in the call of the function, the initial value of the data type would be assigned to those input variables.
Usually, the parameterpEPDB
(pointer Entry Point Description Block) is not required to implement a C-block. Hence, you can ignore this internal parameter. However, if you are using specific RTS APIs, the parameterpEPDB
is required to be passed on. -
Line
LC_this->LC_VD_VAR2 = lFunction_MUL_01.LC_VD_MUL_01;
= assignment of the results to the variableVAR2
.
Result of the above implementation: If you load the application onto the built-in PLC, the Values of Variables view will display the value 20
for variable Var2
.
Example 2: MUL_02 hfunction with a generic data type
The following interface declares a function with 2 inputs but now with the generic data type ANY
.
Example 2 for interface |
---|
|
The application Test_02
is calling the specified vendor block MUL_02
(one call type-coded with INT
and the other call type-coded with SINT
) and assigning its return value to an appropriate variable.
Example 2 for application using the vendor block |
---|
|
As a consequence, the following lines are required within the H-file lcfu___MUL_02.h
.
If you would use the call with other data types than INT
and SINT
, the H-file would require the appropriate lines for those data types as well.
Example 2 for H-file |
---|
|
Result of the above implementation: If you load the application onto the built-in PLC, the Values of Variables view will display the value 60
for variable Var3
and the value 12
for variable Var5
.
Example 3: FB_MUL_01 function block with a concrete data type
The following interface declares a function block with 2 inputs of data type INT
and 1 output of data type INT
.
Example 3 for interface |
---|
|
The application Test_01
is calling the specified vendor block FB_MUL_01
and assigning its output to the variable Var2
.
Example 3 for application using the vendor block |
---|
|
The following lines are required within the H-file lcfu___fb_mul_01.h
so that Neuron Power Engineer is able to build the application for Test_01
. The lines /* ... */
are just comments that have been added to explain the structure.
Example 3 for H-file |
---|
|
Here are the basic differences to the example for functions:
-
The type definition must declare the inputs of the function block and its data type.
Local variables would have to be declared as well within the type definition. But this function block does not have any local variables. -
Hence, the inputs of the function block are required within the initialization macro as well.
-
The initialization macro for the warm boot (=
WINIT
macro) is required. TheWINIT
macro defines the behavior of the function block in case of a warm restart whereas theINIT
macro defines the behavior in case of a cold restart.
TheWINIT
macro is similar to theINIT
macro but has the additional retain flagRF
.
The line#define LC_WINIT_FunctionBlock_FB_MUL_01(p,RF) { if (RF==0) LC_INIT_FunctionBlock_FB_MUL_01(p) }
is sufficient to guarantee a correct code generation, if an instance of the function block would be declared in aVAR ... END_VAR
section with the keywordRETAIN
. Although this example declares the function block in in aVAR ... END_VAR
section without the keywordRETAIN
, it is a good idea to integrate this line for theWINIT
macro – you, as the manufacturer of the function block – cannot be sure whether the function block will be used with or without the keywordRETAIN
.
If the function block block itself contains a section with the keywordRETAIN
, the contents of theWINIT
macro must look different. Please contact Neuron for details on this contents. -
The name server data structure is required as well.
The line#define LCNS_EL_CNT___FB_MUL_01 0
is sufficient to guarantee a correct code generation. But when the H-file is auto-generated, the content looks different. In this case, do not have to change the auto-generated content. -
The implementation specifies the "C-function" for the function block not specifying the inputs. Reason: The inputs are already provided by the data structure
(LC_this)
.
Result of the above implementation: If you load the application onto the built-in PLC, the Values of Variables view will display the value 30
for variable Var2
.