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
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
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ý.