Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Интерфейс USB в современных нестандандартных периферийных устройствах - Слизовский Е.В

..pdf
Скачиваний:
136
Добавлен:
24.05.2014
Размер:
1.07 Mб
Скачать

обращения к нему FT2XX.dll, то автору не пришлось тратить время на разработку собственного драйвера.

Для обращения к драйвером может использоваться функция DeviceIOControl. Функция DeviceIOControl должна принимать следующие параметры:

дескриптор хоста, порта или устройства, полученный с помощью вызова

CreateFile

код вызываемой функции

входной буфер и его размер

выходной буфер и его размер

указатель на переменную, в которою будет возвращено число реально переданных (или прочитанных) байтов

41

3.1.2 Введение в Windows Driver Model

WDM (Windows Driver Model, драйверная модель Windows) – новая модель архитектуры драйверов, предложенная Microsoft для Windows 2000. Конечно, эта архитектура развивалась, начиная с Windows 3.11, продолжала развиваться в Windows 98 и Windows NT, но по-настоящему полной она стала только в Windows 2000.

С точки зрения WDM, существует три типа драйверов:

драйвер шины (Bus Driver) , драйвер обслуживающий контроллер шины, адаптер, мост или любые другие устройства, имеющие дочерние устройства. Драйверы шин нужны для работы системы и поэтому предоставляются Microsoft. Для каждого типа шины (USB, PCI, PCMCIA) в системе имеется свой драйвер. Сторонние разработчики создают драйверы для новых или специфических шин

(VME, Multibus, Futurebus)

функциональный драйвер (Function Driver) – основной драйвер устройства, предоставляющий его функциональный интерфейс. Обязателен, кроме тех случаев, когда устройство используется без драйверов (т.е. ввод/вывод осуществляется драйвером шины или драйвером фильтров шины (см. ниже)). Функциональный драйвер по определению обладает наиболее полной информацией об устройстве. Обычно к специфическим регистрам устройства имеет доступ только этот драйвер.

драйвер фильтра (Filter Driver) – драйвер, поддерживающий дополнительную функциональность устройства (или существующего драйвера) или изменяющий запросы на ввод/вывод и ответы на них от других драйверов (это часто используется для коррекции устройств, предоставляющих неверную информацию о своих требованиях к аппаратным ресурсам). В принципе, такие драйверы необязательны и их может быть несколько. Они могут работать как на более высоком уровне, чем функциональный драйвер или драйвер шины, так и на более низком. Обычно эти драйверы предоставляются производителями или независимыми поставщиками оборудования.

Согласно типам драйверов, существует три типа объектов:

объекты физических устройств (PDO, Physical Device Object)

объекты функциональных устройств (FDO, Functional Device Object)

объекты фильтров устройств (FiDO, Filter Device Object)

Объекты PDO создаются для каждого физически идентифицируемого элемента аппаратуры, подключённого к шине данных. Объект FDO подразумевает единицу логической функциональности устройства. Объекты фильтров предоставляют дополнительную функциональность. Последовательность загрузки драйверов для ОС Windows 2000 и старше подробно описана в [1].

42

3.1.3 Спецификация Plug and Play для USB

Появление огромного числа моделей периферийных устройств привело к очевидной невозможности их ручного конфигурирования. Для правильного конфигурирования устройств зачастую необходимо выбрать множество параметров (порты, аппаратные прерывания, ячейки памяти), при этом необходимо учитывать, например, то, что некоторые устройства могут использовать фиксированные номера прерываний, а некоторые – требуют фиксированного номера. Вполне очевидно, что немногие пользователи ПК обладают достаточными знаниями для правильного конфигурирования современного периферийного оборудования ПК из чего вытекает необходимость автоматического конфигурирования устройств.

Протокол Plug and Play позволяет значительно простить конфигурирование нового оборудования. Перед началом работы система (BIOS при начальной загрузке, Windows при запуске) опрашивает устройства, определяя их требования к системным ресурсам и пытается бесконфликтно распределить ресурсы между устройствами. Если это не удаётся, конфликтующие устройства, скорее всего, будут работать некорректно или не будут работать совсем. Спецификацией Plug and Play (сокращённо PnP) предусматривается также «горячее» подкючение устройств, т.е. подключение во время работы (разумеется, только для соответствующих шин).

