OpenPLC指针分析

217 阅读1分钟
1.指针的简单应用
PROGRAM program0
  VAR
    A : INT := 250;
    pt : REF_TO INT;
    Data : INT;
  END_VAR
  
  pt := REF(A);
  Data := pt^;
END_PROGRAM


CONFIGURATION Config0
  RESOURCE Res0 ON PLC
    TASK task0(INTERVAL := T#20ms,PRIORITY := 0);
    PROGRAM instance0 WITH task0 : program0;
  END_RESOURCE
END_CONFIGURATION

编译之后的POUS.c

void PROGRAM0_init__(PROGRAM0 *data__, BOOL retain) {
  __INIT_VAR(data__->A,250,retain)
  __INIT_VAR(data__->PT,NULL,retain)
  __INIT_VAR(data__->DATA,0,retain)
}

// Code part
void PROGRAM0_body__(PROGRAM0 *data__) {
  // Initialise TEMP variables

  __SET_VAR(data__->,PT,,((__GET_VAR_REF(data__->A,))));
  __SET_VAR(data__->,DATA,,(*__GET_VAR(data__->PT,)));

  goto __end;

__end:
  return;
} // PROGRAM0_body__() 
2.期望类似于C语言*p=250的应用
PROGRAM program0
  VAR
    A : INT := 250;
    pt : REF_TO INT;
    Data : INT;
  END_VAR
  
  pt := REF(A);
  pt^ := 520;
END_PROGRAM


CONFIGURATION Config0
  RESOURCE Res0 ON PLC
    TASK task0(INTERVAL := T#20ms,PRIORITY := 0);
    PROGRAM instance0 WITH task0 : program0;
  END_RESOURCE
END_CONFIGURATION

编译之后的POUS.c

void PROGRAM0_init__(PROGRAM0 *data__, BOOL retain) {
  __INIT_VAR(data__->A,250,retain)
  __INIT_VAR(data__->PT,NULL,retain)
  __INIT_VAR(data__->DATA,0,retain)
}

// Code part
void PROGRAM0_body__(PROGRAM0 *data__) {
  // Initialise TEMP variables

  __SET_VAR(data__->,PT,,((__GET_VAR_REF(data__->A,))));
  __SET_VAR(data__->,(*PT),(*),520);   //应该是 __SET_VAR(data__->,*__GET_VAR(data__->PT,),,520);

  goto __end;

__end:
  return;
} // PROGRAM0_body__() 
3.SET_VAR相关的宏定义
#define __SET_VAR(prefix, name, suffix, new_value)\
	if (!(prefix name.flags & __IEC_FORCE_FLAG)) prefix name.value suffix = new_value
//
#define __GET_VAR_BY_REF(name, ...)\
	((name.flags & __IEC_FORCE_FLAG) ? &(name.fvalue __VA_ARGS__) : &(name.value __VA_ARGS__))
        
//获取name变量本身的引用
#define __GET_VAR_REF(name, ...)\
	(&(name.value __VA_ARGS__))
//获取name变量本身的解引用
#define __GET_VAR_DREF(name, ...)\
	(*(name.value __VA_ARGS__))
4.bison中关于变量赋值定义的规则
variable:
  symbolic_variable
| prev_declared_direct_variable
| eno_identifier
	{$$ = new symbolic_variable_c($1, locloc(@$)); $$->token = $1->token;}
;


symbolic_variable:
/* NOTE: To be entirely correct, variable_name must be replacemed by
 *         prev_declared_variable_name | prev_declared_fb_name | prev_declared_global_var_name
 */
  prev_declared_fb_name
	{$$ = new symbolic_variable_c($1, locloc(@$)); $$->token = $1->token;}
| prev_declared_global_var_name
	{$$ = new symbolic_variable_c($1, locloc(@$)); $$->token = $1->token;}
| prev_declared_variable_name
	{$$ = new symbolic_variable_c($1, locloc(@$)); $$->token = $1->token;}
| multi_element_variable
/*
| identifier
	{$$ = new symbolic_variable_c($1, locloc(@$)); $$->token = $1->token;}
*/
| symbolic_variable '^'     
	/* Dereferencing operator defined in IEC 61131-3 v3. However, implemented here differently then how it is defined in the standard! See following note for explanation! */
	{$$ = new deref_operator_c($1, locloc(@$));
	 if (!allow_ref_dereferencing) {
	   print_err_msg(locf(@$), locl(@$), "Derefencing REF_TO datatypes with '^' is not allowed (use -r option to activate support for this IEC 61131-3 v3 feature)."); 
	   yynerrs++;
	 }
}
/*自己添加的解引用规则*/
| deref_expression
	{$$ = new deref_expression_c($1, locloc(@$));}
;
5.对比codesys

image.png

image.png image.png