Rambler's Top100
"Knowledge itself is power"
F.Bacon
Поиск | Карта сайта | Помощь | О проекте | ТТХ  
 Подземелье Магов
  
 

Фильтр по датам

 
 К н и г и
 
Книжная полка
 
 
Библиотека
 
  
  
 


Поиск
 
Поиск по КС
Поиск в статьях
Яndex© + Google©
Поиск книг

 
  
Тематический каталог
Все манускрипты

 
  
Карта VCL
ОШИБКИ
Сообщения системы

 
Форумы
 
Круглый стол
Новые вопросы

 
  
Базарная площадь
Городская площадь

 
   
С Л С

 
Летопись
 
Королевские Хроники
Рыцарский Зал
Глас народа!

 
  
ТТХ
Конкурсы
Королевская клюква

 
Разделы
 
Hello, World!
Лицей

Квинтана

 
  
Сокровищница
Подземелье Магов
Подводные камни
Свитки

 
  
Школа ОБЕРОНА

 
  
Арсенальная башня
Фолианты
Полигон

 
  
Книга Песка
Дальние земли

 
  
АРХИВЫ

 
 

Сейчас на сайте присутствуют:
 
  
 
Во Флориде и в Королевстве сейчас  05:54[Войти] | [Зарегистрироваться]

Работа с портами ввода-вывода в DELPHI

Дмитрий Кузан
дата публикации 18-04-2001 00:00

Работа с портами ввода-вывода в DELPHI

Я не претендую на полное освещение данного материала,
а просто хочу поделиться своими знаниями
о портах ввода-вывода. Наверняка найдется
гуру который об этом знает лучше меня.

Итак…
1.Что такое порт.

Известно что в компьютере очень много собрано различных устройств, возникает вопрос как операционная система общается с ними. Для этого и служит порт, то есть эта «дверь» через которую программа (операционная система) может управлять данным устройством (считывать данные, заносить их).Причем я разделяю порты на две категории (это чисто мое разделение) - порты общеизвестные (COM LPT) и порты внутренние ,служащие для связи с внутренними устройствами ЭВМ.

2.Некоторые правила для работы с портами

Следует иметь в виду что при разработке программ имеющих дело работы с портами следует учитывать следующие факторы :
  • а) Стараться использовать функции высокого уровня для доступа к портам (в частности WinAPI) и не прибегать к низкоуровневым операциям чтения/записи портов. Если вы все-таки решили писать низкоуровневое чтение то эти процедуры нужно выносить в отдельную DLL или VXD, по следующим причинам - известно, что операционная система Windows95/98 а особенно NT являются по своей сути многозадачными системами. То есть если ваша программа обращается конкретно к порту не через динамический вызов функции DLL или VXD ( использования механизма DLL) а напрямую то это может сказаться на корректной работе системы или даже завалить ее. И даже если в Windows95/98 такой подход вполне может работать то в Windows NT вследствие его архитектуры не разрешит непосредственное чтение/запись напрямую, а использование механизма DLL или VXD позволяет обойти эту проблему.
  • б)Если вы работаете с каким-то нестандартным портом ввода-вывода (например портом хранящим состояние кнопок пульта ДУ TVTunera то наверняка в комплекте поставки родного софта найдется DLL или VXD для управления этим устройством и отпадет нужда писать код, так я при работе с пультом ДУ TVTunerа использую стандартную DLL поставляемую в комплекте, это сразу решило вопросы связанные с управлением портами данного тюнера)
Итак, отступление — немного практики…
Маленький пример для работы с портами (первый пример был уже опубликован в королевстве Дельфи и представлял собой пример работы с весами ПетрВес)
function PortInit : boolean; //инициализация
var f: THandle;  
    ct: TCommTimeouts; 
    dcb: TDCB;
