PicManía by RedRaven |
Búsqueda personalizada
|
EL USB DESENCADENADO : HID USB |
||
Clase de dispositivos de comunicaciones |
Cómo realizar un proyecto
con el USB 2.0 emulando un Dispositivo de Interfaz Humana, o sea un
HID USB.
Un PIC con USB 2.0 que funciona como un Teclado USB, aunque podríamos
implementar también un Ratón o incluso un Joystick. |
|
PIC's, Hardware mínimo y Antecedentes varios. |
|
|
|
|
|
|
Descripción del proyecto. |
|
|
|
|
|
Firmware. |
|
|
|
|
|
|
#include USB_kbd_HID.h |
|
Los código a enviar como Keys pulsadas |
|
rr2_hid_bkd_usb_monitor.c |
||
///////////////////////////////////////////////////////////////////////// //// //// rr2_hid_kbd_usb_monitor.c //// //// by RedPic //// //// 08/10/2006 //// ///////////////////////////////////////////////////////////////////////// #include <18F4550.h> #fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN #use delay(clock=48000000) #DEFINE USB_HID_DEVICE TRUE #define USB_EP1_TX_ENABLE USB_ENABLE_INTERRUPT //turn on EP1 for IN bulk/interrupt transfers #define USB_EP1_TX_SIZE 8 #define USB_EP1_RX_ENABLE USB_ENABLE_INTERRUPT //turn on EP1 for IN bulk/interrupt transfers #define USB_EP1_RX_SIZE 8 #include <pic18_usb.h> #include <.\include\usb_kbd_HID.h> //USB Configuration and Device descriptors for this UBS device #include <usb.c> //handles usb setup tokens and get descriptor reports #include <ctype.h> ///////////////////////////////////////////////////////////////////////////// // // Defines y Zarandajas // ///////////////////////////////////////////////////////////////////////////// #define LED1 PIN_E0 #define LED2 PIN_E1 #define LED3 PIN_E2 #define LED_ON output_high #define LED_OFF output_low #define PIN_SOURCE PIN_B1 ///////////////////////////////////////////////////////////////////////////// // // RAM // ///////////////////////////////////////////////////////////////////////////// int8 connected; int8 enumerated; int8 rx_msg[USB_EP1_RX_SIZE]; int8 tx_msg[8]={2,0,0,0,0,0,0,0}; char NextChar='0'; int1 hay_dato=0; int8 i; ///////////////////////////////////////////////////////////////////////////// // // usb_debug_task() // // When called periodically, displays debugging information over serial // to display enumeration and connection states. Also lights LED2 and LED3 // based upon enumeration and connection status. // ///////////////////////////////////////////////////////////////////////////// void usb_debug_task(void) { enumerated=usb_enumerated(); if(enumerated){ LED_ON(LED1); LED_OFF(LED3); } else{ LED_ON(LED3); LED_OFF(LED1); } } ///////////////////////////////////////////////////////////////////////////// // // usb_keyboard_task() // // Sends a packet of keyboard data. The protocol was specified in the HID // report descriptor (see usb_desc_kbmouse.h), and is: // tx_msg[0] = HID report id (2) // tx_msg[1] = modifier (an 8bit bitmap of shift, tab, alt keypress) // tx_msg[2] = const 0 // tx_msg[3:7] = an array of held down keys. a=4, b=5, etc. // if msg[2:7]={0} then no keys are held down // // rx_msg[1] = HID report id (2) // rx_msg[0] = 5bit bitmap of led status // ///////////////////////////////////////////////////////////////////////////// int8 char_2_usb_kbd_code(char c){ int8 ic; if(isAlpha(c)){ ic=c-'a'+4; } else{ if(c=='0'){ ic=39; } else{ ic=c-'1'+30; } } return(ic); } void usb_keyboard_task(void) { static char Char_Tx; if(hay_dato==1){ hay_dato=0; tx_msg[3]=char_2_usb_kbd_code(NextChar); usb_put_packet(1,tx_msg,sizeof(tx_msg),USB_DTS_TOGGLE); ++NextChar; if(NextChar>'z'){ NextChar='0'; } if(NextChar>'9'&&NextChar<'a'){ NextChar='a'; } LED_OFF(LED2); delay_ms(5); }else{ tx_msg[3]=0; usb_put_packet(1,tx_msg,sizeof(tx_msg),USB_DTS_TOGGLE); delay_ms(5); } } ///////////////////////////////////////////////////////////////////////////// // // usb_rx_task() // // Listens to EP1 for any incoming packets. The only report ID that is // configurd to send us data is 2 (keyboard LED status, see above) // ///////////////////////////////////////////////////////////////////////////// void usb_rx_task(void){ if (usb_kbhit(1)){ usb_get_packet(1, rx_msg, sizeof(rx_msg)); } } ///////////////////////////////////////////////////////////////////////////// // // recibe por interrupción ext // ///////////////////////////////////////////////////////////////////////////// #int_ext void ext_handler(void){ if(hay_dato==0){ hay_dato=1; LED_ON(LED2); } } void main() { hay_dato=0; delay_ms(500); LED_OFF(LED1); LED_OFF(LED2); LED_OFF(LED3); usb_init_cs(); port_b_pullups(true); set_tris_b(0b00000001); output_high(PIN_SOURCE); ext_int_edge(0,L_TO_H); enable_interrupts(int_ext); enable_interrupts(global); while (TRUE) { usb_task(); usb_debug_task(); if (usb_enumerated()) { usb_keyboard_task(); usb_rx_task(); delay_ms(5); } } } |
||
|
|
|
|
|
|
|
|
|
|
|
|
USB_kbd_HID.h |
||
/////////////////////////////////////////////////////////////////////////// /// usb_kbd_HID.h //// //// //// /////////////////////////////////////////////////////////////////////////// #IFNDEF __USB_DESCRIPTORS__ #DEFINE __USB_DESCRIPTORS__ #include <usb.h> ////////////////////////////////////////////////////////////////// /// /// HID Report. Tells HID driver how to handle and deal with /// received data. HID Reports can be extremely complex, /// see HID specifcation for help on writing your own. /// /// First it defines a block for the first report ID for a mouse /// protocol. Second it defines a block for the second report ID /// for a keyboard protocol. /// ////////////////////////////////////////////////////////////////// const char USB_CLASS_SPECIFIC_DESC[] = { 0x05, 0x01, //usage page (generic desktop) //0,1 0x09, 0x06, //usage (keyboard) //2,3 0xA1, 0x01, //collection (application) //4,5 0x85, 0x02, //report id (2) //6,7 0x05, 0x07, //usage page (key codes) //8,9 0x19, 0xE0, //usage min (224) //10,11 0x29, 0xE7, //usage max (231) //12,13 0x15, 0x00, //logical min (0) //14,15 0x25, 0x01, //logical max (1) //16,17 0x75, 0x01, //report size (1) //18,19 0x95, 0x08, //report count (8) //20, 21 0x81, 0x02, //input (data, variable, absolute) [modifier byte] //22,23 0x95, 0x01, //report count (1) //24,25 0x75, 0x08, //report size (8) //26,27 0x81, 0x01, //input (constant) [reserved byte] //28,29 0x95, 0x05, //report count (5) //30,31 0x75, 0x01, //report size (1) //32,33 0x05, 0x08, //usage page (page# for leds) //34,35 0x19, 0x01, //usage min (1) //36,37 0x29, 0x05, //usage max (5) //38,39 0x91, 0x02, //output (data, var, abs) [led report] //40,41 0x95, 0x01, //report count (1) //42,43 0x75, 0x03, //report size (3) //44,45 0x91, 0x01, //output (constant) [led report padding] //46,47 0x95, 0x05, //report count (5) //48,49 0x75, 0x08, //report size (8) //50,51 0x15, 0x00, //logical min (0) //52,53 0x25, 0x65, //logical max (101) //54,55 0x05, 0x07, //usage page (key codes) //56,57 0x19, 0x00, //usage min (0) //58,59 0x29, 0x65, //usage max (101) //60,61 0x81, 0x00, //input (data, array) //62,63 0xC0 //end collection //64 }; //if a class has an extra descriptor not part of the config descriptor, // this lookup table defines where to look for it in the const // USB_CLASS_SPECIFIC_DESC[] array. //first element is the config number (if your device has more than one config) //second element is which interface number //set element to 0xFFFF if this config/interface combo doesn't exist const int16 USB_CLASS_SPECIFIC_DESC_LOOKUP[USB_NUM_CONFIGURATIONS][1] = { //config 1 //interface 0 0 }; //if a class has an extra descriptor not part of the config descriptor, // this lookup table defines the size of that descriptor. //first element is the config number (if your device has more than one config) //second element is which interface number //set element to 0xFFFF if this config/interface combo doesn't exist const int16 USB_CLASS_SPECIFIC_DESC_LOOKUP_SIZE[USB_NUM_CONFIGURATIONS][2] = { //config 1 //interface 0 sizeof(USB_CLASS_SPECIFIC_DESC) }; ////////////////////////////////////////////////////////////////// /// /// start config descriptor /// right now we only support one configuration descriptor. /// the config, interface, class, and endpoint goes into this array. /// ////////////////////////////////////////////////////////////////// #DEFINE USB_TOTAL_CONFIG_LEN 41 //config+interface+class+endpoint const char USB_CONFIG_DESC[] = { //IN ORDER TO COMPLY WITH WINDOWS HOSTS, THE ORDER OF THIS ARRAY MUST BE: // config(s) // interface(s) // class(es) // endpoint(s) //config_descriptor for config index 1 USB_DESC_CONFIG_LEN, //length of descriptor size ==0 USB_DESC_CONFIG_TYPE, //constant CONFIGURATION (CONFIGURATION 0x02) ==1 USB_TOTAL_CONFIG_LEN,0, //size of all data returned for this config ==2,3 1, //number of interfaces this device supports ==4 0x01, //identifier for this configuration. (IF we had more than one configurations) ==5 0x00, //index of string descriptor for this configuration ==6 0xC0, //bit 6=1 if self powered, bit 5=1 if supports remote wakeup (we don't), bits 0-4 unused and bit7=1 ==7 0x32, //maximum bus power required (maximum milliamperes/2) (0x32 = 100mA) //8 //interface descriptor 1 (MOUSE) USB_DESC_INTERFACE_LEN, //length of descriptor =9 USB_DESC_INTERFACE_TYPE, //constant INTERFACE (INTERFACE 0x04) =10 0x00, //number defining this interface (IF we had more than one interface) ==11 0x00, //alternate setting ==12 2, //number of endpoints for this interface //13 0x03, //class code, 03 = HID ==14 0x00, //subclass code //boot ==15 0x00, //protocol code ==16 0x00, //index of string descriptor for interface ==17 //class descriptor 1 (HID) USB_DESC_CLASS_LEN, //length of descriptor ==18 USB_DESC_CLASS_TYPE, //dscriptor type (0x21 == HID) ==19 0x00,0x01, //hid class release number (1.0) (try 1.10) ==20,21 0x00, //localized country code (0 = none) ==22 0x01, //number of hid class descrptors that follow (1) ==23 0x22, //report descriptor type (0x22 == HID) ==24 USB_CLASS_SPECIFIC_DESC_LOOKUP_SIZE[0][0], 0x00, //length of report descriptor ==25,26 //endpoint descriptor 1 IN USB_DESC_ENDPOINT_LEN, //length of descriptor ==27 USB_DESC_ENDPOINT_TYPE, //constant ENDPOINT (ENDPOINT 0x05) ==28 0x81, //endpoint number and direction (0x81 = EP1 IN) ==29 USB_ENDPOINT_TYPE_INTERRUPT, //transfer type supported (0x03 is interrupt) ==30 USB_EP1_TX_SIZE,0x00, //maximum packet size supported ==31,32 10 //polling interval, in ms. (cant be smaller than 10 for slow speed devices) ==33 //endpoint descriptor 1 OUT USB_DESC_ENDPOINT_LEN, //length of descriptor ==34 USB_DESC_ENDPOINT_TYPE, //constant ENDPOINT (ENDPOINT 0x05) ==35 0x01, //endpoint number and direction (0x01 = EP1 OUT) ==36 USB_ENDPOINT_TYPE_INTERRUPT, //transfer type supported (0x03 is interrupt) ==37 USB_EP1_RX_SIZE,0x00, //maximum packet size supported ==38,39 10 //polling interval, in ms. (cant be smaller than 10 for slow speed devices) ==40 }; //****** BEGIN CONFIG DESCRIPTOR LOOKUP TABLES ******** //since we can't make pointers to constants in certain pic16s, this is an offset table to find // a specific descriptor in the above table. //NOTE: DO TO A LIMITATION OF THE CCS CODE, ALL HID INTERFACES MUST START AT 0 AND BE SEQUENTIAL // FOR EXAMPLE, IF YOU HAVE 2 HID INTERFACES THEY MUST BE INTERFACE 0 AND INTERFACE 1 #define USB_NUM_HID_INTERFACES 1 //the maximum number of interfaces seen on any config //for example, if config 1 has 1 interface and config 2 has 2 interfaces you must define this as 2 #define USB_MAX_NUM_INTERFACES 1 //define how many interfaces there are per config. [0] is the first config, etc. const char USB_NUM_INTERFACES[USB_NUM_CONFIGURATIONS]={1}; //define where to find class descriptors //first dimension is the config number //second dimension specifies which interface //last dimension specifies which class in this interface to get, but most will only have 1 class per interface //if a class descriptor is not valid, set the value to 0xFFFF const int16 USB_CLASS_DESCRIPTORS[USB_NUM_CONFIGURATIONS][1][1]= { //config 1 //interface 0 //class 1 18 }; //****** END CONFIG DESCRIPTOR LOOKUP TABLES ******** #if (sizeof(USB_CONFIG_DESC) != USB_TOTAL_CONFIG_LEN) #error USB_TOTAL_CONFIG_LEN not defined correctly #endif ////////////////////////////////////////////////////////////////// /// /// start device descriptors /// ////////////////////////////////////////////////////////////////// const char USB_DEVICE_DESC[] = { //starts of with device configuration. only one possible USB_DESC_DEVICE_LEN, //the length of this report ==1 0x01, //the constant DEVICE (DEVICE 0x01) ==2 0x10,0x01, //usb version in bcd (pic167xx is 1.1) ==3,4 0x00, //class code ==5 0x00, //subclass code ==6 0x00, //protocol code ==7 USB_MAX_EP0_PACKET_LENGTH, //max packet size for endpoint 0. (SLOW SPEED SPECIFIES 8) ==8 0x61,0x04, //vendor id (0x04D8 is Microchip, or is it 0x0461 ??) 0x57,0x00, //product id ==11,12 //don't use ffff says usb-by-example guy. oops 0x00,0x01, //device release number ==13,14 0x01, //index of string description of manufacturer. therefore we point to string_1 array (see below) ==15 0x02, //index of string descriptor of the product ==16 0x00, //index of string descriptor of serial number ==17 USB_NUM_CONFIGURATIONS //number of possible configurations ==18 }; #if (sizeof(USB_DEVICE_DESC) != USB_DESC_DEVICE_LEN) #error USB_DESC_DEVICE_LEN not defined correctly #endif ////////////////////////////////////////////////////////////////// /// /// start string descriptors /// String 0 is a special language string, and must be defined. People in U.S.A. can leave this alone. /// ////////////////////////////////////////////////////////////////// //the offset of the starting location of each string. offset[0] is the start of string 0, offset[1] is the start of string 1, etc. const char USB_STRING_DESC_OFFSET[]={0,4,12}; //number of strings you have, including string 0. #define USB_STRING_DESC_COUNT sizeof(USB_STRING_DESC_OFFSET) char const USB_STRING_DESC[]={ //string 0 4, //length of string index USB_DESC_STRING_TYPE, //descriptor type 0x03 (STRING) 0x09,0x04, //Microsoft Defined for US-English //string 1 8, //length of string index USB_DESC_STRING_TYPE, //descriptor type 0x03 (STRING) 'R',0, 'R',0, '2',0, //string 2 46, //length of string index USB_DESC_STRING_TYPE, //descriptor type 0x03 (STRING) 'U',0, 'S',0, 'B',0, ' ',0, 'K',0, 'e',0, 'y',0, 'b',0, 'o',0, 'a',0, 'r',0, 'd',0, ' ',0, 'b',0, 'y',0, ' ',0, 'R',0, 'e',0, 'd',0, 'p',0, 'i',0, 'c',0 }; |
||
|
|
|
|
|
|
Recursos, todo lo necesario. |
|
Aquí tenéis todo los
necesario para este proyecto: El Firmware
para el 18F4550, .hex y el .c para el CCS C, |
|
Nota: RRUSB_Complete_zip incluye
también los recursos para los demás métodos de conexión USB descritos en
El USB desencadenado |
|
Enlaces imprescindibles. |
|
|
|
|
Esta página se modificó el 27/12/2008
|