Основными функциями PnP являются:

определение и идентификация подключаемых устройств.

уведомление ОС о подключении или отключении устройств

автоматическое конфигурирование устройств (по возможности, без вмешательства пользователя)

Для поддержки PnP устройство должно удовлетворять следующим условиям:

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

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

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

Первые попытки введения PnP относятся к Windows 95, в Windows98 разработка продолжилась, а в Windows 2000 и XP PnP вместе с «горячим» подключением является обычным режимом работы.

Согласно спецификации USB, каждое USB-устройство должно соответствовать спецификации PnP. Шина USB поддерживает динамическое подключение и отключение устройств, поэтому нумерация шины является постоянным процессом, отслеживающим изменения физической топологии.

43

3.2 Инструменты для программирования USB-периферии.

Для разработки программного обеспечения автор использовал среду Borland Delphi 7.0 Build 4.453. Все программы для ПК разрабатывались в этой среде на языке Object Pascal, поэтому листинги программ для ПК приведены именно на этом языке.

При написании программ использовались также средства Windows XP DDK (Windows XP Driver Developer Kit, комплект разработчика драйверов для Windows XP): Device Tree, ChkInf, GenInf и некоторые другие.

Программа Device Tree позволяет отобразить дерево драйверов и соответствующих устройств. Отображение дерева устройств производится с двух точек зрения: с точки зрения принадлежности объектов устройств драйверам и с точки зрения взаимного подчинения объектов устройств при выполнении нумерации устройств.

Для каждого драйвера отображается список всех обрабатываемых кодов (рабочих процедур), размер, атрибуты драйвера и некоторые другие параметры. У этой (и других программ, входящих в состав Windows DDK) есть неприятная особенность – они могут привести к краху системы.

Программа GenInf позволяет сгенерировать inf-файл. Сама программа представляет собой ни что иное, как стандартный для Windows мастер, последовательно отвечая на вопросы которого можно получить вполне приемлемый вариант inf-файла.

44

3.3 Программирование м/с FT245BM, использование драйверов FTDI

3.3.1 Основные функции библиотеки FT2XX

Все функции FT2XX можно разделить на четыре основных группы:

Классические интерфейсные функции, такие как FT_ListDevices, FT_Open, FT_Close и т.п. (всего 33 функции)

Функции обращения к ЭСППЗУ (10 фнкций)

Расширенные функции API (5 функций)

Функции Win32 API (19 функций)

Для создания простых приложений, использующих FT2XX, необходимо лишь несколько из 67 функций, все функции подробно рассмотрены в [10]. Для нормального функционирования ИМС FT245BM достаточно всего лишь 13 функций:

FT_Open

FT_Close

FT_Read

FT_Write

FT_OpenEx FT_ResetDevice FT_Purge FT_SetTimeOuts FT_GetStatus FT_GetQueueStatus FT_SetBreakOn FT_SetBreakOff FTSetEvenNotification

Многие функции, использующиеся для управления ИМС FT232BM или FT2232C в режиме УАПП, не используются для управления FT245BM.

Пример модуля обращения к FT2XX приведён в приложениях, там же приведён текст тестовой программы для демонстрации работоспособности драйвера и устройства. Программы для МК КР1878ВЕ1, работающего совместно с FT245BM приведены ниже. Тестовая программа обеспечивает получение списка подключенных устройств, открытие выбранного устройства, чтение данных из устройства в файл и запись данных из файла в устройство, а также отправку - получение данных по 1 байту и сравнение отправленных и полученных данных.

3.3.2 Программа опроса датчика ускорения

Программа опроса датчика ускорения осуществляет получение 11-разрядных данных из устройства, вывод данных в файл и их графическое представление, отсчёт времени измерения, установку дискретности отсчёта, усреднение результатов измерении при низкой частоте дискретизации, запоминание минимумов и максимумов значений ускорения, а также просмотр сохранённых файлов. Наиболее интересные фрагменты исходного текста программы и изображения некоторых её форм приведены в приложениях.

.

45

3.4 Программирование МК КР1878ВЕ1

3.4.1 Система команд МК КР1878ВЕ1

Ассемблер МК КР1878ВЕ1 содержит несколько групп команд:

