Dušan Ferbas Programování Mosaic 12. 6. 2024 12:02 14. 4. 2023 16:20

Dobrý den,

snažím se najít způsob, jak vyfiltrovat množinu čísel bitovým vzorem.

Např. mám typy zařízení, definované enumeračním datovým typem, který jsem si v nějakém návodě přečetl, že Mosaic překládá jako USINT.
Proto není možné použít např. 16#0100 pro enum hodnotu.

Nyní mám funkční blok a chtěl bych, aby při volání s pattern := 16#0001 OR 16#0004 pracoval se zařízeními Inverter a Battery, při volání s pattern := 16#0008 pak jen s Meter. Veškeré mé pokusy končí v Mosaicu na nepovolenéí kombinaci typů nebo na ěčem podobném.
Napadá mě přestat používat enum a použít číslo nebo udělat funkci s case podle enumu a přiřadit potřebné číslo.
Jde to udělat nějak elegantněji a jednodušeji?

  EDeviceType : (NaN,
   Inverter,
   StringBox,
   Battery,
   Meter,
   System,
   MiB_Xtender,
   MiB_varioTrack,
   MiB_varioString,
   MiB_Battery,
   MiB_System
 );

 

  tmp : WORD;
END_VAR
VAR CONSTANT
  DEV_MAPPING : ARRAY [1 .. 9] OF WORD := [
    0, 16#0001, 16#0002, 16#0004, 16#0008, 16#0010, 16#0020, 16#0040, 16#0080
  ];
END_VAR
...
  (* check if communication with this device type is required *)
  tmp := SHL(1, DevInfoActPtr^.DeviceType);		//nejde
  IF tmp AND pattern THEN
  IF DEV_MAPPING[DevInfoActPtr^.DeviceType] AND pattern THEN 	//ani tahle indexace pole nejde

 

Odpovědi 2

M.B. 14. 4. 2023 9:27

Dobrý den,

s pohledu jazyka ST, který neurčuje jak má být hodnota ENUM implementována, a proto s ním běžnými způsoby nedovoluje pracovat jako s číslem, je nejlepší napsat funkci, která bude vracet masku podle enumerace.

FUNCTION GetDeviceTypeMask : WORD
  VAR_INPUT
    devType : EDeviceType;
  END_VAR

  CASE devType OF
    Inverter :
      GetDeviceTypeMask := 1;
    StringBox :
      GetDeviceTypeMask := 2;
    Battery :
      GetDeviceTypeMask := 4;
    Meter :
      GetDeviceTypeMask := 8;
    System :
      GetDeviceTypeMask := 16;
    MiB_Xtender :
      GetDeviceTypeMask := 32;
    MiB_varioTrack :
      GetDeviceTypeMask := 64;
    MiB_varioString :
      GetDeviceTypeMask := 128;
    MiB_Battery :
      GetDeviceTypeMask := 256;
    MiB_System :
      GetDeviceTypeMask := 512;
  ELSE
    GetDeviceTypeMask := 0;
  END_CASE;
END_FUNCTION

Další možnost je použítí pojmenovaných konstant místo enumerace, kde hodnota konstanty bude požadovaná maska.

Jako posledním uvádím možnost konverze ENUM na USINT použitím pointeru. Tuto možnost však nedoporučuji, protože je závislá na tom, nad jakým typem a jakým způsobem je ENUM implementován.

FUNCTION GetDeviceTypeNum : USINT
  VAR_INPUT
    devType : EDeviceType;
  END_VAR
  VAR_TEMP
    p : PTR_TO USINT;
  END_VAR

  p := ADR(devType);
  GetDeviceTypeNum := p^;

END_FUNCTION

 

Dušan Ferbas 14. 4. 2023 16:20

Dobrý den,

děkuji za promptní odpověď.
Ještě mám dotaz ze 7.4. CFC x ST.

Nezávisle na Vás jsem zvolil něco podobného. Nicméně při přidání do enumu je nutné přidat i do této funkce, což je nectnost tohoto řešení :-).
Ve funkci jsem zapomněl ošetřit ten chybový stav, za tip děkuji.

 DEV_TYPE_INVERTER : WORD        := 16#0001;
 DEV_TYPE_STRINGBOX : WORD       := 16#0002;
 DEV_TYPE_BATTERY : WORD         := 16#0004;
 DEV_TYPE_METER : WORD           := 16#0008;
 DEV_TYPE_SYSTEM : WORD          := 16#0010;
 DEV_TYPE_MIB_XTENDER : WORD     := 16#0020;
 DEV_TYPE_MIB_VARIOTRACK : WORD  := 16#0040;
 DEV_TYPE_MIB_VARIOSTRING : WORD := 16#0080;
 DEV_TYPE_MIB_BATTERY : WORD     := 16#0100;

 

FUNCTION ENUM_TO_BIT_PATTERN : WORD
(*
 This auxilliary function "converts" enum to bit pattern.
*)
 VAR_INPUT
   devType : EDeviceType;
 END_VAR

 CASE devType OF
   Inverter:
     ENUM_TO_BIT_PATTERN := DEV_TYPE_INVERTER;
   StringBox:
     ENUM_TO_BIT_PATTERN := DEV_TYPE_STRINGBOX;
   Battery:
     ENUM_TO_BIT_PATTERN := DEV_TYPE_BATTERY;
   Meter:
     ENUM_TO_BIT_PATTERN := DEV_TYPE_METER;
   System:
     ENUM_TO_BIT_PATTERN := DEV_TYPE_SYSTEM;
   MiB_Xtender:
     ENUM_TO_BIT_PATTERN := DEV_TYPE_MIB_XTENDER;
   MiB_varioTrack:
     ENUM_TO_BIT_PATTERN := DEV_TYPE_MIB_VARIOTRACK;
   MiB_varioString:
     ENUM_TO_BIT_PATTERN := DEV_TYPE_MIB_VARIOSTRING;
   MiB_Battery:
     ENUM_TO_BIT_PATTERN := DEV_TYPE_MIB_BATTERY;
 END_CASE;
END_FUNCTION

Tento dotaz je vyřešený.