我正在尝试在 Beckhoff 中重用我在 Codesys 中使用多年的 FB。 Beckhoff 基于 Codesys,因此我预计不会出现任何问题。我认为该错误与 Codesys 中可能的类型转换有关,但在 Beckhoff 中则不然。错误:无法将类型“UDINT”转换为类型“POINTER TO BOOL”。
在我的代码下面可以找到。该 FB 已在多个项目中使用 IFM 的 PLC 工作了 5 年以上。
FUNCTION_BLOCK FC_AlarmsHandler
VAR_INPUT
LI_bIN: BOOL;
/// Reset Alarms bits - only Alarms that are acknowledged
LI_bReset: BOOL;
/// Acknowledge all active Alarms bits at once
LI_bAckAll: BOOL;
/// Hold time of new alarm
LI_rHoldTimeNewAlarms: REAL;
/// Base address of Alarms group struct
LI_adrAlarmsGroup: DWORD;
/// Number of Alarms group elements
LI_sizeofAlarmsGroup: UINT;
/// Base address of Alarms struct
LI_adrAlarms: DWORD;
/// Base address of Alarms old array of bool
LI_adrAlarmsOld: DWORD;
/// Base address of Alarms hold array of bool
LI_adrAlarmsHold: DWORD;
/// Base address of Alarms acknowledge array of bool
LI_adrAlarmsAck: DWORD;
LI_adrAlarmsText: POINTER TO STRING(64);
END_VAR
VAR_OUTPUT
LQ_bOUT: BOOL;
/// New Alarm -> this output is one cycle high
LQ_bNewAlarm: BOOL;
/// When an alarm is active, this output is high
LQ_bAlarmActive: BOOL;
/// Alarm gone -> this output is one cycle high
LQ_bAlarmGone: BOOL;
END_VAR
VAR
LT_bInit: BOOL;
/// offset for group address
LT_adrOffsetGroup: DWORD;
LT_iNumberOfAlarmGroupElements: UINT;
/// Number of lines for alarm visualization table in Hmi
LT_iNumberOfHmiLines: INT;
/// Number of lines for alarm history visualization table in Hmi
LT_iNumberOfHmiHistoryLines: INT;
LT_ptAlarms: POINTER TO BOOL;
LT_ptAlarmsOld: POINTER TO BOOL;
LT_ptAlarmsHold: POINTER TO BOOL;
LT_ptAlarmsAck: POINTER TO BOOL;
LT_ptAlarmsText: POINTER TO STRING(64);
LT_iCounterAlarmsElements: INT;
/// Timer for holding new alarm
fbTofNewAlarm: TOF;
END_VAR
LQ_bOUT:=LI_bIN;
// Init
IF LT_bInit = FALSE THEN
LT_adrOffsetGroup := LI_adrAlarmsGroup - LI_adrAlarms;
LT_iNumberOfAlarmGroupElements := LI_sizeofAlarmsGroup / SIZEOF(LT_ptAlarms^);
// Alarm array for HMI
LT_iNumberOfHmiLines := GDI_Alarms.iNumberOfHmiLines;
// Alarm history array for HMI
LT_iNumberOfHmiHistoryLines := GDI_Alarms.iNumberOfHmiHistoryLines;
LT_bInit := TRUE;
END_IF
(***************************************************************************)
(* Alarm handling *)
(***************************************************************************)
[HERE I AM HAVING MY PROBLEMS]
// Init new scan cycle
LT_ptAlarms := LI_adrAlarms + (LT_adrOffsetGroup * SIZEOF(LT_ptAlarms^));
LT_ptAlarmsText := LI_adrAlarmsText + (LT_adrOffsetGroup * SIZEOF(LT_ptAlarmsText^));
LT_ptAlarmsOld := LI_adrAlarmsOld + (LT_adrOffsetGroup * SIZEOF(LT_ptAlarmsOld^));
LT_ptAlarmsHold := LI_adrAlarmsHold + (LT_adrOffsetGroup * SIZEOF(LT_ptAlarmsHold^));
LT_ptAlarmsAck := LI_adrAlarmsAck + (LT_adrOffsetGroup * SIZEOF(LT_ptAlarmsAck^));
LQ_bNewAlarm:= FALSE;
LQ_bAlarmActive := FALSE;
LQ_bAlarmGone := FALSE;
FOR LT_iCounterAlarmsElements := 1 TO LT_iNumberOfAlarmGroupElements DO // Scan all data of group
// Check for new alarms
IF LT_ptAlarms^ AND NOT LT_ptAlarmsOld^ THEN
LQ_bNewAlarm:= TRUE;
END_IF
// Reset current alarms
IF LI_bReset AND LT_ptAlarmsAck^ AND NOT LT_ptAlarms^ THEN
LT_ptAlarms^ := FALSE;
ELSE
LT_ptAlarms^ := LT_ptAlarms^ OR LT_ptAlarmsOld^; (* keep alarms true *)
END_IF
// Hold new alarms
IF fbTofNewAlarm.Q = TRUE THEN
LT_ptAlarmsHold^ := LT_ptAlarms^ OR LT_ptAlarmsHold^;
ELSE
LT_ptAlarmsHold^ := LT_ptAlarms^;
END_IF
// Acknowlegde current alarms
IF LI_bAckAll THEN
LT_ptAlarmsAck^ := LT_ptAlarms^;
END_IF
// check if alarm is gone
IF NOT LT_ptAlarms^ AND LT_ptAlarmsOld^ THEN
LQ_bAlarmGone := TRUE;
END_IF
// Alarms active
IF LT_ptAlarms^ THEN
LQ_bAlarmActive:= TRUE;
END_IF
// Save old value
LT_ptAlarmsOld^ := LT_ptAlarms^;
// Next element
LT_ptAlarms := LT_ptAlarms + SIZEOF(LT_ptAlarms^); // Pointer to next element
LT_ptAlarmsText := LT_ptAlarmsText + SIZEOF(LT_ptAlarmsText^); // Pointer to next element
LT_ptAlarmsOld := LT_ptAlarmsOld + SIZEOF(LT_ptAlarmsOld^); // Pointer to next element
LT_ptAlarmsHold := LT_ptAlarmsHold + SIZEOF(LT_ptAlarmsHold^); // Pointer to next element
LT_ptAlarmsAck := LT_ptAlarmsAck + SIZEOF(LT_ptAlarmsAck^); // Pointer to next element
END_FOR
fbTofNewAlarm(in:= LQ_bNewAlarm, PT:= REAL_TO_TIME(LI_rHoldTimeNewAlarms), Q=> , ET=> );
我已经尝试添加转换 UDINT_TOPBOOL、UDINT_TODWORD (因为标准指针数据类型),但这不起作用。
我强烈怀疑您这些年来一直使用 32 位版本的 CODESYS,现在正在转向 64 位 Beckhoff PLC。
如果是这样,您的问题不是从 CODESYS 迁移到 TwinCAT 造成的,而是从 32 位迁移到 64 位造成的。亲自尝试一下:返回 CODESYS,然后选择任何 64 位运行时。编译时会出现与 TwinCAT 中相同的错误。
您可能不应该使用 DWORD 变量来传递地址。使用“指针”。更好的是,使用“参考”。这将在不同的 CPU 架构上编译和工作。
您似乎正在使用偏移量计算在单个结构中找到的许多变量的地址,而不是使用指向该结构的单个指针(或引用)并使用“。”访问其字段。我还没有完全分析你的代码,但在我看来,它会大大简化它,因为你将摆脱所有指针计算并将这项工作卸载给编译器。