Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2003.03.17;
Скачать: CL | DM;

Вниз

Совмещение 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 вся ветка

Текущий архив: 2003.03.17;
Скачать: CL | DM;

Наверх




Память: 0.54 MB
Время: 0.02 c
14-54259
ZeroDivide
2003-02-28 10:59
2003.03.17
В роли рака


4-54367
Shuric
2003-01-24 21:48
2003.03.17
Приветик всем... Может кто подскажет?


3-53871
jtiger
2003-02-19 11:01
2003.03.17
Проблема при записи текста на русском текста в MSSQL2000


14-54219
France
2003-03-03 09:06
2003.03.17
Сегодня историческая дата!!!


1-54035
dim-
2003-03-04 15:30
2003.03.17
как можно получить снимок с панели?