MementoMori 4 20 ноября, 2012 Опубликовано 20 ноября, 2012 (изменено) · Жалоба Господа, помогите организовать обмен данными между USB устройством и программой хостом. За основу взят пример от ST - "Custom HID" для IAR. Контроллер STM32F103RBT6 К нему прилагается программа для компа - "HID Demonstrator", в программе жмешь кнопки, на устройстве загораются светодиоды. Хочу ее модифицировать, дабы передавать данные. НАшел в интернете пример для C++ Builder который позволяет принимать и отправлять пакеты, тоже его модифицировал С программой HID Demonstrator управлять светодиодами получается. А вот с собственной не получается передать и двух байт. Подскажите, чего не хвататет в программе. ЛИчно мне непонятно, где в программе-хосте указание писать в конкретный ендпоинт... Итак ближе к делу. ПРограмма для STM32F103: #include "stm32f10x.h" #include "usb_lib.h" #include "hw_config.h" #include "common.h" #include "stdio.h" #define nReportCnt 22 unsigned char str[10]; extern unsigned char Receive_Buffer[2]; extern unsigned char Transi_Buffer[2]; extern u8 USB_ReceiveFlg; extern u8 TimeCount; //*******************************************************************************/ int main(void) { Set_System(); USB_Interrupts_Config(); // Включаем подтяжку для USB RCC->APB2ENR |= (1 << 5); // enable clock for GPIOD GPIOD->CRL &= ~0x00000F00; // clear port PD2 GPIOD->CRL |= 0x00000700; // PD2 General purpose output open-drain, max speed 50 MHz GPIOD->BRR = 0x0004; // reset PD2 (set to low) // Настраиваем светодиоды RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;//Затактировали порт GPIOA->CRL &= ~GPIO_CRL_CNF2;//определили режим работы. GPIOA->CRL |= GPIO_CRL_MODE2_0;//определили направление. GPIOA->CRL &= ~GPIO_CRL_CNF3;//определили режим работы. GPIOA->CRL |= GPIO_CRL_MODE3_0;//определили направление. Set_USBClock(); USB_Init(); LCD_Init(); LCD_Clear(RED); while (1) { if (USB_ReceiveFlg == TRUE) // Проверяем, не поймала ли чего void EP1_OUT_Callback(void) (прописана в USB_ENDP.C) { // Если поймала - рисуем на экране sprintf(str,"Recieved byte: %X ", Receive_Buffer[0]); WriteString(0,240,str,BLUE); USB_ReceiveFlg=0;//СБРАСЫВАЕМ ФЛАЖОК Delay(5000000); LCD_Clear(RED); // } } } Вот как устроен обработчик обращений к Endpoint void EP1_OUT_Callback(void) { BitAction Led_State; /* Read recieved data (2 bytes) */ USB_SIL_Read(EP1_OUT, Receive_Buffer); USB_ReceiveFlg=1; //установка этого флажка призвана обеспечить реакцию дисплея если с хоста прийдет хоть что-нибудь. // при дрыганьи светодиодами через HID Demonstrator флажок устанавливается, сообщения идут // При использовании моей программы под C++ Builder - ноль реакции //Ниже - это работа со светодиодами. Пока не удалял, помогает хоть как-то сориентироваться. if (Receive_Buffer[1] == 0) { Led_State = Bit_RESET; GPIOA->BSRR =GPIO_BSRR_BR3; } else { Led_State = Bit_SET; GPIOA->BSRR =GPIO_BSRR_BS3; } switch (Receive_Buffer[0]) { case 1: if (Led_State != Bit_RESET) { STM_EVAL_LEDOn(LED1); GPIOA->BSRR =GPIO_BSRR_BS2; } else { STM_EVAL_LEDOff(LED1); GPIOA->BSRR =GPIO_BSRR_BR2; } break; case 2: if (Led_State != Bit_RESET) { STM_EVAL_LEDOn(LED2); GPIOA->BSRR =GPIO_BSRR_BS2; } else { STM_EVAL_LEDOff(LED2); GPIOA->BSRR =GPIO_BSRR_BR2; } break; case 3: if (Led_State != Bit_RESET) { STM_EVAL_LEDOn(LED3); GPIOA->BSRR =GPIO_BSRR_BS2; } else { STM_EVAL_LEDOff(LED3); GPIOA->BSRR =GPIO_BSRR_BR2; } break; case 4: if (Led_State != Bit_RESET) { STM_EVAL_LEDOn(LED4); GPIOA->BSRR =GPIO_BSRR_BS2; } else { STM_EVAL_LEDOff(LED4); GPIOA->BSRR =GPIO_BSRR_BR2; } break; case 5: if (Led_State != Bit_RESET) { STM_EVAL_LEDOn(LED4); GPIOA->BSRR =GPIO_BSRR_BS2; } else { STM_EVAL_LEDOff(LED4); GPIOA->BSRR =GPIO_BSRR_BR2; } break; default: STM_EVAL_LEDOff(LED1); STM_EVAL_LEDOff(LED2); STM_EVAL_LEDOff(LED3); STM_EVAL_LEDOff(LED4); break; } #ifndef STM32F10X_CL SetEPRxStatus(ENDP1, EP_RX_VALID); #endif /* STM32F10X_CL */ } Вот дескрипторы программы для STM32 /* USB Standard Device Descriptor */ const uint8_t CustomHID_DeviceDescriptor[CUSTOMHID_SIZ_DEVICE_DESC] = { 0x12, /*bLength */ USB_DEVICE_DESCRIPTOR_TYPE, /*bDescriptorType*/ 0x00, /*bcdUSB */ 0x02, 0x00, /*bDeviceClass*/ 0x00, /*bDeviceSubClass*/ 0x00, /*bDeviceProtocol*/ 0x40, /*bMaxPacketSize40*/ 0x83, /*idVendor (0x0483)*/ 0x04, 0x50, /*idProduct = 0x5750*/ 0x57, 0x00, /*bcdDevice rel. 2.00*/ 0x02, 1, /*Index of string descriptor describing manufacturer */ 2, /*Index of string descriptor describing product*/ 3, /*Index of string descriptor describing the device serial number */ 0x01 /*bNumConfigurations*/ } ; /* CustomHID_DeviceDescriptor */ /* USB Configuration Descriptor */ /* All Descriptors (Configuration, Interface, Endpoint, Class, Vendor */ const uint8_t CustomHID_ConfigDescriptor[CUSTOMHID_SIZ_CONFIG_DESC] = { 0x09, /* bLength: Configuation Descriptor size */ USB_CONFIGURATION_DESCRIPTOR_TYPE, /* bDescriptorType: Configuration */ CUSTOMHID_SIZ_CONFIG_DESC, /* wTotalLength: Bytes returned */ 0x00, 0x01, /* bNumInterfaces: 1 interface */ 0x01, /* bConfigurationValue: Configuration value */ 0x00, /* iConfiguration: Index of string descriptor describing the configuration*/ 0xC0, /* bmAttributes: Bus powered */ 0x32, /* MaxPower 100 mA: this current is used for detecting Vbus */ /************** Descriptor of Custom HID interface ****************/ /* 09 */ 0x09, /* bLength: Interface Descriptor size */ USB_INTERFACE_DESCRIPTOR_TYPE,/* bDescriptorType: Interface descriptor type */ 0x00, /* bInterfaceNumber: Number of Interface */ 0x00, /* bAlternateSetting: Alternate setting */ 0x02, /* bNumEndpoints */ 0x03, /* bInterfaceClass: HID */ 0x00, /* bInterfaceSubClass : 1=BOOT, 0=no boot */ 0x00, /* nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse */ 0, /* iInterface: Index of string descriptor */ /******************** Descriptor of Custom HID HID ********************/ /* 18 */ 0x09, /* bLength: HID Descriptor size */ HID_DESCRIPTOR_TYPE, /* bDescriptorType: HID */ 0x10, /* bcdHID: HID Class Spec release number */ 0x01, 0x00, /* bCountryCode: Hardware target country */ 0x01, /* bNumDescriptors: Number of HID class descriptors to follow */ 0x22, /* bDescriptorType */ CUSTOMHID_SIZ_REPORT_DESC,/* wItemLength: Total length of Report descriptor */ 0x00, /******************** Descriptor of Custom HID endpoints ******************/ /* 27 */ 0x07, /* bLength: Endpoint Descriptor size */ USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: */ 0x81, /* bEndpointAddress: Endpoint Address (IN) */ 0x03, /* bmAttributes: Interrupt endpoint */ 0x08, /* wMaxPacketSize: 8 Bytes max */ 0x00, 0x20, /* bInterval: Polling Interval (32 ms) */ /* 34 */ 0x07, /* bLength: Endpoint Descriptor size */ USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: */ /* Endpoint descriptor type */ 0x01, /* bEndpointAddress: */ /* Endpoint Address (OUT) */ 0x03, /* bmAttributes: Interrupt endpoint */ 0x08, /* wMaxPacketSize: 8 Bytes max */ 0x00, 0x20, /* bInterval: Polling Interval (20 ms) */ /* 41 */ } ; /* CustomHID_ConfigDescriptor */ const uint8_t CustomHID_ReportDescriptor[CUSTOMHID_SIZ_REPORT_DESC] = { 0x05, 0x8c, /* USAGE_PAGE (ST Page) */ 0x09, 0x01, /* USAGE (Demo Kit) */ 0xa1, 0x01, /* COLLECTION (Application) */ /* 6 */ /* Led 1 */ 0x85, 0x01, /* REPORT_ID (1) */ 0x09, 0x01, /* USAGE (LED 1) */ 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ 0x75, 0x08, /* REPORT_SIZE (8) */ 0x95, 0x01, /* REPORT_COUNT (1) */ 0xB1, 0x82, /* FEATURE (Data,Var,Abs,Vol) */ 0x85, 0x01, /* REPORT_ID (1) */ 0x09, 0x01, /* USAGE (LED 1) */ 0x91, 0x82, /* OUTPUT (Data,Var,Abs,Vol) */ /* 26 */ /* Led 2 */ 0x85, 0x02, /* REPORT_ID 2 */ 0x09, 0x02, /* USAGE (LED 2) */ 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ 0x75, 0x08, /* REPORT_SIZE (8) */ 0x95, 0x01, /* REPORT_COUNT (1) */ 0xB1, 0x82, /* FEATURE (Data,Var,Abs,Vol) */ 0x85, 0x02, /* REPORT_ID (2) */ 0x09, 0x02, /* USAGE (LED 2) */ 0x91, 0x82, /* OUTPUT (Data,Var,Abs,Vol) */ /* 46 */ /* Led 3 */ 0x85, 0x03, /* REPORT_ID (3) */ 0x09, 0x03, /* USAGE (LED 3) */ 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ 0x75, 0x08, /* REPORT_SIZE (8) */ 0x95, 0x01, /* REPORT_COUNT (1) */ 0xB1, 0x82, /* FEATURE (Data,Var,Abs,Vol) */ 0x85, 0x03, /* REPORT_ID (3) */ 0x09, 0x03, /* USAGE (LED 3) */ 0x91, 0x82, /* OUTPUT (Data,Var,Abs,Vol) */ /* 66 */ /* Led 4 */ 0x85, 0x09, /* REPORT_ID 4) */ 0x09, 0x09, /* USAGE (LED 4) */ 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ 0x75, 0x08, /* REPORT_SIZE (8) */ 0x95, 0x01, /* REPORT_COUNT (1) */ 0xB1, 0x82, /* FEATURE (Data,Var,Abs,Vol) */ 0x85, 0x09, /* REPORT_ID (4) */ 0x09, 0x09, /* USAGE (LED 4) */ 0x91, 0x82, /* OUTPUT (Data,Var,Abs,Vol) */ /* 86 */ /* key Push Button */ 0x85, 0x05, /* REPORT_ID (5) */ 0x09, 0x05, /* USAGE (Push Button) */ 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ 0x75, 0x01, /* REPORT_SIZE (1) */ 0x81, 0x82, /* INPUT (Data,Var,Abs,Vol) */ 0x09, 0x05, /* USAGE (Push Button) */ 0x75, 0x01, /* REPORT_SIZE (1) */ 0xb1, 0x82, /* FEATURE (Data,Var,Abs,Vol) */ 0x75, 0x07, /* REPORT_SIZE (7) */ 0x81, 0x83, /* INPUT (Cnst,Var,Abs,Vol) */ 0x85, 0x05, /* REPORT_ID (2) */ 0x75, 0x07, /* REPORT_SIZE (7) */ 0xb1, 0x83, /* FEATURE (Cnst,Var,Abs,Vol) */ /* 114 */ /* Tamper Push Button */ 0x85, 0x06, /* REPORT_ID (6) */ 0x09, 0x06, /* USAGE (Tamper Push Button) */ 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ 0x75, 0x01, /* REPORT_SIZE (1) */ 0x81, 0x82, /* INPUT (Data,Var,Abs,Vol) */ 0x09, 0x06, /* USAGE (Tamper Push Button) */ 0x75, 0x01, /* REPORT_SIZE (1) */ 0xb1, 0x82, /* FEATURE (Data,Var,Abs,Vol) */ 0x75, 0x07, /* REPORT_SIZE (7) */ 0x81, 0x83, /* INPUT (Cnst,Var,Abs,Vol) */ 0x85, 0x06, /* REPORT_ID (6) */ 0x75, 0x07, /* REPORT_SIZE (7) */ 0xb1, 0x83, /* FEATURE (Cnst,Var,Abs,Vol) */ /* 142 */ /* ADC IN */ 0x85, 0x07, /* REPORT_ID (7) */ 0x09, 0x07, /* USAGE (ADC IN) */ 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ 0x26, 0xff, 0x00, /* LOGICAL_MAXIMUM (255) */ 0x75, 0x08, /* REPORT_SIZE (8) */ 0x81, 0x82, /* INPUT (Data,Var,Abs,Vol) */ 0x85, 0x07, /* REPORT_ID (7) */ 0x09, 0x07, /* USAGE (ADC in) */ 0xb1, 0x82, /* FEATURE (Data,Var,Abs,Vol) */ /* 161 */ 0xc0 /* END_COLLECTION */ }; /* CustomHID_ReportDescriptor */ /* USB String Descriptors (optional) */ const uint8_t CustomHID_StringLangID[CUSTOMHID_SIZ_STRING_LANGID] = { CUSTOMHID_SIZ_STRING_LANGID, USB_STRING_DESCRIPTOR_TYPE, 0x09, 0x04 } ; /* LangID = 0x0409: U.S. English */ const uint8_t CustomHID_StringVendor[CUSTOMHID_SIZ_STRING_VENDOR] = { CUSTOMHID_SIZ_STRING_VENDOR, /* Size of Vendor string */ USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType*/ /* Manufacturer: "STMicroelectronics" */ 'S', 0, 'T', 0, 'M', 0, 'i', 0, 'c', 0, 'r', 0, 'o', 0, 'e', 0, 'l', 0, 'e', 0, 'c', 0, 't', 0, 'r', 0, 'o', 0, 'n', 0, 'i', 0, 'c', 0, 's', 0 }; const uint8_t CustomHID_StringProduct[CUSTOMHID_SIZ_STRING_PRODUCT] = { CUSTOMHID_SIZ_STRING_PRODUCT, /* bLength */ USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */ 'S', 0, 'T', 0, 'M', 0, '3', 0, '2', 0, ' ', 0, 'C', 0, 'u', 0, 's', 0, 't', 0, 'm', 0, ' ', 0, 'H', 0, 'I', 0, 'D', 0 }; uint8_t CustomHID_StringSerial[CUSTOMHID_SIZ_STRING_SERIAL] = { CUSTOMHID_SIZ_STRING_SERIAL, /* bLength */ USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */ 'S', 0, 'T', 0, 'M', 0,'3', 0,'2', 0, '1', 0, '0', 0 }; ТЕПЕРЬ К ХОСТУ. ВЫДЕРЖКИ ИЗ ПРОГРАММЫ ДЛЯ C++ Builder Подключение. Сразу скажу - все работает, дескриптор читается, ошибок нет int connect() // этой функцией будем подключаться к устройству { int i, n, res=0; string exampleDeviceName = ""; string temp; // exampleDeviceName += vendorName; // exampleDeviceName += " "; // exampleDeviceName += productName; exampleDeviceName = "STMicroelectronics STM32 Custm HID"; n = hid.EnumerateHIDDevices(); // узнаем все Hid устройства // vid и pid указаны в hidlibrary.h константой idstring for (i=0; i<n; i++) // ищем среди них наше { hid.Connect(i); temp=+"Подключено "+hid.GetConnectedDeviceName(); Form1->Memo1->Lines->Add(temp.c_str()); // GetConnectedDeviceName() возвращает string, // где через пробел указаны vendor и product Name. // Сравниваем, если совпало - значить устройство наше if (hid.GetConnectedDeviceName() == exampleDeviceName ) { res = 1; break; } } return res; } ОБработчик кнопки "Отправить данные" - на STM32 - никакой реакции // Кнопка "Отправить данные" void __fastcall TForm1::Button2Click(TObject *Sender) { if ( 1 == connect() ) { pdata.b0 = 0x00; pdata.b1 = 0x00; ShowMessage("OK"); hid.SendData(&pdata); } else { AnsiString s = ""; s += vendorName; s += " "; s += productName; s += " не подключено."; ShowMessage(s); } } //--------------------------------------------------------------------------- Файл дескриптора. Я не знаю, странный он какой-то, писался для общения с AVR, тем не менее привожу как есть, он был в проекте для Builder C++ #ifndef __usbconfig_h_included__ #define __usbconfig_h_included__ /* Основное описание: * Этот файл является примером конфигурации (со встроенной документацией) для * драйвера USB. Он кофигурирует V-USB для сигнала USB D+, подсоединенного к * порту D бит 2 (который также является входом аппаратного прерывания 0 [iNT0] * на многих чипах) и сигнала USB D- к порту D бит 4. Вы можете подсоединить * эти сигналы на любой другой порт, однако D+ должен быть также подключен на * вход аппаратного прерывания INT0, которое имеет наивысший приоритет, * см. секцию в конце файла). */ /* ------------------------- Аппаратные настройки -------------------------- */ #define USB_CFG_IOPORTNAME D /* Указан порт, к которому подключена шина USB. Если Вы сконфигурируете "B", * будут использоваться регистры PORTB, PINB и DDRB. */ #define USB_CFG_DMINUS_BIT 4 /* Это номер бита в USB_CFG_IOPORT, куда подключен сигнал D-, может * использоваться любой бит в порте. */ #define USB_CFG_DPLUS_BIT 2 /* Это номер бита в USB_CFG_IOPORTNAME, куда подключен сигнал D+, может * использоваться любой бит в порте. Пожалуйста, примите во внимание, что D+ * должен быть также подсоединен к ножке прерывания INT0! [Вы можете также * использовать другие прерывания, см. секцию "Optional MCU Description" далее, * или Вы можете подсоединить D- к прерыванию, как это необходимо если Вы * используете опцию USB_COUNT_SOF. Если Вы используете D- для прерывания, * оно будет срабатывать также от маркеров Start-Of-Frame каждую * милисекунду.] */ #define USB_CFG_CLOCK_KHZ (F_CPU/1000) /* Тактовая частота чипа AVR в килогерцах. Допустимые величины 12000, 15000, * 16000, 16500 и 20000. Версия кода на 16.5 МГц не требует кварца, она * допускает уход частоты +/- 1% от номинальной. Все другие частоты требуют * точности 2000 ppm, и в этом случае обязательно нужен кварц! * Константа F_CPU должна быть определена в проекте, не нужно нигде писать * вручную. */ #define USB_CFG_CHECK_CRC 0 /* Установите 1 если хотите чтобы драйвер V-USB проверял целостность входящих * пакетов данных (CRC сумы). Проверка CRC требует достаточно много места для * кода и на данный момент поддерживается только для частоты 18 MHz. Так что * обязательно используйте частоту 18 MHz для включения этой опции. */ /* ----------------- Дополнительные Аппаратные настройки ------------------- */ /* #define USB_CFG_PULLUP_IOPORTNAME D */ /* Если Вы подсоединили 1.5k pullup резистор от D- к ножке порта вместо V+, * Вы можете подсоединять и отсоединять устройство програмным путем вызовая * макрос usbDeviceConnect() и usbDeviceDisconnect() (см. usbdrv.h). * Эта константы задают порт, к которому подключен pullup резистор. */ /* #define USB_CFG_PULLUP_BIT 4 */ /* This constant defines the bit number in USB_CFG_PULLUP_IOPORT (defined * above) where the 1.5k pullup resistor is connected. See description * above for details. * Эта константа определяет номер бита порта в USB_CFG_PULLUP_IOPORTNAME (задан * више) куда подключен 1.5k pullup резистор. См. описание, указанное ранее. */ /* ----------------------- Функциональный диапазон ------------------------- */ #define USB_CFG_HAVE_INTRIN_ENDPOINT 1 /* Задайте здесь 1, если Вы хотите скомпилировать версию с двумя конечными * точками (endpoints): default control endpoint 0 и interrupt-in endpoint * (любой другой endpoint номер). */ #define USB_CFG_HAVE_INTRIN_ENDPOINT3 0 /* Задайте здесь 1, если Вы хотите скомпилировать версию с тремя конечными * точками (endpoints): default control endpoint 0, interrupt-in endpoint 3 * (или номер, сконфигурированный далее) и catch-all default interrupt-in * endpoint как указано ранее. * Вы должны также задать USB_CFG_HAVE_INTRIN_ENDPOINT в 1 для этой опции. */ #define USB_CFG_EP3_NUMBER 3 /* Если так называемая конечная точка (endpoint) 3 используется, можно теперь * ее сконфигурировать на любой другой номер конечной точки (за исключением 0). * Если не задано, то по умолчанию 3. */ /* #define USB_INITIAL_DATATOKEN USBPID_DATA1 */ /* Этот define определяет условие старта (startup condition) для переключения * данных (data toggling) в момент конечных точек interrupt/bulk 1 и 3. * По умолчанию USBPID_DATA1. Поскольку токен переключается ПЕРЕД отправкой * любых данных, первый пакет отправляется c противоположной величиной * от этой конфигурации! */ #define USB_CFG_IMPLEMENT_HALT 0 /* Задайте здесь 1, если Вы хотите также реализовать возможность ENDPOINT_HALT * для endpoint 1 (interrupt endpoint). Несмотря на то, что Вам эта возможность * может не понадобиться, она требуется по стандарту. Мы ввели эту опцию в * конфигурацию потому что эта функция значительно раздувает код. */ #define USB_CFG_SUPPRESS_INTR_CODE 0 /* Задайте здесь 1, если Вы хотите определить interrupt-in endpoints, но не * хотите отправлять любые данные с их помощью. Если эта опция включена, то * функции usbSetInterrupt() и usbSetInterrupt3() будут пропущены. Полезно * при необходимости interrupt-in endpoints для соответсвия интерфейсу * (например HID), но без отправки даных с их помощью. Прилично экономит * флеш память для кода и оперативную память буффера передачи данных. */ #define USB_CFG_INTR_POLL_INTERVAL 100 /* Если Вы скомпилировали версию с endpoint 1 (interrupt-in), то здесь задается * интервал опроса (poll interval). Величина указана в милисекундах и не должна * быть меньше 10 ms для низкоскоростных устройств. */ #define USB_CFG_IS_SELF_POWERED 0 /* Задайте здесь 1 если устройство имеет собственный источник питания. * Установка в 0 соответствует устройству, запитанному от шины USB. */ #define USB_CFG_MAX_BUS_POWER 100 /* Установите эту переменную на max величину потребления мощности Вашего * устройства от шины USB. Величина указана в милиамперах. */ #define USB_CFG_IMPLEMENT_FN_WRITE 1 /* Задайте здесь 1, если Вы хотите, чтобы функция usbFunctionWrite() * вызывалась для передач control-out. Задайте 0 если Вам это не нужно, * что позволит сэкономить несколько байт. */ #define USB_CFG_IMPLEMENT_FN_READ 1 /* Задайте 1 если Вам нужно отправлять управляющие запросы ответы, которые * генерируются "на лету" при вызове usbFunctionRead(). Если Вам нужно только * отправить данные из статического буфера, задайте 0 и возвращайте данные из * usbFunctionSetup(). Это сэкономит некоторое количество байт. */ #define USB_CFG_IMPLEMENT_FN_WRITEOUT 0 /* Задайте 1 если Вы хотите использовать interrupt-out (или bulk out) * endpoints. Вы должны реализовать функцию usbFunctionWriteOut(), которая * принимает все interrupt/bulk данные, отправленные в любую endpoint, * отличную от 0. Номер endpoint можно найти в 'usbRxToken'. */ #define USB_CFG_HAVE_FLOWCONTROL 0 /* Задайте 1, если Вы хотите реализовать управление потоком (flowcontrol) * через данные USB. Смотрим описание макроса usbDisableAllRequests() и * usbEnableAllRequests() в usbdrv.h. */ #define USB_CFG_DRIVER_FLASH_PAGE 0 /* Если устройство имеет больше чем 64 kBytes флеш памяти, определите это * в 64 k страницу где находятся константы (дескрипторы) драйвера. Другими * словами: установить в 1 для загрузчиков (boot loaders) на ATMega128. */ #define USB_CFG_LONG_TRANSFERS 0 /* Задайте 1, если Вы хотите отправлять/принимать блоки оазмером более 254 байт * в одиночной control-in или control-out передаче. Обратите внимание, что эта * возможность увеличивает размер драйвера. */ /* #define USB_RX_USER_HOOK(data, len) if(usbRxToken == (uchar)USBPID_SETUP) blinkLED(); */ /* Этот macro является крюком (hook), если Вы хотите сделать нечто * нетрадиционное. Если макрос задан, он вставляется в начало обработки * принимаемого сообщения. Если Вы "съели" (обработали) сообщение и не хотите * включать дальнейшую обработку по умолчанию, сделайте обычный возврат после * Ваших действий. Одно из возможных применений (кроме отладки) - мигание * статусным светодиодом при каждом пакете. */ /* #define USB_RESET_HOOK(resetStarts) if(!resetStarts){hadUsbReset();} */ /* Этот macro является хуком для обработки события USB RESET. Он имеет один * параметр, позволяющий отличать старт состояния RESET от окончания * состояния RESET. */ /* #define USB_SET_ADDRESS_HOOK() hadAddressAssigned(); */ /* Этот macro (если задан) выполняется когда принят запрос USB SET_ADDRESS. */ #define USB_COUNT_SOF 0 /* Задайте здесь 1, если Вам нужна глобальная переменная "usbSofCount", * в которой подсчитываются пакеты SOF. Эта возможность требует подключения * аппаратного прерывания к D- вместо D+. */ /* #ifdef __ASSEMBLER__ * macro myAssemblerMacro * in YL, TCNT0 * sts timer0Snapshot, YL * endm * #endif * #define USB_SOF_HOOK myAssemblerMacro * This macro (if defined) is executed in the assembler module when a * Start Of Frame condition is detected. It is recommended to define it to * the name of an assembler macro which is defined here as well so that more * than one assembler instruction can be used. The macro may use the register * YL and modify SREG. If it lasts longer than a couple of cycles, USB messages * immediately after an SOF pulse may be lost and must be retried by the host. * What can you do with this hook? Since the SOF signal occurs exactly every * 1 ms (unless the host is in sleep mode), you can use it to tune OSCCAL in * designs running on the internal RC oscillator. * Please note that Start Of Frame detection works only if D- is wired to the * interrupt, not D+. THIS IS DIFFERENT THAN MOST EXAMPLES! */ #define USB_CFG_CHECK_DATA_TOGGLING 0 /* Установите в 1 если хотите фильтровать повторяющиеся (duplicate) пакеты * данных отправленные хостом. Повторения возникают лишь в результате ошибок * связи, когда хост не получил ACK. Помните, фильтровать придется самим у * usbFunctionWriteOut() и usbFunctionWrite(). Используйте глобальную * usbCurrentDataToken и статическую переменную для каждого * control- и out-endpoint для проверки на повторяющиеся пакеты. */ #define USB_CFG_HAVE_MEASURE_FRAME_LENGTH 0 /* Задайте здесь 1, если Вам нужна функция usbMeasureFrameLength() - тогда она * скомпилируется. Эта функция может использоваться для подстройки генератора * RC микроконтроллера AVR. */ #define USB_USE_FAST_CRC 0 /* Ассемблерная часть имеет две реализации для алгоритма CRC. Одна быстрее, * вторая меньшая по объему. Используйте меньшую лишь в передачах сообщений * не критичных к таймингам. Быстрая реализация требует 31 цикл на байт, а * меньшая требует 61 - 69 циклов. Быстрая реализация может быть на 32 байта * кода большей при передачах данных и выводит AVR на состояние близкое к * пределу возможностей. */ /* ---------------- Параметры, описывающие USB-устройство ------------------ */ #define USB_CFG_VENDOR_ID 0x83, 0x04 /* 0483 = voti.nl */ /* USB вендор ID для устройства, младший байт идет первым. Если Вы * зарегистрировали свой собственный Vendor ID, укажите его здесь. В * противном случае используйте одну из свободно предоставляемых пар * VID/PID obdev. Прочитайте правила USB-IDs-for-free.txt! */ #define USB_CFG_DEVICE_ID 0x50, 0x57 /* obdev's shared PID for HIDs */ /* Это ID продукта, младший байт идет первым. Он интерпретируется в контексте * vendor ID. Если Вы зарегистрировали свой собственный VID на usb.org, или * если пользуетесь лицензией на PID от кого-нибудь еще, укажите его здесь. * Иначе используйте предоставленную obdev свободно распространяемую * пару VID/PID. Прочитайте правила USB-IDs-for-free.txt! */ #define USB_CFG_DEVICE_VERSION 0x00, 0x02 /* Номер версии устройства: сначала младший номер, затем старший номер. */ #define USB_CFG_VENDOR_NAME 'V', 'd', 'd', 'd', 'd', ' ', 'V', 'd', 'd', 'd', 'd', 'd', 'd', 'd' #define USB_CFG_VENDOR_NAME_LEN 14 /* Здесь указывают имя вендора (vendor name), возвращаемое устройством. * Имя должно предоставляться как список символов в одиночных * кавычках, а USB_CFG_VENDOR_NAME_LEN задает их количество. Символы * интерпретируются как Unicode (UTF-16). Если Вам не нужно имя вендора, * закомментируйте этот макрос. ВСЕГДА указывайте имя вендора, содержащее Ваше * доменное имя Internet, если Вы используете свободно распространяемую пару * obdev VID/PID. За деталями обращайтесь к файлу USB-IDs-for-free.txt. */ #define USB_CFG_DEVICE_NAME 'V', 'd', 'd', 'd', 'd', ' ', 'V', 'd', 'd', 'd', 'd', 'd', 'd', 'd' #define USB_CFG_DEVICE_NAME_LEN 14 /* Здесь указывается имя устройства (device name) таким же способом, как и в * предыдущем параметре указывается имя вендора. Если Вам не нужно имя * устройства, закомментируйте этот макрос. См. файл USB-IDs-for-free.txt * перед назначением имени, если Вы используете свободно распространяемую * пару obdev VID/PID. */ /*#define USB_CFG_SERIAL_NUMBER 'N', 'o', 'n', 'e' */ /*#define USB_CFG_SERIAL_NUMBER_LEN 0 */ /* Серийный номер (serial number). Если серийный номер Вам не нужен, * закомментируйте макрос. Может оказаться полезным предоставить serial number * по другим соображениям, отличающимся от времени компиляции. См. секцию, * описывающую свойства дескриптора далее, где указано как сделать точное * управление дескрипторами USB (USB descriptors), такими как string * descriptor для серийного номера. */ #define USB_CFG_DEVICE_CLASS 0 #define USB_CFG_DEVICE_SUBCLASS 0 /* См. спецификацию USB, если Вы хотите приспособить устройство к * существующему классу устройств (device class). Класс 0xff является * "специфическим для вендора" ("vendor specific"). */ #define USB_CFG_INTERFACE_CLASS 3 #define USB_CFG_INTERFACE_SUBCLASS 0 #define USB_CFG_INTERFACE_PROTOCOL 0 /* См. спецификацию USB, если Вы хотите, чтобы устройство отвечало требованиям * существующего класса или протокола. Следующие классы должны быть установлены * на уровне интерфейса: * HID class 3, нетребуется подклассов и протоколов (может оказаться полезным!) * CDC class 2, используйте подкласс 2 и протокол 1 для ACM */ #define USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH 22 /* Задайте здесь длину HID report descriptor, если Вы реализовали HID * устройство. Иначе не задавайте этот параметр или установите его в 0. * Если используете этот параметр, то Вы должны добавить символьный массив * PROGMEM, названный "usbHidReportDescriptor", в код, который содержит * report descriptor. Не забудьте держать массив и этот параметр в * соответствии! */ /* #define USB_PUBLIC static */ /* Используйте этот define, если Вы используете директиву #include usbdrv.c * вместо линкования. Эта техника экономит несколько байт flash-памяти. */ /* --------------- Тонкое управление через дескрипторы USB ----------------- */ /* Если Вы не хотите использовать дескрипторы по умолчанию драйвера USB, * Вы можете предоставить Ваши собственные. Это может быть сделано * как (1) статические данные фиксированной длины в памяти flash, * (2) статические данные фиксированной длины в RAM, или (3) динамические во * время выполнения в функции usbFunctionDescriptor(). Смотрим usbdrv.h для * большей информации по таким дескрипторам. Поддержка дескрипторов * конфигурируется через свойства дескриптора. Если не заданы свойства или * если они равны 0, используется дескриптор по умолчанию. * Возможны свойства: * + USB_PROP_IS_DYNAMIC: данные для дескриптора должны быть захвачены (fetched) * во время выполнения через usbFunctionDescriptor(). Если используется * механизм usbMsgPtr, данные по умолчанию у FLASH. * Добавьте свойство USB_PROP_IS_RAM если хотите RAM указатели. * + USB_PROP_IS_RAM: данные, возвращенные usbFunctionDescriptor() или * найденные в статической памяти RAM, не в памяти flash. * + USB_PROP_LENGTH(len): если данные в статической памяти (RAM или flash), * драйвер должен знать длину дескриптора. Дескриптор сам по себе найден по адресу, * известному как идентификатор (см. далее). * Список статических имен дескрипторов (должен быть задекларирован PROGMEM в flash): * char usbDescriptorDevice[]; * char usbDescriptorConfiguration[]; * char usbDescriptorHidReport[]; * char usbDescriptorString0[]; * int usbDescriptorStringVendor[]; * int usbDescriptorStringDevice[]; * int usbDescriptorStringSerialNumber[]; * Другие дескрипторы не могут быть предоставлены статически, они должны * предоставляться динамически во время выполнения. * * Свойства дескрипторов объединяются по ИЛИ либо складываются вместе, например: * #define USB_CFG_DESCR_PROPS_DEVICE (USB_PROP_IS_RAM | USB_PROP_LENGTH(18)) * * Следующие дескрипторы заданы: * USB_CFG_DESCR_PROPS_DEVICE * USB_CFG_DESCR_PROPS_CONFIGURATION * USB_CFG_DESCR_PROPS_STRINGS * USB_CFG_DESCR_PROPS_STRING_0 * USB_CFG_DESCR_PROPS_STRING_VENDOR * USB_CFG_DESCR_PROPS_STRING_PRODUCT * USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER * USB_CFG_DESCR_PROPS_HID * USB_CFG_DESCR_PROPS_HID_REPORT * USB_CFG_DESCR_PROPS_UNKNOWN (for all descriptors not handled by the driver) * * Помните что string дескрипторы не просто строки, они являются * Unicode strings prefixed with a 2 byte header. Пример: * int serialNumberDescriptor[] = { * USB_STRING_DESCRIPTOR_HEADER(6), * 'S', 'e', 'r', 'i', 'a', 'l' * }; */ #define USB_CFG_DESCR_PROPS_DEVICE 0 #define USB_CFG_DESCR_PROPS_CONFIGURATION 0 #define USB_CFG_DESCR_PROPS_STRINGS 0 #define USB_CFG_DESCR_PROPS_STRING_0 0 #define USB_CFG_DESCR_PROPS_STRING_VENDOR 0 #define USB_CFG_DESCR_PROPS_STRING_PRODUCT 0 #define USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER 0 #define USB_CFG_DESCR_PROPS_HID 0 #define USB_CFG_DESCR_PROPS_HID_REPORT 0 #define USB_CFG_DESCR_PROPS_UNKNOWN 0 /* --------------------- Дополнительные настройки MCU ---------------------- */ /* Следующие конфигурации работают по умолчанию в usbdrv.h. Вам обычно не нужно * устанавливать их. Только если Вам нужно запустить драйвер на устройстве, * которое пока не обрабатывается компилятором, который не полностью * поддерживается (как, например, IAR C) или если используете прерывание, * отличное от INT0, Вы можете задать кое-что из этого. */ /* #define USB_INTR_CFG MCUCR */ /* #define USB_INTR_CFG_SET ((1 << ISC00) | (1 << ISC01)) */ /* #define USB_INTR_CFG_CLR 0 */ /* #define USB_INTR_ENABLE GIMSK */ /* #define USB_INTR_ENABLE_BIT INT0 */ /* #define USB_INTR_PENDING GIFR */ /* #define USB_INTR_PENDING_BIT INTF0 */ /* #define USB_INTR_VECTOR INT0_vect */ Custom_HID.rar Hid_example_host_software.rar Изменено 20 ноября, 2012 пользователем IgorKossak [codebox] для длинного кода!!! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MementoMori 4 22 ноября, 2012 Опубликовано 22 ноября, 2012 (изменено) · Жалоба Тихо сам с собою... С записью разобрался. Помогите вкурить про чтение. ИЗначально пример был настроен на отправку данных от хоста и получение от устройства показаний АЦП, по прерыванию. По факту жмешь кнопку "Write", хост отправляет данные и принимает в ответ показания АЦП. Вот код, мной покоцанный. ПРосто сейчас чищу этот пример, удаляя все лишнее, насколько это возможно. /******************************************************************************* * Function Name : DMA1_Channel1_IRQHandler * Description : This function handles DMA1 Channel 1 interrupt request. * Input : None * Output : None * Return : None *******************************************************************************/ void DMA1_Channel1_IRQHandler(void) { Send_Buffer[0] = 0x01; if((ADC_ConvertedValueX >>4) - (ADC_ConvertedValueX_1 >>4) > 4) { Send_Buffer[1] = (uint8_t)(ADC_ConvertedValueX >>4); USB_SIL_Write(EP1_IN, (uint8_t*) Send_Buffer, 8); SetEPTxValid(ENDP1); ADC_ConvertedValueX_1 = ADC_ConvertedValueX; } DMA_ClearFlag(DMA1_FLAG_TC1); } /******************************************************************************* * Function Name : EXTI9_5_IRQHandler * Description : This function handles External lines 9 to 5 interrupt request. * Input : None * Output : None * Return : None *******************************************************************************/ void EXTI9_5_IRQHandler(void) { Send_Buffer[0]=0xCC; Send_Buffer[1]=0xCC; Send_Buffer[2]=0xCC; USB_SIL_Write(EP1_IN, (uint8_t*) Send_Buffer, 8); SetEPTxValid(ENDP1); EXTI_ClearITPendingBit(KEY_BUTTON_EXTI_LINE); } /******************************************************************************* * Function Name : EXTI15_10_IRQHandler * Description : This function handles External lines 15 to 10 interrupt request. * Input : None * Output : None * Return : None *******************************************************************************/ void EXTI15_10_IRQHandler(void) { Send_Buffer[0]=0xCC; Send_Buffer[1]=0xCC; Send_Buffer[2]=0xCC; USB_SIL_Write(EP1_IN, (uint8_t*) Send_Buffer, 8); SetEPTxValid(ENDP1); EXTI_ClearITPendingBit(TAMPER_BUTTON_EXTI_LINE); } А я хочу, чтобы HID устройство помещало в Endpoint данные ПОСЛЕ получения данных от хоста, то есть чтобы было что-то вроде Хост: "Привет"; HID: "И тебе привет" Вот что я сделал: void EP2_IN_Callback(void) { WriteString(0,150,"DDDDDDDDDDDDd",0x001F); Transi_Buffer[0]=0x01; Transi_Buffer[1]=0xCC; Transi_Buffer[2]=0xCC; USB_SIL_Write(EP1_IN, (uint8_t*) Transi_Buffer, 8); SetEPTxValid(ENDP1); } В результате этого HID начинает бесконечно посылать в ответ пакеты. А мне и АЦП отключить бы (а низзя, без кода в обработчиках прерываний не работает). Ткните носом куда-нибудь кроме учебника, который я сейчас читаю. Изменено 22 ноября, 2012 пользователем IgorKossak [codebox] для длинного кода Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
YAM 0 22 ноября, 2012 Опубликовано 22 ноября, 2012 · Жалоба Хм.... Вот мой дескриптор #define W2B(w) (w) & 255, (w) >> 8 const uint8_t CustomHID_ReportDescriptor[CUSTOMHID_SIZ_REPORT_DESC] = { 0x06, W2B(0xFF00), // USAGE_PAGE (Generic Desktop) 0x09, 0x01, // USAGE (Vendor Usage 1) 0xA1, 0x01, // COLLECTION (Application) 0x15, 0x00, // LOGICAL_MINIMUM (0) 0x26, W2B(0x00FF), // LOGICAL_MAXIMUM (255) 0x75, 0x08, // REPORT_SIZE (8) 0x95, 129, // REPORT_COUNT (размер данных) 0x09, 0x00, // USAGE (Undefined) 0xB2, W2B(0x0102), // FEATURE (Data,Var,Abs,Buf) 0xC0 // END_COLLECTION }; /* CustomHID_ReportDescriptor */ гоняю туда-сюда 129 байт данных, где 1-й байт мой ID пакета... данные гоняю с помощью SetFeature и GetFeature. в CustomHID_Data_Setup (usb_prop.c) добавил обработку ................... /*** GET_REPORT ***/ else if ((Type_Recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT)) && RequestNo == GET_REPORT) { CopyRoutine = CustomHID_GetReport; } /*** SET_REPORT ***/ else if ((Type_Recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT)) && RequestNo == SET_REPORT) { CopyRoutine = CustomHID_SetReport; } else ................... В соответствующих обработчиках получаю данные от хоста, либо передаю их. Прерывания для USB я не использовал, сделал все на поллинге. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MementoMori 4 22 ноября, 2012 Опубликовано 22 ноября, 2012 (изменено) · Жалоба У меня вопрос. Правильно ли я понял, что поллинг, это когда хост читает из дескриптора некую переменную времени, и затем с соответствующей частотой опрашивает HID устройство, то есть при этом в программе нет кода, который непрерывно генерирует эти запросы? Второй вопрос. Я не совсем понял, какая связь между прерываниями и запросами? 0x95, 129, // REPORT_COUNT (размер данных) Хм... а разве в дескрипторе эта цифра означает длину пакета вместе с ID? У меня стало работать когда я эту длину указал как 16, а размеры буферов и ендпоинтов по 17. А нельзя ли ваши файлы с дескриптором и usb_prop полностью? И где у вас в дескрипторе Report ID? что такое W2B? Мой компилятор это не понимает. Изменено 22 ноября, 2012 пользователем Memento Mori Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
YAM 0 22 ноября, 2012 Опубликовано 22 ноября, 2012 · Жалоба Ключевое слово "мой ID пакета" и он никакого отношения к Report ID не имеет... Мне просто надо было обмениваться данными по 128 байт, но надо знать что это за данные, для этого у меня и "мой ID пакета" и используется. Поллинг - для того, чтобы не использовать прерывания от USB, у меня критичная по времени задача, которая по прерываниям и работает... Хост при обмене данными использует SetReport для отсылки команды или данных девайсу и GetReport-ом получает ответ. Если ответ готов, первый байт, который у меня "мой ID пакета" - возвращается ненулевым - и означает, что девайс отдал свои данные, либо ответ на команду. Если же он нулевой - это означает что данные для хоста еще не готовы и отсылается опять GetReport до истечения таймаута ответа, либо его получения... я не буду приводить usb_prop.с полностью. Думаю хватит и того, что я привел. Я все сделал по аналогии с CustomHID_GetProtocolValue, и кроме того все остальное подсматривал у http://www.obdev.at/products/vusb/index.html... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MementoMori 4 22 ноября, 2012 Опубликовано 22 ноября, 2012 · Жалоба К сожалению того что вы выложили недостаточно. Не знает моя библиотека CustomHID_GetReport Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
_3m 9 23 ноября, 2012 Опубликовано 23 ноября, 2012 · Жалоба Помогите вкурить про чтение. ... В результате этого HID начинает бесконечно посылать в ответ пакеты. А мне и АЦП отключить бы (а низзя, без кода в обработчиках прерываний не работает). У вас в дескрипторе Input endpoint объявлен как interrupt. Он так и должен работать - бесконечно гнать в писюк данные. Единственный способ его заткнуть - выдавать NAK. Но NAK долго выдавать не рекомендуентся потому что по NAK не сбрасывается счетчик ошибок в хост контроллере. Поэтому если вы хотите получать данные только по запросу от писюка используете передачу через Control transfer. Еще не рекомендую для начала делать длину репорта с учетом Id больше чем размер эндпойнта. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
YAM 0 23 ноября, 2012 Опубликовано 23 ноября, 2012 · Жалоба К сожалению того что вы выложили недостаточно. Не знает моя библиотека CustomHID_GetReport Конечно не знает, я же написал, что "все сделал по аналогии с CustomHID_GetProtocolValue"... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MementoMori 4 23 ноября, 2012 Опубликовано 23 ноября, 2012 · Жалоба ОК, сделал в дескрипторе так: USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: */ 0x81, /* bEndpointAddress: Endpoint Address (IN) */ 0x00, /* bmAttributes: control transfer endpoint */ в usb_endp.c так: void EP2_IN_Callback(void) { WriteString(0,150,"IN_CALLBACK",0x001F); Transi_Buffer[0]=0x01; //ReportID Transi_Buffer[1]=0xCC; Transi_Buffer[2]=0xCC; } а в основном цикле так: USB_SIL_Write(EP1_IN, (uint8_t*)Transi_Buffer, 8); SetEPTxValid(ENDP1); не работает. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MementoMori 4 23 ноября, 2012 Опубликовано 23 ноября, 2012 · Жалоба Поэтому если вы хотите получать данные только по запросу от писюка используете передачу через Control transfer. Ну вот дескриптор от другого примера, который работает - хост по нажатию кнопки шлет строку и получает в ответ другую: USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: */ 0x82, /* bEndpointAddress: Endpoint Address (IN) */ // bit 3...0 : the endpoint number // bit 6...4 : reserved // bit 7 : 0(OUT), 1(IN) 0x03, /* bmAttributes: Interrupt endpoint */ 0x40,//0x02, /* wMaxPacketSize: 20 Bytes max */ 0x00, 0x20, /* bInterval: Polling Interval (21 ms) */ /* 34 */ 0x07, /* bLength: Endpoint Descriptor size */ USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: */ /* Endpoint descriptor type */ 0x01, /* bEndpointAddress: */ /* Endpoint Address (OUT) */ 0x03, /* bmAttributes: Interrupt endpoint */ 0x40,//0x02, /* wMaxPacketSize: 20 Bytes max */ 0x00, 0x10, /* bInterval: Polling Interval (32 ms) */ /* 41 */ А вот обработчик единственного, кроме USB_LP_CAN_RX0_IRQHandler, задействованного прерывания void TIM2_IRQHandler(void) // 1s enter { if (TIM_GetITStatus(TIM2, TIM_IT_CC1) != RESET) { // for LED test if (GPIOA->ODR & 0x04 ) GPIOA->ODR &= (~0x04); else GPIOA->ODR |= 0x04; if (TimeCount<0xff) TimeCount++; TIM_ClearITPendingBit(TIM2, TIM_IT_CC1 ); } } Хоть в нем и нет ничего кроме моргания светодиодом, комментирование строк в нем приводит к тому, что обмен данными не идет. Как это работает, кто-нибудь может объяснить? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MementoMori 4 23 ноября, 2012 Опубликовано 23 ноября, 2012 (изменено) · Жалоба Черт.. я уже не знаю, что делать. Выкладываю РАБОЧИЙ проект - все отлично, принимает данные отправляет данные, хоть и настроен на прерывание. у него один существенный минус, он написан под FWLib. А в ГИБРИДНОМ проекте имеет место быть StdPeriph. Выдираю USBLib из РАБОЧЕГО проекта, копирую в ГИБРИДНЫЙ - естественно не компилируется, выдает ряд ошибок. Кое-как устраняю эти ошибки - компилирую, запускаю - пишет "неизвестное устройство" Что я менял - строки типа "#include "stm32f10x_map.h" "stm32f10x_lib.h" убирал, вставляя на их место "stm32f10x.h" - в нем все есть и действительно ошибки исчезали. Не получилос только совладать с USB_LP_CAN_RX0_IRQСhanel - заменил его на USB_LP_CAN1_RX0_IRQn. Просто "...CAN..." в StdPeriph нет, там есть именно "...CAN1..." Ну и закомментировал пару строк в void DisableClock(void) { // RCC_APB1PeriphClockCmd(RCC_APB1Periph_ALL,DISABLE); //RCC_APB2PeriphClockCmd(RCC_APB2Periph_ALL,DISABLE); } так как аналога не нашел. Господа, я не прошу писать за меня программу - уже есть проект с настроенной системой ендпоинтов и репортов. Не получается заставить его работать с другой библиотекой периферии. Выкладываю проекты и расчитываю на вашу помощь. HYBRID_Priject.rar WORKING_Project.rar Изменено 23 ноября, 2012 пользователем Memento Mori Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться