Сообщение от
Евгений Кислов
Выложите простейший проект (только работа с файлом), в котором воспроизводится ваша проблема.
Код:
BLINK1sek(ENABLE:=xEnb , TIMELOW:=T#2000MS , TIMEHIGH:=T#2000MS );
// детектируем сигнал записи в файл
fbWriteTrig(CLK:=BLINK1sek.OUT);
wSek:=USINT_TO_REAL(usiSek)/100 + usiSek;
// если получен сигнал записи, то подготавливаем строку архива и взводим соответствующий флаг
IF fbWriteTrig.Q THEN
// собираем строку архива - метку времени и значения
sArchEntry := CONCAT(sCurrentDate, c_sDelimiter);
sArchEntry := CONCAT(sArchEntry, sCurrentTime);
sArchEntry := CONCAT(sArchEntry, c_sDelimiter);
sArchEntry := CONCAT(sArchEntry, '#0=');
//sArchEntry := CONCAT(sArchEntry, WORD_TO_STRING(stExportData.wValue) );
//sArchEntry := CONCAT(sArchEntry, c_sDelimiter);
sArchEntry := CONCAT(sArchEntry, REAL_TO_FSTRING(wSek, 2) );
sArchEntry := CONCAT(sArchEntry, '$N');
sArchEntry := CONCAT(sArchEntry, '$R');
// получаем путь к выбранному устройству
sDevicePath := DEVICE_PATH(iDevicePath);
// склеиваем его с именем выбранного файла
sFileName := CONCAT(sDevicePath, sVisuFileName);
xWBusy := TRUE;
END_IF
CASE eState OF
FileWork.OPEN: // шаг открытия файла
IF xWBusy THEN
fbFileOpen(xExecute:=TRUE, sFileName:=sFileName, eFileMode:=File.MODE.MREADPLUS);
END_IF
// если файл, в который производится запись, не существует, то создадим его и запишем в него заголовок архива
IF fbFileOpen.eError=FILE.ERROR.NOT_EXIST THEN
fbFileOpen(xExecute:=FALSE);
eState := FileWork.CREATE;
xTitle := TRUE;
END_IF
IF fbFileOpen.eError=FILE.ERROR.WRONG_PARAMETER THEN
fbFileOpen(xExecute:=FALSE);
eState := FileWork.CLOSE;
iK:=iK+1;
END_IF
// если файл существует и был успешно открыт, то переходим к шагу записи в файл
IF fbFileOpen.xDone THEN
hFile := fbFileOpen.hFile;
fbFileOpen(xExecute:=FALSE);
eState := FileWork.GET_POS;
END_IF
FileWork.CREATE: // шаг создания файла
// в созданном файле еще нет записей
uiArchEntry:=0;
fbFileOpen(xExecute:=TRUE, sFileName:=sFileName, eFileMode:=FILE.MODE.MWRITE);
IF fbFileOpen.xDone THEN
hFile := fbFileOpen.hFile;
fbFileOpen(xExecute:=FALSE);
// после создания файла можно перейти к шагу записи данных
eState := FileWork.WRITE;
END_IF
IF fbFileOpen.xError THEN
// обработка ошибок
END_IF
FileWork.GET_POS:
fbFileGetPos( xExecute:=TRUE, hFile:=hFile );
IF fbFileGetPos.xDone THEN
udiCurPos:=fbFileGetPos.udiPos;
fbFileGetPos(xExecute:=FALSE);
// вернемся на шаг открытия файла для ожидания следующего управляющего сигнала
eState := FileWork.SET_READ_POS;
END_IF
IF (udiCurPos = udiArchSize) AND (uiArchEntry >= 30) THEN
udiCurPos:=0;
eState := FileWork.SET_READ_POS;
END_IF
IF fbFileGetPos.xError THEN
fbFileGetPos(xExecute:=FALSE);
END_IF
FileWork.SET_READ_POS:
fbFileSetPos( xExecute:=TRUE, hFile:=hFile, udiPos:=udiCurPos );
IF fbFileSetPos.xDone THEN
fbFileSetPos(xExecute:=FALSE);
// вернемся на шаг открытия файла для ожидания следующего управляющего сигнала
eState := FileWork.WRITE;
END_IF
IF fbFileSetPos.xError THEN
fbFileSetPos(xExecute:=FALSE);
//eState := FileWork.OPEN;
END_IF
FileWork.WRITE: // шаг записи в буфер
// если это первая запись в файле - то перед ней запишем заголовок
//IF xTitle THEN
// sArchEntry := CONCAT(c_sTitle, sArchEntry);
// после первой записи заголовок записывать уже не нужно
// xTitle := FALSE;
//END_IF
// запись строки архива в файл
fbFileWrite(xExecute:=TRUE, hFile:=hFile, pBuffer:=ADR(sArchEntry), szSize:=INT_TO_UDINT(LEN(sArchEntry)));
IF fbFileWrite.xDone THEN
fbFileWrite(xExecute:=FALSE);
// после записи число строк в архиве увеличилось на одну
uiArchEntry:=uiArchEntry+1;
// теперь можно перейти к шагу сброса буфера в файл
eState := FileWork.FLUSH;
END_IF
IF fbFileWrite.xError THEN
// обработка ошибок
END_IF
FileWork.FLUSH: // шаг сброса буфера в файл
fbFileFlush(xExecute:=TRUE, hFile:=hFile);
IF fbFileFlush.xDone THEN
fbFileFlush(xExecute:=FALSE);
// теперь можно перейти к шагу закрытия файла
eState:=FileWork.CLOSE;
END_IF
IF fbFileFlush.xError THEN
// обработка ошибок
END_IF
FileWork.CLOSE: // шаг закрытия файла
fbFileClose(xExecute:=TRUE, hFile:=hFile);
IF fbFileClose.xDone THEN
fbFileClose(xExecute:=FALSE);
xWBusy := FALSE;
// теперь можно перейти к шагу определения размера файла
eState := FileWork.GET_SIZE;
ELSE
xWBusy := FALSE;
eState := FileWork.GET_SIZE;
END_IF
FileWork.GET_SIZE: // шаг определения размера файла
fbFileGetSize(xExecute:=TRUE, sFileName:=sFileName);
// определяем размер файла
IF fbFileGetSize.xDone THEN
udiArchSize:=fbFileGetSize.szSize;
fbFileGetSize(xExecute:=FALSE);
// вернемся на шаг открытия файла для ожидания следующего управляющего сигнала
eState := FileWork.OPEN;
END_IF
// размер несуществующего файла...
IF fbFileGetSize.eError=FILE.ERROR.NOT_EXIST THEN
// очевидно, можно интерпретировать как ноль
udiArchSize := 0;
fbFileGetSize(xExecute:=FALSE);
// вернемся на шаг открытия файла для ожидания следующего управляющего сигнала
eState := FileWork.OPEN;
ELSIF fbFileGetSize.xError THEN
fbFileGetSize(xExecute:=FALSE);
eState := FileWork.OPEN;
END_IF
END_CASE
Если вместо MREADPLUS указать MAPPD код работает, но без кольцевой перезаписи, в таком виде только растет счетчик ошибки WRONG_PARAMETER в переменной iK.