Перейти к содержанию
    

USB HID LPC1768

В одно время сделал устройство в виде небольшой клавиатуры с кнопками и светодиодами на микропроцессоре LPC1343.

За основу было взято описание использования встроенного аппаратного стека HID устройства в этот микропроцессор: http://www.nxp.com/documents/application_note/AN10904.pdf

и презентация http://ics.nxp.com/literature/presentation...lpc13xx.usb.pdf

 

Структура с настройками этого устройства приведена ниже:

    HidDevInfo.idVendor = USB_VENDOR_ID;
    HidDevInfo.idProduct = USB_PROD_ID;
    HidDevInfo.bcdDevice = USB_DEVICE;
    HidDevInfo.StrDescPtr = (uint32_t)&USB_StringDescriptor[0];
    HidDevInfo.InReportCount = 17;
    HidDevInfo.OutReportCount = 1;
    HidDevInfo.SampleInterval = 0x02;
    HidDevInfo.InReport = GetInReport;
    HidDevInfo.OutReport = SetOutReport;

 

Для LPC1768 существует аналогичный пример от Keil, который лежит в папке с установленной программой по адресу: "C:\Keil\ARM\Boards\Keil\MCB1700\USBHID\"

 

Вопрос к тем, кто разбирался с этим HID.

 

В этом примере функции SetOutReport и GetInReport могут передавать и принимать только один байт. Каким образом размер буфера можно увеличить до 64 (в описанном мной примере это делается путем установки переменных InReportCount и OutReportCount )?

 

Второй вопрос: как поднять скорость вызова функции GetInReport() до 2 мс?

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В этом примере функции SetOutReport и GetInReport могут передавать и принимать только один байт. Каким образом размер буфера можно увеличить до 64 (в описанном мной примере это делается путем установки переменных InReportCount и OutReportCount )?

 

Второй вопрос: как поднять скорость вызова функции GetInReport() до 2 мс?

 

 

1. Как минимум придестся корректировать дескрипторы REPORT'ов и еще очень полезно было бы скорректировать размеры пакетов в дескрипторах крнечных точек Interrupt In и Interrupt Out. Возможно, придется дорабатывать и сами функции.

2. Задайте соотв. интервал опроса в дескрипторе конечной точки прерывания. По умолнанию клавиатуры используют интервал в 10 мС ...

Изменено пользователем kovigor

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Недавно "допиливал" данный код. У меня это выглядит так:

 

hiduser.c

#define HID_INPUT_REPORT_BYTES			33			 /* size of report in Bytes */
#define HID_OUTPUT_REPORT_BYTES			33			 /* size of report in Bytes */
#define HID_FEATURE_REPORT_BYTES		2			  /* size of report in Bytes */

/* HID Demo Variables */
extern U8 InReport[HID_INPUT_REPORT_BYTES];
extern U8 OutReport[HID_OUTPUT_REPORT_BYTES];
extern U8 SetupReport[HID_FEATURE_REPORT_BYTES];

/* HID Demo Functions */
extern void GetInReport  (void);
extern void SetOutReport (void);
extern void SetupFuture  (void);

BOOL HID_GetReport (void) {

 /* ReportID = SetupPacket.wValue.WB.L; */
 switch (SetupPacket.wValue.WB.H) {
case HID_REPORT_INPUT:
  GetInReport();
  memcpy(EP0Buf, InReport, HID_INPUT_REPORT_BYTES);
//m_DEBUG("Packet(Get)= 0x%02x bytes\n", InReport[0]);
  memset(InReport, 0, HID_INPUT_REPORT_BYTES); 
  break;
case HID_REPORT_OUTPUT:
  return (__FALSE);		/* Not Supported */
case HID_REPORT_FEATURE:
  /* EP0Buf[] = ...; */
  /* break; */
  return (__FALSE);		/* Not Supported */
 }
 return (__TRUE);
}

BOOL HID_SetReport (void) {

 /* ReportID = SetupPacket.wValue.WB.L; */
m_DEBUG("Packet= 0x%02x\n", SetupPacket.wValue.WB.H);
 switch (SetupPacket.wValue.WB.H) {
case HID_REPORT_INPUT:
  return (__FALSE);		/* Not Supported */
case HID_REPORT_OUTPUT:
  memcpy(OutReport, EP0Buf, HID_OUTPUT_REPORT_BYTES);
  SetOutReport();
  break;
case HID_REPORT_FEATURE:
  memcpy(SetupReport, EP0Buf, HID_FEATURE_REPORT_BYTES);
  SetupFuture();
  break;
 }
 return (__TRUE);
}

