реклама на сайте
подробности

 
 
 
Reply to this topicStart new topic
> Помогите довести до ума программу для STM32F103 и USB
Memento Mori
сообщение Nov 20 2012, 11:17
Сообщение #1


Частый гость
**

Группа: Участник
Сообщений: 151
Регистрация: 1-10-12
Пользователь №: 73 751



Господа, помогите организовать обмен данными между USB устройством и программой хостом.

За основу взят пример от ST - "Custom HID" для IAR. Контроллер STM32F103RBT6
К нему прилагается программа для компа - "HID Demonstrator", в программе жмешь кнопки, на устройстве загораются светодиоды.
Хочу ее модифицировать, дабы передавать данные. НАшел в интернете пример для C++ Builder который позволяет принимать и отправлять пакеты, тоже его модифицировал

С программой HID Demonstrator управлять светодиодами получается. А вот с собственной не получается передать и двух байт.

Подскажите, чего не хвататет в программе.
ЛИчно мне непонятно, где в программе-хосте указание писать в конкретный ендпоинт...

Итак ближе к делу. ПРограмма для STM32F103:

CODE
#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
CODE

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

CODE

/* 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

Подключение. Сразу скажу - все работает, дескриптор читается, ошибок нет
CODE
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 - никакой реакции

CODE
// Кнопка "Отправить данные"
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++

CODE


#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 */




Сообщение отредактировал IgorKossak - Nov 20 2012, 20:59
Причина редактирования: [codebox] для длинного кода!!!

Прикрепленные файлы
Прикрепленный файл  Custom_HID.rar ( 619.22 килобайт ) Кол-во скачиваний: 55
Прикрепленный файл  Hid_example_host_software.rar ( 3.88 мегабайт ) Кол-во скачиваний: 43
 
Go to the top of the page
 
+Quote Post
Memento Mori
сообщение Nov 22 2012, 13:21
Сообщение #2


Частый гость
**

Группа: Участник
Сообщений: 151
Регистрация: 1-10-12
Пользователь №: 73 751



Тихо сам с собою...
С записью разобрался.
Помогите вкурить про чтение.

ИЗначально пример был настроен на отправку данных от хоста и получение от устройства показаний АЦП, по прерыванию.
По факту жмешь кнопку "Write", хост отправляет данные и принимает в ответ показания АЦП.
Вот код, мной покоцанный. ПРосто сейчас чищу этот пример, удаляя все лишнее, насколько это возможно.

