Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "WinAPI";
Текущий архив: 2003.03.17;
Скачать: [xml.tar.bz2];

Вниз

Совмещение DOS и Widows   Найти похожие ветки 

 
Shuric   (2002-11-26 22:46) [0]

Я уже испрашивал совета (речь идет о снятии данных с АЦП) на тему выполнения процедуры без ее прерывания (допустим прерыванием Windows), но параллейно вопросу у меня возникло несколько дуратских идей... Не мог бы кто-нибудь высказать свое мнение (по пунктам) о реализации следующей идеи.
1. Раз программа под DOS работает совершенно (имеется в виду что под Windows), будет ли она работать так же и в свернутом режиме.
2. Если да, то можно ли реализовать следующий подход:
Для снятия данных использовать DOS программу, как-то обмениваться данными с Windows родительской программой (которая по идее должна отображать принятые данные)
3. И если да, то как совместно использовать память (допустим, Windows программа проверяет некие адреса на изменение данных... Понимаю, что есть разница под выделении памяти и разрядности :), но все же)
4. И если да, то как читать "память"


 
Cobalt   (2002-11-26 23:11) [1]

1)Если не ошибаюсь, то свернутые окна (программы, не имеющие в данный момент фокуса ввода) имеют приоритет ниже, чем "текущая" (Рихтер), так что... Тестируй свою (Дос-)программу.

2)Для начала - Дос-программы не умеют общаться с Вин-программами. Они о них даже не подозревают, ибо выполняются в совсем другой ОС.
А вот Вин-проги вполне могут обращаться к запущенным ими Дос-прогам, напр. читая их поток вывода (stdOut)
3) Только в одном направлении, или через файл, проверяя его на время последнего изменения.
4) отпал сам собой.


 
Shuric   (2002-11-27 00:05) [2]

Cobalt

Во первых как изменить статус приоритета выполнения DOS программы

Во вторых, DOS программе и не нужно общаться, ей все то надо предоставить адресс и клепать данные туда (пусть будет массив плюс допустим пару байт прочел не прочел Windows программой)... Пусть DOS программа сохранит адрес ну в файл... Опрос Windows программой адреса по таймеру... (как сделать?)

Формировать файл с данными программой DOS, допустим каждые 20 ms невозможно по этому только память...


 
SottNick   (2002-11-27 07:39) [3]

а у меня другие вопросы
1. Как это читать данные с АЦП? Ведь не к процессору же компа он подключен. Данные читаются с какого-то порта?
2. Если протокол обмена известен или есть исходник DOS-проги, то от нее лучше отказаться за бесполезностью...
3. Отображение результатов обмена в любом случае прерывает сам обмен, хоть тресни. А менее 20мс - для отображения результатов - интересная задачка...
4. Решение: ЕГО НЕТ. :o) Делаешь, как все белые люди, приложение для отображения инфы, в нем поток для сбора данных с высоким приоритетом. Или, вряд ли тебя это спасет, приложение - аналог досовской проги без событий, сообщений, окон и других прелестей жизни с абсолютным приоритетом.


 
msts   (2002-11-27 11:57) [4]

дешево и сердито:

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls;

const

WM_DATAPACKET = WM_USER+1000;
DATA_PACKET_SIZE = 19; {-1}
DP_BUFFER_SIZE = 99; {-1}

type

TData = packed record
a : integer;
b : integer;
c : integer;
end;

TDataPacket = array[0..DATA_PACKET_SIZE] of TData;

PDataPacket = ^TDataPacket;

TDataBuffer = array[0..DP_BUFFER_SIZE] of PDataPacket;

TReceiveDataThread = class(TThread)
private
FOwner : THandle;
FSuspending : boolean;
protected
procedure Execute; override;
procedure SendDataPacket(Data : PDataPacket);
function ReceiveDataPacket(Data : PDataPacket) : PDataPacket;
function CreateDataPacket : PDataPacket;
public
constructor Create(Owner : THandle; CreateSuspended: Boolean);
procedure Suspending;
procedure Resumes;
end;

TForm1 = class(TForm)
PaintBox1: TPaintBox;
Timer1: TTimer;
Button1: TButton;
procedure FormCreate(Sender: TObject);
procedure PaintBox1Paint(Sender: TObject);
procedure Timer1Timer(Sender: TObject);
procedure Button1Click(Sender: TObject);
private
Buffer : TBitmap;
DataBuffer : TDataBuffer;
DataBufferPos : integer;
Thread : TReceiveDataThread;
procedure WMDataPacket(var Message: TMessage); message WM_DATAPACKET;
procedure PaintBuffer(Canvas : TCanvas);
public
end;

