Автор статьи Семенов Ю.В.
Установка драйверов USB фирмы FTDI.
<<< Начало
После появления на экране сообщения об
обнаружении нового USB устройства необходимо установить соответствующие драйверы
фирмы FTDI. Они находятся в файле D2XX10401.zip на сайте фирмы. Производитель
рекомендует распаковать этот файл на дискету и дальнейшую установку производить
с неё [7]. В ответ на сообщение об
обнаружении нового устройства необходимо нажать кнопку «Далее». На следующем
экране мастера установки следует отметить радио кнопку «Да (рекомендуется)» и
нажать кнопку «Далее». На третьем экране необходимо указать установку с флоппи
диска или ввести полный путь к файлу Ftd2xx.inf на жёстком диске. Для
продолжения установки нажимается кнопка «Далее». Если выбрана установка с флоппи
диска, то он должен быть предварительно вставлен в дисковод. На четвёртом экране
мастера установки выводится имя устройства и введённый ранее путь к драйверу.
Если в этой информации нет ошибок, то следует нажать кнопку «Далее». Появление
пятого экрана говорит об успешной установке драйвера устройства. Нажатием кнопки
«Готово» установка завершается. Для осуществления описанных выше манипуляций
достаточно наличие модуля USB. Установка его в материнскую плату
необязательна. Для работы с устройством
со стороны компьютера, автор использовал С++ Builder 6. В принципе, подойдёт и
С++ Builder 5. На следующем этапе
потребуется создать новый каталог, в который надо переписать файлы Ftd2xx.h и
Ftd2xx.dll из архива D2XX10401.zip. К сожалению, файл Ftd2xx.lib, присутствующий
в архиве, несовместим с С++ Builder 6. Для генерации его рабочей версии
необходимо использовать утилиту IMPLIB. Для этого, в созданный каталог
переписывается файл implib.exe из C:\ Borland\ CBuilder6\ Bin\. Здесь С: - имя
диска, где установлен С++ Builder 6. Утилита запускается из текущего каталога с
помощью командной строки «implib.exe Ftd2xx.dll». После этого в текущем каталоге
появится файл Ftd2xx.lib, который соответствует требованиям С++ Builder 6. С
целью экономии места, файлы implib.exe и Ftd2xx.dll можно удалить из текущего
каталога, так как они присутствуют в других каталогах и не нужны напрямую для
создания проекта на С++ Builder 6. После
подготовки файлов, связанных с динамической библиотекой Ftd2xx.dll, создаётся
проект на С++ Builder 6 обычным способом. В файл проекта перед функцией WinMain
необходимо вставить макрос USELIB("Ftd2xx.lib"), указывающий на использование
внешней динамической библиотеки. В заголовочный файл формы добавляется директива
#include "FTD2XX.h", которая подключает заголовочный файл динамической
библиотеки. Затем файлы проекта и формы должны быть сохранены в текущем
каталоге. После проведения операций, описанных выше, компилятор и компоновщик
будут связывать функции, предназначенные для работы с USB, с соответствующей
динамической библиотекой, а та, в свою очередь, с предварительно установленным
драйвером устройства. Текущее содержимое переменных, структур и прочих форм
данных, с которыми оперируют функции USB, станет доступно в процессе отладки.
Программа для работы с индикатором по USB.
Предлагаемая программа написана в среде
С++ Builder 6 и предназначена для демонстрации порядка работы со стороны
компьютера с USB с помощью функций динамической библиотеки Ftd2xx.dll фирмы
FTDI. При разработке программы использовался документ [8], в котором содержится
подробное описание функций для работы с
USB. Форма для решения поставленной выше
учебной задачи может выглядеть, как показано на рис. 6.
Рис.6 Предполагаемый вид формы.
На форме имеется меню (компонент
TMainMenu) с именем MainMenu1. Пункт «Файл» с именем File содержит подпункты
«Передача» (имя Translate) и «Выход» (имя Exit). Пункт меню «EEPROM» с таким же
именем содержит два подпункта «Прошить» (имя Program) и «Прочитать» (имя Read).
Пункт меню «Файл» -> «Передача» и кнопка «Выполнить» (компонент TВutton, имя
Execute), расположенная на форме, ссылаются на одну и ту же функцию. На форме
расположено два окна типа TЕdit. Левое окно с именем TxD предназначено для ввода
символов, а правое с именем RxD для их вывода. Внизу формы расположен компонент
RichEdit1 типа RichEdit. Под меню находится панель Panel1 типа TPanel. На ней
расположены три кнопки типа TBitBtn. Левая кнопка имеет имя Left, средняя –
Right, а последняя, правая кнопка – Clear. Свойство Glyph этих кнопок ссылается
на различные битовые матрицы, которые содержат пиктограммы, соответствующие
действиям кнопок. Над окнами ввода, вывода и компонентом RichEdit1 располагаются
метки типа TLabel, в свойство Caption которых занесены надписи, описывающие
назначение этих компонентов. Ниже
приводится файл заголовка программного модуля приведённой выше формы, имеющей
имя USBTrans. В нём содержатся объявления всех используемых компонентов.
//--------------------------------------------------------------------------- #ifndef
USBFTDIH #define
USBFTDIH //--------------------------------------------------------------------------- #include
"FTD2XX.h" #include <Classes.hpp> #include
<Controls.hpp> #include <StdCtrls.hpp> #include
<Forms.hpp> #include <Menus.hpp> #include
<ExtCtrls.hpp> #include <ComCtrls.hpp> #include
<Buttons.hpp> //--------------------------------------------------------------------------- class
TUSBTrans : public TForm { __published: // IDE-managed
Components
TMainMenu
*MainMenu1;
TMenuItem
*File;
TMenuItem
*EEPROM;
TMenuItem
*Program;
TMenuItem
*Exit;
TMenuItem
*N1;
TMenuItem
*Translate;
TEdit
*TxD;
TEdit
*RxD;
TLabel
*Label1;
TLabel
*Label2;
TButton
*Execute;
TTimer
*Timer1;
TMenuItem
*Read;
TRichEdit
*RichEdit1;
TLabel
*Label3;
TPanel
*Panel1;
TBitBtn
*Left;
TBitBtn
*Right;
TBitBtn
*Clear;
void __fastcall ExitClick(TObject
*Sender);
void __fastcall TranslateClick(TObject
*Sender);
void __fastcall Timer1Timer(TObject
*Sender);
void __fastcall ProgramClick(TObject
*Sender);
void __fastcall ReadClick(TObject
*Sender);
void __fastcall LeftClick(TObject
*Sender);
void __fastcall RightClick(TObject
*Sender);
void __fastcall ClearClick(TObject *Sender); private: // User
declarations
FT_PROGRAM_DATA
ftData;
FT_STATUS
USBStat;
FT_HANDLE hUSB; public: // User
declarations
__fastcall TUSBTrans(TComponent*
Owner);
void USBErr(FT_STATUS
ftStatus);
void CommandTrans(char
Command); }; //--------------------------------------------------------------------------- extern
PACKAGE TUSBTrans
*USBTrans; //--------------------------------------------------------------------------- #endif
В конструкторе модуля формы для получения
дескриптора подключённого устройства используется функция FT_Open, объявленная
следующим образом:
FT_STATUS FT_Open (int iDevice, FT_HANDLE *ftHandle ).
Функция возвращает переменную типа
FT_STATUS, содержащую информацию о завершении. Если возвращаемое значение
содержит FT_OK, то функция завершена успешно. В противном случае функция
завершена с ошибкой. iDevice - целое
число. Если к компьютеру подключено одно устройство, то этот параметр равен 0. В
случае нескольких устройств это число может принимать значения 1,2 и так далее.
*ftHandle – возвращаемый функцией
указатель на переменную типа FT_HANDLE, содержащую дескриптор подключенного
устройства. В рассматриваемом случае
подключается одно устройство. Поэтому первый параметр функции FT_Open равен
0. После получения дескриптора необходимо
привести устройство в исходное состояние. Для этого служит функция
FT_ResetDevice, объявленная как:
FT_STATUS FT_ResetDevice (FT_HANDLE ftHandle ).
Возвращаемое значение аналогично функции
FT_Open. ftHandle – дескриптор
устройства, которое необходимо сбросить, полученный с помощью
FT_Open. Текст конструктора, содержащий
примеры применения описанных выше функций, приведён ниже.
__fastcall TUSBTrans::TUSBTrans(TComponent*
Owner)
:
TForm(Owner) { RichEdit1->Visible=false; Label3->Visible=false; Timer1->Enabled=false; USBStat=FT_Open(0,&hUSB); if(!USBStat==FT_OK) { USBErr(USBStat); return; }; FT_ResetDevice(hUSB); if(!USBStat==FT_OK) { USBErr(USBStat); return; }; }
Здесь же в конструкторе выполняются
действия, необходимые при инициализации программы. Следует обратить внимание на
то, что при старте таймер должен находиться в пассивном
состоянии. При выходе из программы
необходимо освободить используемый дескриптор. Это достигается с помощью функции
FT_STATUS FT_Close (FT_HANDLE ftHandle )
Возвращаемое значение такое же, как и у
функций рассмотренных выше. ftHandle –
дескриптор устройства, которое необходимо деактивировать, полученный ранее с
помощью FT_Open. Пример использования
функции FT_Close приведён в обработчике нажатия на кнопку «Выход».
void __fastcall TUSBTrans::ExitClick(TObject
*Sender) { FT_Close(hUSB); USBTrans->Close(); }
Передача данных от компьютера к
устройству по USB осуществляется после нажатия на кнопку «Выполнить» на форме
или выбора меню «Файл» -> «Передача». Обработчик этого события приведён
ниже. void __fastcall TUSBTrans::TranslateClick(TObject *Sender) { int
i; DWORD EventDWord; DWORD TxBytes; char TxBuffer[16]; DWORD
dwBytesToWrite; DWORD
dwBytesWritten; RichEdit1->Visible=false; Label3->Visible=false; Timer1->Enabled=false; if(TxD->Text.Length()<1) { MessageBox(NULL,"Передавать
нечего","Ошибка
ввода",MB_OK); return; }; if(TxD->Text.Length()>16) { MessageBox(NULL,"В
поле Передача больше 16 символов","Ошибка
ввода",MB_OK); return; }; StrPCopy(TxBuffer,TxD->Text); dwBytesToWrite=TxD->Text.Length(); USBStat=FT_Purge(hUSB,FT_PURGE_TX); if
(!USBStat==FT_OK) { USBErr(USBStat); return; }; USBStat=FT_Write(hUSB,TxBuffer,dwBytesToWrite,&dwBytesWritten); if
(!USBStat==FT_OK) { USBErr(USBStat); return; }; Timer1->Interval=50; Timer1->Enabled=true; }
При передаче данных в программе
использовано две функции. Первая из них FT_Purge объявлена как:
FT_STATUS FT_Purge (FT_HANDLE ftHandle, DWORD dwMask )
Эта функция предназначена для очистки
приёмного или передающего буфера
устройства. Функция возвращает значение
FT_OK, если она завершилась успешно или код ошибки, если выполнение закончилось
неудачно. ftHandle – дескриптор
устройства, у которого надо очистить один из буферов или оба
вместе. dwMask – любая комбинация из
FT_PURGE_RX и FT_PURGE_TX. В примере
очищается буфер передачи с целью исключения из него посторонних символов,
оставшихся от предыдущего сеанса
связи. Следующая функция является одной
из базовых. Она осуществляет непосредственную передачу данных от компьютера к
устройству. Эта функция объявлена как:
FT_STATUS FT_Write (FT_HANDLE ftHandle, LPVOID lpBuffer, DWORD
dwBytesToWrite, LPDWORD lpdwBytesWritten)
Функция возвращает значение FT_OK, если
она завершилась успешно или код ошибки, если выполнение закончилось
неудачно. ftHandle – дескриптор
устройства, которому надо передать
данные. lpBuffer – указатель на буфер,
содержащий передаваемые
данные. dwBytesToWrite – число байт для
записи в устройство. lpdwBytesWritten –
указатель на переменную типа DWORD, содержащую число байт реально записанных в
устройство. Кроме передачи данных от
компьютера к устройству в обсуждаемом обработчике осуществляется предварительная
проверка длины строки. В случае если строка пустая или она длиннее 16 символов,
передача не производится, а на экран выводится соответствующее
сообщение. В случае успешного завершения
функции FT_Write включается таймер с минимально возможным интервалом. Это
связано с тем, что ответные данные от устройства должны приниматься через
некоторый промежуток времени, необходимый для физического обмена данными по USB.
К сожалению, операционная система компьютера не в состоянии реально обеспечить
промежутки времени менее 50 мс, хотя такой интервал можно указать в свойстве
Interval компонента TTimer. Таким
образом, приём данных целесообразно организовать по событию от таймера, которое
наступает через некоторый промежуток времени от момента передачи данных. В
примере это 50 мс. На обработчике события
от таймера следует остановиться более подробно. Его текст расположен ниже.
void __fastcall TUSBTrans::Timer1Timer(TObject *Sender) { DWORD
EventDWord; DWORD RxBytes,TxBytes; char RxBuffer[16]; DWORD
dwBytesReceived; Timer1->Enabled=false; FT_GetStatus(hUSB,&RxBytes,&TxBytes,&EventDWord); if
(RxBytes>16)return; if (RxBytes >
0) { USBStat=FT_Read(hUSB,RxBuffer,RxBytes,&dwBytesReceived);
if (!USBStat ==
FT_OK)
{
USBErr(USBStat);
return;
}; } else { return; }; RxBuffer[RxBytes]=0x00; RxD->Text=AnsiString((const
char*)RxBuffer); }
Первым исполняемым оператором обработчика
является отключение таймера. Это нужно для следующей
передачи. В обработчике события от
таймера применено две функции, связанные с обменом данными по USB. Первая из них
это:
FT_STATUS FT_GetStatus (FT_HANDLE ftHandle, LPDWORD lpdwAmountInRxQueue,
LPDWORD lpdwAmountInTxQueue, LPDWORD
lpdwEventStatus) Функция предназначена
для получения данных о числе символов в очередях на передачу и приём и о
событиях, произошедших с каналом. В случае успешного завершения эта функция
возвращает FT_OK или код ошибки, если операция не
удалась. ftHandle – дескриптор
устройства, статус которого
опрашивается. lpdwAmountInRxQueue –
указатель на переменную типа DWORD, содержащую число байт в очереди
приёма. lpdwAmountInTxQueue – указатель
на переменную типа DWORD, содержащую число байт в очереди передачи.
lpdwEventStatus – указатель на
переменную типа DWORD, содержащую код текущего
события. В примере функция FT_GetStatus
используется перед чтением данных из приёмного буфера для проверки числа
принятых байт на допустимую
величину. Если проверка прошла успешно,
производится приём данных из буфера приёма с помощью функции:
FT_STATUS FT_Read (FT_HANDLE ftHandle, LPVOID lpBuffer, DWORD dwBytesToRead,
LPDWORD lpdwBytesReturned)
В случае успешного завершения эта функция
возвращает FT_OK или код ошибки, если операция не
удалась. ftHandle – дескриптор
устройства, из буфера которого принимаются
данные. lpBuffer – указатель на буфер
приёма устройства. dwBytesToRead –
количество байт, которые должны быть приняты из
устройства. lpdwBytesReturned – указатель
на переменную типа DWORD, содержащую число байт реально принятых из
устройства. После чтения данных, к
приёмному буферу добавляется 0, его содержимое приводится к типу AnsiString и
выводится в свойство Text окна RxD типа
TEdit. На этом обзор функций и примеров,
связанных с организацией обмена данными по USB можно считать завершённым. Однако
упомянутая динамическая библиотека содержит ещё ряд функций, обеспечивающих
разнообразные способы управления каналом USB. С ними читатель может разобраться
самостоятельно. В примере используется
функция:
void USBErr(FT_STATUS ftStatus) Эта
функция описана в заголовочном файле модуля формы и предназначена для
декодирования кода ошибки канала связи и выдачи соответствующих
сообщений. ftStatus – переменная,
содержащая код ошибки. Текст функции
приведён ниже. void TUSBTrans::USBErr(FT_STATUS USBStat) { switch
(USBStat) { case 1: { MessageBox(NULL,"Неверный дескриптор","Ошибка
USB",MB_OK); break; } case 2: { MessageBox(NULL,"Устройство не
найдено","Ошибка USB",MB_OK); break; } case
3: { MessageBox(NULL,"Канал не инициализирован","Ошибка
USB",MB_OK); break; } case 4: { MessageBox(NULL,"Ошибка
ввода-вывода","Ошибка USB",MB_OK); break; } case
5: { MessageBox(NULL,"Передавать нечего","Ошибка
USB",MB_OK); break; } case 6: { MessageBox(NULL,"Недоступный
ресурс","Ошибка USB",MB_OK); break; } case
7: { MessageBox(NULL,"Неверная скорость обмена","Ошибка
USB",MB_OK); break; } case 8: { MessageBox(NULL,"Стирание
недоступно","Ошибка USB",MB_OK); break; } case
9: { MessageBox(NULL,"Запись невозможна","Ошибка
USB",MB_OK); break; } case 10: { MessageBox(NULL,"Ошибка
записи","Ошибка USB",MB_OK); break; } case
11: { MessageBox(NULL,"Чтение ЭСППЗУ невозможно","Ошибка
USB",MB_OK); break; } case 12: { MessageBox(NULL,"Запись ЭСППЗУ
невозможна","Ошибка USB", MB_OK); break; } case
13: { MessageBox(NULL,"Стирание ЭСППЗУ невозможно","Ошибка USB",
MB_OK); break; } case 14: { MessageBox(NULL,"ЭСППЗУ
отсутствует","Ошибка USB",MB_OK); break; } case
15: { MessageBox(NULL,"ЭСППЗУ не программируется","Ошибка USB",
MB_OK); break; } case 16: { MessageBox(NULL,"Неверные
аргументы","Ошибка
USB",MB_OK); break; } default: { MessageBox(NULL,"Неизвестная
ошибка","Ошибка
USB",MB_OK); } }; } Приведённый
текст состоит из одного оператора switch, где каждый из кодов ошибки вызывает
своё сообщение. Содержимое ЭСППЗУ,
расположенного совместно с микросхемой контроллера USB, определяется с помощью
специальной структуры типа FT_PROGRAM_DATA, объявленной как:
typedef struct ft_program_data
{
WORD VendorId;
WORD ProductId;
char *Manufacturer;
char *ManufacturerId;
char *Description;
char *SerialNumber;
WORD
MaxPower;
WORD PnP;
WORD SelfPowered;
WORD RemoteWakeup;
UCHAR Rev4; // non-zero if Rev4 chip, zero
otherwise
UCHAR IsoIn; // non-zero if in endpoint is
isochronous
UCHAR IsoOut; // non-zero if out endpoint is
isochronous
UCHAR PullDownEnable; // non-zero if pull down
enabled
UCHAR SerNumEnable; // non-zero if serial number to be
used
UCHAR USBVersionEnable; // non-zero if chip uses
USBVersion
WORD USBVersion; // BCD (0x0200 => USB2) } FT_PROGRAM_DATA,
*PFT_PROGRAM_DATA;
VendorId – код владельца
продукта. ProductId – код самого
продукта. *Manufacturer – строка с
названием производителя. *ManufacturerId
– строка с кодом
производителя. *Description – строка с
описанием устройства. *SerialNumber –
строка с серийным номером. Всегда «FT000001» или
NULL. MaxPower – максимальный
потребляемый ток в миллиамперах. Минимум 0, максимум
500. PnP – устройство Plug and Play. 0 –
запрещено, 1– разрешено. SelfPowered –
самопитание. 0 – питание от USB, 1 – питание от собственного
устройства. RemoteWakeup – удалённый
перевод в активное состояние. 0 – невозможно, 1 –
возможно. Остальные члены структуры
представляют собой расширение для четвёртой
версии. Rev4 – не ноль – микросхема
версии 4, ноль – другая версия. IsoIn –
не ноль, если вход устройства
изохронный. IsoOut – не ноль, если выход
устройства изохронный. PullDownEnable –
не ноль, если разрешена нагрузка между выводом и общим
проводом. SerNumEnable – не ноль, если
микросхеме разрешено использовать серийный
номер. USBVersionEnable – не ноль, если
микросхеме разрешено использовать код версии
USB. USBVersion – двоично-десятичное
представление кода версии USB. 200 – USB
2.0. При выборе пункта меню «EEPROM»
-> «Прошить» вызывается обработчик, текст которого приведён ниже.
void __fastcall TUSBTrans::ProgramClick(TObject
*Sender) { ftData.VendorId=0x0403; ftData.ProductId=0x6001; ftData.Manufacturer="FTDI"; ftData.ManufacturerId="FT"; ftData.Description="USB
HS Serial
Converter"; ftData.SerialNumber="FT000001"; ftData.MaxPower=44; ftData.PnP=1; ftData.SelfPowered=0; ftData.RemoteWakeup=1; ftData.Rev4=false; ftData.IsoIn=false; ftData.IsoOut=false; ftData.PullDownEnable=false; ftData.SerNumEnable=false; ftData.USBVersionEnable=false; ftData.USBVersion=0; USBStat
= FT_EE_Program(hUSB,&ftData); if (!USBStat ==
FT_OK) { USBErr(USBStat); return; }; MessageBox(NULL,"ЭСППЗУ
запрграммировано","Сообщение
USB",MB_OK); } Как видно из
приведённого фрагмента, ЭСППЗУ программируется стандартными данными, взятыми из
примера фирмы FTDI [4]. Однако, возможно заполнение структуры и программирование
ЭСППЗУ своими данными. Программирование выполняется с помощью функции:
FT_STATUS FT_EE_Program (FT_HANDLE ftHandle, PFT_PROGRAM_DATA lpData
) ftHandle – дескриптор устройства,
ЭСППЗУ которого требуется
запрограммировать. LpData – указатель на
структуру типа FT_PROGRAM_DATA. При
выборе пункта меню «EEPROM» -> «Прочитать» вызывается следующий обработчик.
void __fastcall TUSBTrans::ReadClick(TObject *Sender) { AnsiString
astrStr; char ManufacturerBuf[32]; char ManufacturerIdBuf[16]; char
DescriptionBuf[64]; char SerialNumberBuf[16]; ftData.Manufacturer =
ManufacturerBuf; ftData.ManufacturerId =
ManufacturerIdBuf; ftData.Description =
DescriptionBuf; ftData.SerialNumber =
SerialNumberBuf; RichEdit1->Visible=true; Label3->Visible=true; RichEdit1->Lines->Clear(); USBStat=FT_EE_Read(hUSB,&ftData); if
(!USBStat ==
FT_OK) { USBErr(USBStat); return; }; RichEdit1->Lines->Add("Код
владельца="+IntToHex(ftData.VendorId,4)); RichEdit1->Lines->Add("Код
продукта="+IntToHex(ftData.ProductId,4)); RichEdit1->Lines->Add("Производитель: "+AnsiString(ftData.Manufacturer)); RichEdit1->Lines->Add("Код
производителя: " +
AnsiString(ftData.ManufacturerId)); RichEdit1->Lines->Add("Описание
продукта: " +
AnsiString(ftData.Description)); RichEdit1->Lines->Add("Серийный номер:
" +
AnsiString(ftData.SerialNumber)); RichEdit1->Lines->Add("Максимальное
потребление="+IntToStr(ftData.MaxPower)+"mA"); if(ftData.PnP==0)
astrStr="Нет"; else astrStr="Да"; RichEdit1->Lines->Add("Режим PNP:
"+astrStr); if(ftData.SelfPowered==0) astrStr="Нет"; else
astrStr="Да"; RichEdit1->Lines->Add("Самопитание:
"+astrStr); if(ftData.RemoteWakeup==0) astrStr="Нет"; else
astrStr="Да"; RichEdit1->Lines->Add("Дистанционное пробуждение:
"+astrStr); if(ftData.Rev4) astrStr="Да"; else
astrStr="Нет"; RichEdit1->Lines->Add("4-я версия:
"+astrStr); if(ftData.IsoIn) astrStr="Да"; else
astrStr="Нет"; RichEdit1->Lines->Add("Изохронность входа:
"+astrStr); if(ftData.IsoOut) astrStr="Да"; else
astrStr="Нет"; RichEdit1->Lines->Add("Изохронность выхода:
"+astrStr); if(ftData.PullDownEnable) astrStr="Да"; else
astrStr="Нет"; RichEdit1->Lines->Add("Подтягивание к нулю:
"+astrStr); if(ftData.SerNumEnable) astrStr="Да"; else
astrStr="Нет"; RichEdit1->Lines->Add("Использование серийного номера:
"+astrStr); if(ftData.USBVersionEnable) astrStr="Да"; else
astrStr="Нет"; RichEdit1->Lines->Add("Использование версии USB:
"+astrStr); RichEdit1->Lines->Add("Версия
USB="+IntToHex(ftData.VendorId,4)); }
В этом фрагменте следует обратить
внимание на объявление строковых переменных структуры. Для каждой из них сначала
создаётся буфер фиксированной длины, а затем строковой переменной структуры
присваивается адрес первого символа соответствующего буфера, который является
указателем на этот буфер. Если этого не сделать, то последующие манипуляции со
структурой вызовут исключение, так как длины строковых переменных, на которые
ссылается структура, не будут
определены. Чтение ЭСППЗУ и заполнение
структуры производится с помощью функции:
FT_STATUS FT_EE_Read (FT_HANDLE ftHandle, PFT_PROGRAM_DATA
lpData) ftHandle – дескриптор устройства,
ЭСППЗУ которого требуется
прочесть. LpData – указатель на структуру
типа FT_PROGRAM_DATA. Затем в обработчике
заполняются последовательно строки компонента RichEdit1, который предварительно
был сделан видимым. Содержимое строк соответствует содержимому
ЭСППЗУ. В нижеследующем фрагменте
программы обрабатываются нажатия кнопок на панели. Поскольку этот текст отвечает
в основном за передачу команд в устройство, нет смысла рассматривать его
подробно. void TUSBTrans::CommandTrans(char Command) { char
TxBuffer[2]; DWORD dwBytesToWrite; DWORD
dwBytesWritten; RichEdit1->Visible=false; Label3->Visible=false; Timer1->Enabled=false; TxBuffer[0]=Command; TxBuffer[1]=0x00; dwBytesToWrite=1; USBStat=FT_Purge(hUSB,FT_PURGE_TX); if
(!USBStat==FT_OK) { USBErr(USBStat); return; }; USBStat=FT_Write(hUSB,TxBuffer,dwBytesToWrite,&dwBytesWritten); if
(!USBStat==FT_OK) { USBErr(USBStat); return; }; } //--------------------------------------------------------------------------- void
__fastcall TUSBTrans::LeftClick(TObject
*Sender) { CommandTrans(0x80); } //--------------------------------------------------------------------------- void
__fastcall TUSBTrans::RightClick(TObject
*Sender) { CommandTrans(0x81); } //--------------------------------------------------------------------------- void
__fastcall TUSBTrans::ClearClick(TObject
*Sender) { CommandTrans(0x82); } //---------------------------------------------------------------------------
В этом фрагменте следует обратить
внимание на отсутствие оператора, включающего таймер после передачи команды.
Таким образом, чтение после передачи команды не
производится. Желающие проверить
программу в работе могут создать форму, приведённую на рис. 6. Затем нужно
автоматически создать обработчики соответствующих событий и заполнить их текстом
рассмотренной программы.
Заключение.
На этом завершается цикл статей,
посвящённый USB решениям фирмы FTDI. Как видно из рассмотренного примера,
применение этих микросхем приводит к значительному упрощению достаточно сложной
задачи. На взгляд автора, это связано с принципиально новым подходом,
предлагаемым фирмой FTDI на рынке полупроводников. Фирма поставляет не только
микросхемы, но и рабочее программное обеспечение к ним. Раньше такой подход
реализовывался только для микропроцессоров и контроллеров. Теперь дело дошло и
до интерфейсных микросхем. Следует
подчеркнуть ещё одну особенность. Далеко не все зарубежные фирмы поставляют своё
математическое обеспечение свободно, как это делает FTDI. Такой подход
способствовал росту популярности в России микроконтроллеров фирмы Microchip,
отладочная среда на которые также свободно доступна. В связи с этим, следует
ожидать и роста популярности микросхем фирмы FTDI, тем более что появились более
мощные микросхемы контроллеров USB, такие как FT8U245BM и FT8U232BM. К
сожалению, они не были доступны автору при разработке устройства, фрагмент
которого был рассмотрен выше.
Литература
7. www.ftdichip.com/Documents/AN232-03.pdf 8.
www.ftdichip.com/Documents/D2XXPG2.pdf
|