|
Подскажите d2xx и FT232R, настроить события в Delphi |
|
|
|
Feb 15 2008, 16:24
|
Группа: Новичок
Сообщений: 8
Регистрация: 15-02-08
Пользователь №: 35 073

|
Добрый вечер! Помогите пожалуйста разобратся с передачей данных через USB с использованием D2XX. Не могу понять как построить программу, что бы по приходу данных во входной буфер выполнялось его считывание. В инфе прочитал о функции "FT_SetEventNotification" которой можно задавать различные условия, Ну отдуплить как реализовать не могу. Подскажите хоть небольшим примером. Пожалуйста натолкните на путь истинны.
|
|
|
|
|
Feb 15 2008, 17:52
|

Профессионал
    
Группа: Модераторы
Сообщений: 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
|
|
|
|
|
Feb 15 2008, 20:02
|
Группа: Новичок
Сообщений: 8
Регистрация: 15-02-08
Пользователь №: 35 073

|
То есть, если я правильно понял, при поступлении данных никаких событий не просиходит. Просто необходимо периодически проверять состояние буфера или флага отвечающего за поступление данных?.
|
|
|
|
|
Feb 17 2008, 08:25
|
Группа: Новичок
Сообщений: 8
Регистрация: 15-02-08
Пользователь №: 35 073

|
Большшое спасибо за разъяснение!
Но я только начинающий в этой среде, хотя по мелочам и раньше занимался Delphi.
Но я не могу понять:
-- Если моя программа состоит из набора процедур, и их выполнение происходит по определенному внешнему событию установленным мною компонентами. Других процедур у меня нет, а компонент D2xx не существует, что бы относительно этого компонента создать процедуру. Так где мне расположить функцию ожидания события?
Извените может я сильно туплю???
Если можно небольшой пример привести, в том что бы разобратся где и в каких частях программы располагать функции.
Большое спасибо! Вячеслав.
|
|
|
|
|
Feb 17 2008, 13:03
|

Профессионал
    
Группа: Модераторы
Сообщений: 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);
|
|
|
|
|
Feb 18 2008, 08:28
|
Группа: Новичок
Сообщений: 8
Регистрация: 15-02-08
Пользователь №: 35 073

|
Не, как бы все понятно, но и втоже время нет. Как это все работает мне кажется я разобрался но программу составить не могу. Привожу пример моего использования USB?: по нажатию одной кнопки запрашиваю данные о производителе и серийном номере, по нажатию второй начинаю прием данных с порта. Данные в порт приходят, пакетом из 8 байт, каждые 0,5 с. Хотелось бы не просто каждые 0,5 секунды отсчетом таймера заходить и забирать данные, а вызывать событие которое будет обрабатыватся отдельной процедурой. МОЖЕТ Я ИДИОТ И МНЕ НУЖНО ИЗУЧАТЬ МАТЧАСТЬ Код 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.
|
|
|
|
|
Feb 18 2008, 08:53
|

Профессионал
    
Группа: Модераторы
Сообщений: 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....
|
|
|
|
|
Feb 18 2008, 13:58
|
Группа: Новичок
Сообщений: 8
Регистрация: 15-02-08
Пользователь №: 35 073

|
Из приведенных примеров и других нетовскиъх форумов, я понял что поступление данных неможет вызвать самостоятельную обработку. Необходимо периодически проверять состояния порта или временно ожидать прием данных (WaitForSingleObject) и по статусу обрабатывать.
На самом деле я хотел чтобы при поступлении данных процес сразуже передавался на обработку данных, независимо где находится программа.
Или же все-таки можно такое организовать??
|
|
|
|
|
Feb 18 2008, 14:15
|

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

|
Цитата(Lexx_kvv @ Feb 18 2008, 16:58)  Или же все-таки можно такое организовать?? Можно организовать! Надо в форме сделать обработчик сообщения. А сообщение посылать по появлению данных, как это сделать я уже писал. Но надо хотя бы понимать принцип работы VCL и WinApi. Кстати исходники VCL есть и там можно посомтреть как происходит обработка сообщений они очень поянтные.
|
|
|
|
|
Feb 18 2008, 20:28
|
Группа: Новичок
Сообщений: 8
Регистрация: 15-02-08
Пользователь №: 35 073

|
Это я понял, но как я могу посылать сообщения если незнаю наличая данных в буфере. Система должна послать сообщение о поступлении данных в буфер, а я должен написать процедуру обработки данного сообщения.
|
|
|
|
|
Feb 19 2008, 06:32
|
Группа: Новичок
Сообщений: 8
Регистрация: 15-02-08
Пользователь №: 35 073

|
При работе С Delphi7 был компонент COM, который обеспечивал работу COM порта, в нем был набор event по которым винда уходила в обработку прерывания, на основе D2xx можно создать такой компонент?
|
|
|
|
|
Feb 19 2008, 11:54
|

Профессионал
    
Группа: Модераторы
Сообщений: 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;
|
|
|
|
|
Feb 20 2008, 15:26
|
Группа: Новичок
Сообщений: 8
Регистрация: 15-02-08
Пользователь №: 35 073

|
Большое спасибо! Буду разбирать. Пока удалось реализовать с помощью таймера и опроса всего содержимого буфера,с возможностью корекции по принятым данным.
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|