var
Form1: TForm1;

implementation

uses Types;

{$R *.dfm}

{ TForm1 }

procedure TForm1.FormCreate(Sender: TObject);
begin
Buffer := TBitmap.Create;
with Buffer do begin
PixelFormat := pf8bit;
Height := PaintBox1.Height;
Width := PaintBox1.Width;
Canvas.Brush.Color:=clBlack;
Canvas.FillRect(Canvas.ClipRect);
end;
Timer1.Enabled := false;
Timer1.Interval := 10;

FillChar(DataBuffer, SizeOf(DataBuffer), 0);
DataBufferPos := 0;
Thread := TReceiveDataThread.Create(Self.Handle,True);
// Thread.Priority := tpHigher;
// Thread.Priority := tpHighest; -- не рекомендую
// так как все построено на сообщениях то -
// Thread их посылает быстрее чем форма успевает выбрать из очереди
// в результате увеличивается объем занимаемой памяти (очень быстро)
// и последующий крах
end;

procedure TForm1.PaintBox1Paint(Sender: TObject);
begin
if Buffer.Canvas.LockCount=0 then
PaintBox1.Canvas.Draw(0,0,Buffer);
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
if Buffer.Canvas.LockCount=0 then begin
Buffer.Canvas.Lock;

PaintBox1.Tag := PaintBox1.Tag +1;

with Buffer do begin
Canvas.Brush.Color:=clBlack;
Canvas.FillRect(Canvas.ClipRect);
Canvas.Font.Color := clWhite;
Canvas.TextOut(10,10, IntToStr(PaintBox1.Tag));
Canvas.Pen.Color:=clBlue;
PaintBuffer(Canvas);
end;

PaintBox1.Canvas.Draw(0,0,Buffer);
Buffer.Canvas.Unlock;
end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
Timer1.Enabled := not Timer1.Enabled;
if Timer1.Enabled then Thread.Resumes else Thread.Suspending;
end;

procedure TForm1.WMDataPacket(var Message: TMessage);
var
t : PDataPacket;
begin
t := DataBuffer[DataBufferPos];
DataBuffer[DataBufferPos]:=PDataPacket(Message.WParam);
if t<>nil then FreeMem(t);
if DataBufferPos+1>DP_BUFFER_SIZE then DataBufferPos:=0 else DataBufferPos := DataBufferPos +1;
end;


 
msts   (2002-11-27 11:58) [5]


procedure TForm1.PaintBuffer(Canvas: TCanvas);
var
t,i,x,x_ : integer;

function PaintDataPacket(Data : PDataPacket) : boolean;
var
j : integer;
begin

for j:=0 to DATA_PACKET_SIZE do begin
Canvas.MoveTo(x,Data^[j].a);
Canvas.LineTo(x,Data^[j].b);
Dec(x);
end;

result := (x_ > x);
end;

begin
x := Canvas.ClipRect.Right;
x_ := Canvas.ClipRect.Left;
t := DataBufferPos;
for i:=0 to DP_BUFFER_SIZE do begin
if t=0 then t:=DP_BUFFER_SIZE else t:=t-1;
if DataBuffer[t]<>nil then
if PaintDataPacket(DataBuffer[t]) then break;
end;
end;

{ TReceiveDataThread }

constructor TReceiveDataThread.Create(Owner : THandle; CreateSuspended: Boolean);
begin
inherited Create(CreateSuspended);
FOwner := Owner;
FSuspending := false;
end;

function TReceiveDataThread.CreateDataPacket: PDataPacket;
begin
GetMem(result,SizeOf(TDataPacket))
end;

procedure TReceiveDataThread.Execute;
begin
while true do SendDataPacket(ReceiveDataPacket(CreateDataPacket));
end;

function TReceiveDataThread.ReceiveDataPacket(Data: PDataPacket): PDataPacket;
var
i : integer;
begin
for i:=0 to DATA_PACKET_SIZE do begin
Data^[i].a:=random(40)+10;
Data^[i].b:=random(40)+10;
Data^[i].c:=0;
end;
result := Data;
end;

procedure TReceiveDataThread.Resumes;
begin
FSuspending := false;
Resume;
end;

