Пытаюсь достучаться до СОМ-порта - функция GetCommState() возвращает -1, что означает - порт не проинициализирован
Код:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls;
type
TForm1 = class(TForm)
Edit1: TEdit;
Timer1: TTimer;
Edit2: TEdit;
procedure FormCreate(Sender: TObject);
procedure Timer1Timer(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
hCOM,hOUTFILE:tHandle;
DCB:tDCB;
Stat:tCOMStat;
count,Errors,bytes,ByteCount:dWord;
lock:boolean;
DataBuf:array[1..4096] of byte;
i:integer;
implementation
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
begin
Form1.Edit1.text:='';
lock:=true;
Stat.cbInQue:=0;
ByteCount:=0;
hCOM:=CreateFile('\\.\COM2',GENERIC_READ or GENERIC_WRITE,0,nil,
OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
if hCOM=INVALID_HANDLE_VALUE then begin
MessageDlg('Не могу открыть порт',mtWarning,[mbok],0);
Application.Terminate;
end;
SetupComm(hCOM,4096,4096);
With DCB do begin
BaudRate:=9600;
ByteSize:=8;
Parity:=0;
StopBits:=ONESTOPBIT;
end;
if not SetCommState(hCOM,DCB) then begin
MessageDlg('Не могу сконфигурировать порт',mtWarning,
[mbok],0);
Application.Terminate;
end;
lock:=false;
end;
procedure TForm1.Timer1Timer(Sender: TObject);
begin
if not lock then begin
edit2.text := boolToStr(GetCommState(hCOM, DCB));
lock:=true;
ClearCommError(hCOM,Errors,@stat);
if Stat.cbInQue>0 then begin
count:=Stat.cbInQue;
ReadFile(hCOM,DataBUF,Count,Bytes,nil);
for i:=1 to count do begin
Form1.Edit1.Text:=Form1.Edit1.Text+inttostr(databuf)+' ';
end;
end;
lock:=false;
end;
end;
end.
Другие языки программирования и технологии
Инициализация COM-порта! (delphi)
Я понимаю так, что ошибка от того, что ты изменяешь значения полей структуры DCB не правильно. Ты же не все поля изменяешь, а только некоторые. А в остальные, в те, которые ты не изменяешь, не понятно что пишется. Для того, чтобы код был корректен, необходимо сначала прочитать структуру GetCommState, а потом изменить нужные поля и записать структуру SetCommState.
Я делал так.
//Переменные для работы с портом.
type
TModems = packed record
DSR,CTS,RING,RLSD : boolean;
end;
Var
cId : THandle; //дескриптор порта
DCB : TDCB; //DCB порта
TimeOuts : TCommTimeouts; // таймауты порта
Stat : TComStat; //статус порта
Modems : TModems; //состояние модемных линий
RecivBuff : array[0..255] of byte; //буфер принимаемых байт
CntByte : integer; //количество принятых байт в буфере
Terminated : boolean; //флажок для корректного закрытия порта
//Открытие порта, настройка параметров, старт дочернего потока для обработки событий порта.
function InitsComm(Num : integer) : boolean;
var
ThreadId : Dword;
begin
Result := False;
//получаем дескриптор порта в асинхронном режиме
cId := CreateFile(PChar('\\.\COM'+ IntToStr(Num),
GENERIC_READ or GENERIC_WRITE,
0,nil,OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,0);
if cId = INVALID_HANDLE_VALUE then Exit;
//устанавливаем маску эвентов (фактически маску прерываний)
//в данном случае будем иметь возникновение эвентов по принятию
//хотя бы одного байта и возможности записи в порт еще байт (ов)
if not (SetCommMask(cId,EV_RXCHAR or EV_TXEMPTY) and
//устанавливаем размер внутренних буферов приема-передачи в //драйвере порта
SetupComm(cId,256,256) and
//очищаем буферы приема-передачи (в принципе необязательно)
PurgeComm(cId,PURGE_TXABORT or PURGE_RXABORT or
PURGE_TXCLEAR or PURGE_RXCLEAR) and
//получаем текущее DCB порта
GetCommState(cId,DCB))
then begin
CloseHandle(cId);
Exit;
end;
//изменяем DCB
DCB.BaudRate := 9599;//реальная скорость будет 9600
DCB.ByteSize := 8;
DCB.Parity := NoParity;
DCB.StopBits := OneStopBit;
//выполняем настройку порта с новым DCB
if not SetCommState(cId,DCB) then begin
CloseHandle(cId);
Exit;
end;
//получаем текущие параметры таймаутов
GetCommTimeouts(cId,TimeOuts);
//настраиваем текущие параметры таймаутов таким образом,
//чтобы ReadFile и WriteFile возвращали значения немедленно
TimeOuts.ReadIntervalTimeout := MAXDWORD;
TimeOuts.ReadTotalTimeoutMultiplier := 0;
TimeOuts.ReadTotalTimeoutConstant := 0;
TimeOuts.WriteTotalTimeoutMultiplier := 0;
TimeOuts.WriteTotalTimeoutConstant := 0;
//выполняем настройку порта с новыми таймаутами
if not SetCommTimeouts(cId,TimeOuts) then begin
CloseHandle(cId);
Exit;
end;
//опускаем флаг завершения дочернего потока
Terminated := False;
//стартуем дочерний поток (функция потока - ReadsComm)
//для обработки эвентов порта и устанавливаем приоритет
CommThread := CreateThread(nil,0,@ReadsComm,nil,0,ThreadID);
if CommThread = 0 then begin
CloseHandle(cId);
Exit;
end;
SetThreadPriority(CommThread,8);
end;
Result := True;
end;
Кстати, есть хороший компонент TBComPort. Можно качнуть тут.
Если есть вопросы - автор оперативно отвечает. В моем случает ответ пришел буквально через 5-6 часов после отправки письма.
Я делал так.
//Переменные для работы с портом.
type
TModems = packed record
DSR,CTS,RING,RLSD : boolean;
end;
Var
cId : THandle; //дескриптор порта
DCB : TDCB; //DCB порта
TimeOuts : TCommTimeouts; // таймауты порта
Stat : TComStat; //статус порта
Modems : TModems; //состояние модемных линий
RecivBuff : array[0..255] of byte; //буфер принимаемых байт
CntByte : integer; //количество принятых байт в буфере
Terminated : boolean; //флажок для корректного закрытия порта
//Открытие порта, настройка параметров, старт дочернего потока для обработки событий порта.
function InitsComm(Num : integer) : boolean;
var
ThreadId : Dword;
begin
Result := False;
//получаем дескриптор порта в асинхронном режиме
cId := CreateFile(PChar('\\.\COM'+ IntToStr(Num),
GENERIC_READ or GENERIC_WRITE,
0,nil,OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,0);
if cId = INVALID_HANDLE_VALUE then Exit;
//устанавливаем маску эвентов (фактически маску прерываний)
//в данном случае будем иметь возникновение эвентов по принятию
//хотя бы одного байта и возможности записи в порт еще байт (ов)
if not (SetCommMask(cId,EV_RXCHAR or EV_TXEMPTY) and
//устанавливаем размер внутренних буферов приема-передачи в //драйвере порта
SetupComm(cId,256,256) and
//очищаем буферы приема-передачи (в принципе необязательно)
PurgeComm(cId,PURGE_TXABORT or PURGE_RXABORT or
PURGE_TXCLEAR or PURGE_RXCLEAR) and
//получаем текущее DCB порта
GetCommState(cId,DCB))
then begin
CloseHandle(cId);
Exit;
end;
//изменяем DCB
DCB.BaudRate := 9599;//реальная скорость будет 9600
DCB.ByteSize := 8;
DCB.Parity := NoParity;
DCB.StopBits := OneStopBit;
//выполняем настройку порта с новым DCB
if not SetCommState(cId,DCB) then begin
CloseHandle(cId);
Exit;
end;
//получаем текущие параметры таймаутов
GetCommTimeouts(cId,TimeOuts);
//настраиваем текущие параметры таймаутов таким образом,
//чтобы ReadFile и WriteFile возвращали значения немедленно
TimeOuts.ReadIntervalTimeout := MAXDWORD;
TimeOuts.ReadTotalTimeoutMultiplier := 0;
TimeOuts.ReadTotalTimeoutConstant := 0;
TimeOuts.WriteTotalTimeoutMultiplier := 0;
TimeOuts.WriteTotalTimeoutConstant := 0;
//выполняем настройку порта с новыми таймаутами
if not SetCommTimeouts(cId,TimeOuts) then begin
CloseHandle(cId);
Exit;
end;
//опускаем флаг завершения дочернего потока
Terminated := False;
//стартуем дочерний поток (функция потока - ReadsComm)
//для обработки эвентов порта и устанавливаем приоритет
CommThread := CreateThread(nil,0,@ReadsComm,nil,0,ThreadID);
if CommThread = 0 then begin
CloseHandle(cId);
Exit;
end;
SetThreadPriority(CommThread,8);
end;
Result := True;
end;
Кстати, есть хороший компонент TBComPort. Можно качнуть тут.
Если есть вопросы - автор оперативно отвечает. В моем случает ответ пришел буквально через 5-6 часов после отправки письма.
А порт-то у тебя есть? У меня, например, нету.
Больше никто не использует этот порт?
Попробуй другой порт, если есть.
Не парься и качни готовый компонент.
Больше никто не использует этот порт?
Попробуй другой порт, если есть.
Не парься и качни готовый компонент.
Похожие вопросы
- Что такое COM порт?
- Можно ли подключить компы (создать нечто подобное сетке) через COM-порты?
- Какой принцип обращения в c++ builder 6 к com порту для приема/передачи пакетов информации от внешнего устройства?
- Как USB эмулировать в com порт? нужно подключить сканер штрих кода (opticon std 3201) чтоб 1с 7.7 видела сканер
- Согласны с этим - Глубинные причины ненависти к Delphi/Pascal ?
- Люди. ) Расскажите пожалуйста что означает слово ИНИЦИАЛИЗАЦИЯ.
- Delphi:Прочитал, что если при динамическом создании компонента если указать Name объекта, то в последующем можно ->
- что такое инициализация? что такое инициализация?
- Как в Delphi сделать справку?
- Помогите найти ошибку Delphi легкая программка