реклама на сайте
подробности

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> Подскажите d2xx и FT232R, настроить события в Delphi
Lexx_kvv
сообщение Feb 15 2008, 16:24
Сообщение #1





Группа: Новичок
Сообщений: 8
Регистрация: 15-02-08
Пользователь №: 35 073



Добрый вечер!

Помогите пожалуйста разобратся с передачей данных через USB с использованием D2XX.
Не могу понять как построить программу, что бы по приходу данных во входной буфер выполнялось его считывание. В инфе прочитал о функции "FT_SetEventNotification" которой можно задавать различные условия, Ну отдуплить как реализовать не могу.

Подскажите хоть небольшим примером. Пожалуйста натолкните на путь истинны. 07.gif
Go to the top of the page
 
+Quote Post
KRS
сообщение Feb 15 2008, 17:52
Сообщение #2


Профессионал
*****

Группа: Модераторы
Сообщений: 1 951
Регистрация: 27-08-04
Из: Санкт-Петербург
Пользователь №: 555



Цитата(Lexx_kvv @ Feb 15 2008, 19:24) *
Не могу понять как построить программу, что бы по приходу данных во входной буфер выполнялось его считывание.

Само выполняться не будет, данные надо читать (например FT_Read)

Цитата(Lexx_kvv @ Feb 15 2008, 19:24) *
В инфе прочитал о функции "FT_SetEventNotification" которой можно задавать различные условия, Ну отдуплить как реализовать не могу.

В том же даташите есть пример.
Если вы хотите работать по событию вам надо
1. Создать event
2. Вызвать FT_SetEventNotification
3. Подождать event
4. вызвать FT_GetStatus и узнать сколько есть байт в приемном буфере.
5. вызвать FT_Read
Go to the top of the page
 
+Quote Post
Lexx_kvv
сообщение Feb 15 2008, 20:02
Сообщение #3





Группа: Новичок
Сообщений: 8
Регистрация: 15-02-08
Пользователь №: 35 073



То есть, если я правильно понял, при поступлении данных никаких событий не просиходит. Просто необходимо периодически проверять состояние буфера или флага отвечающего за поступление данных?.
Go to the top of the page
 
+Quote Post
KRS
сообщение Feb 16 2008, 10:42
Сообщение #4


Профессионал
*****

Группа: Модераторы
Сообщений: 1 951
Регистрация: 27-08-04
Из: Санкт-Петербург
Пользователь №: 555



Цитата(Lexx_kvv @ Feb 15 2008, 23:02) *
То есть, если я правильно понял, при поступлении данных никаких событий не просиходит. Просто необходимо периодически проверять состояние буфера или флага отвечающего за поступление данных?.

Происходит, если вы установили event через FT_SetEventNotification, то по приему данных он установится и можно проверять не переодически, а по событию дождаться которого можно например WaitForSingleObject

А можно вообще использовать функции FT_W32_xxx и работать как обычно с файлами OVERLAPPED IO
Go to the top of the page
 
+Quote Post
Lexx_kvv
сообщение Feb 17 2008, 08:25
Сообщение #5





Группа: Новичок
Сообщений: 8
Регистрация: 15-02-08
Пользователь №: 35 073



Большшое спасибо за разъяснение!

Но я только начинающий в этой среде, хотя по мелочам и раньше занимался Delphi.

Но я не могу понять:

-- Если моя программа состоит из набора процедур, и их выполнение происходит по определенному внешнему событию установленным мною компонентами. Других процедур у меня нет, а компонент D2xx не существует, что бы относительно этого компонента создать процедуру. Так где мне расположить функцию ожидания события?

Извените может я сильно туплю???

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

Большое спасибо! Вячеслав.
Go to the top of the page
 
+Quote Post
KRS
сообщение Feb 17 2008, 13:03
Сообщение #6


Профессионал
*****

Группа: Модераторы
Сообщений: 1 951
Регистрация: 27-08-04
Из: Санкт-Петербург
Пользователь №: 555