Двухоперандные (Сложение, вычитание, сравнение, пересылка и т.п.) команды производят арифметические или логические операции над двумя операндами, адреса которых образуются из индексов, содержащихся в команде и значений регистров сегментов. Один из операндов не изменяет своего содержимого и обозначается src(источник). Результа операции помещается во второй операнд, обозначаемый dst(приёмник).

Литерные (Сложение с литёрой, вычитание литёры, сравнение с литёрой, установка разрядов. сброс разрядов ).команды производят арифметические и логические операции с операндом dst и литерой const, указанной в самой команде. Результат операции помещается в dst.

Однооперандные (инверсия, смена знака, обмен тетрад, сдвиг) команды производят арифметический или логические действия над операндом, адрес которого образуется из индекса, содержащегося в самой команде, и значения регистра адреса сегмента. Результат операции помещается в тот же операнд, обозначаемый dst.

Команды работы со служебными регистрами и регистром состояния процессора

предназначены для безусловной непосредственной установки необходимых значений регистров адресов сегментов для тех случаев, когда необходима адресация к новым переменным или регистрам ввода/вывода, не охватываемым текущими сегментами. Также этими командами загружаются регистры косвенной адресации и устанавливаются режимы их работы.

Команды передачи управления производят передачу управления программе, находящейся по адресу, указанному в младших десяти разрядах команды перехода, либо безусловно, либо по одному из условий перехода.

Специальные команды относятся к классу команд, не вписывающихся в предыдущие разделы и предназначены, в основном, для управления определёнными состояниями процессора.

Одной из специфических особенностей МК является выполнение любой команды за два такта. Так одновременно выполняется несколько команд, то нельзя использовать операнд dst предыдущей команды в следующей команде, в таких случаях необходимо построить программу иначе или вставить команду NOP между командами.

Более подробно система команд МК рассматривается в [3].

3.4.2. Арифметические подпрограммы для КР1878ВЕ1

Для использования МК для решения различных задач могут потребоваться различные арифметические подпрограммы. В приложениях приведены тексты следующих арифметических подпрограмм: знакового и беззнакового умножения двух 8-разрядных чисел, знакового и беззнакового умножения двух 16-разрядных чисел, знакового и беззнакового деления одного 8-разрядного числа на другое, беззнакового деления одного 16-разрядного числа на другое.

3.4.3. Программа обработки сигнала датчика ускорения

Для преобразования сигнала датчика ускорения используется программа, блок-схема которой изображена на рис. 3.2. Работа программы производится по прерываниям от линии PA3 МК. Для понижения энергопотребление предусмотрено использование команды WAIT.

Исходный текст программы приведён в Приложениях.

46

Рис 3.2 Упрощённая блок-схема алгоритма работы программы опроса датчика ускорения.

47

Приложения

Приложение 1. Модуль обращения к FT2XX

unit D2XXUnit;

interface

Uses Windows,Forms,Dialogs;

Type FT_Result = Integer;

// выходные функции

Function GetFTDeviceCount : FT_Result;

Function GetFTDeviceDescription( DeviceIndex : DWord ) : FT_Result; Function GetFTDeviceSerialNo( DeviceIndex : DWord ) : FT_Result; Function Open_USB_Device : FT_Result;

Function Close_USB_Device : FT_Result;

Function Write_USB_Device_Buffer( Write_Count : Integer ) : Integer; Function Read_USB_Device_Buffer( Read_Count : Integer ) : Integer; Function Reset_USB_Device : FT_Result;

Function Purge_USB_Device_Out : FT_Result;

Function Purge_USB_Device_In : FT_Result;

Function Set_USB_Device_RTS : FT_Result;

Function Clr_USB_Device_RTS : FT_Result;

Function Set_USB_Device_DTR : FT_Result;

Function Clr_USB_Device_DTR : FT_Result; Function Set_USB_Device_BaudRate : FT_Result;

Function Set_USB_Device_DataCharacteristics : FT_Result; Function Set_USB_Device_FlowControl : FT_Result; Function Get_USB_Device_ModemStatus : FT_Result; Function Set_USB_Device_Chars : FT_Result;

Function Set_USB_Device_TimeOuts(ReadTimeOut,WriteTimeOut:DWord) : FT_Result; Function Get_USB_Device_QueueStatus : FT_Result;

