Эксперименты с LPT-портом (Delphi)

создание собственных программ управления станком, управление LPT

Модераторы: Ruz_and, Master-VRI, al-drw, Мастак

gumel
Сообщения: 17
Зарегистрирован: Ср май 04, 2011 17:54

Эксперименты с LPT-портом (Delphi)

Сообщение gumel » Вс июн 05, 2011 20:30

Скажу сразу: в программировании я не спец, а просто самоучка.

Поскольку с LPT портом я никогда не работал (в плане программирования), решил начать с простого.
LPT порт имеет 25 пинов. Наибольший интерес представляют пины с 1 по 17. Т.к. именно через них происходит обмен информации между устройством и компьютером. Обмен информацией может происходить в обе стороны, от компьютера к устройству и наоборот. На первом этапе я решил разобраться каким макаром можно отправлять и получать данные используя LPT порт.

Для Delphi я нашел несколько библиотек по работе с LPT портом. В основном эти библиотеки используют драйвера *.sys и позволяют осуществлять работу с LPT портом. Честно скажу, я вообще ничего не понимаю про эти драйвера, поэтому решил пойти более простым путем. Есть такая библиотека inpout32.dll, которая позволяет работать с портами без особых проблем. Минус ее в том, что я не могу отследить изменение состояния регистров порта, если такие происходят. Может у меня просто не хватает знаний, х.з. в общем.

Короче, много писать не буду. Для тестирования программы спаял такую штуку:
Изображение
использовал 3 светодиода (проверка чтения порта), и 3 кнопки (проверка записи в порт)

Программа получилась такой:
Изображение

Как можете заметить, в LPT порте есть 3 регистра (output, input и in/out). Работу первых двух я полностью протестировал. Работу последнего протестировал в плане чтения, в плане записи побоялся замыкать пины этого регистра, потому что до конца не уверен что этот регистр может работать и на чтение и запись одновременно, а спалить порт говорят очень легко ))

вот сама программа:
test_inpout32 exe-шник.rar
откомпилированная программа
(250.27 КБ) 984 скачивания

не хватает только самой библиотеки.

Программа показывает состояние трех регистров LPT порта (цветные кружочки №№ 1-17).
Попробуйте пощелкайте курсором мышки по этим кружкам, сами все поймете. Синие будут меняться только от внешнего устройства.

А это архив с исходниками Delphi 7 (кстати там есть нужная DLL-ка для откомпилированного ехе-шника)
testing_inpout32 исходники.rar
(68.26 КБ) 1051 скачивание


На всякий случай, приведу код самого главного и самодельного юнита из этих исходников:

Код: Выделить всё

unit LPTinpout32;

interface

function LptChangeOutput: Boolean; // проводится загрузка текущего состояние регистра OUTPUT, на выходе TRUE в случае нового значения
function LptChangeInput: Boolean;  // проводится загрузка текущего состояние регистра INPUT, на выходе TRUE в случае нового значения
function LptChangeInOut: Boolean;  // проводится загрузка текущего состояние регистра IN/OUT, на выходе TRUE в случае нового значения

function LptOutput: Byte; // значение регистра OUTPUT
function LptInput: Byte;  // значение регистра INPUT
function LptInOut: Byte;  // значение регистра IN/OUT

procedure LptSetOutput(newValue: Byte); // установка нового значения регистра OUTPUT
procedure LptSetInOut(newValue: Byte);  // установка нового значения регистра IN/OUT

function LptGetPin(PinNumb: Byte): Boolean;        // есть ли напряжение на ножке PinNumb
procedure LptSetPin(PinNumb: Byte; Volt: Boolean); // устанавливает/снимает напряжение на ножке PinNumb
 
implementation

function Inp32(PortAdr: Word): Byte; stdcall; external inpout32.dll;
function Out32(PortAdr: Word; Data: Byte): Byte; stdcall; external inpout32.dll;

type
  TLPTrec = record      // ЗАПИСЬ ТАБЛИЦЫ ПИНОВ ДЛЯ LPT ПОРТА
    RegNumb : Byte;     // номер регистра (0 - регистр ДАННЫХ OUTPUT, 1 - регистр СОСТОЯНИЯ INPUT, 2 - регистр КОНТРОЛЯ IN/OUT)
    BitNumb : Byte;     // номер бита в регистре
    Inversed: Boolean;  // инверсия бита (некоторые пины работают наоборот)
  end;