Цитата(Lexx_kvv @ Feb 17 2008, 11:25) *
-- Если моя программа состоит из набора процедур, и их выполнение происходит по определенному внешнему событию установленным мною компонентами. Других процедур у меня нет, а компонент D2xx не существует, что бы относительно этого компонента создать процедуру. Так где мне расположить функцию ожидания события?

Самое простое и логичное вообще создать нить (thread) и вынести общение с FTDI туда, причем скорее всего вам вообще можно обойтись без event, а использовать блокирующее чтение и запись (если данные например идут только в одну сторону или по почереди с начала запрос потом ответ (полудуплекс)). А внутри нити после чтения данных можно послать Message который уже обрабатывать в основной ните ( в форме определить что то типа procedure OnMyMessage(var Msg: TMessage); message WM_MY_MESSAGE;) а при инициализации формы или ... вызвать BeginThread(....)
Примерно так
Код
function FTDI_Thread(Parameter : Pointer) : Integer;
begin
  .....
  .....
  repeat
       FT_Read(......);
       .......
       PostMessage(....);
       .......
  until ......
  .......
  ExitThread(0);
Go to the top of the page
 
+Quote Post
Lexx_kvv
сообщение Feb 18 2008, 08:28
Сообщение #7





Группа: Новичок
Сообщений: 8
Регистрация: 15-02-08
Пользователь №: 35 073



Не, как бы все понятно, но и втоже время нет. Как это все работает мне кажется я разобрался но программу составить не могу. Привожу пример моего использования USB?: по нажатию одной кнопки запрашиваю данные о производителе и серийном номере, по нажатию второй начинаю прием данных с порта. Данные в порт приходят, пакетом из 8 байт, каждые 0,5 с. Хотелось бы не просто каждые 0,5 секунды отсчетом таймера заходить и забирать данные, а вызывать событие которое будет обрабатыватся отдельной процедурой.

МОЖЕТ Я ИДИОТ И МНЕ НУЖНО ИЗУЧАТЬ МАТЧАСТЬ 07.gif

Код
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls, Grids, TeEngine, Series, TeeProcs, Chart,
  AxCtrls, OleCtrls, VCF1,D2XXUnit;