begin
  f := Windows.CreateFile(PChar('COM1'), GENERIC_READ or    
                              GENERIC_WRITE,
                              FILE_SHARE_READ or FILE_SHARE_WRITE,
                              nil, OPEN_EXISTING,
                              FILE_ATTRIBUTE_NORMAL, 0);
  if (f < 0) or not Windows.SetupComm(f, 2048, 2048)or not 
      Windows.GetCommState(f, dcb) then exit; //init error

  dcb.BaudRate := скоpость;
  dcb.StopBits := стоп-биты;
  dcb.Parity := четность;
  dcb.ByteSize := 8;
  if not Windows.SetCommState(f, dcb)
  or not Windows.GetCommTimeouts(f, ct) then exit; //error
  ct.ReadTotalTimeoutConstant := 50;
  ct.ReadIntervalTimeout := 50;
  ct.ReadTotalTimeoutMultiplier := 1;
  ct.WriteTotalTimeoutMultiplier := 0;
  ct.WriteTotalTimeoutConstant := 10;
  if not Windows.SetCommTimeouts(f, ct)
  or not Windows.SetCommMask(f, EV_RING + EV_RXCHAR + EV_RXFLAG + EV_TXEMPTY)
then exit; //error
  result := true;
end;

function DoneComm: boolean; //закpыть поpт
begin
  result := Windows.CloseHandle(f);
end;

function PostComm(var Buf; size: word): integer; //пеpедача в поpт
var p: pointer; i: integer;
begin
  p := @Buf;
  result := 0;
  while size > 0 do begin
    if not WriteFile(f, p^, 1, i, nil) then exit;
    inc(result, i); inc(integer(p)); dec(size);
    Application.ProcessMessages;
    end;
end;

function ReadComm(var Buf; size: word): integer; //пpием из поpта
var i: integer; ovr: TOverlapped;
begin
  fillChar(buf, size, 0);
  fillChar(ovr, sizeOf(ovr), 0); i := 0; result := -1;
  if not windows.ReadFile(f, buf, size, i, @ovr) then exit;
  result := i;
end;
Данный пример был взят мной из многочисленный FAQ посвященных в DELPHI в сети ФИДО

Итак,для работы с портами COM и LPT нам понадобится знание функций Windows API.

Вот подробное описание функций, которые нам нужны (в эквиваленте C) для работы с портами.
(извините за возможный местами неточный перевод ,если что поправьте меня если что не так перевел)

CreateFile

HANDLE CreateFile(

    LPCTSTR lpFileName,	// указатель на строку PCHAR с именем файла 
    DWORD dwDesiredAccess,	// режим доступа
    DWORD dwShareMode,	// share mode 
    LPSECURITY_ATTRIBUTES lpSecurityAttributes,	// указатель на атрибуты 
    DWORD dwCreationDistribution,	// how to create 
    DWORD dwFlagsAndAttributes,	// атрибуты файла
    HANDLE hTemplateFile 	// хендл на temp файл
   );	
Пример кода на Дельфи
<вырезано>
CommPort := 'COM2';               
hCommFile := CreateFile(Pchar(CommPort),                                      
                        GENERIC_WRITE, 0, nil,                                              
                        OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 
                        0);
<вырезано>
Параметры
LpFileName
Указатель на строку с нулевым символом в конце (PCHAR) , которая определяет название создаваемого объекта (файл, канал, почтовый слот, ресурс связи (в данном случае порты), дисковое устройство, приставка, или каталог)
DwDesiredAccess
Указывает тип доступа к объекту ,принимает значение
  • GENERIC_READ - для чтения
  • GENERIC_WRITE - для записи (смешивание с GENERIC_READ операцией GENERIC_READ and GENERIC_WRITE предостовляет полный доступ )
dwShareMode
Набор разрядных флагов, которые определяют как объект может быть разделен по доступу к нему. Если dwShareMode - 0, объект не может быть разделен. Последовательные операции открытия объекта будут терпеть неудачу, пока маркер(дескриптор) открытого объекта не будет закрыт. Фактически предоставляется монопольный доступ.

Чтобы разделять объект(цель), используйте комбинацию одних или большее количество следующих значений:
  • FILE_SHARE_DELETE (Только для Windows NT)
  • FILE_SHARE_READ
  • FILE_SHARE_WRITE