const
  LPTPINTABLE: array [1..17] of TLPTrec = (     // ТАБЛИЦА ПЕРЕВОДА ПИНОВ LPT ПОРТА
    (RegNumb: 2; BitNumb: 0; Inversed: True),   // пин 1
    (RegNumb: 0; BitNumb: 0; Inversed: False),  // пин 2
    (RegNumb: 0; BitNumb: 1; Inversed: False),  // пин 3
    (RegNumb: 0; BitNumb: 2; Inversed: False),  // пин 4
    (RegNumb: 0; BitNumb: 3; Inversed: False),  // пин 5
    (RegNumb: 0; BitNumb: 4; Inversed: False),  // пин 6
    (RegNumb: 0; BitNumb: 5; Inversed: False),  // пин 7
    (RegNumb: 0; BitNumb: 6; Inversed: False),  // пин 8
    (RegNumb: 0; BitNumb: 7; Inversed: False),  // пин 9
    (RegNumb: 1; BitNumb: 6; Inversed: False),  // пин 10
    (RegNumb: 1; BitNumb: 7; Inversed: True),   // пин 11
    (RegNumb: 1; BitNumb: 5; Inversed: False),  // пин 12
    (RegNumb: 1; BitNumb: 4; Inversed: False),  // пин 13
    (RegNumb: 2; BitNumb: 1; Inversed: True),   // пин 14
    (RegNumb: 1; BitNumb: 3; Inversed: False),  // пин 15
    (RegNumb: 2; BitNumb: 2; Inversed: False),  // пин 16
    (RegNumb: 2; BitNumb: 3; Inversed: True));  // пин 17

  ADDRREGLPT: array [0..2] of Integer = ($378, $379, $37A); // адреса регистров OUTPUT, INPUT, IN/OUT

var
  LPTREGVALUE: array [0..2] of Byte; // текущие загруженные значения регистров LPT порта (0-OUTPUT, 1-INPUT, 2-INOUT)

function LoadLptReg(NomReg: Byte): Boolean;
var
  NewVal: Byte;
begin
  NewVal := Inp32(ADDRREGLPT[NomReg]);
  Result := NewVal <> LPTREGVALUE[NomReg];
  if Result then LPTREGVALUE[NomReg] := NewVal;
end;

function LptChangeOutput: Boolean; // проводится загрузка текущего состояние регистра OUTPUT, на выходе TRUE в случае нового значения
begin
  Result := LoadLptReg(0);
end;

function LptChangeInput: Boolean;  // проводится загрузка текущего состояние регистра INPUT, на выходе TRUE в случае нового значения
begin
  Result := LoadLptReg(1);
end;

function LptChangeInOut: Boolean;  // проводится загрузка текущего состояние регистра IN/OUT, на выходе TRUE в случае нового значения
begin
  Result := LoadLptReg(2);
end;

function LptOutput: Byte; // значение регистра OUTPUT
begin
  Result := LPTREGVALUE[0];
end;

function LptInput: Byte;  // значение регистра INPUT
begin
  Result := LPTREGVALUE[1];
end;

function LptInOut: Byte;  // значение регистра IN/OUT
begin
  Result := LPTREGVALUE[2];
end;

procedure SetValueToRegLpt(NomReg, RegValue: Byte);
begin
  LPTREGVALUE[NomReg] := Out32(ADDRREGLPT[NomReg], RegValue);
end;

procedure LptSetOutput(newValue: Byte); // установка нового значения регистра OUTPUT
begin
  SetValueToRegLpt(0, newValue);
end;

procedure LptSetInOut(newValue: Byte);  // установка нового значения регистра IN/OUT
begin
  SetValueToRegLpt(2, newValue);
end;

function GetBit(Value: Byte; BitNum: Byte): Boolean;
begin
  Result := ((Value shr BitNum) and 1) = 1
end;

function LptGetPin(PinNumb: Byte): Boolean;        // есть ли напряжение на ножке PinNumb
begin
  with LPTPINTABLE[PinNumb] do
    begin
      Result := GetBit(LPTREGVALUE[RegNumb], BitNumb);
      if Inversed then Result := not Result;
    end;
end;

procedure SetBit(var Value: Byte; NumBit: Byte; fSet: Boolean);
begin
   if fset then Value := Value or (1 shl NumBit) else
   Value := Value and not (1 shl NumBit)
end;

procedure LptSetPin(PinNumb: Byte; Volt: Boolean); // устанавливает/снимает напряжение на ножке PinNumb
begin
  with LPTPINTABLE[PinNumb] do
    begin
      if Inversed then Volt := not Volt;
      SetBit(LPTREGVALUE[RegNumb], BitNumb, Volt);
      Out32(ADDRREGLPT[RegNumb], LPTREGVALUE[RegNumb]);
    end;
