Помощь - Поиск - Пользователи - Календарь
Полная версия: RS-232 DOS окне
Форум «Всё о Паскале» > Pascal, Object Pascal > Теоретические вопросы
Nightmare
Господа!
Подскажите человеку, как заставить нормально работать DOS приложения из-под ВыньДос с СОМ портом.
Если в .bat вызываются несколько программ, работающих с портом, то с приличной степенью вероятности происходит следующее:
- первая программа отрабатывает нормально
- вторая инициализирует порт, но не может ничего принять (но не всегда)

В чём коза? В БГ или у меня с головой что-то не так?
GLuk
Сколько можно жевать, сабж уже поднимался...
1. Работай под МСДОС 6.22 или ниже
2. Приведи код, если конечно, BAT не отработается под голым ДОС'ом
Nightmare
Да в том-то всё и дело, что проблемы образуются только при работе в DOS-окне ( без GUI все нормально работает ).
Какую часть кода привести? Его там много.
GLuk
1. Зачем тебе нужно работать именно в ДОС-окне под виндой??!
2. Приведи часть, отвечающую, собственно за работу с портом.
3. Пишешь, на всякий случай, на БП 7.0?
4. Чего именно хочешь добиться (программируя COM-порт)?
Nightmare
Использование COM порта (1 или 2) в режиме: Baund=9600 Parity=None Bit=8 Stop=1.
Код

Unit RSFunc;

INTERFACE

Const
 TimeOut = $0FFFF;
 SpeedDivider: Word = $0C;

Var
 PortBase, RSError: Word;

Function LStatReg: Byte;
Function IsRecive( Var Status: Byte ): Boolean;
Function CheckRcv: Boolean;
Function RsIn: Word;
Procedure RsOut( Value: Byte );
Function SetPort( Number: Byte ): Boolean;
...

IMPLEMENTATION

Uses Crt, Dos;

Function LStatReg: Byte; assembler;
asm
           mov      dx, PortBase
           add      dx, 5
           in      al, dx
           xor      ah, ah
end; {LStatReg}

Function IsRecive( Var Status: Byte ): Boolean;
Var
 Temp: Byte;
 Temp1: Boolean;
begin
 asm
           mov      dx, PortBase
           add      dx, 5
           in      al, dx
           mov      Temp, al
           and      ax, 1
           mov      Temp1, al
 end;
 IsRecive := Temp1;
 Status := Temp;
end; {IsRecive}

Function CheckRcv: Boolean; assembler;
asm
           mov      dx, PortBase
           add      dx, 5
           in      al, dx
           and      ax, 1
end; {CheckRcv}

Function RsIn: Word;
Var
 Temp: Word;
 Temp1: Byte;
 Temp2: Boolean;
begin
 RsIn := 0;
 Repeat
   asm
           mov      dx, PortBase
           add      dx, 5
           in      al, dx
           mov      Temp1, al
           and      ax, 1
           mov      Temp2, al
   end;
   If Temp2 then
   begin
     asm
           mov      dx, PortBase
           in      al, dx
           mov      ah, Temp1
           mov      Temp, ax
     end;
     RsIn := Temp;
     Break;
   end else Inc( Temp );
 Until (Temp > $13EC);
end; {RsIn}

Procedure RsOut( Value: Byte );
Var
 Stat: Boolean;
 Temp: Word;
 Temp1: Byte;
begin
 For Temp := 0 to $7530 do
 begin
   Temp1 := LStatReg;
   asm
           mov      Stat, 0
           mov      al, Temp1
           test      al, 1Ch
           je      @@1
           jmp      @@2
     @@1:
           test      al, 20h
           je      @@2
           mov      Stat, 1
     @@2:
   end;
   If Stat then
   begin
     asm
           mov      dx, PortBase
           mov      al, Value
           out      dx, al
     end;
     Break;
   end;
 end;
end; {RsOut}

Function SetPort( Number: Byte ): Boolean;
Var
 Temp: Word;
 Temp1: Byte;
 SD_Lo, SD_Hi: Byte;