CODE
/*******************************************************************************
* 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 начинает бесконечно посылать в ответ пакеты.
А мне и АЦП отключить бы (а низзя, без кода в обработчиках прерываний не работает).

Ткните носом куда-нибудь кроме учебника, который я сейчас читаю.

Сообщение отредактировал IgorKossak - Nov 22 2012, 18:56
Причина редактирования: [codebox] для длинного кода
Go to the top of the page
 
+Quote Post
YAM
сообщение Nov 22 2012, 15:28
Сообщение #3


Местный
***

Группа: Свой
Сообщений: 256
Регистрация: 7-07-04
Из: Ukraine
Пользователь №: 291



Хм....
Вот мой дескриптор
Код
#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 я не использовал, сделал все на поллинге.


--------------------
Go to the top of the page
 
+Quote Post
Memento Mori
сообщение Nov 22 2012, 15:45
Сообщение #4


Частый гость
**

Группа: Участник
Сообщений: 151
Регистрация: 1-10-12
Пользователь №: 73 751



У меня вопрос.
Правильно ли я понял, что поллинг, это когда хост читает из дескриптора некую переменную времени, и затем с соответствующей частотой опрашивает HID устройство, то есть при этом в программе нет кода, который непрерывно генерирует эти запросы?
Второй вопрос. Я не совсем понял, какая связь между прерываниями и запросами?

Код
0x95, 129,          //   REPORT_COUNT (размер данных)


Хм... а разве в дескрипторе эта цифра означает длину пакета вместе с ID? У меня стало работать когда я эту длину указал как 16, а размеры буферов и ендпоинтов по 17.

А нельзя ли ваши файлы с дескриптором и usb_prop полностью?

И где у вас в дескрипторе Report ID?
что такое W2B? Мой компилятор это не понимает.

Сообщение отредактировал Memento Mori - Nov 22 2012, 15:48
Go to the top of the page
 
+Quote Post
YAM
сообщение Nov 22 2012, 16:01
Сообщение #5


Местный
***

Группа: Свой
Сообщений: 256
Регистрация: 7-07-04
Из: Ukraine
Пользователь №: 291



Ключевое слово "мой ID пакета" и он никакого отношения к Report ID не имеет...
Мне просто надо было обмениваться данными по 128 байт, но надо знать что это за данные, для этого у меня и "мой ID пакета" и используется.
Поллинг - для того, чтобы не использовать прерывания от USB, у меня критичная по времени задача, которая по прерываниям и работает...
Хост при обмене данными использует SetReport для отсылки команды или данных девайсу и GetReport-ом получает ответ. Если ответ готов, первый байт, который у меня "мой ID пакета" - возвращается ненулевым - и означает, что девайс отдал свои данные, либо ответ на команду. Если же он нулевой - это означает что данные для хоста еще не готовы и отсылается опять GetReport до истечения таймаута ответа, либо его получения...
я не буду приводить usb_prop.с полностью. Думаю хватит и того, что я привел. Я все сделал по аналогии с CustomHID_GetProtocolValue, и кроме того все остальное подсматривал у http://www.obdev.at/products/vusb/index.html...


--------------------
Go to the top of the page
 
+Quote Post
Memento Mori
сообщение Nov 22 2012, 17:53
Сообщение #6


Частый гость
**

Группа: Участник
Сообщений: 151
Регистрация: 1-10-12
Пользователь №: 73 751



К сожалению того что вы выложили недостаточно. Не знает моя библиотека CustomHID_GetReport
Go to the top of the page
 
+Quote Post
_3m
сообщение Nov 23 2012, 06:24
Сообщение #7


Знающий
****

Группа: Участник
Сообщений: 745
Регистрация: 28-12-06
Пользователь №: 23 960



Цитата(Memento Mori @ Nov 22 2012, 17:21) *
Помогите вкурить про чтение.
...
В результате этого HID начинает бесконечно посылать в ответ пакеты.
А мне и АЦП отключить бы (а низзя, без кода в обработчиках прерываний не работает).

У вас в дескрипторе Input endpoint объявлен как interrupt. Он так и должен работать - бесконечно гнать в писюк данные. Единственный способ его заткнуть - выдавать NAK. Но NAK долго выдавать не рекомендуентся потому что по NAK не сбрасывается счетчик ошибок в хост контроллере.
Поэтому если вы хотите получать данные только по запросу от писюка используете передачу через Control transfer.
Еще не рекомендую для начала делать длину репорта с учетом Id больше чем размер эндпойнта.
Go to the top of the page
 
+Quote Post
YAM
сообщение Nov 23 2012, 06:49
Сообщение #8


Местный
***

Группа: Свой
Сообщений: 256
Регистрация: 7-07-04
Из: Ukraine
Пользователь №: 291



Цитата(Memento Mori @ Nov 22 2012, 21:53) *
К сожалению того что вы выложили недостаточно. Не знает моя библиотека CustomHID_GetReport

Конечно не знает, я же написал, что "все сделал по аналогии с CustomHID_GetProtocolValue"...


--------------------
Go to the top of the page
 
+Quote Post
Memento Mori
сообщение Nov 23 2012, 08:09
Сообщение #9


Частый гость
**

Группа: Участник
Сообщений: 151
Регистрация: 1-10-12
Пользователь №: 73 751



ОК, сделал в дескрипторе так:
Код
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);


не работает.
Go to the top of the page
 
+Quote Post
Memento Mori
сообщение Nov 23 2012, 09:54
Сообщение #10


Частый гость
**

Группа: Участник
Сообщений: 151
Регистрация: 1-10-12
Пользователь №: 73 751



Код
Поэтому если вы хотите получать данные только по запросу от писюка используете передачу через 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 );    
     }  
    
}


Хоть в нем и нет ничего кроме моргания светодиодом, комментирование строк в нем приводит к тому, что обмен данными не идет.

Как это работает, кто-нибудь может объяснить?
Go to the top of the page
 
+Quote Post
Memento Mori
сообщение Nov 23 2012, 20:46
Сообщение #11


Частый гость
**

Группа: Участник
Сообщений: 151
Регистрация: 1-10-12
Пользователь №: 73 751



Черт.. я уже не знаю, что делать.
Выкладываю РАБОЧИЙ проект - все отлично, принимает данные отправляет данные, хоть и настроен на прерывание. у него один существенный минус, он написан под 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);
}

так как аналога не нашел.


Господа, я не прошу писать за меня программу - уже есть проект с настроенной системой ендпоинтов и репортов. Не получается заставить его работать с другой библиотекой периферии.
Выкладываю проекты и расчитываю на вашу помощь.

Сообщение отредактировал Memento Mori - Nov 23 2012, 20:47
Прикрепленные файлы
Прикрепленный файл  HYBRID_Priject.rar ( 952.92 килобайт ) Кол-во скачиваний: 42
Прикрепленный файл  WORKING_Project.rar ( 862.18 килобайт ) Кол-во скачиваний: 54
 
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 21st July 2025 - 18:27
Рейтинг@Mail.ru


Страница сгенерированна за 0.01542 секунд с 7
ELECTRONIX ©2004-2016