type
  TForm1 = class(TForm)
    Button2: TButton;
    Button4: TButton;
    Memo: TMemo;
    procedure LoadClick(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button4Click(Sender: TObject);


  private
    { Private declarations }
  public

    { Public declarations }
  end;

var
  Form1: TForm1;
  temp: string;
  tmp,I:  integer;
  Serial_Number : String;
  Description : String;
  Device_Location:DWord;

implementation

{$R *.dfm}

procedure TForm1.Button2Click(Sender: TObject);
var
  s:string;
  deviceindex:integer;
begin
  GetFTDeviceCount;                           {Количество FT устройств}
  S := IntToStr(FT_Device_Count);
  DeviceIndex := 0;
  GetFTDeviceDescription ( DeviceIndex );
  Description:=FT_Device_String;
  Memo.Lines.Add('Устройство - '+FT_Device_String);
  GetFTDeviceSerialNo( DeviceIndex );
  Serial_Number:=FT_Device_String;
  Memo.Lines.Add('Серийный Номер - '+FT_Device_String);
  GetFTDeviceLocation(DeviceIndex);
  Device_Location:=FT_Device_Location;

  Memo.Lines.Add('Место подключения - '+IntToStr(Device_Location));

end;

procedure TForm1.Button4Click(Sender: TObject);
var
  z,IL:integer;
  s:byte;
  slovo:string;
begin
  If Open_USB_Device_By_Serial_Number(Serial_Number) = FT_OK then
      Begin
    Repeat
    z:=Read_USB_Device_Buffer(8);
    str(z,temp);
    memo.Lines.add(temp);
    if z>0 then
           begin
                slovo:='';
                for IL:=0 to 8 do begin s:=FT_IN_BUFFER[IL];
                temp:=chr(s);
                slovo:=slovo+' '+temp;
                end;
                memo.Lines.add(slovo);
           end;
   Until z = 0;
   Close_USB_Device;
      End
      else
      Begin
        Memo.Lines.Add('Ошибка открытия USB устройства')
      End;
end;
END.
Go to the top of the page
 
+Quote Post
KRS
сообщение Feb 18 2008, 08:53
Сообщение #8


Профессионал
*****

Группа: Модераторы
Сообщений: 1 951
Регистрация: 27-08-04
Из: Санкт-Петербург
Пользователь №: 555



Цитата(Lexx_kvv @ Feb 18 2008, 11:28) *
Не, как бы все понятно, но и втоже время нет. Как это все работает мне кажется я разобрался но программу составить не могу. Привожу пример моего использования USB?: по нажатию одной кнопки запрашиваю данные о производителе и серийном номере, по нажатию второй начинаю прием данных с порта. Данные в порт приходят, пакетом из 8 байт, каждые 0,5 с. Хотелось бы не просто каждые 0,5 секунды отсчетом таймера заходить и забирать данные, а вызывать событие которое будет обрабатыватся отдельной процедурой.


VCL умеет обрабатывать только виндоватые message. Поэтому вам надо его сгенерировать PostMessage из своей нити, как я уже писал. ( в принципе можно и SendMessage, но можно обрести гемор...)

Есть еще путь подправить основной цикл обработки сообщений
это гдето в TApplication.Idle заменить WaitMessage на MsgWaitForSingleObject....
Go to the top of the page
 
+Quote Post
Lexx_kvv
сообщение Feb 18 2008, 13:58
Сообщение #9





Группа: Новичок
Сообщений: 8
Регистрация: 15-02-08
Пользователь №: 35 073



Из приведенных примеров и других нетовскиъх форумов, я понял что поступление данных неможет вызвать самостоятельную обработку. Необходимо периодически проверять состояния порта или временно ожидать прием данных (WaitForSingleObject) и по статусу обрабатывать.

На самом деле я хотел чтобы при поступлении данных процес сразуже передавался на обработку данных, независимо где находится программа.

Или же все-таки можно такое организовать??
Go to the top of the page
 
+Quote Post
KRS
сообщение Feb 18 2008, 14:15
Сообщение #10


Профессионал
*****

Группа: Модераторы
Сообщений: 1 951
Регистрация: 27-08-04
Из: Санкт-Петербург
Пользователь №: 555



Цитата(Lexx_kvv @ Feb 18 2008, 16:58) *
Или же все-таки можно такое организовать??

Можно организовать!
Надо в форме сделать обработчик сообщения. А сообщение посылать по появлению данных, как это сделать я уже писал.
Но надо хотя бы понимать принцип работы VCL и WinApi.
Кстати исходники VCL есть и там можно посомтреть как происходит обработка сообщений они очень поянтные.
Go to the top of the page
 
+Quote Post
Lexx_kvv
сообщение Feb 18 2008, 20:28
Сообщение #11





Группа: Новичок
Сообщений: 8
Регистрация: 15-02-08
Пользователь №: 35 073



Это я понял, но как я могу посылать сообщения если незнаю наличая данных в буфере. Система должна послать сообщение о поступлении данных в буфер, а я должен написать процедуру обработки данного сообщения.
Go to the top of the page
 
+Quote Post
KRS
сообщение Feb 18 2008, 20:36
Сообщение #12


Профессионал
*****

Группа: Модераторы
Сообщений: 1 951
Регистрация: 27-08-04
Из: Санкт-Петербург
Пользователь №: 555



Цитата(Lexx_kvv @ Feb 18 2008, 23:28) *
Это я понял, но как я могу посылать сообщения если незнаю наличая данных в буфере. Система должна послать сообщение о поступлении данных в буфер, а я должен написать процедуру обработки данного сообщения.

не умеют Винды посылать сообщения при срабатывании Event.
это вы должны сделать сами или вызывать всесто WaitEvent/GetEvent MsgWaitForSingleObject.
либо создать нить обработчкиа которая ждет события и делает postmessage или вообще использует блокирующее чтение считывает данные и потом вызывает postmessage (ну можно как один из параметров указатель на данные или ....)
Go to the top of the page
 
+Quote Post
Lexx_kvv
сообщение Feb 19 2008, 06:32
Сообщение #13





Группа: Новичок
Сообщений: 8
Регистрация: 15-02-08
Пользователь №: 35 073



При работе С Delphi7 был компонент COM, который обеспечивал работу COM порта, в нем был набор event по которым винда уходила в обработку прерывания, на основе D2xx можно создать такой компонент?
Go to the top of the page
 
+Quote Post
KRS
сообщение Feb 19 2008, 11:54
Сообщение #14


Профессионал
*****

Группа: Модераторы
Сообщений: 1 951
Регистрация: 27-08-04
Из: Санкт-Петербург
Пользователь №: 555



Выдрал из свего старого проекта.
уже много лет на дельфи не писал. Вам надо реализовать примерно следующее
Код
type TFtdi=class(TObject)
protected
  hCom:THandle;
  hThr:THandle;
  hEvt:THandle;
  Terminate:boolean;
  procedure WorkThread;
public
  hWin:THandle;
  constructor Create;
  destructor Destroy; override;
  function Open(const Port:string):integer;
  function Close:integer;
  ........
end;

constructor TFtdi.Create;
begin
  inherited;
end;

destructor TFtdi.Destroy;
begin
  if hFtdi<>0 then Close;
  inherited;
end;

function Starter(Param:pointer):cardinal;
begin
  TFtdi(Param).WorkThread;
  result:=0;
  ExitThread(0);
end;

function TFtdi.Open(const Port: string): integer;
var Temp:cardinal;
begin
  if hFtdi<>0 then Close;
  hFtdi:= // здесь надо открыть ftdi
  if hFtdi=INVALID_HANDLE_VALUE then
  begin
    hFtdi:=0;
    Result:=GetLastError;
    exit;
  end;
  hEvt:=CreateEvent(nil,true,false,nil);
  //вызываете FT_SetEventNotification с нужными параметрами
  FT_SetEventNotification(......);
  Terminate:=false;
  hThr:=BeginThread(nil,0,@Starter,Self,0,Temp);
  Result:=0;
end;

function TFtdi.Close: integer;
var Num:Cardinal;
begin
  if hThr<>0 then
  begin
    Terminate:=true;
    SetEvent(hEvt);
    if WaitForSingleObject(hThr,50)<>WAIT_OBJECT_0 then
    begin
      TerminateThread(hThr,0);
      WaitForSingleObject(hThr,20);
    end;
    hThr:=0;
  end;
  if hFtdi<>0 then
  begin
    // здесь надо закрыть FTDI
  end;
  hFtdi:=0;
  Result:=GetLastError;
end;

procedure TFtdi.WorkThread;
begin
  repeat
    WaitForSingleObject(hEvt,INFINITE);
            ResetEvent(hEvt);
    if Terminate then
    begin
      ........ // требуется завершение нити
      exit;
    end;
    PostMessage(hWin,WM_PACKET,....,...)
  until false;
end;
Go to the top of the page
 
+Quote Post
Lexx_kvv
сообщение Feb 20 2008, 15:26
Сообщение #15





Группа: Новичок
Сообщений: 8
Регистрация: 15-02-08
Пользователь №: 35 073



Большое спасибо!
Буду разбирать. Пока удалось реализовать с помощью таймера и опроса всего содержимого буфера,с возможностью корекции по принятым данным.
Go to the top of the page
 
+Quote Post

2 страниц V   1 2 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 29th June 2025 - 04:34
Рейтинг@Mail.ru


Страница сгенерированна за 0.01489 секунд с 7
ELECTRONIX ©2004-2016