procedure TReceiveDataThread.SendDataPacket(Data: PDataPacket);
begin
PostMessage(FOwner,WM_DATAPACKET,Integer(Data),0);
if FSuspending then Suspend else Sleep(0); //--- тут уж как надо
end;

procedure TReceiveDataThread.Suspending;
begin
FSuspending := true;
end;

end.


 
msts   (2002-11-27 12:02) [6]

Соответсвенно можно сделать по другому -
завести фиксированный буфер 1000 элементов писать туда из потока
(т.е. без распределения памяти под новые данные - накрывая уже существующие) но тогда форма может не получить некоторые данные - будут накрыты новыми раньше чем она ими воспользуется


 
Shuric   (2002-11-27 15:32) [7]

SottNick ©

DOS программа написана на Си, имеет два include файла, которые поставлялись с АЦП и в общем, занимаются:
1. Запрещение прерывания
2. Опрос порта
3. Разрешение прерывания
По этому, когда прога циклически этим занимается все очень даже быстро. А под винды - изменяешь напругу на входе, а изменения на экране могут быть мгновенными а могут быть и через 10 с

По многочисленным пожеланиям :) фирма учудила и под Windows, причем под Delphi не работало, а под Си нормалек. Пример представлял собой форму с таймером, то есть здесь опрос через их лабуду, да еще и по таймеру :( А по поводу перерисовки - элементарно, только используя не стандартный TBitmap.


 
Shuric   (2002-11-27 15:55) [8]

msts

Спасибочки, буду разбираться...


 
Cobalt   (2002-11-27 22:10) [9]

2 Shuric (27.11.02 00:05)
И смех, и грех...
Поясню - Вин-проги не умеют читать из адресного пространства Дос-прог. Но есть такая вещь, как чтение из потока вывода (stdOut) порожденной Дос(или др. консольной)-проги.
Так что просто выводи все данные "на экран", а Вин-клиент будет их читать и отображать "у себя"

Есть еще один вопрос - при выполнении Дос-проги из Виндов, "скорость реакции"(Дос-проги) - не падает?
И второй вопрос - целесообразность применения Вин-проги? Только для красоты?


 
SottNick   (2002-11-28 06:58) [10]

> Shuric
ЗНАЧИТ
4. Делаешь, как все белые люди, приложение для отображения инфы, в нем поток для сбора данных с высоким приоритетом.

msts тебе почти всё неообходимое дал (и даже перестарался)
данные с порта считывай через драйвер, если он есть, а если нет, на асме накропай (под NT не заработает). Сишные исходники легко переделать.

И разберись с буфером. Нужен ли он тебе динамический такой? Если АЦП работает какими-то сессиями, то создай статический буфер, чтобы размера хватало на одну сессию. Создай переменную-флажок. В потоке считывания перед очередным сохранением данных проверяй, успевает ли комп данные забирать. Если не успевает, сообщай об этом миру (юзеру).

А DOS-прогу выкинь.


 
Shuric   (2002-11-28 15:21) [11]

Cobalt ©
По поводу "не умеют читать из адресного пространства Дос-прог".
Если знать адресное пространство DOS программы, ну, в конечном счете адресок массива с считанными данными, то можно было бы попробовать API CopyMemory :)

"скорость реакции" лучше чем у Windows проги...

А по поводу целесообразности - снятие и отображение енто десятая часть программного комплекса и DOS здесь не катит.


 
Shuric   (2002-11-28 16:02) [12]

SottNick ©

Ты не понял. Пример с исходниками на СИ работает, пример с исходниками на Delphi не работает и исходники на СИ не переделать. Поэтому пришлось пример на СИ упростить и сделать из него DLL :)

Прием данных в примере происходит примерно так

int ready = 0;
m_pADC->Get(ADC_GET_READY, &ready);
if (ready)
{
int data;
m_pADC->Get(ADC_GET_DATA, &data);
и т.д.

и не забывай по таймеру. А что делается в Get() никто кроме разработчиков не знает. Поэтому, если допустим АЦП, имеет свой таймер возможно рассогласования таймеров (не помню, как в науке называется, если представить таймеры как два дискретных процесса)


 
SottNick   (2002-11-29 07:55) [13]

>>Ты не понял. Пример с исходниками на СИ работает,
>>пример с исходниками на Delphi не работает и исходники
>>на СИ не переделать.
>>Поэтому пришлось пример на СИ упростить и
>>сделать из него DLL :)