begin
 RsError := 0;
 PortBase := 0;
 SetPort := False;
 Case Number of
   1: PortBase := $3F8;
   2: PortBase := $2F8;
   else begin
     RsError := $2A;
     Exit;
   end;
 end;
 If PortBase <> 0 then
 begin
   SD_Hi := Hi(SpeedDivider);
   SD_Lo := Lo(SpeedDivider);
   asm
           mov      dx, PortBase
           add      dx, 3
           mov      al, 80h
           out      dx, al
           mov      dx, PortBase
           add      dx, 1
           mov      al, SD_Hi
           out      dx, al
           mov      dx, PortBase
           mov      al, SD_Lo
           out      dx, al
           mov      dx, PortBase
           add      dx, 3
           mov      al, 3
           out      dx, al
           mov      dx, PortBase
           add      dx,  1
           xor      ax, ax
           out      dx, al
   end;
   For Temp := 0 to $9C40 do
   begin
     Temp1 := LStatReg;
     asm
           mov      al, Temp1
           and      ax, 80h
           mov      Temp1, al
     end;
     If Temp1 = 0 then
     begin
       SetPort := True;
       Break;
     end;
   end;
 end else RsError := $2A;
end; {SetPort}
...
end.

Инициализация порта:
Код

...
 If not SetPort(ComPort) then
 begin
   Writeln( 'Ошибка инициализации порта СОМ', ComPort );
   Halt( 255 );
 end;
...

Типовое использование (используется спецификация протокола обмена с удалённым контроллером):
Код

Function Command( P1, P2, P3, P4: Byte ): Boolean;

Var
 ...
 Wait: Word;
 Check: Byte;
 ...
begin
 ...
 Command := False;
 RsError := 0;
 ...

типовая передача данных удалёному контроллеру, Check - CRC
Код
 ...
 RsOut( P1 );
 RsOut( P2 );
 RsOut( P3 );
 RsOut( P4 );
 RsOut( $0F );
 RsOut( $0F );
 RsOut( Check );
 ...

типовое ожидание ответа удалённого контроллера
Код

 ...
 Wait := 0;
 While not CheckRcv and (Wait <> TimeOut) do Inc(Wait);
 If Wait = TimeOut then
 begin
   RsError := 1;
   Exit;
 end;
 If Lo(RsIn) = Check then
 begin
   RsError := 0;
   Command := True;
   Exit;
 end;
 ...
end; {Command}

Всё это писалось довольно давно под DOS. Можно, конечно, периписать под Delphi (Console Mode), но лень - слишком много сделано...
GLuk
Цитата
1. Зачем тебе нужно работать именно в ДОС-окне под виндой??!
2. Приведи часть, отвечающую, собственно за работу с портом.
3. Пишешь, на всякий случай, на БП 7.0?
4. Чего именно хочешь добиться (программируя COM-порт)?


Дык все-таки вопросы-то остались:
1. Зачем тебе нужно работать именно в ДОС-окне под виндой??!
4. Чего именно хочешь добиться (программируя COM-порт)?

И ишшо - код сам писал или надрал откуда-нить?
Nightmare
Цитата

Дык все-таки вопросы-то остались:
1. Зачем тебе нужно работать именно в ДОС-окне под виндой??!
4. Чего именно хочешь добиться (программируя COM-порт)?

И ишшо - код сам писал или надрал откуда-нить?


Идею позаимствовал, писал сам.

