опечатку, как объяснение не рассматриваете?
Вид для печати
Конечно рассматриваю. Если бы Владислав ответил, что это опечатка, то вопрос был бы сразу закрыт.
Да, очепятка.
Владислав, добрый день!
Подскажите по такому вопросу:
Делаю архивирование на флешку.
С записью все ОК.
Некая проблема с чтением.
При MinCycleLenght в 1 мс - выходит статус ASYNC_BLOCK_ACCESS
Опытным путем понял, что при цикле в 4 мс ошибка не вылетает, и все нормально работает.
Флешка пустая, 8 гб.
Далее от ошибки не избавиться никак, помогает лишь перезагрузка.
Пробовал при ошибке выполнять OwenFileCloseAllOpenAsync, так же не помогает.
И подскажите - SysLibDir не поддерживается?
Можно как то папки создавать?
Если всё и сразу делать с циклом 1 мс - конечно будет блокировка, вы сколько файлов за раз пытаетесь обрабатывать? Максимум можно 5 штук.
Файл один.
Чтение и запись разнесены (и блокируют друг друга, чтобы избежать одновременной работы с файлом).
Все обращения к файл разделены на два этапа (как в примере).
Цитата:
CASE state OF
0: (*Открытие файла - этап 1*)
res:=OwenFileOpenAsync(Queue[0],'r',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(Queue[0],'r',ADR(handle));
IF res=ASYNC_DONE THEN (*если "готов", и нет ошибок, то переход в состояние 2*)
IF handle<>0 THEN
state:=11;(*нет ошибок, переход на чтение длины файла 1*)
ELSE
state:=0;(*иначе можно перейти на 1 этап открытия файла, либо предусмотреть собственное действие самостоятельно *)
END_IF
ELSIF res<0 THEN
state:=0;
END_IF
11: (*Чтение размера, этап 1*)
res:=OwenFileGetSizeAsync(Queue[0],ADR(sizeRead));(*возвращает дескриптор файла, либо 0 (в некоторых случаях 4 294 967 295 или -1) в случае ошибки*)
IF res=ASYNC_WORKING THEN
state:=12;(*нет ошибок, переход на открытие файла этап 2*)
ELSE
state:=4;
END_IF
12: (*Чтение размера, этап 2*)
res:=OwenFileGetSizeAsync(Queue[0],ADR(sizeRead));(*возвращает дескриптор файла, либо 0 (в некоторых случаях 4 294 967 295 или -1) в случае ошибки*)
IF res=ASYNC_DONE THEN
(*нет ошибок, переход на открытие файла этап 2*)
По условию либо state:=13; либо state:=2;
ELSE
state:=4;
END_IF
13: (*Установим начальную позиция для чтения этап 1*)
res:=OwenFileSetPosAsync(handle,posQueue,ADR(resul t));(*возвращает дескриптор файла, либо 0 (в некоторых случаях 4 294 967 295 или -1) в случае ошибки*)
IF res=ASYNC_WORKING THEN
state:=14;(*нет ошибок, переход на открытие файла этап 2*)
ELSE
state:=4;
END_IF
14: (*Установим начальную позиция для чтения этап 1*)
res:=OwenFileSetPosAsync(handle,posQueue,ADR(resul t));(*возвращает дескриптор файла, либо 0 (в некоторых случаях 4 294 967 295 или -1) в случае ошибки*)
IF res=ASYNC_DONE THEN
state:=2;(*нет ошибок, переход на открытие файла этап 2*)
ELSE
state:=4;
END_IF
2: (*Чтение из файл - этап 1*)
(*Читаем кусок из файла*)
res:=OwenFileReadAsync(handle,ADR(arrPostData), sizeRead, ADR(result));(*пишем данные *)
IF res=ASYNC_WORKING THEN
state:=3;(*нет ошибок, переход на запись файла этап 2, либо по усмотрению пользователя*)
ELSE
state:=4;(*иначе можно перейти на этап закрытия файла, либо предусмотреть собственное действие самостоятельно *)
END_IF
3: (*Запись в файл - этап 2*)
res:=OwenFileReadAsync(handle,ADR(arrPostData), sizeRead, ADR(result));(*пишем данные *)
IF res=ASYNC_DONE THEN
SysMemCpy(ADR(strAll),ADR(arrPostData),2048);
state:=4;
bGoGet:=TRUE;
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));
IF res=ASYNC_DONE THEN
bDataRead:=FALSE;
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
ASYNC_BLOCK_ACCESS возвращается если есть доступ к библиотеке с др. запросом до окончания первого.
Как же тогда возможность работы с 5 файлами?
Тогда точно будет доступ к библиотеке с другим запросом, до окончания первого.
Что делать с этим ASYNC_BLOCK_ACCESS?
Только перезагружать?
Чтобы не плодить тем:
Столкнулся с аналогичной проблемой.
Использовал работающий блок на ПЛК160/ПЛК110[М01] записи в файл на библиотеке SysLibFile на ПЛК110[M02]. На выходе получал пустой файл. Перепроверил опять же на ПЛК160 - работает. Переписал блок на библиотеке OwenLibFileAsync - на выходе пустой файл. Писал на внутреннюю флэш. Подумал, что возможно дело в старой прошивке (стояла 0.52). При попытке записать файл прошивки: либо практически сразу отваливалась связь и записывался только кусок файла, либо сразу ошибка 80. Помучился с этим делом, но записать так и не получилось. А вот после этого попробовал создать загрузочный проект - и ошибка 80:. Также обнаружил, что при включении плк зуммер не пищит (но правда не помню работал ли он вообще, так что возможно этот момент не принципиален).
С чем такое поведение может быть связано и можно ли это победить не отправляя в СЦ?
1. А каким образом это сделать?
2. Попробую.
3. Не проверял. Попробую.
У меня такая проблема тоже была при использовании SysLibFile на М02, пришел на OwenLibFileAsync.
Для форматирование есть команда в ПЛК-Браузер formatFFS.
И не забудьте, что OwenFileOpenAsync, stMode = 'a', 'w+', 'r'
Да это вроде помню)
Уважаемый Владислав!
Помогите разобраться с асинхронным выводом в файл с помощью библиотеки OwenAsyncLibFile. На основе Вашего примера пытаюсь организовать запись в файл непрерывного ряда значений переменной, которая получает приращение в рабочем цикле:
b:=b+1;
Запись в файл производится функцией:
res:=OwenFileWriteAsync(handle,ADR(bufout),14,ADR( result));
В примере обращает на себя внимание то, что запись происходит дважды: первый раз в цикле с CASE 2: и второй в цикле с CASE 3:. Получается, мы в разных циклах даем задание на передачу строковой переменной для записи. В программе одной переменной в циклах могут могут соответствовать разные строки. Методом проб и ошибок я добился нужного результата. Но вопросы остались:
В какую из попыток происходит действительно передача строки?
Как проконтролировать в программе какая из строк передана?
Хотелось бы получить более подробную информацию о работе функций библиотеки OwenAsyncLibFile от первоисточника. Или дайте ссылки на документацию, где описан порядок их работы.
в case 2 Вы задаёте библиотеке следующую команду, в Вашем случае на запись.
а в case 3 вы периодически опрашиваете библиотеку: "Не выполнила ли ты мою команду"
Собственно запись в файл происходит асинхронно в промежутке между case2 и ответом ASYNC_DONE в case3.
И подавать на вход функции записи строку надо всегда одну и ту же и не менять её значение до ASYNC_DONE! Стековые переменные для данных записи не использовать, только статические или глобальные переменные.
Спасибо.
Следовать этому совету - возражений нет. Однако, хотелось бы уточнить понятия: стековые, статические переменные. В РЭ ПЛК (в.1.9) в "Руководстве пользователя по программированию ПЛК в CoDeSys 2.3" упоминаются "стек ранее введенных команд", "стек вызовов". Стековые переменные не упоминаются. Статические переменные тоже.
Прошу уточнить Ваш совет.
в "Руководстве пользователя по программированию ПЛК в CoDeSys 2.3" нет основ программирования, подразумевается, что они уже изучены
Если Вы получили строку/массив через входные параметры функции/ФБ - это 95% стековая переменная.
Если Вы получили переменную по указателю - её содержимое внезапно может поменяться где-то там и Вы получите трудноотлаживаемую ошибку.
Если Вы объявили переменную в блоке VAR - она статическая
Если Вы объявили переменную в блоке VAR_GLOBAL - она глобальная
Вот именно на Си я читаю и пишу нормально без каких либо проблем в качестве отладки использую плату DISCAVERI STM32F407VG там вот не возникает вопросов как прочитать левый файл , и обработать , хоть по байтно хоть как , для чего мне сначала читать строчку , далее ложить ее в буфер а потом из этой строчки еще и выковыривать нужные мне данные , нельзя как то по проще все реализовать
Видео уроки они полезные как это реализовываеться , если появился новый интерфейс , новая шина , то к ней нужна полная техническая документация , по причине того что везде пишут и говорят что можно читать левые файлы с флешки , в итоге
приобрели не можем победить звоним в тех поддержку , техподдержка задает глупый вопрос , а зачем вам читать левые файлы с флешки записанные на ПК , ЕСЛИ ИНТЕРЕСНО Я МОГУ ВЫЛОЖИТЬ НЕ ОДИН ПРИМЕР РЕАЛИЗАЦИИ ФЛЕШ на отладке STM и там все просто и понятно , и документация есть , и примеров гора , и форум у них такой что просто если человек немного не понимает то в течении какого то времени появляеться его пример работы , и это еще не все плюшки , я промолчю про реализацию виртуального COM порта , ну смысл не в этом , та документация котороя есть она не полная , и один пример с архивацией , а как прочитать файл записанный на ПК такого примера нет , и начинаються вот такие вопросы , и они будут эти вопросы
в примере как надо писать OwenFileOpenAsync('usb:work\recept.txt','r',ADR(ha ndle)) hendle - возвращает 0 , значит ошибка как я понимаю
Добрый день вопрос есть функция , Функция SysFileReadAsync есть к ней ряд входных данных , и вот что прикольно я сам должен угадать порядок установки , и где смотреть пример по работе с этой функцией Ссылаться на документацию что там все есть не надо вот что там написано Функция SysFileReadAsync
Функция чтения данных из файла, открытого с помощью SysFileOpenAsync,возвращает значение типа DWORD–количество считанных байт данных.
Входные переменные:
File–типа DWORD–дескриптор файла, число, которое возвратила функция SysFileOpenAsync;
Buffer–адрес буфера, содержащего данные, которые необходимо записать в файл, число, которое возвратила функция ADRс аргументом –именем переменной-буфера; тип–массив, например, массив байт или строка.
Size–типа DWORD–размер буфера в байтах, можно использовать функцию SIZEOFс аргументом –именем переменной-буфера.
Использование функции –аналогично SysFileWriteAsync(см. рисунок 4.9).
SysFileReadAsync === SysFileRead + асинхронность. Чего там угадывать то. И пример есть.
Тогда вопрос в следующим , как мне посмотреть что приходит в буфер , точнее как мне разложить и вывести все на монитор , на Си знаю как sprintf() и гоним куда угодно хоть в COM порт хоть на дисплей , к стати дисплей есть установлен и работает ИП320 , я не силен в этом языке так что простите меня за такие вопросы
в онлайн режиме в окне объявлений раскрываете массив нажатием на плюсик и смотрите какие данные в ячейках. Можно это всё перевести в строку и вывести на экран, но всё зависит от наличия опыта и знания где посотреть. В библиотеке на oscat.de много функция по работе со строками
Добрый день!
На втором этапе появляется статус- как с этим бороться?Код:ASYNC_QUERY_FULL:= -1001, (*>5 запросов в очереди*)
Код:CASE g_LogState OF
0: (*Открытие файла - этап 1*)
g_LogRes := OwenFileOpenAsync( g_LogFileLog, 'a', ADR(g_LogHandle));
IF g_LogRes = ASYNC_WORKING THEN g_LogState := 1;
END_IF
1: (*Открытие файла - этап 2*)
g_LogRes := OwenFileOpenAsync( g_LogFileLog, 'a', ADR(g_LogHandle));
IF g_LogRes = ASYNC_DONE THEN
IF g_LogHandle<>0 THEN g_LogState := 2;
ELSE g_LogState := 0;
END_IF
ELSIF g_LogRes<0 THEN
g_LogState := 0;
END_IF
.....
О библиотеке OwenLibFileAsync.
Читаю только что скачанную документацию.
Какая-то путаница с возвращаемыми типами у функций:
Функция SysFileOpenAsync
Функция возвращает значение типа DWORD
Функция SysFileCloseAsync
возвращает значение типа BOOL
Функция SysFileWriteAsync
возвращает значение типа DWORD – количество записанных байт данных
А в примерах функции вызываются в виде:
res:=OwenFileXxxAsync(xxx);
переменная res имеет тип ASYNC_RET_VALUE (в документации отсутствует описание этого типа, догадайся сам)
Ну ладно, ASYNC_RET_VALUE, допустим, совместимо с DWORD (как по мне, должна быть ошибка), но DWORD и BOOL один и тот же тип?
Примеры с IF-ами и CASE-ми выглядят громоздко и запутанно.
Я бы хотел написать так:
Гораздо компактнее и проще.Код:(***********************************************************)
VAR
f_work: T_F_WORK; (*перечислимый тип: открыть, закрыть, записать и т.д.*)
res: ASYNC_RET_VALUE;
END_VAR
(*вызываем нужную функцию*)
CASE f_work OF
F_OPEN:
res := OwenFileOpenAsync(f_name,'a',ADR(f_handle));
F_CLOSE:
res := OwenFileCloseAsync(f_handle, ADR(f_result));
F_WRITE:
res := OwenFileWriteAsync(f_handle, ADR(f_buff), SIZEOF(f_buff), ADR(f_result));
F_NONE: ;
END_CASE
(*обрабатываем результат*)
CASE res OF
ASYNC_WORKING: (*ждем...*);
ASYNC_DONE:
f_work := F_NONE;
(*проверка на ошибки*)
(*...*);
(*а еще res возвращает некоторые ошибки!*)
(*как к ним относиться, неясно*)
(*но ведь как-то надо обработать!*)
(* ASYNC_PAUSED:
ASYNC_QUERY_FULL:
ASYNC_BLOCK_ACCESS:
ASYNC_GENERAL_ERROR:
ASYNC_INVALID_HANDLE_ERROR:
*)
END_CASE
(********************************************************************)
И опять, в описании не сказано, имеется ли логическая переменная для возврата наличия ошибки для всех функций (в старом описании такая переменная имелась). А ведь это позволит написать обработку файловых ошибок в одном месте, а не размазывать по всей программе.
Документацию надо бы поправить и дополнить.
Добрый день.
Все функции возвращают тип ASYNC_RET_VALUE
Описание этого типа есть в самой библиотеке
Вложение 44982
Коды ошибок попадают в переменную res (типа ASYNC_RET_VALUE).
Через CASE они обрабатываются без проблем.
Путаницу с типами возвращаемого значения хорошо бы убрать:
https://ftp.owen.ru/CoDeSys23/05_Lib...bFileAsync.pdf
(в описании функции возвращают разные значения: и bool, и позицию, и количество записанных байтов, и результат ASYNC_RET_VALUE...)
и добавить описание входного/выходного параметра ADR(result).
И если все функции возвращают ASYNC_RET_VALUE, то как узнать, сколько байтов записала функция записи или позицию в файле? Достигнут ли конец файла?
Также хотелось бы знать, что надо делать при получении значений
ASYNC_PAUSED,
ASYNC_BLOCK_ACESS:
- снимать запрос и повторять через некоторое (какое?) время?
- ждать (сколько времени?) другого ответа, непрерывно повторяя запрос?
- или что-то еще?
Как можно определить, сколько осталось места на носителе?
Что произойдет, когда кончится место?
ASYNC_BLOCK_ACESS - Значит в пользовательском коде есть логическая ошибка
ASYNC_PAUSED - подождать и повторить запрос
Асинхронная библиотека это просто надстройка для асинхронного доступа над стандартной SysLibFile. И место на диске определяется аналогично как через SysLibFile
И функции возвращают 2 значения, состояние асинхронной машины и *когда возвратится DONE) - ответ соответствующей функции SysLibFile, через указатель.
В смысле свободное место на диске/флешке ?
И на флешке, и на виртуальном диске в памяти, и во флешь-памяти контроллера...
Это не syslibfile а к syslibdir.
Но походу до неё еще не дошли руки ))
РАЗМЕР СВОБОДНОГО МЕСТА=РАЗМЕР ДИСКА - СУММА(РАЗМЕРОВ ВСЕХ ФАЙЛОВ)
Надо хотя бы знать размер ram-диска и диска в контроллере. Я - не знаю.