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

Помогите довести до ума программу для STM32F103 и USB

Господа, помогите организовать обмен данными между 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

Изменено пользователем IgorKossak
[codebox] для длинного кода!!!

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


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

Тихо сам с собою...

С записью разобрался.

Помогите вкурить про чтение.

 

ИЗначально пример был настроен на отправку данных от хоста и получение от устройства показаний АЦП, по прерыванию.

По факту жмешь кнопку "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 начинает бесконечно посылать в ответ пакеты.

А мне и АЦП отключить бы (а низзя, без кода в обработчиках прерываний не работает).

 

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

Изменено пользователем IgorKossak
[codebox] для длинного кода

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


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

Хм....

Вот мой дескриптор

#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 я не использовал, сделал все на поллинге.

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


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

У меня вопрос.

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

Второй вопрос. Я не совсем понял, какая связь между прерываниями и запросами?

 

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

 

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

 

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

 

И где у вас в дескрипторе Report ID?

что такое W2B? Мой компилятор это не понимает.

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

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


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

Ключевое слово "мой ID пакета" и он никакого отношения к Report ID не имеет...

Мне просто надо было обмениваться данными по 128 байт, но надо знать что это за данные, для этого у меня и "мой ID пакета" и используется.

Поллинг - для того, чтобы не использовать прерывания от USB, у меня критичная по времени задача, которая по прерываниям и работает...

Хост при обмене данными использует SetReport для отсылки команды или данных девайсу и GetReport-ом получает ответ. Если ответ готов, первый байт, который у меня "мой ID пакета" - возвращается ненулевым - и означает, что девайс отдал свои данные, либо ответ на команду. Если же он нулевой - это означает что данные для хоста еще не готовы и отсылается опять GetReport до истечения таймаута ответа, либо его получения...

я не буду приводить usb_prop.с полностью. Думаю хватит и того, что я привел. Я все сделал по аналогии с CustomHID_GetProtocolValue, и кроме того все остальное подсматривал у http://www.obdev.at/products/vusb/index.html...

 

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


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

К сожалению того что вы выложили недостаточно. Не знает моя библиотека CustomHID_GetReport

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


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

Помогите вкурить про чтение.

...

В результате этого HID начинает бесконечно посылать в ответ пакеты.

А мне и АЦП отключить бы (а низзя, без кода в обработчиках прерываний не работает).

У вас в дескрипторе Input endpoint объявлен как interrupt. Он так и должен работать - бесконечно гнать в писюк данные. Единственный способ его заткнуть - выдавать NAK. Но NAK долго выдавать не рекомендуентся потому что по NAK не сбрасывается счетчик ошибок в хост контроллере.

Поэтому если вы хотите получать данные только по запросу от писюка используете передачу через Control transfer.

Еще не рекомендую для начала делать длину репорта с учетом Id больше чем размер эндпойнта.

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


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

К сожалению того что вы выложили недостаточно. Не знает моя библиотека CustomHID_GetReport

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

 

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


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

ОК, сделал в дескрипторе так:

 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);

 

не работает.

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


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

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

 

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

 

Как это работает, кто-нибудь может объяснить?

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


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

Черт.. я уже не знаю, что делать.

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

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

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


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

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

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

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

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

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

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

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

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

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