Во время операции чтения временной период начинает отсчитываться с момента приема первого символа. Общий интервал времени на операцию чтения рассчитывается как произведение значения ReadTotalTimeoutMultiplier на количество запрошенных символов N. и к этому произведению добавляется значение ReadTo 1аГПтеои1;Соп81 ап I:

N ■ Кеа^о1а1Тл_теои1Ми11:1р11ег + Кеа^о1а1Тл.теои1:Соп51ап1

Пусть, например, вам требуется прочитать 100 символов при скорости порта 12000. И пусть на каждый символ используется 8 бит данных, бит дополнения четности, стоповый бит и стартовый бит - итого 11 бит на символ. Значит, на всю операцию чтения требуется 100 11 / 12000 секунд или 93 миллисекунд. К этому времени надо прибавить 99 интервалов между импульсами. Например, если средний ожидаемый интервал между окончанием одного и началом следующего символа равен 1 миллисекунде, то на всю операцию чтения потребуется 93 + 99 = 192 мс. Для решения подобной задачи можно задать ReadIntervalTimeout = 4 мс (в 2 раза больше среднего значения, складывающегося из времени передачи символа и промежутка между ними). Значение ReadTotalTimeoutMultiplier можно установить равным 2 мс, и задать какое-то значение ReadTotalTimeoutConstant в качестве страховки от возможных колебаний скорости чтения. В результате в нашем примере общее время может составить, например, 300 мс. Если операция чтения выполняется дольше, разумно предположить, что это вызвано какими-то ошибками внешнего устройства. В этом заключается смысл задания тайм-аута: через заданный интервал времени считывание прекратится и тем самым можно будет избежать возможного "зависания" программы. При этом будут возвращены символы, прием которых завершился до истечения тайм-аута. Остальные символы можно получить следующей операцией чтения. Если между началами двух последовательных символов пройдет более 4 миллисекунд, то операция чтения также будет завершена.

Параметры EWriteTotalTimeoutMultiplier и EWriteTotalTimeoutConstant аналогичны параметрам EReadTotalTimeoutMultiplier и EReadTotalTimeoutConstant, но относятся к операции записи.

Рассмотренная функция GetCommTimeouts позволяет определить текущие временные параметры порта. А функция SetCommTimeouts устанавливает эти параметры порта:

function SetCommTimeouts(hFile: THandle;
const lpCommTimeouts: TCommTimeouts): BOOL;

Теперь можно расширить предыдущее приложение, введя в него возможность настройки временных параметров. На рис. 11.10 в правой панели расположены окна редактирования, отображающие и задающие эти параметры. Их имена в приведенном далее коде EReadlntervalTimeout, EReadTotalTimeoutMultiplier, EReadTotalTimeoutConstant, EWriteTotalTimeoutMultiplier, EWriteTotalTimeoutConstant. Ниже приведены фрагменты кода этого приложения, относящиеся к временным параметрам.

var port: THandle = 0;
lpDCB: TDCB;
lpCommTimeouts: TCommTimeouts;

procedure TForml.ButtonlClick(Sender: TObject); begin if port = 0

then port := CreateFile(PChar(ComboBoxl.Text) , GENERIC_READ or GENERIC_WRITE, 0, nil, OPEN_EXISTING, 0, 0);

GetCommTimeouts(port, lpCommTimeouts); with lpCommTimeouts do begin EReadlntervalTimeout.Text := IntToStr(ReadlntervalTimeout); EReadTotalTimeoutMultiplier.Text :=

IntToStr(ReadTotalTimeoutMultiplier); EReadTotalTimeoutConstant.Text :=

IntToStr(ReadTotalTimeoutCoristant); EWriteTotalTimeoutMultiplier . Text: : =

IntToStr(WriteTotalTimeoutMultiplier); EWriteTotalTimeoutConstant.Text :=

IntToStr(WriteTotalTimeoutConstant);
end;
Button2.Enabled := truer-end;

procedure TForml.Button2Click(Sender: TObject); begin

try

with lpCommTimeouts do begin ReadlntervalTimeout := StrToInt(EReadlntervalTimeout.Text); ReadTotalTimeoutMultiplier :=

StrToInt(EReadTotalTimeoutMultiplier.Text) ; ReadTotalTimeoutConstant :=

StrToInt(EReadTotalTimeoutConstant.Text); WriteTotalTimeoutMultiplier :=

StrToInt(EWriteTotalTimeoutMultiplier.Text) ; WriteTotalTimeoutConstant :=

StrToInt(EWriteTotalTimeoutConstant.Text) ;

end; except

on EConvertError do begin

ShowMessage('Ошибочное значение временного интервала' + #13'Установка не произведена');
exit ;
end;
end;

if not SetCommTimeouts(port, lpCommTimeouts) then begin

ShowMessage('Значения временных интервалов недопустимые' + #13'Установка не произведена');
ButtonlClick(Sender) ;
exit ;
end;
ButtonlClick(Sender);
end;

procedure TForml.ComboBoxlChange(Sender: TObject); begin

Button2.Enabled := false; if (port 0) then begin

EReadlntervalTimeout.Text := '';
EReadTotalTimeoutMultiplier.Text := '';
EReadTotalTimeoutConstant.Text := '';
EWriteTotalTimeoutMultiplier.Text := '';
EWriteTotalTimeoutConstant.Text :^ '';
CloseHandle(port) ;
port := 0;
end;
end;

Вряд ли приведенный код требует каких-то комментариев.

11.17.6 Имя пользователя || Оглавление || 11.18.2 Синхронный режим работы


⇐ Предыдущая страница|

Приемы программирования в Delphi на основе VCL



Новости за месяц

  • Сентябрь
    2020
  • Пн
  • Вт
  • Ср
  • Чт
  • Пт
  • Сб
  • Вс