Листинг 18.1
procedure IniCOM;
var i:integer;
begin
{инициализация СОМ — номер в строке stcom}
hCOM:=CreateFile(Pchar(stcom),
GENERIC_READ+GENERIC_WRITE,0,nil,OPEN_EXISTING,0,0);
if (hCom = INVALID_HANDLE_VALUE) then
begin
st:=stcom+'не найден';
Application.MessageBox(Pchar(st),'Error',MB_OK);
exit;
end ;
if GetCommState(hCOM,pDCB)
then st:=stcom+': baud=9600 parity=N data=8 stop=l';
if BuildCommDCB(Pchar(st), pDCB) the n SetCommState(hCOM,pDCB)
else
begin
st:=stcom+' занят или заданы неверные параметры';
Application.MessageBox(Pchar(st),'Error',MB_OK);
exit;
end ;
GetCommTimeouts(hCom,comtime); {устанавливаем задержки:}
comtime.WriteTotalTimeoutMultiplier:=1;
comtime.WriteTotalTimeoutConstant:=10;
comtime.ReadlntervalTimeout:=10;
comtime.ReadTotalTimeoutMultiplier:=1;
comtime.ReadTotalTimeoutConstant:=2 000; {ждем чтения 2 с}
SetCommTimeouts(hCom,comtime);
ab[1]:=ord('A');{будем посылать инициализацию модема}
ab[2]:=ord('T');
ab[3]:=13 ;{CR}
ab[4]:=10 ;{LF}
WriteFile(hCOM,ab,4,xn,nil);
if ReadFile(hCOM,ab,10,xn,nil) then {ответ модема 10 знаков}
begin
st:=»;
for i:=1 to 10 do st:=st+chr(ab[i]);
if pos('OK',st)<>0 then
begin
st:=stcom+' занят модемом';
Application.MessageBox(Pchar(st),'Error',MB_OK);
CloseHandle(hCOM); hCOM:=0;
Forml.Label7.Caption:='COM?';
exit;
end;
end;
Form1.Labe17.Caption:=s tcom+' 9600 1;
end;
Сначала текст тут мало отличается от того, что описано во всех стандартных рекомендациях по программированию порта. Единственный момент, который несколько выходит за рамки стандарта: мы не устанавливаем поля структуры DCВнапрямую, а используем функцию BuildCommDCB. Я это делаю отчасти потому, что структура DCBв Delphi транслируется из API не полностью (сравните ее описание в Windows.pas и в Win32.hip), и хотя для данного случая, разумеется, все нужные поля имеются, но функция BuildCommDCBвсе равно удобнее.
После стандартных установок мы сразу выполняем два действия, о которых упоминают далеко не всегда. Во-первых, мы устанавливаем все возможные задержки (timeout) для разных вариантов приема и передачи. В параметрах, которые заканчиваются на «Multiplier» можно для простоты всегда ставить «1» (если больше, то процедуры чтения/записи будут отслеживать еще и скорость поступления байтов, что нам не требуется). А остальные из этих параметров делают следующее: если задержка посылки через порт больше, чем writeTotaiTimeoutConstant(в миллисекундах), то будет прервана передача, а при задержке между поступающими байтами больше, чем ReadIntervaiTimeout, и при задержке всей процедуры чтения (в данном случае — самый главный параметр) больше, чем ReadTotalTimeoutConstant, будет прерван прием. Последний параметр мы установили равным двум секундам. При выборе этих параметров следует иметь в виду, что один байт при скорости 9600 передается/принимается примерно за 1 мс. Если эти параметры вообще не устанавливать (оставить их в значении «0», как по умолчанию), то при отсутствии принимаемых байтов процедура чтения через ReadFileпросто зациклится и «повесит» всю программу.
Во-вторых, мы определяем, не является ли установленный нами порт модемом. Так как мы рассматриваем «чистый» RS-232, то для нас модемный порт все равно как бы занят. Определяем модем мы очень просто: посылаем в выбранный порт символьный код инициализации, который одинаков для всех модемов: «AT» (65 84 13 10). В ответ мы от модема должны получить строку «АТOK» (65 84 13 10 13 10 79 75 13 10), но все такие подробности нам не требуются, подозреваю, что строка для разных модемов может немного отличаться. Но в любом случае в ней должны содержаться символы «ОК», если модем, конечно, свободен (с занятым модемом я предоставляю читателю разобраться самостоятельно). В последнем операторе, если порт инициализировался нормально, выводим в Labelномер порта и скорость.
Эту процедуру мы выполним сразу при запуске (для СОМ1). Заодно напишем процедуру (листинг 18.2) закрытия порта (ведь порт все время занят, пока программа запущена).
Листинг 18.2
procedure TForm1.FormCreate(Sender:TObject);
begin
{инициализация COM1 при запуске}
stcom:='COM1';
IniCOM;
end;
procedure TForm1.FormDestroy(Sender:TObject);
begin{уничтожаем COM}
CloseHandle(hCOM);
Читать дальше
Конец ознакомительного отрывка
Купить книгу