1. Чтоб не переписывать под Delphi
4. Оно нормально работало под DOS, пока не стали запускать потоком из .bat
GLuk
На com'e какое-то устройство висит? (я это имел в виду, вопр. 4)
Значит все-таки в ДОС'е при запуске из bat не пашет?
вопр. 1: Значит это прога обязательно должна запускаться под виндой?
А ты трейсить не пробовал? (глупый конечно вопрос, но выдыруг чо?)
Nightmare
Да, на COM'е висит устройство с предопределённым протоколом обмена. В голом DOS'е как раз все нормально пашет, даже в эмуляции DOS ( v. 7 ) W'95 W'98, а с GUI ни в какую.
По поводу обязательности запуска: очень желательно, поскольку подавляющая масса софта писана именно под DOS.
По поводу трассировки: каждая программа отрабатывает абсолютно нормально.
Вообще сейчас обходимся тем, что отдельно запускаем каждую программу, благо их не так уж много в одном пакете, но они же разные: приходится напрягаться по поводу последовательности выполнения, а .bat использовать не получается.
Выхода, в принципе, два:
1. переписать под Delphi
2. функционально объеденить отдельные программы в одну
И то и другое делать ОЧЕНЬ лениво.
GLuk
Прости глупого, но все-таки не могу понять почему нужно запускать их под виндой в окошке, если "подавляющяя масса софта писана именно под ДОС"??
Вероятно это из-за того, что какая-то часть под винду?

+ ко всему, надеюсь ты знаешь, что в режиме v86 под протектед моуд, далеко не все проги пашут именно так как надо, тут многое зависит от того, что меняется система прерываний, а эмуляция ее виндой исполняется очень говенно (IMHO).
На всякий случай, bat оформлен в виде:
@echo off
prog1.exe
prog2.exe
..................
??

На мой взгляд лучше объединить их в одну, но не переписывать под делфя...

А что за устройство на коме (конкретно), помимо того что протокол заранее известен??
Nightmare
Исключительно потому, что основной софт пашет под ВыньДос.
.bat оформлен именно так, как ты предположил, т.е. потоковый вызов программ. В единичных случаях обрабатываются коды возврата.
На порте висит терминал сбора данных на базе MCS-51, а софт, в основном, диагностический. Используется не каждый день, но когда нужно...sad.gif
ПО поводу эмуляции системы прерываний, я вообще молчу... (трудно подобрать приличные слова).
Если совсем честно, я просто прохлопал момент, в который эта байда перестала работать по человечески. А потом было уже поздно.

У  меня сложилось впечатление, что перед повторной инициализацией порта либо должно пройти какое-то время, либо он наглухо блокируется GUI для конкретной задачи, причем как ОНО чувствует это я  не представляю ( инициализация порта идет по физическим адресам ), если только ОНО криво обрабатывает даже прямое обращение к порту из DOS-сессии. Хотя этого я раньше не замечал.

Возникла, правда, одна идея - имитировать .bat программно ( запускать программы Exec'ом ) или использовать конвертор .bat -> .exe, но пока не пробывал. Может поможет...
GLuk
А что - вроде как неплохая идея, только вот про конвертор из bat->exe первый раз слышу. Что это такое?: либо он скидывает все екзешники под себя (оверлеем к примеру). А потом типа вися "резидентом" их запускает...
А вот при запуске бат'ом ТОЧНО?! глючит после запуска второй проги?
И что за винда-то?
Nightmare
Винда разная, но преимущественно '98. Вторая прога затыкается примерно 8-9 раз из 10.
А конвертор был довольно интересный (правда потерял я его...). На выходе получалась программуля .exe по структуре .com ( relocation = 0), которая функционально соответствовала .bat. Программы запускались Exec'ом, вывод на экран через int 21h,  ну короче такое ощущение, что программа собрана из стандартных кусков кода, соответствующих одной строке .bat.
GLuk
Что за EXE по структуре COM, в смысле расширение было екзешное. И relocation=0 - это количество перемещаемых (настраиваемых) элементов? Короче говоря это в смысле заголовок пустой?
Такую прогу написать-то несложно, если хочешь могу написать, но я думаю ты и сам сумеешь..
Nightmare
Все именно так и есть. Написать могу, но не вижу особой необходимости, проще получается Exec'ом, и как обычно, не на Паскале.
А вообще опять получается, что выкрутились не найдя причины. Но зато вроде работает.
GLuk
Нашел этот конвертор, кстати (bat->com):
http://www.dospage.by.ru/files/turbobat.zip
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.