usbdesc.c

const U8 HID_ReportDescriptor[] = {
 HID_UsagePageVendor( 0x00					 ),
 HID_Usage		  ( 0x01					 ),
 HID_Collection	 ( HID_Application		  ),
HID_LogicalMin   ( 0						),  
HID_LogicalMaxS  ( 0xFF					 ),
HID_ReportSize   ( 8						), 
HID_ReportCount  ( HID_INPUT_REPORT_BYTES   ),
HID_Usage		( 0x01					 ),
HID_Input		( HID_Data | HID_Variable | HID_Absolute ),
HID_ReportCount  ( HID_OUTPUT_REPORT_BYTES  ),
HID_Usage		( 0x01					 ),
HID_Output	   ( HID_Data | HID_Variable | HID_Absolute ),
HID_ReportCount  ( HID_FEATURE_REPORT_BYTES ),
HID_Usage		( 0x01					 ),
HID_Feature	  ( HID_Data | HID_Variable | HID_Absolute ),
 HID_EndCollection,
};

 

Для понимания того, как заполняется дескриптор, рекомендую почитать документ "HID Usage Tables".

Изменено пользователем IgorKossak
[codebox]

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Недавно "допиливал" данный код. У меня это выглядит так:

 

hiduser.c

#define HID_INPUT_REPORT_BYTES            33             /* size of report in Bytes */
#define HID_OUTPUT_REPORT_BYTES            33             /* size of report in Bytes */
#define HID_FEATURE_REPORT_BYTES        2              /* size of report in Bytes */
};

 

Для понимания того, как заполняется дескриптор, рекомендую почитать документ "HID Usage Tables".

 

Спасибо за подсказку. Не нашел сразу эти константы.

 

Допилил следующие моменты:

1. Файл usbcfg.h

#define USB_MAX_PACKET0     64   //8     // максимальный размер конечной точки

2. Файл usbdesc.c

#define HID_INPUT_REPORT_BYTES       64             /* size of report in Bytes */
#define HID_OUTPUT_REPORT_BYTES      64             /* size of report in Bytes */
#define HID_FEATURE_REPORT_BYTES     1              /* size of report in Bytes */

3. Немного переделал функции репортов примерно таким образом (используется непосредственно буфер конечной точки для экономии памяти)

BOOL HID_GetReport (void) {

 /* ReportID = SetupPacket.wValue.WB.L; */
 switch (SetupPacket.wValue.WB.H) {
   case HID_REPORT_INPUT:
  memset(EP0Buf, 0, HID_INPUT_REPORT_BYTES);
     GetInReport(EP0Buf);
     break;
   case HID_REPORT_OUTPUT:
     return (__FALSE);        /* Not Supported */
   case HID_REPORT_FEATURE:
     /* EP0Buf[] = ...; */
     /* break; */
     return (__FALSE);        /* Not Supported */
 }
 return (__TRUE);
}


/*
*  HID Set Report Request Callback
*   Called automatically on HID Set Report Request
*    Parameters:      None (global SetupPacket and EP0Buf)
*    Return Value:    TRUE - Success, FALSE - Error
*/

BOOL HID_SetReport (void) {

 /* ReportID = SetupPacket.wValue.WB.L; */
 switch (SetupPacket.wValue.WB.H) {
   case HID_REPORT_INPUT:
     return (__FALSE);        /* Not Supported */
   case HID_REPORT_OUTPUT:
     SetOutReport(EP0Buf);
     break;
   case HID_REPORT_FEATURE:
     return (__FALSE);        /* Not Supported */
 }
 return (__TRUE);
}

 

4. Интервал опроса описывается в файле usbdesc.c в следующей структуре. Вместо константы 0ч20 по умолчанию (32 мс), я вставил директиву HID_INPUT_REPORT_INTERVAL для удобства.

