//{$DEFINE COMM_UNIT}//Простой пример работы с последовательными портами//Код содержит интуитивно понятные комментарии и строки на шведском языке,//нецелесообразные для перевода.//Compiler maakt Simple_Comm.Dll of Simple_Com.Dcu afhankelijk van 1e Regel
(COMM_UNIT)
{$IFNDEF COMM_UNIT}library Simple_Comm;
{$ELSE}unit Simple_Comm;
interface{$ENDIF}uses Windows, Messages;
const
M_BaudRate = 1;
const
M_ByteSize = 2;
const
M_Parity = 4;
const
M_Stopbits = 8;
{$IFNDEF COMM_UNIT}{$R Script2.Res}//versie informatie{$ENDIF}{$IFDEF COMM_UNIT}function Simple_Comm_Info: PChar; StdCall;
function
Simple_Comm_Open(Port: PChar; BaudRate: DWORD; ByteSize, Parity, StopBits:
Byte; Mas
k: Integer; WndHandle: HWND; WndCommand: UINT; var Id: Integer): Integer;
StdCall;
function Simple_Comm_Close(Id: Integer): Integer; StdCall;
function
Simple_Comm_Write(Id: Integer; Buffer: PChar; Count: DWORD): Integer; StdCall;
function Simple_Comm_PortCount: DWORD; StdCall;
const
M_None = 0;
const
M_All = 15;
implementation{$ENDIF}const
InfoString = 'Simple_Comm.Dll (c) by E.L. Lagerburg 1997';
const
MaxPorts = 5;
const
bDoRun: array[0..MaxPorts - 1] of boolean
= (False, False, False, False, False);
const
hCommPort: array[0..MaxPorts - 1] of Integer = (0, 0, 0, 0, 0);
const
hThread: array[0..MaxPorts - 1] of Integer = (0, 0, 0, 0, 0);
const
dwThread: array[0..MaxPorts - 1] of Integer = (0, 0, 0, 0, 0);
const
hWndHandle: array[0..MaxPorts - 1] of Hwnd = (0, 0, 0, 0, 0);
const
hWndCommand: array[0..MaxPorts - 1] of UINT = (0, 0, 0, 0, 0);
const
PortCount: Integer = 0;
function Simple_Comm_Info: PChar; stdcall;
begin
Result := InfoString;
end;
//Thread functie voor lezen compoortfunction Simple_Comm_Read(Param: Pointer): Longint; stdcall;
var
Count: Integer;
id: Integer;
ReadBuffer: array[0..127] of byte;
begin
Id := Integer(Param);
while bDoRun[id] dobegin
ReadFile(hCommPort[id], ReadBuffer, 1, Count, nil);
if (Count > 0) thenbeginif ((hWndHandle[id] <> 0) and
(hWndCommand[id] > WM_USER)) then
SendMessage(hWndHandle[id], hWndCommand[id], Count,
LPARAM(@ReadBuffer));
end;
end;
Result := 0;
end;
//Export functie voor sluiten compoortfunction Simple_Comm_Close(Id: Integer): Integer; stdcall;
beginif (ID < 0) or (id > MaxPorts - 1) or (not bDoRun[Id]) thenbegin
Result := ERROR_INVALID_FUNCTION;
Exit;
end;
bDoRun[Id] := False;
Dec(PortCount);
FlushFileBuffers(hCommPort[Id]);
ifnot
PurgeComm(hCommPort[Id], PURGE_TXABORT + PURGE_RXABORT + PURGE_TXCLEAR +
PURGE_RXCL
EAR) thenbegin
Result := GetLastError;
Exit;
end;
if WaitForSingleObject(hThread[Id], 10000) = WAIT_TIMEOUT thenifnot TerminateThread(hThread[Id], 1) thenbegin
Result := GetLastError;
Exit;
end;
CloseHandle(hThread[Id]);
hWndHandle[Id] := 0;
hWndCommand[Id] := 0;
ifnot CloseHandle(hCommPort[Id]) thenbegin
Result := GetLastError;
Exit;
end;
hCommPort[Id] := 0;
Result := NO_ERROR;
end;
procedure Simple_Comm_CloseAll; stdcall;
var
Teller: Integer;
beginfor Teller := 0 to MaxPorts - 1 dobeginif bDoRun[Teller] then
Simple_Comm_Close(Teller);
end;
end;
function GetFirstFreeId: Integer; stdcall;
var
Teller: Integer;
beginfor Teller := 0 to MaxPorts - 1 dobeginifnot bDoRun[Teller] thenbegin
Result := Teller;
Exit;
end;
end;
Result := -1;
end;
//Export functie voor openen compoortfunction
Simple_Comm_Open(Port: PChar; BaudRate: DWORD; ByteSize, Parity, StopBits:
Byte; Mas
k: Integer; WndHandle: HWND; WndCommand: UINT; var Id: Integer): Integer;
stdcall;
var
PrevId: Integer;
ctmoCommPort: TCOMMTIMEOUTS; //Lees specificaties voor de compoort
dcbCommPort: TDCB;
beginif (PortCount >= MaxPorts) or (PortCount < 0) thenbegin
result := error_invalid_function;
exit;
end;
result := 0;
previd := id;
id := getfirstfreeid;
if id = -1 thenbegin
id := previd;
result := error_invalid_function;
exit;
end;
hcommport[id] := createfile(port, generic_read or
generic_write, 0, nil, open_existing, file_attribute_normal, 0);
if hcommport[id] = invalid_handle_value thenbegin
bdorun[id] := false;
id := previd;
result := getlasterror;
exit;
end;
//lees specificaties voor het comm bestand
ctmocommport.readintervaltimeout := maxdword;
ctmocommport.readtotaltimeoutmultiplier := maxdword;
ctmocommport.readtotaltimeoutconstant := maxdword;
ctmocommport.writetotaltimeoutmultiplier := 0;
ctmocommport.writetotaltimeoutconstant := 0;
//instellen specificaties voor het comm bestandifnot setcommtimeouts(hcommport[id], ctmocommport) thenbegin
bdorun[id] := false;
closehandle(hcommport[id]);
id := previd;
result := getlasterror;
exit;
end;
//instellen communicatie
dcbcommport.dcblength := sizeof(tdcb);
ifnot getcommstate(hcommport[id], dcbcommport) thenbegin
bdorun[id] := false;
closehandle(hcommport[id]);
id := previd;
result := getlasterror;
exit;
end;
if (mask and m_baudrate <> 0) then
dcbCommPort.BaudRate := BaudRate;
if (Mask and M_ByteSize <> 0) then
dcbCommPort.ByteSize := ByteSize;
if (Mask and M_Parity <> 0) then
dcbCommPort.Parity := Parity;
if (Mask and M_Stopbits <> 0) then
dcbCommPort.StopBits := StopBits;
ifnot SetCommState(hCommPort[Id], dcbCommPort) thenbegin
bDoRun[Id] := FALSE;
CloseHandle(hCommPort[Id]);
Id := PrevId;
Result := GetLastError;
Exit;
end;
//Thread voor lezen compoort
bDoRun[Id] := TRUE;
hThread[Id] := CreateThread(nil, 0, @Simple_Comm_Read, Pointer(Id), 0,
dwThread[Id]
);
if hThread[Id] = 0 thenbegin
bDoRun[Id] := FALSE;
CloseHandle(hCommPort[Id]);
Id := PrevId;
Result := GetLastError;
Exit;
endelsebegin
SetThreadPriority(hThread[Id], THREAD_PRIORITY_HIGHEST);
hWndHandle[Id] := WndHandle;
hWndCommand[Id] := WndCommand;
Inc(PortCount);
Result := NO_ERROR;
end;
end;
//Export functie voor schrijven naar compoort;function
Simple_Comm_Write(Id: Integer; Buffer: PChar; Count: DWORD): Integer; stdcall;
var
Written: DWORD;
beginif (Id < 0) or (id > Maxports - 1) or (not bDoRun[Id]) thenbegin
Result := ERROR_INVALID_FUNCTION;
Exit;
end;
ifnot WriteFile(hCommPort[Id], Buffer, Count, Written, nil) thenbegin
Result := GetLastError();
Exit;
end;
if (Count <> Written) then
Result := ERROR_WRITE_FAULT
else
Result := NO_ERROR;
end;
//Aantal geopende poorten voor aanroepende applicatiefunction Simple_Comm_PortCount: DWORD; stdcall;
begin
Result := PortCount;
end;
{$IFNDEF COMM_UNIT}exports
Simple_Comm_Info Index 1,
Simple_Comm_Open Index 2,
Simple_Comm_Close Index 3,
Simple_Comm_Write Index 4,
Simple_Comm_PortCount index 5;
procedure DLLMain(dwReason: DWORD);
beginif dwReason = DLL_PROCESS_DETACH then
Simple_Comm_CloseAll;
end;
begin
DLLProc := @DLLMain;
DLLMain(DLL_PROCESS_ATTACH); //geen nut in dit gevalend.
{$ELSE}initializationfinalization
Simple_Comm_CloseAll;
end.
{$ENDIF}
Другое решение: создание модуля I / O(ввода / вывода)под Windows 95 / NT.Вот он:
)
(с TDCB в SetCommStatus вы можете управлять DTR и т.д.)
(Примечание: XonLim и XoffLim не должны быть больше 600, иначе под NT это
работает неправильно)
unit My_IO;
interfacefunction OpenComm(InQueue, OutQueue, Baud: LongInt): Boolean;
function SetCommTiming: Boolean;
function SetCommBuffer(InQueue, OutQueue: LongInt): Boolean;
function SetCommStatus(Baud: Integer): Boolean;
function SendCommStr(S: string): Integer;
function ReadCommStr(var S: string): Integer;
procedure CloseComm;
var
ComPort: Word;
implementationuses Windows, SysUtils;
const
CPort: array[1..4] ofstring = ('COM1', 'COM2', 'COM3', 'COM4');
var
Com: THandle = 0;
function OpenComm(InQueue, OutQueue, Baud: LongInt): Boolean;
beginif Com > 0 then
CloseComm;
Com := CreateFile(PChar(CPort[ComPort]),
GENERIC_READ or GENERIC_WRITE,
0, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
Result := (Com > 0) and SetCommTiming and
SetCommBuffer(InQueue, OutQueue) and
SetCommStatus(Baud);
end;
function SetCommTiming: Boolean;
var
Timeouts: TCommTimeOuts;
beginwith TimeOuts dobegin
ReadIntervalTimeout := 1;
ReadTotalTimeoutMultiplier := 0;
ReadTotalTimeoutConstant := 1;
WriteTotalTimeoutMultiplier := 2;
WriteTotalTimeoutConstant := 2;
end;
Result := SetCommTimeouts(Com, Timeouts);
end;
function SetCommBuffer(InQueue, OutQueue: LongInt): Boolean;
begin
Result := SetupComm(Com, InQueue, OutQueue);
end;
function SetCommStatus(Baud: Integer): Boolean;
var
DCB: TDCB;
beginwith DCB dobegin
DCBlength := SizeOf(Tdcb);
BaudRate := Baud;
Flags := 12305;
wReserved := 0;
XonLim := 600;
XoffLim := 150;
ByteSize := 8;
Parity := 0;
StopBits := 0;
XonChar := #17;
XoffChar := #19;
ErrorChar := #0;
EofChar := #0;
EvtChar := #0;
wReserved1 := 65;
end;
Result := SetCommState(Com, DCB);
end;
function SendCommStr(S: string): Integer;
var
TempArray: array[1..255] of Byte;
Count, TX_Count: Integer;
beginfor Count := 1 to Length(S) do
TempArray[Count] := Ord(S[Count]);
WriteFile(Com, TempArray, Length(S), TX_Count, nil);
Result := TX_Count;
end;
function ReadCommStr(var S: string): Integer;
var
TempArray: array[1..255] of Byte;
Count, RX_Count: Integer;
begin
S := '';
ReadFile(Com, TempArray, 255, RX_Count, nil);
for Count := 1 to RX_Count do
S := S + Chr(TempArray[Count]);
Result := RX_Count;
end;
procedure CloseComm;
begin
CloseHandle(Com);
Com := -1;
end;
end.
Привет! Я перевёл текст на русский язык:
Заголовок: Первая часть кода определяет константы и переменные, используемые в целом библиотеке.
Функции: В этой библиотеке есть пять основных функций:
- Simple_Comm_Open: Открывает последовательный порт с указанным скоростью передачи, размером байта, паритетом и стоп-битом. Возвращает ID, которое можно использовать для выполнения последующих операций.
- Simple_Comm_Close: Закрывает последовательный порт, ранее открытый функцией Simple_Comm_Open.
- Simple_Comm_Write: Пишет данные в последовательный порт.
- Simple_Comm_Read: Читает данные из последовательного порта.
- Simple_Comm_Info: Возвращает информацию о библиотеке сериальной коммуникации.
Исполнение: Часть кода, отвечающая за выполнение функций и процедур, которые составляют библиотеку. Каждая функция реализована с помощью вызовов Windows API, таких как CreateFile, WriteFile, ReadFile и т.д.
Функция Simple_Comm_Open создает файловый обрабатчик для последовательного порта с помощью CreateFile. Затем она настраивает параметры времени общения с помощью SetCommTimeouts, настраивает размер буфера общения с помощью SetupComm и настраивает сигналы DTR и RTS с помощью SetCommState.
Функция Simple_Comm_Close закрывает файловый обрабатчик для последовательного порта с помощью CloseHandle.
Альтернативное решение: Код предлагает альтернативное решение создания модуля ввода/вывода под Windows 95/NT. Это涉глашает создание DLL, экспортирующей функции для открытия, закрытия, чтения и записи данных в последовательный порт.
В целом, эта библиотека предоставляет простой способ выполнить сериальную коммуникацию под Windows с помощью языка программирования Pascal.
Работа с последовательными портами: модуль для управления доступом к последовательным портам под Windows.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.