Function Open_USB_Device_By_Serial_Number( Serial_Number : string ) : FT_Result; Function Open_USB_Device_By_Device_Description( Device_Description : string ) : FT_Result;

Var

// Заголовок порта

FT_HANDLE : DWord = 0;

//Не используется в нынешних версиях, приравнивается к 0 PV_Device : DWord = 0;

//Сохранение значений текущих установок

//Ручная конфигурация до вызова SetUp_USB_Device FT_Current_Baud : Dword;

FT_Current_DataBits : Byte; FT_Current_StopBits : Byte; FT_Current_Parity : Byte; FT_Current_FlowControl : Word; FT_RTS_On : Boolean; FT_DTR_On : Boolean; FT_Event_On : Boolean; FT_Error_On : Boolean; FT_XON_Value : Byte = $11; FT_XOFF_Value : Byte = $13; FT_EVENT_Value : Byte = $0; FT_ERROR_Value : Byte = $0;

//Может быть использована CFGUnit, как флаг некорректного значения

FT_SetupError : Boolean;

//Разрешает/запрещает выдачу сообщений об ошибках

FT_Enable_Error_Report : Boolean = True;

Const

48

//Значения FT_Result FT_OK = 0; FT_INVALID_HANDLE = 1;

FT_DEVICE_NOT_FOUND = 2; FT_DEVICE_NOT_OPENED = 3; FT_IO_ERROR = 4; FT_INSUFFICIENT_RESOURCES = 5; FT_INVALID_PARAMETER = 6; FT_SUCCESS = FT_OK;

//Флаги FT_Open_Ex

FT_OPEN_BY_SERIAL_NUMBER = 1;

FT_OPEN_BY_DESCRIPTION = 2; // Флаги FT_List_Devices

FT_LIST_NUMBER_ONLY = $80000000; FT_LIST_BY_INDEX = $40000000; FT_LIST_ALL = $20000000;

//Выбор скорости (для МС с УАПП) FT_BAUD_300 = 300; FT_BAUD_600 = 600; FT_BAUD_1200 = 1200; FT_BAUD_2400 = 2400; FT_BAUD_4800 = 4800; FT_BAUD_9600 = 9600; FT_BAUD_14400 = 14400; FT_BAUD_19200 = 19200; FT_BAUD_38400 = 38400; FT_BAUD_57600 = 57600; FT_BAUD_115200 = 115200; FT_BAUD_230400 = 230400; FT_BAUD_460800 = 460800; FT_BAUD_921600 = 921600;

//Количество бит данных (только для использования с УАПП) FT_DATA_BITS_7 = 7;

FT_DATA_BITS_8 = 8;

//Стоповые биты, только с УАПП

FT_STOP_BITS_1 = 0;

 

FT_STOP_BITS_2 = 2;

 

// Паритет

 

FT_PARITY_NONE = 0;

 

FT_PARITY_ODD = 1;

 

FT_PARITY_EVEN = 2;

 

FT_PARITY_MARK = 3;

 

FT_PARITY_SPACE = 4;

 

FT_FLOW_NONE = $0000;

 

FT_FLOW_RTS_CTS = $0100;

 

FT_FLOW_DTR_DSR = $0200;

 

FT_FLOW_XON_XOFF = $0400;

 

FT_PURGE_RX = 1;

 

FT_PURGE_TX = 2;

 

// Размер Буфера ВВ

// 32k

FT_In_Buffer_Size = $8000;

FT_In_Buffer_Index = FT_In_Buffer_Size - 1;

FT_Out_Buffer_Size = $8000;

// 32k

FT_Out_Buffer_Index = FT_Out_Buffer_Size - 1; // DLL Name

FT_DLL_Name = 'ftd2xx.dll';

var

//Описание Буферов ввода и вывода

FT_In_Buffer : Array[0..FT_In_Buffer_Index] of byte; FT_Out_Buffer : Array[0..FT_Out_Buffer_Index] of byte;

//Переменная, используемая для обнаружения Тайм-аутов

//Прикрепляется к таймеру в основной форме проекта

//Декрементируется каждые 10 мс, если FT_TimeOut_Count <> 0 FT_TimeOut_Count : Integer = 0;

49

//Используется для подсчёта реального количества

