Конференция "WinAPI" » Работа с LPT-портом [D7, WinXP]
 
  • Alex_C (26.11.09 08:23) [0]
    Кто нибудь при работе с LPT-портом использовал драйвер DLPortIO? Написал на заказ программу - простенькую по управлению некоторым оборудованием через LPT (там всего лишь на некоторых ножках порта выставляется высокий или низкий уровень). У меня все работает, а у заказчика (который в другом городе) такая проблема: если запустить мою программу - ничего не работает. Если перед этим запустить другую программу, которая работает с LPT тоже при помощи этого драйвера, выйти из нее, а потом опять запустить мою - то все работает. Как такое может быть?
  • Сергей М. © (26.11.09 08:25) [1]

    > Как такое может быть?


    Да как обычно - ошибка у тебя в программе)
  • Alex_C (26.11.09 08:58) [2]

    > Да как обычно - ошибка у тебя в программе)


    Это понятно... )))
    Не понятно где? И как такое может быть в принципе - ну если вообще не работало - тут ясно, а так...
  • Сергей М. © (26.11.09 09:06) [3]

    > Не понятно где?


    Известно где - в 17-й строке)


    > как такое может быть в принципе


    А оч просто - за тобой вообще-то замечена дурная привычка не анализировать рез-ты вызовов API-функций. Она, думаю, как раз и играет с тобой "злую шутку")
  • miek (26.11.09 09:06) [4]
    ошибка в 17 строке
  • Alex_C (26.11.09 09:13) [5]
    Собственно нет там 17 строки...
    Их существенно меньше )))


          Lpt := TDLPortIO.Create(nil);
          Lpt.DriverPath := ExtractFileDir(ParamStr(0));
          Lpt.DLLPath := ExtractFileDir(ParamStr(0));
          Lpt.OpenDriver;
          if not Lpt.ActiveHW then
          begin
            FreeAndNil(Lpt);
            raise Exception.Create('Error LPT port for CW/PTT');
          end;



    а далее уже пишем в порт. Pin - номер вывода на котором устанавливаем уровень сигнала, LPTBase - адрес порта.


    procedure LPTPinOn(Pin: integer; State: Boolean);
    const
      // Masks
      BIT0 : Byte = $01;
      BIT1 : Byte = $02;
      BIT2 : Byte = $04;
      BIT3 : Byte = $08;
      BIT4 : Byte = $10;
      BIT5 : Byte = $20;
      BIT6 : Byte = $40;
      BIT7 : Byte = $80;
    begin
     if Lpt = nil then
     begin
       Application.MessageBox('LTP port not open!', 'Error!', MB_OK);
       Exit;
     end;
     if (State) then
     begin
       case Pin of
         1:  Lpt.Port[LPTBase+2] := Lpt.Port[LPTBase+2] and (not BIT0);  // Inverted
         2:  Lpt.Port[LPTBase] := Lpt.Port[LPTBase] or BIT0;
         3:  Lpt.Port[LPTBase] := Lpt.Port[LPTBase] or BIT1;
         4:  Lpt.Port[LPTBase] := Lpt.Port[LPTBase] or BIT2;
         5:  Lpt.Port[LPTBase] := Lpt.Port[LPTBase] or BIT3;
         6:  Lpt.Port[LPTBase] := Lpt.Port[LPTBase] or BIT4;
         7:  Lpt.Port[LPTBase] := Lpt.Port[LPTBase] or BIT5;
         8:  Lpt.Port[LPTBase] := Lpt.Port[LPTBase] or BIT6;
         9:  Lpt.Port[LPTBase] := Lpt.Port[LPTBase] or BIT7;
         (*
         10: Port[FLPTBase+1] := Port[FLPTBase+1] or BIT6;
         11: Port[FLPTBase+1] := Port[FLPTBase+1] and (not BIT7);  // Inverted
         12: Port[FLPTBase+1] := Port[FLPTBase+1] or BIT5;
         13: Port[FLPTBase+1] := Port[FLPTBase+1] or BIT4;
         *)

         14: Lpt.Port[LPTBase+2] := Lpt.Port[LPTBase+2] and (not BIT1);  // Inverted
         (*
         15: Port[FLPTBase+1] := Port[FLPTBase+1] or BIT3;
         *)

         16: Lpt.Port[LPTBase+2] := Lpt.Port[LPTBase+2] or BIT2;
         17: Lpt.Port[LPTBase+2] := Lpt.Port[LPTBase+2] and (not BIT3);  // Inverted
       else
         // pins 18-25 (GND), and other invalid pins
       end
     end else
     begin
       case Pin of
         1:  Lpt.Port[LPTBase+2] := Lpt.Port[LPTBase+2] or BIT0;    // Inverted
         2:  Lpt.Port[LPTBase] := Lpt.Port[LPTBase] and (not BIT0);
         3:  Lpt.Port[LPTBase] := Lpt.Port[LPTBase] and (not BIT1);
         4:  Lpt.Port[LPTBase] := Lpt.Port[LPTBase] and (not BIT2);
         5:  Lpt.Port[LPTBase] := Lpt.Port[LPTBase] and (not BIT3);
         6:  Lpt.Port[LPTBase] := Lpt.Port[LPTBase] and (not BIT4);
         7:  Lpt.Port[LPTBase] := Lpt.Port[LPTBase] and (not BIT5);
         8:  Lpt.Port[LPTBase] := Lpt.Port[LPTBase] and (not BIT6);
         9:  Lpt.Port[LPTBase] := Lpt.Port[LPTBase] and (not BIT7);
         (*
         10: Port[FLPTBase+1] := Port[FLPTBase+1] and (not BIT6);
         11: Port[FLPTBase+1] := Port[FLPTBase+1] or BIT7;    // Inverted
         12: Port[FLPTBase+1] := Port[FLPTBase+1] and (not BIT5);
         13: Port[FLPTBase+1] := Port[FLPTBase+1] and (not BIT4);
         *)

         14: Lpt.Port[LPTBase+2] := Lpt.Port[LPTBase+2] or BIT1;    // Inverted
         (*
         15: Port[FLPTBase+1] := Port[FLPTBase+1] and (not BIT3);
         *)

         16: Lpt.Port[LPTBase+2] := Lpt.Port[LPTBase+2] and (not BIT2);
         17: Lpt.Port[LPTBase+2] := Lpt.Port[LPTBase+2] or BIT3;    // Inverted
       else
         // pins 18-25 (GND), and other invalid pins
       end
     end;
    end;

  • Сергей М. © (26.11.09 09:59) [6]

    > Alex_C   (26.11.09 09:13) [5]


    ну уже что-то чем совсем ничего)

    Ну так и что не работает ?
  • Вариант (26.11.09 10:46) [7]

    > Alex_C   (26.11.09 08:23)  


    > Если перед этим запустить другую программу, которая работает
    > с LPT тоже при помощи этого драйвера, выйти из нее, а потом
    > опять запустить мою - то все работает. Как такое может быть?
    >

    Как вариант, та программа настраивает порт на нужный режим работы (ECP,EPP,SPP....).
  • Сергей М. © (26.11.09 11:32) [8]

    > та программа настраивает порт на нужный режим работы


    Оч даже себе вариант.

    При этом отсутствие аналогичной ф-ти в программе автора топика как раз и м.б. ошибкой в 17-й строке)
  • vastani (26.11.09 15:48) [9]
    Ну приветик Alex_C, теперь тебе здесь! ))))))))
    только что отписал тебе по ком-портам в ветке, а ты тут уж про LPT, замутил?! ))))))
    Придется тебе пиво высылать виртуальной бандеролью! )
    А твоя проблема, голубчик в том, что та прога в отличие от твоей УМЕЕТ РЕГИСТИРОВАТЬ В СИСТЕМЕ доайвер и активировать его в .... кажись менеджер драйверов или служда называется....
    У меня 1:1 это пройдено и именно с этим драйвером!
    Когда ты пускаешь свою прогу она пользуется "чужими трудами" :) вернее результатами. Система уже имеет подгруженный драйвер и расшатенные вещи, а твоя лишь юзает оные!
  • vastani (26.11.09 15:54) [10]

    const
      DISPLAY_NAME : PChar = 'DriverLINX Port I/O Driver';
      DRV =  'DLPortIO';
      NmLIB = DRV + '.DLL';
      FNmDRV = 'DRIVERS\' + DRV + '.SYS';
    { Имя символuческой связи }
      NmDRV_LINK : PChar = '\\.\'+ DRV;
      NmDRV : PChar = DRV;
    procedure TForm1.KOLForm1Close(Sender: PObj; var Accept: Boolean);
    begin
    if hDRV <> INVALID_HANDLE_VALUE then CloseHandle( hDRV );
    // if UnregService and winnt then
    begin // разрегистрировать сервис
     if hDLL <> 0 then
     begin
      hSCMan := OpenSCManager_( nil, nil, SC_MANAGER_ALL_ACCESS ); // Связаться с менеджером сервисов
      if 0 <> hSCMan then
      begin
       hService := OpenService_( hSCMan, NmDRV, SERVICE_ALL_ACCESS); // Получить хэндл сервиса lptwdmio
       if hService <> 0 then
       begin
        DeleteService_( hService );      // Пометить сервис как подлежащий удалению. Драйвер останется в памяти до ближайшей перезагрузки.
        CloseServiceHandle_( hService ); // Освобождаем хэндл
       end;
       CloseServiceHandle_( hSCMan ); // Высвободить хэндл менеджера сервисов
      end;
     FreeLibrary( hDLL ); // Высвободить хэндл библиотеки AdvApi32.dll
     end;
    end;
    end;
    ///////////////////////
    var
     SysName  : AnsiString;    // Имя файла драйвера
     ServiceArg       : PChar;               // Вспомогательная переменная для вызова StartService
     CreateService_      : PCreateService;      // -//- CreateService
     StartService_       : PStartService;       // -//- StartService
    procedure ConnectDRV;
    begin
      SetLastError( NO_ERROR );
      hDRV := CreateFile( NmDRV_LINK,
            GENERIC_READ or GENERIC_WRITE,
            FILE_SHARE_READ or FILE_SHARE_WRITE,
            nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
    end;
    begin
    // Первичная инициализация
    hDRV := INVALID_HANDLE_VALUE;
    // UnregService := False;
    hDLL := 0;
    // Попытка связаться с драйвером
    ConnectDRV;
    if hDRV = INVALID_HANDLE_VALUE then
    //  if winnt then // Не удалось связаться с драйвером. Он не был установлен вручную.
     begin
      // Windows NT -- пробуем запустить драйвер через менеджер управления сервисами
      hDLL := LoadLibrary(PChar('ADVAPI32.DLL')); // Получим указатели на ф-и менеджера сервисов.
      if hDLL <> 0 then
      begin
       // Re: чтобы программа работала и на NT, и на 9x, используем динамическую загрузку AdvApi32.dll
       // Получим указатели на ф-и в AdvApi32.dll
       OpenSCManager_ := POpenSCManager(GetProcAddress( hDLL, PChar('OpenSCManagerA')));
       CloseServiceHandle_ := PCloseServiceHandle(GetProcAddress( hDLL, PChar('CloseServiceHandle')));
       CreateService_ := PCreateService(GetProcAddress( hDLL, PChar('CreateServiceA')));
       StartService_ := PStartService (GetProcAddress( hDLL, PChar('StartServiceA' )));
       OpenService_ := POpenService  (GetProcAddress( hDLL, PChar('OpenServiceA'  )));
       DeleteService_ := PDeleteService(GetProcAddress( hDLL, PChar('DeleteService' )));
       // Свяжемся с менеджером сервисов
       hSCMan := OpenSCManager_( nil, nil, SC_MANAGER_ALL_ACCESS );
       if 0 <> hSCMan then
         begin // Связались успешно
         SysName := GetWorkDir + 'DLPortIO.SYS'; // имя бинарника sys в рабочей папке
         if not FileExists( SysName ) then
         SysName := GetSystemDir + FNmDRV; // имя бинарника sys в SYSTEM32
        // Попытка создания сервиса
         hService:= CreateService_( hSCMan,
        NmDRV,  // имя сервиса
        DISPLAY_NAME, // отображаемое имя
        SERVICE_ALL_ACCESS,  // права доступа
        1,    // SERVICE_KERNEL_DRIVER
        3,    // SERVICE_DEMAND_START
        1,    // SERVICE_ERROR_NORMAL
        PChar( SysName ),
        nil, nil, nil, nil, nil);
         if 0 = hService then
    begin // Возможно, сервис был создан ранее
    hService := OpenService_( hSCMan, NmDRV, SERVICE_ALL_ACCESS ); // откроем его
    end;
         if 0 <> hService then
    begin // ОК, запускаем сервис
    ServiceArg := nil;
    StartService_( hService, 0, ServiceArg ); // Наш драйвер должен загрузиться...
    //   UnregService := True;             // При разрушении объекта не забыть пометить сервис для удаления
    CloseServiceHandle_( hService ); // Освобождаем хэндл
    end;
         CloseServiceHandle_( hSCMan ); // Освобождаем хэндл
         end;
      end;
      // Вторично пытаемся связаться с драйвером
     ConnectDRV;
     end;
  • vastani (26.11.09 15:57) [11]
    теги блин слетели.... ну ниче копи-паст а там красивее...
    Вообще гдето так. Надеюсь разберешься!
  • vens © (26.11.09 15:59) [12]
    ваава
  • Сергей М. © (26.11.09 21:40) [13]
    Какой выдающийся поток сознания !..
  • Alex_C (27.11.09 08:41) [14]
    Нет ребят!
    Не надо драйвер в системе регистрировать :)
    Все и так работает - подсказали уже: кстати ОЧЕНЬ важная информация для тех, кто хочет работать с LTP портом: оказывется перед началом работы на 1-й ножке порта нужно выставить 0 - и все начинает работать. На мой вопрос - а зачем? Ответиль не смогли - просто чисто опытным путем выяснили. Но факт - инициализация порта должна выглядеть так:

         Lpt := TDLPortIO.Create(nil);
         Lpt.DriverPath := ExtractFileDir(ParamStr(0));
         Lpt.DLLPath := ExtractFileDir(ParamStr(0));
         Lpt.OpenDriver;
         if not Lpt.ActiveHW then
         begin
           FreeAndNil(Lpt);
           raise Exception.Create('Error LPT port for CW/PTT');
         end;
         LPTPinOn(1, False);



    Кстати, может кто знает а почему так?
  • Вариант (30.11.09 06:03) [15]

    > Alex_C   (27.11.09 08:41) [14]


    С точки зрения интерфейса центроникс - 1 пин разъема параллельного порта (LPT) - это сигнал Strobe. Обмен данными с принтером завязан естественно с сигналом строб.
    Но например для зажигания лампочек цветомузыки значения может и не иметь. Так что  просто надо знать протокол обмена на уровне интерфейса с тем железом, которым ты управляешь через порт. И указывать нужный режим работы порта в программе (см [7]) -  тоже будет правильно. А то так возможно и будет у разных клиентов работать по разному.
 
Конференция "WinAPI" » Работа с LPT-портом [D7, WinXP]
Есть новые Нет новых   [134431   +15][b:0][p:0.005]