а по моему всё просто, как в армии
Вот тебе функция Get. Меряй.
function Get(port:word):word; pascal; assembler;
cli
nop
nop
nop
mov dx,port
in ax,dx
nop
nop
sti
end;

все nop можно попробовать выкинуть
проверяй на практике
только использование немного по другому
ready:=Get(ADC_GET_READY);
if (ready and 1)<>0
then
data:=Get(ADC_GET_DATA);


и еще
чтобы АЦП без посредника работало с компом, это надо поискать
скорее всего какой-то контроллер ловит прерывания
от тебя и договаривается с ацп сам
и никакие рассогласования с таймером возникнуть не могут (не должны)
в любом случае твой код (который работает) не держит между чтениями равное время, т.к. работает в многозадачной среде


 
SottNick   (2002-11-29 08:00) [14]

слово пропало
повторяю
function Get(port:word):word; pascal; assembler;
asm
cli
nop
nop
nop
mov dx,port
in ax,dx
nop
nop
sti
end;


 
Shuric   (2002-11-29 15:29) [15]

SottNick ©

Где-то читал и еще больше мне говорили, что конструкция "запретить - разрешить" прерывания удобоварима только для 16-ти разрядной среды, а для 32 это бывает смерти подобно...


 
Victor_Cr   (2002-11-30 00:02) [16]

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


 
Shuric   (2002-11-30 23:49) [17]

Думаю пора эту тему закрывать, ввиду невозможности использовать DOS прогму как "дойную корову", хотя если вдруг кто-нибудь предложит примерчик на обмен с консольным приложением (а то, закончив аспирантуру и сдав экзамен по английскому - ни чего не понимаю в описании страшных функций группы :)) буду просто прыгать на "одной ноге" и кстати если консольное 16 то может быть там забацить прерывания...


 
alnitak   (2003-01-03 21:47) [18]

По вопросу обмена Win9x c DOS-программой ,если есть ее исходники, прошу к alnitak@yandex.ru.
Можно использовать и досовское прерывание таймера (перестроенное
вплоть до 1 мс). Однако период прерывания будет немного размыт
(по сравнению с DOS). Учитывая последнее обстоятельство используйте мультимедийный таймер (WinAPI). Результат почти тот же, но наворотов меньше и прямо из DELPHI. Тем более, что и любые порты можно читать и писать из ассемблерных вставок.

с уважением alnitak



 
OlegZ   (2003-01-25 14:58) [19]

Могу предложить следующее. DOS программа резидентна. До входа в Win она загружается, формирует в памяти буфер для обмена с Win - программой, адрес этого буфера пишет в специальный файл. Потом, когда Вы уже под Win, она по прерываниям опрашивает АЦП и заполняет данными буфер. Win - программа при запуске читает из файла адрес буфера, а затем по Delphi - таймеру забирает данные. Никакой потери нет, если буфер достаточного объема. Есть особенность: область памяти, где сидит DOS - программа и буфер должна быть защищена от вторжения Windows и приложений.
Я такую схему реализовал на Borland Pascal и Delphi3 для работы в W95/98 с АЦП под шину ISA. Все четко, данные идут непрерывно в фоновом режиме.
Если кого интересует, пишите zapisnyh@mtu-net.ru Могу дать исходные тексты.


 
Shuric   (2003-01-25 16:26) [20]

Э э э... Спасибо, спасибо всем. Не могу подобрать слова, облечающию мою тупость, но это все в прошлом году осталось ;) Только повернутый программер может решать задачу о сложении 2 + 2 на трех страницах (из орешника). Беда была решена заменой таймера в Win на цикл, плюс в нем, для реализации обработки инфы от АЦП - CreateEvent...



Страницы: 1 вся ветка

Форум: "WinAPI";
Текущий архив: 2003.03.17;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.52 MB
Время: 0.008 c
14-54232
Kranch
2003-02-27 23:41
2003.03.17
Hosting


8-54125
Noname_
2002-12-04 12:14
2003.03.17
UYVY -> RGB


3-53891
RDA
2003-02-24 17:44
2003.03.17
Глюки с АДО


3-53952
Roki
2003-02-26 15:03
2003.03.17
Мастера, скажите, какое событие происходит?


14-54167
wwwwww
2003-02-27 16:13
2003.03.17
FAQ Shell





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский