Код:
PROGRAM USB_PRG
VAR
Name_old:STRING(12);
rTMP1,rTMP2,rTMP3,rTMP4:REAL;
LAG1,LAG2:LAG;
(*Переменные для обслуживания библиотеки SysLibTime*)
GetTime: CurTimeEx;
TimeAndDate: SystemTimeDate;
Sys_Time: SysTime64;
set_time: BOOL := 0; (*установить дату*)
set_date: BOOL := 0; (*установить время*)
(*Переменные для обслуживания библиотеки OwenLibFileAsync*)
pref:STRING:='usb:'; (*префикс названия файла, варианты префиксов:
usb: - съемный flash-носитель;
ffs: (или отсутствие!) - внутренняя память;
ram: тестовый RAM диск*)
handle:DWORD:=0; (*дескриптор файла*)
res: ASYNC_RET_VALUE; (*переменная для организации работы библиотеки OwenLibFileAsync*)
result:DWORD; (*размер буфера*)
StartArchivation: BOOL; (*Переменная запуска архивации. Для начала архивации задайте переменной значение TRUE, для остановки архивации - FALSE.*)
timer_archiv: TON; (*таймер архивации*)
header: STRING(255); (*заголовок таблицы*)
need_new_header: BOOL := 0; (*необходимость сформировать новый заголовок*)
start_archiv: BOOL := 0;
divider:DWORD;
index_old:WORD;
R_TRIG:R_TRIG;
count:INT;
END_VAR
VAR RETAIN
name_of_file: STRING; (*название файла с префиксом*)
today: UINT; (*сегодняшнее число*)
END_VAR
IF Messages.ALARM[0] <> '' THEN
TRIP:=TRUE;
IF Name='' THEN Name:='LOGFILES'; END_IF;
(*Далее сохраняем на USB*)
(*-------------Работа с временем и датой ПЛК------------*)
(* Получаем текущее время и дату*)
HH := Hour ; (* Значение времени в часах *)
MM := Minute ; (* Значение времени в минутах *)
SS := Second ; (* Значение времени в секундах *)
DD := Day ; (* Значение даты в днях *)
MT := Month ; (* Значение даты в месяцах *)
YYYY:= Year ; (* Значение даты в годах *)
(*Если set_time - истина, то можно менять время*)
IF set_time THEN
set_time:=0;
TimeAndDate.Minute:=MM;
TimeAndDate.Second:=SS;
TimeAndDate.Hour:=HH;
GetTime (SystemTime:=Sys_Time , TimeDate:= TimeAndDate);
END_IF
(*Если set_date - истина, то можно менять дату*)
IF set_date THEN
set_date:=0;
TimeAndDate.Day:=DD;
TimeAndDate.Month:=MT;
TimeAndDate.Year:=YYYY;
GetTime (SystemTime:=Sys_Time , TimeDate:= TimeAndDate);
END_IF;
index:=index;
Messages.FLAG[index]:=Messages.FLAG[index];
IF NOT Messages.FLAG[index] THEN (*если необходимо архивировать, то*)
IF Name<>Name_old THEN (*если наступил новый день, то формируем новый файл с новым именем даты*)
name_of_file:=CONCAT(pref,Name);
name_of_file:=CONCAT(name_of_file,UINT_TO_STRING(DD));
name_of_file:=CONCAT(name_of_file,'.');
name_of_file:=CONCAT(name_of_file,UINT_TO_STRING(MT));
name_of_file:=CONCAT(name_of_file,'.');
name_of_file:=CONCAT(name_of_file,UINT_TO_STRING(YYYY));
name_of_file:=CONCAT(name_of_file,'.csv');
today:=DD;(*запомнить дату *)
need_new_header:=1;(*далее в новом файле необходимо будет создать "шапку" архива*)
Name_old:=Name;
END_IF
(*-------------Работа с библиотекой OwenLibFileAsync------------*)
CASE state OF
0: (*Открытие файла - этап 1*)
res:=OwenFileOpenAsync(name_of_file,'a',ADR(handle));;(*возвращает дескриптор файла, либо 0 (в некоторых случаях 4 294 967 295 или -1) в случае ошибки*)
IF res=ASYNC_WORKING THEN
state:=1;(*нет ошибок, переход на открытие файла этап 2*)
ELSE state:=0;
END_IF
1: (*Открытие файла - этап 2*)
res:=OwenFileOpenAsync(name_of_file,'a',ADR(handle));
IF res=ASYNC_DONE THEN (*если "готов", и нет ошибок, то переход в состояние 2*)
IF handle<>0 THEN
state:=2;(*нет ошибок, переход на запись этап 1*)
ELSE
state:=0;(*иначе можно перейти на 1 этап открытия файла, либо предусмотреть собственное действие самостоятельно *)
END_IF
ELSIF res<0 THEN
state:=0;
END_IF
2: (*Запись в файл - этап 1*)
IF need_new_header THEN (*если новый день суток, формируем новую" шапку"*)
(*формируем колонку Дата*)
header:=CONCAT('Индекс',';');(*|число.месяц.год.|*)
(*формируем колонку с именем первой переменной var1*)
header:=CONCAT(header,'Сообщение');(*|var1*)
header:=CONCAT(header,';');(*|var1|*)
header:=CONCAT(header, '$0A');(*OA =Line Feed - перевод строки, см. таблицу ASCII -символов*)
(*заполняем следующую строку непосредственно данными*)
header:=CONCAT(header,UINT_TO_STRING(index));(*|число*)
header:=CONCAT(header,';');(*|число.*)
(*формируем значение первой переменной var1*)
header:=CONCAT(header, Messages.ALARM[index]);(**)
header:=CONCAT(header,';');(**)
header:=CONCAT(header, '$0A');(*OA =Line Feed - перевод строки, см. ASCII таблицу*)
need_new_header:=0;(*сбрасываем необходимость формировать "шапку" в следующий раз*)
ELSE (*иначе, если файл открывается на дозапись,то формируем только строку архива в формате |число.месяц.год|часы.минуты.секунды|значение var1|значение var2|*)
(*заполняем следующую строку непосредственно данными*)
header:=CONCAT(header,UINT_TO_STRING(index));(*|число*)
header:=CONCAT(header,';');(*|число.*)
(*формируем значение первой переменной var1*)
header:=CONCAT(header, Messages.ALARM[index]);(**)
header:=CONCAT(header,';');(**)
header:=CONCAT(header, '$0A');(*OA =Line Feed - перевод строки, см. ASCII таблицу*)
END_IF
(*Пишем строку в файл*)
res:=OwenFileWriteAsync(handle,ADR(header), LEN(header), ADR(result));(*пишем данные *)
IF res=ASYNC_WORKING THEN
state:=3;(*нет ошибок, переход на запись файла этап 2, либо по усмотрению пользователя*)
ELSE
state:=4;(*иначе можно перейти на этап закрытия файла, либо предусмотреть собственное действие самостоятельно *)
END_IF
3: (*Запись в файл - этап 2*)
res:=OwenFileWriteAsync(handle,ADR(header), LEN(header), ADR(result));
IF res=ASYNC_DONE THEN
IF result=LEN(header) THEN (*если результат равен длине строки, то перейти к закрытию файла, либо по усмотрению пользователя*)
state:=4;
ELSE
state:=4;(*иначе всё равно перейти на закрытие *)
END_IF
ELSIF res<0 THEN
state:=0;
END_IF
4: (*Закрываем файл - этап 1*)
res:=OwenFileCloseAsync(handle, ADR(result));
IF res=ASYNC_WORKING THEN
state:=5;(*нет ошибок, переход на закрытие файла этап 2*, либо по усмотрению пользователя*)
ELSE
state:=0;(*иначе можно перейти на этап открытия файла, либо предусмотреть собственное действие самостоятельно *)
END_IF
5: (*Закрываем файл - этап 2*)
res:=OwenFileCloseAsync(handle, ADR(result));
Messages.FLAG[index]:=1;
IF index<=98 THEN index:=index+1; END_IF;
IF res=ASYNC_DONE THEN header:='';
handle:=0;
IF result=0 THEN
state:=0;(*если файл закрыт успешно, то выходим из условного оператора CASE *)
ELSE
state:=0;(*иначе всё равно выходим, либо предусмореть собственное действие*)
END_IF
ELSIF res<0 THEN (*выход, либо собственное действие*)
state:=0;
END_IF
ELSE state:=0;
END_CASE
END_IF;
(*
Messages_ALARM1_old:=Messages.ALARM[99];
index_old:=index;
*)
IF index>=99 THEN
FOR i:=0 TO 98 BY 1 DO
Messages.FLAG[i]:=0;
Messages.ALARM[i]:='';
END_FOR;
index:=0;
TRIP:=FALSE;
END_IF;
END_IF;
Messages.FLAG[i]:=Messages.FLAG[i];
Count:=Count+1;
Прошу подсказать как можно организовать вывод текстовых сообщений с индексом и временем возникновения события