/* USB Configuration Descriptor */
/*   All Descriptors (Configuration, Interface, Endpoint, Class, Vendor) */
const U8 USB_ConfigDescriptor[] = {
/* Configuration 1 */
 USB_CONFIGUARTION_DESC_SIZE,       /* bLength */
 USB_CONFIGURATION_DESCRIPTOR_TYPE, /* bDescriptorType */
 WBVAL(                             /* wTotalLength */
   USB_CONFIGUARTION_DESC_SIZE +
   USB_INTERFACE_DESC_SIZE     +
   HID_DESC_SIZE               +
   USB_ENDPOINT_DESC_SIZE
 ),
 0x01,                              /* bNumInterfaces */
 0x01,                              /* bConfigurationValue: 0x01 is used to select this configuration */
 0x00,                              /* iConfiguration: no string to describe this configuration */
 USB_CONFIG_BUS_POWERED /*|*/       /* bmAttributes */
/*USB_CONFIG_REMOTE_WAKEUP*/,
 USB_CONFIG_POWER_MA(100),          /* bMaxPower, device power consumption is 100 mA */

/* Interface 0, Alternate Setting 0, HID Class */
 USB_INTERFACE_DESC_SIZE,           /* bLength */
 USB_INTERFACE_DESCRIPTOR_TYPE,     /* bDescriptorType */
 0x00,                              /* bInterfaceNumber */
 0x00,                              /* bAlternateSetting */
 0x01,                              /* bNumEndpoints */
 USB_DEVICE_CLASS_HUMAN_INTERFACE,  /* bInterfaceClass */
 HID_SUBCLASS_NONE,                 /* bInterfaceSubClass */
 HID_PROTOCOL_NONE,                 /* bInterfaceProtocol */
 0x04,                              /* iInterface */
/* HID Class Descriptor */
/* HID_DESC_OFFSET = 0x0012 */
 HID_DESC_SIZE,                     /* bLength */
 HID_HID_DESCRIPTOR_TYPE,           /* bDescriptorType */
 WBVAL(0x0100), /* 1.00 */          /* bcdHID */
 0x00,                              /* bCountryCode */
 0x01,                              /* bNumDescriptors */
 HID_REPORT_DESCRIPTOR_TYPE,        /* bDescriptorType */
 WBVAL(HID_REPORT_DESC_SIZE),       /* wDescriptorLength */
/* Endpoint, HID Interrupt In */
 USB_ENDPOINT_DESC_SIZE,            /* bLength */
 USB_ENDPOINT_DESCRIPTOR_TYPE,      /* bDescriptorType */
 USB_ENDPOINT_IN(1),                /* bEndpointAddress */
 USB_ENDPOINT_TYPE_INTERRUPT,       /* bmAttributes */
 WBVAL(0x0004),                     /* wMaxPacketSize */
 HID_INPUT_REPORT_INTERVAL,          /* 32ms */          /* bInterval */
/* Terminator */
 0                                  /* bLength */
};

5. Последним этапом перенес все нужные константы в одно место, в hiduser.h

#ifndef __HIDUSER_H__
#define __HIDUSER_H__

#define HID_INPUT_REPORT_BYTES       64             /* size of report in Bytes */
#define HID_OUTPUT_REPORT_BYTES      64             /* size of report in Bytes */
#define HID_INPUT_REPORT_INTERVAL    0x20           /* report interval in ms (32 ms)  */
#define HID_FEATURE_REPORT_BYTES     1              /* size of report in Bytes */

/* HID Number of Reports */
#define HID_REPORT_NUM      1

/* HID In/Out Endpoint Address */
#define HID_EP_IN       0x81

/* HID Global Variables */
extern U8   HID_Protocol;
extern U8   HID_IdleTime[HID_REPORT_NUM];

/* HID Requests Callback Functions */
extern BOOL HID_GetReport   (void);
extern BOOL HID_SetReport   (void);
extern BOOL HID_GetIdle     (void);
extern BOOL HID_SetIdle     (void);
extern BOOL HID_GetProtocol (void);
extern BOOL HID_SetProtocol (void);


#endif  /* __HIDUSER_H__ */

 

6. Прикрепляю сей проект к этому топику :)

USBHID.zip

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

РЕАЛИЗАЦИЯ ИНТЕРФЕЙСА USB-HID В МИКРОПРОЦЕССОРНОЙ СИСТЕМЕ  https://studzachet.ru/primeryi-uchebnyix-rabot/realizacziya-interfejsa-usb/

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

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

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...