LpSecurityAttributes
Указатель на структуру SECURITY_ATTRIBUTES, которая определяет может ли возвращенный дескриптор быть унаследован дочерними процессами. Если lpSecurityAttributes НУЛЕВОЙ, маркер не может быть унаследован. Используется только в windows NT.
dwCreationDistribution
Определяет поведение функции если объект уже существует и как он будет открыт в этом случае Принимает одно из следующих значений :
CREATE_NEW
Создает новый объект (файл) Выдает ошибку если указанный объект (файл) уже существует.
CREATE_ALWAYS
Создает новый объект (файл) Функция перезаписывает существующий объект (файл)
OPEN_EXISTING
Открывает объект (файл) Выдает ошибку если указанный объект (файл) не существует.(Для более детального смотрите SDK)
OPEN_ALWAYS
Открывает объект (файл), если он существует. Если объект (файл) не существует, функция создает его, как будто dwCreationDistribution были CREATE_NEW.
TRUNCATE_EXISTING
Открывает объект (файл). После этого объект (файл) будет усечен до нулевого размера.Выдает ошибку если указанный объект (файл) не существует.
DwFlagsAndAttributes
Атрибуты объекта (файла) , атрибуты могут комбинироваться
  • FILE_ATTRIBUTE_ARCHIVE
  • FILE_ATTRIBUTE_COMPRESSED
  • FILE_ATTRIBUTE_HIDDEN
  • FILE_ATTRIBUTE_NORMAL
  • FILE_ATTRIBUTE_OFFLINE
  • FILE_ATTRIBUTE_READONLY
  • FILE_ATTRIBUTE_SYSTEM
  • FILE_ATTRIBUTE_TEMPORARY
HTemplateFile
Определяет дескриптор с GENERIC_READ доступом к временному объекту(файлу). Временный объект(файл)поставляет атрибуты файла и расширенные атрибуты для создаваемого объекта (файла) ИСПОЛЬЗУЕТСЯ ТОЛЬКО В WINDOWS NT Windows 95: Это значение должно быть установлено в Nil.

Возвращаемые значения

Если функция преуспевает, возвращаемое значение - открытый дескриптор к указанному объекту(файлу). Если файл не существует - 0.
Если произошли функциональные сбои, возвращаемое значение - INVALID_HANDLE_VALUE. Чтобы получить расширенные данные об ошибках, вызовите GetLastError.

Обратите внимание !
Для портов, dwCreationDistribution параметр должен быть OPEN_EXISTING, и hTemplate должен быть Nil. Доступ для чтения-записи должен быть определен явно.

SECURITY_ATTRIBUTES

Структура содержит описание защиты для объекта и определяет,может ли дескриптор быть унаследован дочерними процессами.
typedef struct _SECURITY_ATTRIBUTES 
{   DWORD  nLength; 
    LPVOID lpSecurityDescriptor; 
    BOOL   bInheritHandle; 
} SECURITY_ATTRIBUTES; 

Параметры

NLength
Определяет размер, в байтах, этой структуры. Набор это значение к размеру структуры SECURITY_ATTRIBUTES В Windows NT функции которые используют структуру SECURITY_ATTRIBUTES, не проверяют значение nLength.
LpSecurityDescriptor
Дескриптор указывающий на описатель защиты для объекта, Если дескриптор ПУСТОЙ объект может быть назначен в наследование дочерними процессами.
BInheritHandle
Определяет, унаследован ли возвращенный дескриптор, когда новый дескриптор, создан. Если это значение принимает ИСТИНУ новый дескриптор наследует от головного.
Замечания
Указатель на структуру SECURITY_ATTRIBUTES используется как параметр в большинстве функций работы с окнами в Win32 API.

Продолжение следует...

Дмитрий Кузан
18 апреля 2001 г.
Специально для Королевства Delphi




Смотрите также материалы по темам:
[Работа с портами ввода/вывода]

 Обсуждение материала [ 19-11-2009 17:40 ] 18 сообщений
  
Время на сайте: GMT минус 5 часов

Если вы заметили орфографическую ошибку на этой странице, просто выделите ошибку мышью и нажмите Ctrl+Enter.
Функция может не работать в некоторых версиях броузеров.

Web hosting for this web site provided by DotNetPark (ASP.NET, SharePoint, MS SQL hosting)  
Software for IIS, Hyper-V, MS SQL. Tools for Windows server administrators. Server migration utilities  

 
© При использовании любых материалов «Королевства Delphi» необходимо указывать источник информации. Перепечатка авторских статей возможна только при согласии всех авторов и администрации сайта.
Все используемые на сайте торговые марки являются собственностью их производителей.

Яндекс цитирования