Задача: написать некую функцию для для опроса Db (200 byte) при обнаружении первого бита равного "1" выдавать его номер тоесть например: в шестом байте 3 бит = 1 то результатом функции будет 5*8+3=43.
Функция готова и даже работает (иногда ) проблема в том что при некоторых ситуациях она вызывает зацикливание и контроллер естественно уходит в стоп по превышению времени цикла.
Помогите разобраться!
FUNCTION "AIS_LOOK_FOR_ALARM" : VOID
TITLE =
VERSION : 0.1
VAR_INPUT
DB_source : INT ;
lenght_byte : INT ;
start_byte : INT ;
END_VAR
VAR_OUTPUT
ALARM_NUMBER : WORD ;
END_VAR
VAR_TEMP
db_s : WORD ;
item : INT ;
SB : INT ;
PS : DWORD ;
item_p : INT ;
status_byte : BYTE ;
DES_ALARM : INT ;
OSTATOK : INT ;
END_VAR
BEGIN
NETWORK
TITLE =
L #start_byte;
T #SB;
L 0;
T #item;
L #DB_source;
T #db_s;
loop: L 0;
T #OSTATOK;
T #DES_ALARM;
L #SB;
L #item;
+I ;
SLD 3;
T #PS;
AUF DB [#db_s];
L DBB [#PS];
T #status_byte;
L B#16#0;
<>I ;
SPB calc;
L #item;
INC 1;
T #item;
L #lenght_byte;
>=I ;
SPB end;
SPA loop;
calc: L 0;
T #OSTATOK;
T #DES_ALARM;
L #item;
L 0;
==I ;
SPB m000;
L #item;
DEC 1;
T #item_p;
L 8;
*I ;
T #DES_ALARM;
//Номер бита в найденом байте
m000: NOP 0;
U L 12.0;
SPBN m001;
L 1;
T #OSTATOK;
SPA end;
m001: U L 12.1;
SPBN m002;
L 2;
T #OSTATOK;
SPA end;
m002: U L 12.2;
SPBN m003;
L 3;
T #OSTATOK;
SPA end;
m003: U L 12.3;
SPBN m004;
L 4;
T #OSTATOK;
SPA end;
m004: U L 12.4;
SPBN m005;
L 5;
T #OSTATOK;
SPA end;
m005: U L 12.5;
SPBN m004;
L 6;
T #OSTATOK;
SPA end;
m006: U L 12.6;
SPBN m006;
L 7;
T #OSTATOK;
SPA end;
m007: U L 12.7;
SPBN m007;
L 8;
T #OSTATOK;
SPA end;
end: L #DES_ALARM;
L #OSTATOK;
+I ;
T #ALARM_NUMBER;
END_FUNCTION
L "DB500".DB_Report_Check
L 800
>I
JC lops
L "DB500".Number_Reports
T "DB500".DB_Number_Loops
lops: L "DB500".DB_Number_Loops //загрузка стартового значения для циклов
DBad: T "DB500".DB_Number_Loops //скока циклов осталось
L "DB500".DB_Report_Check
OPN DB [DBW 4]
A DBX 22.0
S "Mem_Report_Present"
A DBX 22.0
JC next
A "Mem_Report_Present"
JC next
L "DB500".DI_Report_Check
L 1
+I
T "DB500".DI_Report_Check
L "DB500".DB_Report_Check
L 1
+I
T "DB500".DB_Report_Check
L "DB500".DB_Number_Loops //загрузка циклов для вычитания
LOOP DBad
JU end
next: T "DB500".DB_Number
L 200
-I
T "DB500".DI_Number
L 1
+I
T "DB500".DI_Report_Check
L 200
+I
T "DB500".DB_Report_Check
L "DB500".DB_Number_Loops
L 1
-I
T "DB500".DB_Number_Loops
FUNCTION "AIS_LOOK_FOR_ALARM" : VOID
TITLE =
VERSION : 0.1
VAR_INPUT
DB_source : INT ;
lenght_byte : INT ;
start_byte : INT ;
END_VAR
VAR_OUTPUT
ALARM_NUMBER : WORD ;
END_VAR
VAR_TEMP
db_s : WORD ;
item : INT ;
SB : INT ;
PS : DWORD ;
item_p : INT ;
status_byte : BYTE ;
DES_ALARM : INT ;
OSTATOK : INT ;
END_VAR
BEGIN
NETWORK
TITLE =
L #start_byte;
T #SB;
L #DB_source;
T #db_s;
L 0;
lops: T #item;
L #item;
L #lenght_byte;
>=I ;
SPB calc;
L 0;
T #OSTATOK;
T #DES_ALARM;
L #SB;
L #item;
+I ;
SLD 3;
T #PS;
AUF DB [#db_s];
L DBB [#PS];
T #status_byte;
L 2#0;
<>I ;
SPB calc;
L #item;
LOOP lops;
calc: L 0;
T #OSTATOK;
T #DES_ALARM;
L #item;
L 0;
==I ;
SPB m000;
L #item;
DEC 1;
T #item_p;
L 8;
*I ;
T #DES_ALARM;
//Номер бита в найденом байте
m000: NOP 0;
U L 12.0;
SPBN m001;
L 1;
T #OSTATOK;
SPA end;
m001: U L 12.1;
SPBN m002;
L 2;
T #OSTATOK;
SPA end;
m002: U L 12.2;
SPBN m003;
L 3;
T #OSTATOK;
SPA end;
m003: U L 12.3;
SPBN m004;
L 4;
T #OSTATOK;
SPA end;
m004: U L 12.4;
SPBN m005;
L 5;
T #OSTATOK;
SPA end;
m005: U L 12.5;
SPBN m004;
L 6;
T #OSTATOK;
SPA end;
m006: U L 12.6;
SPBN m006;
L 7;
T #OSTATOK;
SPA end;
m007: U L 12.7;
SPBN m007;
L 8;
T #OSTATOK;
SPA end;
end: L #DES_ALARM;
L #OSTATOK;
+I ;
T #ALARM_NUMBER;
END_FUNCTION
как было сказано указатель циклов обязан быть >0,иначе он не выйдет из него
ну нашёл бит,а дальше остальные проверять не надо?
может просто без циклов сделать?
понятно,что не красиво,зато просто
можно сделать циклами,тока ответь на вопросы
это так,наскоряк накидал
L L#0
T #DES_ALARM_WORD //Set to 0
T #DES_ALARM_BYTE //Set to 0
T #OSTATOK //Set to 0
L DBD0
<>D
T #status_dword
L 0
JC Chck
L L#0
L DBD4
<>D
T #status_dword
L 4
JC Chck
// и т.д и т.п.
L L#0
L DBD196
<>D
T #status_dword
L 196
JC Chck
JU All0
Chck: T Int_Temp
L 8
*I
T #DES_ALARM_DWORD
L 0
L LB12 // 1st byte #status_dword
<>I
T #status_byte
L 0
JC Byte
// и т.д и т.п.
L 0
L LB16 // 4 byte #status_dword
<>I
T #status_byte
L 4
JC Byte
JU All0
Byte: T Byte_Temp
L 8
*I
T #DES_ALARM_BYTE
// теперь проверка бита как ты сделал
All0:L #DES_ALARM_WORD
L #DES_ALARM_BYTE
+I
L #OSTATOK
+I
T #ALARM_NUMBER
ДЛя текущей задачи вроде как и не надо! Но может потребоваться!
Похоже дело не только в цикле где то ещё косяк т. к. что с LOOP что просто переходом эффект одинаковый тоесть функция работает в тех случаях когда бит находится не на краях байта то есть не 1ый или не 8 ой как только эти биты то контроллер встаёт по TIME CYCLE EXCEPT вот вариант последней версии вместе с DB и вызовом
Есть у кого какие мысли! Может кто из опытных программеров откомпилирует исходник
DATA_BLOCK "DB11_данные ПК"
VERSION : 0.0
STRUCT
D0 : WORD ;
D01 : WORD ; //аварии 1-16
D02 : WORD ; //аварии 17-32
D03 : WORD ; //аварии 33-48
D04 : WORD ; //аварии 49-64
D05 : WORD ; //аварии 65-80
D06 : WORD ; //аварии 81-96
D07 : WORD ; //аварии 97-112
D08 : WORD ; //аварии 113-128
D09 : WORD ; //аварии 129-144
D010 : WORD ; //аварии 145-160
D011 : WORD ; //аварии 161-176
D012 : WORD ; //аварии 177-192
D013 : WORD ; //аварии 193-208
D014 : WORD ; //аварии 209-224
D015 : WORD ; //аварии 225-240
D016 : WORD ; //сообщения 241-256
D017 : WORD ; //сообщения 257-272
D018 : WORD ; //сообщения 273-288
D019 : WORD ; //сообщения 289-304
D020 : WORD ; //сообщения 305-320
D021 : WORD ; //сообщения 321-336
D022 : WORD ;
END_STRUCT ;
BEGIN
D0 := W#16#0;
D01 := W#16#0;
D02 := W#16#0;
D03 := W#16#0;
D04 := W#16#0;
D05 := W#16#0;
D06 := W#16#1010;
D07 := W#16#1010;
D08 := W#16#1010;
D09 := W#16#1010;
D010 := W#16#0;
D011 := W#16#0;
D012 := W#16#0;
D013 := W#16#0;
D014 := W#16#0;
D015 := W#16#111;
D016 := W#16#101;
D017 := W#16#0;
D018 := W#16#0;
D019 := W#16#0;
D020 := W#16#0;
D021 := W#16#42;
D022 := W#16#0;
END_DATA_BLOCK
FUNCTION "AIS_LOOK_FOR_ALARM" : VOID
TITLE =
VERSION : 0.1
VAR_INPUT
DB_source : INT ;
lenght_byte : INT ;
start_byte : INT ;
END_VAR
VAR_OUTPUT
ALARM_NUMBER : WORD ;
END_VAR
VAR_TEMP
db_s : WORD ;
item : INT ;
SB : INT ;
PS : DWORD ;
item_p : INT ;
status_byte : BYTE ;
DES_ALARM : INT ;
OSTATOK : INT ;
item_t : INT ;
END_VAR
BEGIN
NETWORK
TITLE =
L #start_byte;
T #SB;
L #DB_source;
T #db_s;
L #lenght_byte;
lops: T #item;
L #lenght_byte;
L #item;
-I ;
T #item_p;
L #SB;
L #item_p;
+I ;
SLD 3;
T #PS;
AUF DB [#db_s];
L DBB [#PS];
T #status_byte;
L B#16#0;
<>I ;
SPB ext;
L #item;
LOOP lops;
ext: L 0;
T #OSTATOK;
T #DES_ALARM;
L #item_p;
L 0;
==I ;
SPB m000;
L #item_p;
DEC 1;
T #item_t;
L 8;
*I ;
T #DES_ALARM;
//Номер бита в найденом байте
m000: NOP 0;
U L 12.0;
SPBN m001;
L 1;
T #OSTATOK;
SPA end;
m001: U L 12.1;
SPBN m002;
L 2;
T #OSTATOK;
SPA end;
m002: U L 12.2;
SPBN m003;
L 3;
T #OSTATOK;
SPA end;
m003: U L 12.3;
SPBN m004;
L 4;
T #OSTATOK;
SPA end;
m004: U L 12.4;
SPBN m005;
L 5;
T #OSTATOK;
SPA end;
m005: U L 12.5;
SPBN m004;
L 6;
T #OSTATOK;
SPA end;
m006: U L 12.6;
SPBN m006;
L 7;
T #OSTATOK;
SPA end;
m007: U L 12.7;
SPBN m007;
L 8;
T #OSTATOK;
SPA end;
end: L #DES_ALARM;
L #OSTATOK;
+I ;
T #ALARM_NUMBER;
END_FUNCTION
ORGANIZATION_BLOCK OB 1
VERSION : 0.1
VAR_TEMP
OB1_EV_CLASS : BYTE ; //Bits 0-3 = 1 (Coming event), Bits 4-7 = 1 (Event class 1)
OB1_SCAN_1 : BYTE ; //1 (Cold restart scan 1 of OB 1), 3 (Scan 2-n of OB 1)
OB1_PRIORITY : BYTE ; //Priority of OB Execution
OB1_OB_NUMBR : BYTE ; //1 (Organization block 1, OB1)
OB1_RESERVED_1 : BYTE ; //Reserved for system
OB1_RESERVED_2 : BYTE ; //Reserved for system
OB1_PREV_CYCLE : INT ; //Cycle time of previous OB1 scan (milliseconds)
OB1_MIN_CYCLE : INT ; //Minimum cycle time of OB1 (milliseconds)
OB1_MAX_CYCLE : INT ; //Maximum cycle time of OB1 (milliseconds)
OB1_DATE_TIME : DATE_AND_TIME ; //Date and time OB1 started
END_VAR
BEGIN
NETWORK
TITLE =
CALL "AIS_LOOK_FOR_ALARM" (
DB_source := 11,
lenght_byte := 30,
start_byte := 2,
ALARM_NUMBER := MW 10);
END_ORGANIZATION_BLOCK
DATA_BLOCK DB 20
TITLE =
VERSION : 0.1
STRUCT
Alarm1 : INT ;
Alarm2 : INT ;
Alarm3 : INT ;
Alarm4 : INT ;
Alarm5 : INT ;
Alarm6 : INT ;
Alarm7 : INT ;
Alarm8 : INT ;
Alarm9 : INT ;
Alarm10 : INT ;
Alarm11 : INT ;
Alarm12 : INT ;
END_STRUCT ;
BEGIN
Alarm1 := 0;
Alarm2 := 0;
Alarm3 := 0;
Alarm4 := 0;
Alarm5 := 0;
Alarm6 := 0;
Alarm7 := 0;
Alarm8 := 0;
Alarm9 := 0;
Alarm10 := 0;
Alarm11 := 0;
Alarm12 := 0;
END_DATA_BLOCK
FUNCTION FC 1 : VOID
TITLE =
VERSION : 0.1
VAR_INPUT
DB_Number : INT ;
Start_Byte : INT ;
DB_Leight : INT ;
END_VAR
VAR_OUTPUT
Number_Alarm : INT ;
END_VAR
VAR_TEMP
DB_N : INT ;
Loop_Chck : INT ;
Start_Bit : INT ;
End_Bit : INT ;
Check_Bit : DINT ;
END_VAR
BEGIN
NETWORK
TITLE =
L #DB_Number;
T #DB_N;
OPN DB [#DB_N];
L #Start_Byte;
SLW 3;
T #Start_Bit;
L #DB_Leight;
SLW 3;
T #Loop_Chck;
L #Start_Bit;
+I ;
T #End_Bit;
L #Loop_Chck;
lop1: T #Loop_Chck;
L #End_Bit;
TAK ;
-I ;
T #Check_Bit;
A DBX [#Check_Bit];
JC Alrm;
L #Loop_Chck;
LOOP lop1;
L 0;
T #Check_Bit;
JU End;
Alrm: L #Check_Bit;
L #Start_Bit;
-I ;
L 1;
+I ;
End: T #Number_Alarm;
END_FUNCTION
ORGANIZATION_BLOCK OB 1
TITLE = "Main Program Sweep (Cycle)"
VERSION : 0.1
VAR_TEMP
OB1_EV_CLASS : BYTE ; //Bits 0-3 = 1 (Coming event), Bits 4-7 = 1 (Event class 1)
OB1_SCAN_1 : BYTE ; //1 (Cold restart scan 1 of OB 1), 3 (Scan 2-n of OB 1)
OB1_PRIORITY : BYTE ; //Priority of OB Execution
OB1_OB_NUMBR : BYTE ; //1 (Organization block 1, OB1)
OB1_RESERVED_1 : BYTE ; //Reserved for system
OB1_RESERVED_2 : BYTE ; //Reserved for system
OB1_PREV_CYCLE : INT ; //Cycle time of previous OB1 scan (milliseconds)
OB1_MIN_CYCLE : INT ; //Minimum cycle time of OB1 (milliseconds)
OB1_MAX_CYCLE : INT ; //Maximum cycle time of OB1 (milliseconds)
OB1_DATE_TIME : DATE_AND_TIME ; //Date and time OB1 started
END_VAR
BEGIN
NETWORK
TITLE =
CALL FC 1 (
DB_Number := 20,
Start_Byte := 0,
DB_Leight := 20,
Number_Alarm := MW 0);
NOP 0;
END_ORGANIZATION_BLOCK