end;

var
  i: Integer;
   
initialization

for i := 0 to 2 do LoadLptReg(i); // загрузим текущие значения регистров LPT порта

finalization
   
end.


__________________________________

Следующим этапом планирую реализовать генератор импульсов, такой необходимый для управления ШД.

gumel
Сообщения: 17
Зарегистрирован: Ср май 04, 2011 17:54

Re: Эксперименты с LPT-портом (Delphi)

Сообщение gumel » Пн июн 06, 2011 02:36

Для управления ШД нужна строго определенная последовательность импульсов. Обороты ШД будут прямопропорциональны частоте этих импульсов.

Аватара пользователя
Мастак
Сообщения: 168
Зарегистрирован: Сб ноя 14, 2009 00:00
Откуда: Уфа

Re: Эксперименты с LPT-портом (Delphi)

Сообщение Мастак » Пн июн 06, 2011 12:27

Практически полностью похожа на мою прогу )
viewtopic.php?f=15&t=1913
За исключением функциональности и инверсии инвертированных пинов.

То что ты не замыкал контакты контакты порта это хорошо, потому что если это и делать, то через сопротивление. Посмотри в инете какой максимальный ток может пропустить лпт, вольт там 5 , хотя на практике меньше, и посчитай по закону Ома.

И ещё, как модератор прошу тебя не ставь крупные изображения, не у всех инет одинаковый.

gumel
Сообщения: 17
Зарегистрирован: Ср май 04, 2011 17:54

Re: Эксперименты с LPT-портом (Delphi)

Сообщение gumel » Пн июн 06, 2011 19:05

Мастак писал(а):Практически полностью похожа на мою прогу )
viewtopic.php?f=15&t=1913
За исключением функциональности и инверсии инвертированных пинов.

То что ты не замыкал контакты контакты порта это хорошо, потому что если это и делать, то через сопротивление. Посмотри в инете какой максимальный ток может пропустить лпт, вольт там 5 , хотя на практике меньше, и посчитай по закону Ома.

И ещё, как модератор прошу тебя не ставь крупные изображения, не у всех инет одинаковый.


И в правду, проги очень похожие! )))

Меня сейчас волнует способ "общения" с LPT портом. Inpout32.dll позволяет записывать и читать данные регистров порта. Но к огромному сожалению, я не могу знать момента, когда произошли изменения в регистрах. И поэтому приходится с некоторой периодичностью читать порт, проверяя возможные изменения. Это не есть гуд...

Про пины. Я их замыкал только на регистре ввода (10-13 и 15 пин) безо всякого сопротивления, порт пока что живой ))) Думаю, может замкнуть порт ввода-вывода?? (1, 14, 16,17 пины).

gumel
Сообщения: 17
Зарегистрирован: Ср май 04, 2011 17:54

Re: Эксперименты с LPT-портом (Delphi)

Сообщение gumel » Вс июн 19, 2011 17:14

Едем потихоньку дальше.

Выкладываю вторую прогу - генератор импульсов.
Изображение

Генератор организовал разными способами. Это для того чтобы протестировать их и выбрать лучший.
По идее тестирование нужно проводить с осциллографом, но у меня нет пока такого под рукой. Вообще мне хотелось бы выяснить предел возможностей LPT порта, хотя я думаю, он всяко-разно выше возможностей ШД.

Инструкцию писать не буду, думаю так все понятно.

Прошу всех, кому это интересно, протестировать различные способы генерирования импульсов. Тесты лучше всего проводить при разной загрузке процессора, и желательно иметь осциллограф. Большинство способов и так грузят проц на 100%, поэтому доп. нагрузка будет скорее всего влиять на генерируемую частоту. Лично я пока отдаю предпочтение организации потока импульсов через, так называемый, мультимедийный генератор. С его помощью можно легко отлавливать 1/1000 секунды и делать то чего нам нужно, процессор не грузится при этом. 1000 Гц мало это или нет, для задачи по управлению ШД, я не знаю.

Еще, что хотел сказать. Та частота, которую показывает программа, это частота отсылки байтов на LPT порт. А в зависимости от того, какие байты будут слаться на этот порт, то на разных пинах будут свои частоты. И физическая частота будет как минимум в 2 раза меньше! А если еще делать некоторую скважность между импульсами, то тогда еще меньше. В этой программе данные шлются на регистр данных LPT порта (пины 2-9).

Вот готовая программа с исходниками (Delphi 7):
02 testing_impulse_gen.rar
(186.66 КБ) 851 скачивание


Вернуться в «програмирование»

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 2 гостя

cron