//принятых байт функцией FT_Read_Device_All

//в случае тайм-аута FT_All_Bytes_Received : Integer = 0; FT_IO_Status : Ft_Result = FT_OK;

FT_Device_Count : DWord; FT_Device_String_Buffer : Array [1..50] of Char; FT_Device_String : String;

implementation

function FT_Open(PVDevice:Integer; ftHandle:Pointer ) : FT_Result ; stdcall ; External FT_DLL_Name name 'FT_Open';

function FT_Close(ftHandle:Dword) : FT_Result ; stdcall ; External FT_DLL_Name name 'FT_Close';

function FT_Read(ftHandle:Dword; FTInBuf : Pointer; BufferSize : LongInt; ResultPtr : Pointer ) : FT_Result ; stdcall ; External FT_DLL_Name name 'FT_Read';

function FT_Write(ftHandle:Dword; FTOutBuf : Pointer; BufferSize : LongInt; ResultPtr : Pointer ) : FT_Result ; stdcall ; External FT_DLL_Name name 'FT_Write';

function FT_SetBaudRate(ftHandle:Dword;BaudRate:DWord) : FT_Result ; stdcall ; External FT_DLL_Name name 'FT_SetBaudRate';

function FT_SetDataCharacteristics(ftHandle:Dword;WordLength,StopBits,Parity:Byte) : FT_Result ; stdcall ; External FT_DLL_Name name 'FT_SetDataCharacteristics'; function FT_SetFlowControl(ftHandle:Dword;FlowControl:Word;XonChar,XoffChar:Byte) : FT_Result ; stdcall ; External FT_DLL_Name name 'FT_SetFlowControl'; function FT_ResetDevice(ftHandle:Dword) : FT_Result ; stdcall ; External FT_DLL_Name name 'FT_ResetDevice';

function FT_SetDtr(ftHandle:Dword) : FT_Result ; stdcall ; External FT_DLL_Name name 'FT_SetDtr';

function FT_ClrDtr(ftHandle:Dword) : FT_Result ; stdcall ; External FT_DLL_Name name 'FT_ClrDtr';

function FT_SetRts(ftHandle:Dword) : FT_Result ; stdcall ; External FT_DLL_Name name 'FT_SetRts';

function FT_ClrRts(ftHandle:Dword) : FT_Result ; stdcall ; External FT_DLL_Name name 'FT_ClrRts';

function FT_GetModemStatus(ftHandle:Dword;ModemStatus:Pointer) : FT_Result ; stdcall ; External FT_DLL_Name name 'FT_GetModemStatus';

function FT_SetChars(ftHandle:Dword;EventChar,EventCharEnabled,ErrorChar,ErrorCharEnabled : Byte) : FT_Result ; stdcall ; External FT_DLL_Name name 'FT_SetChars'; function FT_Purge(ftHandle:Dword;Mask:Dword) : FT_Result ; stdcall ; External FT_DLL_Name name 'FT_Purge';

function FT_SetTimeouts(ftHandle:Dword;ReadTimeout,WriteTimeout:Dword) : FT_Result ; stdcall ; External FT_DLL_Name name 'FT_SetTimeouts';

function FT_GetQueueStatus(ftHandle:Dword;RxBytes:Pointer) : FT_Result ; stdcall ; External FT_DLL_Name name 'FT_GetQueueStatus';

function FT_GetNumDevices(pvArg1:Pointer;pvArg2:Pointer;dwFlags:Dword) : FT_Result ; stdcall ; External FT_DLL_Name name 'FT_ListDevices';

function FT_ListDevices(pvArg1:Dword;pvArg2:Pointer;dwFlags:Dword) : FT_Result ; stdcall ; External FT_DLL_Name name 'FT_ListDevices';

function FT_OpenEx(pvArg1:Pointer;dwFlags:Dword;ftHandle:Pointer) : FT_Result ; stdcall ; External FT_DLL_Name name 'FT_OpenEx';

Procedure FT_Error_Report(ErrStr: String; PortStatus : Integer); Var Str : String;

Begin

If Not FT_Enable_Error_Report then Exit; If PortStatus = FT_OK then Exit;

Case PortStatus of

FT_INVALID_HANDLE : Str := ErrStr+' - Invalid Handle...';

50