Control de dispositivos a través del módulo USB del PIC18F45/2550

Les traigo ejemplos de control del puerto USB que traen de fábrica los PIC´s de la serie 18Fxx5x. Para esto me he basado en ejemplos encontrados en la red.
Los ejemplos que iré desarrollando van aplicados a las clases CDC (Comunication device class) y el control mediante la API de Windows proporcionada por Microchip mpusbapi.dll (bulk transfer).

El primer ejemplo establece una comunicación bidireccional con la PC, a través de la clase CDC.
Por lo tanto cuando conectemos nuestro PIC (18F2550), aparecerá en el administrador de dispositivos un puerto serie que podemos controlar desde una aplicación programada previamente en un lenguaje como el Visual Basic 6.0.

El firmware del PIC, lo he programado en C de CCS.
El código fuente es el siguiente:
PHP:
// Ejercicio Nº1: Genera un COM virtual y se comunica bidireccionalmente con el a través del PIC18F2550.

#include <18F2550.h> // Definición de registros internos.

#fuses HSPLL,NOMCLR,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN,NOPBADEN

// Fuses utilizados:
/*
HSPLL: utilizamos un cristal HS de alta velocidad, en conjunto con el PLL para generar los 48Mhz.
NOMCLR: Utilizamos reset por software, y dejamos el pin 1 del micro como entrada/salida digital.
NOWDT: No utilizamos el perro guardían.
NOPROTECT: Desactivamos la protección de código.
NOLVP: Desactivamos la programación a bajo voltaje.
NODEBUG: No entramos al modo debug.
USBDIV: signfica que el clock del usb se tomará del PLL/2 = 96Mhz/2 = 48Mhz.
PLL5: significa que el PLL prescaler dividirá en 5 la frecuencia del cristal. para HS = 20Mhz/5 = 4Mhz.
CPUDIV1: El PLL postscaler decide la división en 2 de la frecuencia de salida del PLL de 96MHZ, si queremos 48MHZ, lo dejamos como está.
VREGEN: habilita el regulador de 3.3 volts que usa el módulo USB
*/

#use delay(clock=48000000) // Frecuencia máxima de trabajo.

#include "usb_cdc.h" // Descripción de funciones del USB.
#include "usb_desc_cdc.h" // Descriptores del dispositivo USB.

void main() {
   usb_cdc_init(); // Configuramos al puerto virtual.
   usb_init(); // Inicializamos el stack USB.
   while(!usb_cdc_connected()) {} 
   // espera a detectar una transmisión de la PC (Set_Line_Coding).
   do{
      usb_task();
      if (usb_enumerated()){  // Espera a que el dispositivo sea enumerado por el host.
         if(usb_cdc_kbhit()){ // En espera de nuevos caracteres en el buffer de recepción.
            if(usb_cdc_getc()=='x'){ //¿lo que llegó fué el caracter x?
               printf(usb_cdc_putc, "Se recibe el caracter x.\n\r"); 
               //si, entonces envía una cadena hacia el PC
             }
            if(usb_cdc_getc()=='a'){ //¿lo que llegó fué el caracter a?
               printf(usb_cdc_putc, "Se recibe el caracter a.\n\r");
               //si, entonces envía una cadena hacia el PC               
             }
         }
        }
       }while (TRUE); // bucle infinito.
}
Las librerías usb_desc_cdc.h y usb_cdc.h son las que me permiten comunicar al pic por USB 2.0.
Las mismas están configuradas para que aparezca mi nombre de compañía, (ficticio) nombre de la placa, etc.
También se encuentran configurados los VID y PID para que la PC enumere y enlace al código dentro del PIC con los drivers de la PC.
PHP:
/////////////////////////////////////////////////////////////////////////
////                                                                
////                            usb_cdc.h                           
////                                                                 
//// Library for adding a virtual COM port on your PC over USB using 
//// the standard Communication Device Class (CDC) specification.    
//// Including this file in your code will add all USB code,       
//// interrupts, descriptors and handlers required.  No other        
//// modifications need to be made.                                  
////                                                                 
//// This library creates a virtual RS232 link between the PC and    
//// the PIC, therefore the library provided will be familiar to     
//// anyone with standard UART stream I/O:                         
////                                                                 
//// usb_cdc_kbhit() - Returns TRUE if there is one or more          
////      character received and waiting in the receive buffer.      
////                                                             
//// usb_cdc_getc() - Gets a character from the receive buffer.  If  
////      there is no data in the receive buffer it will wait until  
////      there is data in the receive buffer.  If you do not want   
////      to wait in an infinit loop, use usb_cdc_kbhit() first to  
////      check if there is data before calling usb_cdc_getc().     
////                                                               
//// usb_cdc_putc(char c) - Puts a character into the transmit      
////      buffer.  If the transmit buffer is full it will wait until 
////      the transmit buffer is not full before putting the char    
////      into the transmit buffer.  The transmit buffer is read by  
////      the PC very quickly, and therefore the buffer should only  
////      be full for a few milli-seconds.  If you are concerned     
////      and don't want to be stuck in a long or infinite loop,     
////      use usb_cdc_putready() to see if there is space in the    
////      transmit buffer before putting data into the transmit    
////      buffer.                                                 
////                                                                
//// usb_cdc_putready() - Returns TRUE if there is room left in the  
////      transmit buffer for another character.           
////                                                                 
//// usb_cdc_connected() - Returns TRUE if we received a            
////      Set_Line_Coding.  On most serial terminal programs (such   
////      as Hyperterminal), they will send a Set_Line_Coding        
////      message when the program starts and it opens the virtual   
////      COM port.  This is a simple way to determine if the PC   
////      is ready to display data on a serial terminal program,    
////      but is not garaunteed to work all the time or on other     
////      terminal programs.                                    
////                                                                 
//// usb_cdc_putc_fast(char c) - Similar to usb_cdc_putc(), except   
////      if the transmit buffer is full it will skip the char.    
////                                                           
//// usb_cdc_line_coding - A structure used for Set_Line_Coding and  
////       Get_Line_Coding.  Most of the time you can ignore this.   
////                                                             
//// usb_cdc_break - If the PC has sent a break command, this will   
////       hold the break time (in milli-seconds).  If the PC sends  
////       a value of 0xFFFF the device is supposed to hold the      
////       break until it sends a value of 0                      
////                                                               
//// usb_cdc_carrier - Where Set_Control_Line_State value is stored. 
////       Of most relevance is the field dte_present, which is the  
////       DTR setting.                                          
////                                                               
//// The following functions are also provided, and are ports of the
//// I/O functions in input.c.  See input.c and the CCS manual for   
//// documentation:                                                 
////   get_float_usb() - Read a float number from the user          
////   get_long_usb() - Read a long number from the user             
////   get_int_usb() - Read an integer number from the user          
////   get_string_usb(char *s, int max) - Read a string from the user. 
////   gethex_usb() - Read a byte, in HEX, from the user             
////   gethex1_usb() - Read a HEX character                          
////                                                                 
//// This driver will load all the rest of the USB code, and a set  
//// of descriptors that will properly describe a CDC device for a  
//// virtual COM port (usb_desc_cdc.h)                               
////                                                                 
//// An .INF file is provided (cdc_NTXP.inf) that will load the      
//// standard CDC drivers for a virtual COM port in Windows          
//// NT/2000/XP and above.  Unfortunately we do not provide an .inf  
//// file for Windows 98 and ME.                                     
////                                                                 
/////////////////////////////////////////////////////////////////////////
////                                                                 
//// VERSION HISTORY                                                 
////                                                                 
//// October 27th, 2005: Changed the way incoming packets are        
////               handled in that CDC driver will not flush         
////               endpoint until user has handled all data.  This   
////               will prevent overflows as the USB will NAK       
////               incoming packets until it is ready to receive     
////               more.                                             
////            When using 18F4550 family, the RX buffer is         
////               mapped directly to the endpoint buffer - this    
////               saves a chunk of RAM.                           
////            When using the 18F4550 family, you can increase   
////               the TX and RX size over 64 bytes.                
////            No longer send 0len packets in the TBE interrupt.   
////            Hopefully fixed bugs that caused random crashes    
////               if you tried sending more than 64 bytes.          
////                                                                
//// July 6th, 2005: Global interrupts disabled when writing to TX   
////                   buffer.                                    
////                                                            
//// July 1st, 2005: Initial Release.                         
////                                                             
/////////////////////////////////////////////////////////////////////////
////        (C) Copyright 1996,2005 Custom Computer Services         
//// This source code may only be used by licensed users of the CCS  
//// C compiler.  This source code may only be distributed to other  
//// licensed users of the CCS C compiler.  No other use,           
//// reproduction or distribution is permitted without written       
//// permission.  Derivative programs created using this software   
//// in object code form are not restricted in any way.             
/////////////////////////////////////////////////////////////////////////


//api for the user:
#define usb_cdc_kbhit() (usb_cdc_get_buffer_status.got)
#define usb_cdc_putready() (usb_cdc_put_buffer_nextin<USB_CDC_DATA_IN_SIZE)
#define usb_cdc_connected() (usb_cdc_got_set_line_coding)
void usb_cdc_putc_fast(char c);
char usb_cdc_getc(void);
void usb_cdc_putc(char c);

//input.c ported to use CDC:
float get_float_usb();
signed long get_long_usb();
signed int get_int_usb();
void get_string_usb(char* s, int max);
BYTE gethex_usb();
BYTE gethex1_usb();

//functions automatically called by USB handler code
void usb_isr_tkn_cdc(void);
void usb_cdc_init(void);
void usb_isr_tok_out_cdc_control_dne(void);
void usb_isr_tok_in_cdc_data_dne(void);
void usb_isr_tok_out_cdc_data_dne(void);

void usb_cdc_flush_out_buffer(void);

//Tells the CCS PIC USB firmware to include HID handling code.
#DEFINE USB_HID_DEVICE  FALSE
#DEFINE USB_CDC_DEVICE  TRUE

#define USB_CDC_COMM_IN_ENDPOINT       1
#define USB_CDC_COMM_IN_SIZE           8
#define USB_EP1_TX_ENABLE  USB_ENABLE_INTERRUPT
#define USB_EP1_TX_SIZE  USB_CDC_COMM_IN_SIZE

//pic to pc endpoint config
#define USB_CDC_DATA_IN_ENDPOINT       2
#define USB_CDC_DATA_IN_SIZE           64
#define USB_EP2_TX_ENABLE  USB_ENABLE_BULK
#define USB_EP2_TX_SIZE  USB_CDC_DATA_IN_SIZE

//pc to pic endpoint config
#define USB_CDC_DATA_OUT_ENDPOINT       2
#define USB_CDC_DATA_OUT_SIZE           64
#define USB_EP2_RX_ENABLE  USB_ENABLE_BULK
#define USB_EP2_RX_SIZE  USB_CDC_DATA_OUT_SIZE

/////////////////////////////////////////////////////////////////////////////
//
// Include the CCS USB Libraries.  See the comments at the top of these
// files for more informaciónrmation
//
/////////////////////////////////////////////////////////////////////////////
#ifndef __USB_PIC_PERIF__
#define __USB_PIC_PERIF__    1
#endif

#if __USB_PIC_PERIF__
 #if defined(__PCM__)
  #error CDC requires bulk mode!  PIC16C7x5 does not have bulk mode
 #else
  #include <pic18_usb.h>   //Microchip 18Fxx5x hardware layer for usb.c
 #endif
#else
 #include <usbn960x.c>   //National 960x hardware layer for usb.c
#endif
#include <usb_desc_cdc.h>    //USB Configuration and Device descriptors for this UBS device
#include <usb.c>        //handles usb setup tokens and get descriptor reports

struct {
        int32   dwDTERrate;   //data terminal rate, in bits per second
        int8    bCharFormat;  //num of stop bits (0=1, 1=1.5, 2=2)
        int8    bParityType;  //parity (0=none, 1=odd, 2=even, 3=mark, 4=space)
        int8    bDataBits;    //data bits (5,6,7,8 or 16)
} usb_cdc_line_coding;

//length of time, in ms, of break signal as we received in a SendBreak message.
//if ==0xFFFF, send break signal until we receive a 0x0000.
int16 usb_cdc_break;

int8 usb_cdc_encapsulated_cmd[8];

int8 usb_cdc_put_buffer[USB_CDC_DATA_IN_SIZE];
int1 usb_cdc_put_buffer_free;
#if USB_CDC_DATA_IN_SIZE>=0x100
 int16 usb_cdc_put_buffer_nextin=0;
// int16 usb_cdc_last_data_packet_size;
#else
 int8 usb_cdc_put_buffer_nextin=0;
// int8 usb_cdc_last_data_packet_size;
#endif

struct {
   int1 got;
  #if USB_CDC_DATA_OUT_SIZE>=0x100
   int16 len;
   int16 index;
  #else
   int8 len;
   int8 index;
  #endif
} usb_cdc_get_buffer_status;

int8 usb_cdc_get_buffer_status_buffer[USB_CDC_DATA_OUT_SIZE];
#if (defined(__PIC__))
 #if __PIC__
  //#locate usb_cdc_get_buffer_status_buffer=0x500+(2*USB_MAX_EP0_PACKET_LENGTH)+USB_CDC_COMM_IN_SIZE
  #if USB_MAX_EP0_PACKET_LENGTH==8
     #locate usb_cdc_get_buffer_status_buffer=0x500+24
  #elif USB_MAX_EP0_PACKET_LENGTH==64
     #locate usb_cdc_get_buffer_status_buffer=0x500+136
  #else
   #error CCS BUG WONT LET ME USE MATH IN LOCATE
  #endif
 #endif
#endif

int1 usb_cdc_got_set_line_coding;

struct  {
   int1 dte_present; //1=DTE present, 0=DTE not present
   int1 active;      //1=activate carrier, 0=deactivate carrier
   int reserved:6;
} usb_cdc_carrier;

enum {USB_CDC_OUT_NOTHING=0, USB_CDC_OUT_COMMAND=1, USB_CDC_OUT_LINECODING=2, USB_CDC_WAIT_0LEN=3} __usb_cdc_state=0;

#byte INTCON=0xFF2
#bit INT_GIE=INTCON.7

//handle OUT token done interrupt on endpoint 0 [read encapsulated cmd and line coding data]
void usb_isr_tok_out_cdc_control_dne(void) {
   debug_usb(debug_putc,"CDC %X ",__usb_cdc_state);

   switch (__usb_cdc_state) {
      //printf(putc_tbe,"@%X@\r\n", __usb_cdc_state);
      case USB_CDC_OUT_COMMAND:
         //usb_get_packet(0, usb_cdc_encapsulated_cmd, 8);
         memcpy(usb_cdc_encapsulated_cmd, usb_ep0_rx_buffer,8);
        #if USB_MAX_EP0_PACKET_LENGTH==8
         __usb_cdc_state=USB_CDC_WAIT_0LEN;
         usb_request_get_data();
        #else
         usb_put_0len_0();
         __usb_cdc_state=0;
        #endif
         break;

    #if USB_MAX_EP0_PACKET_LENGTH==8
      case USB_CDC_WAIT_0LEN:
         usb_put_0len_0();
         __usb_cdc_state=0;
         break;
    #endif

      case USB_CDC_OUT_LINECODING:
         //usb_get_packet(0, &usb_cdc_line_coding, 7);
         //printf(putc_tbe,"\r\n!GSLC FIN!\r\n");
         memcpy(&usb_cdc_line_coding, usb_ep0_rx_buffer,7);
         __usb_cdc_state=0;
         usb_put_0len_0();
         break;

      default:
         __usb_cdc_state=0;
         usb_init_ep0_setup();
         break;
   }
}

//handle IN token on 0 (setup packet)
void usb_isr_tkn_cdc(void) {
   //make sure the request goes to a CDC interface
   if ((usb_ep0_rx_buffer[4] == 1) || (usb_ep0_rx_buffer[4] == 0)) {
      //printf(putc_tbe,"!%X!\r\n", usb_ep0_rx_buffer[1]);
      switch(usb_ep0_rx_buffer[1]) {
         case 0x00:  //send_encapsulated_command
            __usb_cdc_state=USB_CDC_OUT_COMMAND;
            usb_request_get_data();
            break;

         case 0x01:  //get_encapsulated_command
            memcpy(usb_ep0_tx_buffer, usb_cdc_encapsulated_cmd, 8);
            usb_request_send_response(usb_ep0_rx_buffer[6]);  //send wLength bytes
            break;

         case 0x20:  //set_line_coding
            debug_usb(debug_putc,"!GSLC!");
            __usb_cdc_state=USB_CDC_OUT_LINECODING;
            usb_cdc_got_set_line_coding=TRUE;
            usb_request_get_data();
            break;

         case 0x21:  //get_line_coding
            memcpy(usb_ep0_tx_buffer, &usb_cdc_line_coding, sizeof(usb_cdc_line_coding));
            usb_request_send_response(sizeof(usb_cdc_line_coding)); //send wLength bytes
            break;

         case 0x22:  //set_control_line_state
            usb_cdc_carrier=usb_ep0_rx_buffer[2];
            usb_put_0len_0();
            break;

         case 0x23:  //send_break
            usb_cdc_break=make16(usb_ep0_rx_buffer[2],usb_ep0_rx_buffer[3]);
            usb_put_0len_0();
            break;

         default:
            usb_request_stall();
            break;
      }
   }
}

//handle OUT token done interrupt on endpoint 3 [buffer incoming received chars]
void usb_isr_tok_out_cdc_data_dne(void) {
   usb_cdc_get_buffer_status.got=TRUE;
   usb_cdc_get_buffer_status.index=0;
#if (defined(__PIC__))
   #if __PIC__
    usb_cdc_get_buffer_status.len=usb_rx_packet_size(USB_CDC_DATA_OUT_ENDPOINT);
   #else
    usb_cdc_get_buffer_status.len=usb_get_packet_buffer(
       USB_CDC_DATA_OUT_ENDPOINT,&usb_cdc_get_buffer_status_buffer[0],USB_CDC_DATA_OUT_SIZE);
   #endif
#else
   usb_cdc_get_buffer_status.len=usb_get_packet_buffer(
      USB_CDC_DATA_OUT_ENDPOINT,&usb_cdc_get_buffer_status_buffer[0],USB_CDC_DATA_OUT_SIZE);
#endif
}

//handle IN token done interrupt on endpoint 2 [transmit buffered characters]
void usb_isr_tok_in_cdc_data_dne(void) {
   if (usb_cdc_put_buffer_nextin) {
      usb_cdc_flush_out_buffer();
   }
   //send a 0len packet if needed
//   else if (usb_cdc_last_data_packet_size==USB_CDC_DATA_IN_SIZE) {
//      usb_cdc_last_data_packet_size=0;
//      printf(putc_tbe, "FL 0\r\n");
//      usb_put_packet(USB_CDC_DATA_IN_ENDPOINT,0,0,USB_DTS_TOGGLE);
//   }
   else {
      usb_cdc_put_buffer_free=TRUE;
      //printf(putc_tbe, "FL DONE\r\n");
   }
}

void usb_cdc_flush_out_buffer(void) {
   if (usb_cdc_put_buffer_nextin) {
      usb_cdc_put_buffer_free=FALSE;
      //usb_cdc_last_data_packet_size=usb_cdc_put_buffer_nextin;
      //printf(putc_tbe, "FL %U\r\n", usb_cdc_put_buffer_nextin);
      usb_put_packet(USB_CDC_DATA_IN_ENDPOINT,usb_cdc_put_buffer,usb_cdc_put_buffer_nextin,USB_DTS_TOGGLE);
      usb_cdc_put_buffer_nextin=0;
   }
}

void usb_cdc_init(void) {
   usb_cdc_line_coding.dwDTERrate=9600;
   usb_cdc_line_coding.bCharFormat=0;
   usb_cdc_line_coding.bParityType=0;
   usb_cdc_line_coding.bDataBits=8;
   (int8)usb_cdc_carrier=0;
   usb_cdc_got_set_line_coding=FALSE;
   usb_cdc_break=0;
   usb_cdc_put_buffer_nextin=0;
   usb_cdc_get_buffer_status.got=0;
   usb_cdc_put_buffer_free=TRUE;
}

////////////////// END USB CONTROL HANDLING //////////////////////////////////

////////////////// BEGIN USB<->RS232 CDC LIBRARY /////////////////////////////

char usb_cdc_getc(void) {
   char c;

   while (!usb_cdc_kbhit()) {}

   c=usb_cdc_get_buffer_status_buffer[usb_cdc_get_buffer_status.index++];
   if (usb_cdc_get_buffer_status.index >= usb_cdc_get_buffer_status.len) {
      usb_cdc_get_buffer_status.got=FALSE;
      usb_flush_out(USB_CDC_DATA_OUT_ENDPOINT, USB_DTS_TOGGLE);
   }

   return(c);
}

void usb_cdc_putc_fast(char c) {
   int1 old_gie;

   //disable global interrupts
   old_gie=INT_GIE;
   INT_GIE=0;

   if (usb_cdc_put_buffer_nextin >= USB_CDC_DATA_IN_SIZE) {
      usb_cdc_put_buffer_nextin=USB_CDC_DATA_IN_SIZE-1;  //we just overflowed the buffer!
   }
   usb_cdc_put_buffer[usb_cdc_put_buffer_nextin++]=c;

   //renable global interrupts
   INT_GIE=old_gie;

   /*
   if (usb_tbe(USB_CDC_DATA_IN_ENDPOINT)) {
      if (usb_cdc_put_buffer_nextin)
         usb_cdc_flush_out_buffer();
   }
   */
   if (usb_cdc_put_buffer_free) {
      usb_cdc_flush_out_buffer();
   }
}

void usb_cdc_putc(char c) {
   while (!usb_cdc_putready()) {
      if (usb_cdc_put_buffer_free) {
         usb_cdc_flush_out_buffer();
      }
      //delay_ms(500);
      //printf(putc_tbe,"TBE=%U CNT=%U LST=%U\r\n",usb_tbe(USB_CDC_DATA_IN_ENDPOINT), usb_cdc_put_buffer_nextin, usb_cdc_last_data_packet_size);
   }
   usb_cdc_putc_fast(c);
}

#include <ctype.h>

BYTE gethex1_usb() {
   char digit;

   digit = usb_cdc_getc();

   usb_cdc_putc(digit);

   if(digit<='9')
     return(digit-'0');
   else
     return((toupper(digit)-'A')+10);
}

BYTE gethex_usb() {
   int lo,hi;

   hi = gethex1_usb();
   lo = gethex1_usb();
   if(lo==0xdd)
     return(hi);
   else
     return( hi*16+lo );
}

void get_string_usb(char* s, int max) {
   int len;
   char c;

   --max;
   len=0;
   do {
     c=usb_cdc_getc();
     if(c==8) {  // Backspace
        if(len>0) {
          len--;
          usb_cdc_putc(c);
          usb_cdc_putc(' ');
          usb_cdc_putc(c);
        }
     } else if ((c>=' ')&&(c<='~'))
       if(len<max) {
         s[len++]=c;
         usb_cdc_putc(c);
       }
   } while(c!=13);
   s[len]=0;
}


// stdlib.h is required for the ato_ conversions
// in the following functions
#ifdef _STDLIB

signed int get_int_usb() {
  char s[5];
  signed int i;

  get_string_usb(s, 5);

  i=atoi(s);
  return(i);
}

signed long get_long_usb() {
  char s[7];
  signed long l;

  get_string_usb(s, 7);
  l=atol(s);
  return(l);
}

float get_float_usb() {
  char s[20];
  float f;

  get_string_usb(s, 20);
  f = atof(s);
  return(f);
}

#endif
La librería de descriptores USB. (Los que me dan el nombre del dispositivo)
PHP:
///////////////////////////////////////////////////////////////////////////
////                         usb_desc_cdc.h                       
////                                                                  
//// An example set of device / configuration descriptors for use with 
//// CCS's CDC Virtual COM Port driver (see usb_cdc.h)
////                                                                  
//// Two examples are provided:                                        
////      ex_usb_serial.c                                           
////      ex_usb_serial2.c                                           
////                                                                 
///////////////////////////////////////////////////////////////////////////
////                                                                   
//// Version History:                                               
////                                                                   
//// 10/28/05:                                                     
////    Bulk endpoint sizes updated to allow more than 255 byte        
////    packets.                                                      
////    Changed device to USB 1.10                                  
///////////////////////////////////////////////////////////////////////////
////        (C) Copyright 1996,2005 Custom Computer Services           
//// This source code may only be used by licensed users of the CCS    
//// C compiler.  This source code may only be distributed to other   
//// licensed users of the CCS C compiler.  No other use,              
//// reproduction or distribution is permitted without written        
//// permission.  Derivative programs created using this software      
//// in object code form are not restricted in any way.               
///////////////////////////////////////////////////////////////////////////

#IFNDEF __USB_DESCRIPTORS__
#DEFINE __USB_DESCRIPTORS__

#include <usb.h>


//////////////////////////////////////////////////////////////////
///
///   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      67  //config+interface+class+endpoint+endpoint (2 endpoints)

   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
         2, //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 0 (comm class interface)
         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
         1, //number of endpoints   ==13
         0x02, //class code, 02 = Comm Interface Class     ==14
         0x02, //subclass code, 2 = Abstract     ==15
         0x01, //protocol code, 1 = v.25ter      ==16
         0x00, //index of string descriptor for interface      ==17

   //class descriptor [functional header]
         5, //length of descriptor    ==18
         0x24, //dscriptor type (0x24 == )      ==19
         0, //sub type (0=functional header) ==20
         0x10,0x01, //      ==21,22 //cdc version

   //class descriptor [acm header]
         4, //length of descriptor    ==23
         0x24, //dscriptor type (0x24 == )      ==24
         2, //sub type (2=ACM)   ==25
         2, //capabilities    ==26  //we support Set_Line_Coding, Set_Control_Line_State, Get_Line_Coding, and the notification Serial_State.

   //class descriptor [union header]
         5, //length of descriptor    ==27
         0x24, //dscriptor type (0x24 == )      ==28
         6, //sub type (6=union)    ==29
         0, //master intf     ==30  //The interface number of the Communication or Dat a Cl ass interface, designated as the masteror controlling interface for the union.
         1, //save intf0      ==31  //Interface number of first slave or associated interface in the union. *

   //class descriptor [call mgmt header]
         5, //length of descriptor    ==32
         0x24, //dscriptor type (0x24 == )      ==33
         1, //sub type (1=call mgmt)   ==34
         0, //capabilities          ==35  //device does not handle call management itself
         1, //data interface        ==36  //interface number of data class interface

   //endpoint descriptor
         USB_DESC_ENDPOINT_LEN, //length of descriptor                   ==37
         USB_DESC_ENDPOINT_TYPE, //constant ENDPOINT (ENDPOINT 0x05)          ==38
         USB_CDC_COMM_IN_ENDPOINT | 0x80, //endpoint number and direction
         0x03, //transfer type supported (0x03 is interrupt)         ==40
         USB_CDC_COMM_IN_SIZE,0x00, //maximum packet size supported                  ==41,42
         250,  //polling interval, in ms.  (cant be smaller than 10)      ==43

   //interface descriptor 1 (data class interface)
         USB_DESC_INTERFACE_LEN, //length of descriptor      =44
         USB_DESC_INTERFACE_TYPE, //constant INTERFACE (INTERFACE 0x04)       =45
         0x01, //number defining this interface (IF we had more than one interface)    ==46
         0x00, //alternate setting     ==47
         2, //number of endpoints   ==48
         0x0A, //class code, 0A = Data Interface Class     ==49
         0x00, //subclass code      ==50
         0x00, //protocol code      ==51
         0x00, //index of string descriptor for interface      ==52

   //endpoint descriptor
         USB_DESC_ENDPOINT_LEN, //length of descriptor                   ==60
         USB_DESC_ENDPOINT_TYPE, //constant ENDPOINT (ENDPOINT 0x05)          ==61
         USB_CDC_DATA_OUT_ENDPOINT, //endpoint number and direction (0x02 = EP2 OUT)       ==62
         0x02, //transfer type supported (0x02 is bulk)         ==63
//         make8(USB_CDC_DATA_OUT_SIZE,0),make8(USB_CDC_DATA_OUT_SIZE,1), //maximum packet size supported                  ==64, 65
         USB_CDC_DATA_OUT_SIZE & 0xFF, (USB_CDC_DATA_OUT_SIZE >> 8) & 0xFF, //maximum packet size supported                  ==64, 65
         250,  //polling interval, in ms.  (cant be smaller than 10)      ==66

   //endpoint descriptor
         USB_DESC_ENDPOINT_LEN, //length of descriptor                   ==53
         USB_DESC_ENDPOINT_TYPE, //constant ENDPOINT (ENDPOINT 0x05)          ==54
         USB_CDC_DATA_IN_ENDPOINT | 0x80, //endpoint number and direction (0x82 = EP2 IN)       ==55
         0x02, //transfer type supported (0x02 is bulk)         ==56
//         make8(USB_CDC_DATA_IN_SIZE,0),make8(USB_CDC_DATA_IN_SIZE,1), //maximum packet size supported                  ==57, 58
         USB_CDC_DATA_IN_SIZE & 0xFF, (USB_CDC_DATA_IN_SIZE >> 8) & 0xFF, //maximum packet size supported                  ==64, 65
         250,  //polling interval, in ms.  (cant be smaller than 10)      ==59
   };

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

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

   //define how many interfaces there are per config.  [0] is the first config, etc.
   const char USB_NUM_INTERFACES[USB_NUM_CONFIGURATIONS]={2};

   //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][USB_MAX_NUM_INTERFACES][4]=
   {
   //config 1
      //interface 0
         //class 1-4
         18,23,27,32,
      //interface 1
         //no classes for this interface
         0xFFFF,0xFFFF,0xFFFF,0xFFFF
   };

   #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[USB_DESC_DEVICE_LEN] ={
      //starts of with device configuration. only one possible
         USB_DESC_DEVICE_LEN, //the length of this report   ==0
         0x01, //the constant DEVICE (DEVICE 0x01)  ==1
         0x10,0x01, //usb version in bcd  ==2,3
         0x02, //class code. 0x02=Communication Device Class ==4
         0x00, //subclass code ==5
         0x00, //protocol code ==6
         USB_MAX_EP0_PACKET_LENGTH, //max packet size for endpoint 0. (SLOW SPEED SPECIFIES 8) ==7
         08,0x04, //vendor id (0x04D8 is Microchip, or is it 0x0461 ?)  ==8,9
         0x0B,0x00, //product id   ==10,11
         0x00,0x01, //device release number  ==12,13
         0x01, //index of string description of manufacturer. therefore we point to string_1 array (see below)  ==14
         0x02, //index of string descriptor of the product  ==15
         0x00, //index of string descriptor of serial number  ==16
         USB_NUM_CONFIGURATIONS  //number of possible configurations  ==17
   };


//////////////////////////////////////////////////////////////////
///
///   start string descriptors
///   String 0 is a special language string, and must be defined.  People in U.S.A. can leave this alone.
///
///   You must define the length else get_next_string_character() will not see the string
///   Current code only supports 10 strings (0 thru 9)
///
//////////////////////////////////////////////////////////////////

//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.
char USB_STRING_DESC_OFFSET[]={0,4,12};

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)
         'C',0,
         'C',0,
         'S',0,
   //string 2
         24, //length of string index
         USB_DESC_STRING_TYPE, //descriptor type 0x03 (STRING)
         'C',0,
         'D',0,
         'C',0,
         '_',0,
         'U',0,
         'S',0,
         'B',0,
         '_',0,
         'P',0,
         'I',0,
         'C',0,

};

#ENDIF
Para la PC el software lo escribí en Visual Basic v6.0, ya que me pareció más fácil para entender.
Igual el programa puede ser migrado a visual C# o algún otro lenguaje de alto nivel.
En caso de no tener dichos lenguajes para probar el circuito se puede utilizar el hiperterminal de Windows.

El código fuente del ejecutable es el siguiente:
PHP:
Option Explicit

Private Sub Caracter1_Click()
    If MSComm1.PortOpen = False Then
        MSComm1.PortOpen = True
    End If
    MSComm1.Output = "x"
End Sub

Private Sub Caracter2_Click()
    If MSComm1.PortOpen = False Then
        MSComm1.PortOpen = True
    End If
    MSComm1.Output = "a"
End Sub

Private Sub conectar_Click()
'comprueva que el puerto este cerrado para poder abrirlo
    If MSComm1.PortOpen = False Then
        'determina el puerto que hemos seleccionado.
        If COM_sel.ListIndex = 0 Then
            MSComm1.CommPort = 1
            End If
        If COM_sel.ListIndex = 1 Then
            MSComm1.CommPort = 2
            End If
        If COM_sel.ListIndex = 2 Then
            MSComm1.CommPort = 3
            End If
        If COM_sel.ListIndex = 3 Then
            MSComm1.CommPort = 4
            End If
        If COM_sel.ListIndex = 4 Then
            MSComm1.CommPort = 5
            End If
        If COM_sel.ListIndex = 5 Then
            MSComm1.CommPort = 6
            End If
        If COM_sel.ListIndex = 6 Then
            MSComm1.CommPort = 7
            End If
        If COM_sel.ListIndex = 7 Then
            MSComm1.CommPort = 8
            End If
        If COM_sel.ListIndex = 8 Then
            MSComm1.CommPort = 9
            End If
        If COM_sel.ListIndex = 9 Then
            MSComm1.CommPort = 10
            End If
        If COM_sel.ListIndex = 10 Then
            MSComm1.CommPort = 11
            End If
            End If
            
MSComm1.OutBufferSize = 1 'tamaño del dato a transmitir.
    MSComm1.InBufferSize = 23
    MSComm1.InputMode = comInputModeText 'los datos se recuperan en modo texto.
    MSComm1.InputLen = 23  ' Buffer de entrada.
    MSComm1.PortOpen = True
    MSComm1.RThreshold = 23 'son 23 caracteres.
End Sub

Private Sub Form_Load()
COM_sel.AddItem "COM1"
COM_sel.AddItem "COM2"
COM_sel.AddItem "COM3"
COM_sel.AddItem "COM4"
COM_sel.AddItem "COM5"
COM_sel.AddItem "COM6"
COM_sel.AddItem "COM7"
COM_sel.AddItem "COM8"
COM_sel.AddItem "COM9"
COM_sel.AddItem "COM10"
COM_sel.AddItem "COM11"
End Sub

Private Sub Form_Unload(Cancel As Integer)
If MSComm1.PortOpen = True Then
    MSComm1.PortOpen = False
End If
End Sub

Private Sub MSComm1_OnComm()
Dim InBuff As String
Select Case MSComm1.CommEvent
    Case comEvReceive
    InBuff = MSComm1.Input
    Debug.Print InBuff
    Texto.Text = ""
    Texto.Text = Left$(InBuff, 23)  ' se recorta los caracteres basura
    MSComm1.PortOpen = False  'cierra el puerto y vacia el buffer
End Select
End Sub
Ejemplo y Actualización:

Manual USB - HID usando Visual C#
 

Adjuntos

  • ejercicio_n1_174.rar
    47.8 KB · Visitas: 7,934
  • Control de dispositivos por USB [ HID + Visual C# ].part1.rar
    5 MB · Visitas: 354
  • Control de dispositivos por USB [ HID + Visual C# ].part2.rar
    5 MB · Visitas: 337
  • Control de dispositivos por USB [ HID + Visual C# ].part3.rar
    5 MB · Visitas: 331
  • Control de dispositivos por USB [ HID + Visual C# ].part4.rar
    4.8 MB · Visitas: 315
Última edición por un moderador:
meta , si tenés tiempo y ganas te pediría si por favor podrías pasar el ejecutable del programa para la pc a otro lenguaje como visual c# que es el que vos tenés más experiencia.
 
El segundo ejemplo establece una comunicación bidireccional con la PC, a través de la clase CDC. La diferencia con respecto al ejemplo anterior es que esta véz se controla un LED conectado al puerto B del PIC y también se detecta si el puerto usb está conectado o no indicándolo con un led.
También detecta cuando el host (pc) enumera al dispositivo (pic) encendiendo un LED verde , cuando el host no ha enumerado al pic prende un led rojo.


El firmware del PIC, lo he programado en C de CCS. (está lo más explicado posible)
el código es el siguiente:
Código:
// Programa: 
/* Detecta si el host envía datos al PIC, mediante las 
   funciones:
    usb_enumerated()
    usb_cdc_kbhit()
    usb_cdc_getc()
    usb_cdc_connected()
*/

#include <18F2550.h> // Definición de registros internos.
#fuses HSPLL,MCLR,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN,NOPBADEN
// Fuses utilizados:
/*
HSPLL: utilizamos un cristal HS de alta velocidad, en conjunto con el PLL para generar los 48Mhz.
NOMCLR: Utilizamos reset por software.
NOWDT: No utilizamos el perro guardían.
NOPROTECT: Desactivamos la protección de código.
NOLVP: Desactivamos la programación a bajo voltaje.
NODEBUG: No entramos al modo debug.
USBDIV: signfica que el clock del usb se tomará del PLL/2 = 96Mhz/2 = 48Mhz.
PLL5: significa que el PLL prescaler dividirá en 5 la frecuencia del cristal. para HS = 20Mhz/5 = 4Mhz.
CPUDIV1: El PLL postscaler decide la división en 2 de la frecuencia de salida del PLL de 96MHZ, si queremos 48MHZ, lo dejamos como está.
VREGEN: habilita el regulador de 3.3 volts que usa el módulo USB.
NOPBADEN: No utilizamos las entradas analógicas del puerto B.
*/
#use delay(clock=48000000) // Frecuencia máxima de trabajo.
#include "usb_cdc.h" // Descripción de funciones del USB.
#include "usb_desc_cdc.h" // Descriptores del dispositivo USB.

// Programa principal.

void main() {
usb_cdc_init(); // Funciones necesarias para iniciar el módulo USB.
usb_init(); // Funciones necesarias para iniciar el módulo USB.
while(!usb_cdc_connected()) { // Mientras el USB no esté conectado.
output_high(PIN_B0); // Función USB no detectada. (Enciende LED rojo)
output_low(PIN_B1);  // (Apaga LED verde)
}
output_high(PIN_B1); // Función USB detectada.    (Enciende LED verde)
output_low(PIN_B0); //  (Apaga LED rojo)
do{
      usb_task();
      if (usb_enumerated()){ // Si el puerto ya fue enumerado por el host :
      output_high(PIN_B2); // Enciende led de enumeración_OK.
      if(usb_cdc_kbhit()){ // en espera de nuevo(s) caracter(es) en el buffer.
            if(usb_cdc_getc()=='a'){ // ¿lo que llegó fué el caracter a?
              output_toggle(PIN_B3); // bascula T implementada con la función output_toggle()
                   }
         }
      }
   }while (TRUE); // bucle eterno
}

Las librerías y el driver para el pic son las mismas que para el ejemplo anterior.

el código fuente del ejecutable para la pc:

Código:
Option Explicit
Dim value As Long
Dim bandera As Boolean
Private Sub enviar_Click()
    Timer1.Enabled = False
    If MSComm1.PortOpen = True Then
      MSComm1.Output = "a"
    End If
    Timer1.Enabled = True
End Sub
Private Sub conectar_Click()
'comprueva que el puerto este cerrado para poder abrirlo
    If MSComm1.PortOpen = False Then
        'determina el puerto que hemos seleccionado.
        If puerto.ListIndex = 0 Then
            MSComm1.CommPort = 1
            End If
        If puerto.ListIndex = 1 Then
            MSComm1.CommPort = 2
            End If
        If puerto.ListIndex = 2 Then
            MSComm1.CommPort = 3
            End If
        If puerto.ListIndex = 3 Then
            MSComm1.CommPort = 4
            End If
        If puerto.ListIndex = 4 Then
            MSComm1.CommPort = 5
            End If
        If puerto.ListIndex = 5 Then
            MSComm1.CommPort = 6
            End If
        If puerto.ListIndex = 6 Then
            MSComm1.CommPort = 7
            End If
        If puerto.ListIndex = 7 Then
            MSComm1.CommPort = 8
            End If
        If puerto.ListIndex = 8 Then
            MSComm1.CommPort = 9
            End If
        If puerto.ListIndex = 9 Then
            MSComm1.CommPort = 10
            End If
        If puerto.ListIndex = 10 Then
            MSComm1.CommPort = 11
            End If
            End If
            
MSComm1.OutBufferSize = 1 'tamaño del dato a transmitir.
    MSComm1.PortOpen = True
End Sub

Private Sub Form_Load()
puerto.AddItem "COM1" ' Añadimos diferentes numeraciones para el puerto serie.
puerto.AddItem "COM2"
puerto.AddItem "COM3"
puerto.AddItem "COM4"
puerto.AddItem "COM5"
puerto.AddItem "COM6"
puerto.AddItem "COM7"
puerto.AddItem "COM8"
puerto.AddItem "COM9"
puerto.AddItem "COM10"
puerto.AddItem "COM11"
puerto.ListIndex = 0   ' Configuramos COM1, como predeterminado.
Timer1.Interval = 50
Timer1.Enabled = True 'activamos el ciclo de escan.
End Sub
Private Sub Timer1_Timer()
On Error GoTo Tratamiento_errores
DoEvents
If MSComm1.PortOpen = True Then
    DoEvents
    estado.BackColor = &HFF00&
    Debug.Print "Conectado"
    MSComm1.PortOpen = False
    Exit Sub
Else
    DoEvents
    MSComm1.PortOpen = True
    Exit Sub
End If
Tratamiento_errores:  Debug.Print Err.Number & ": " & Err.Description
     Select Case Err.Number
        Case 8002   'Número de puerto no válido
            DoEvents
           estado.BackColor = &HFF&
        Case 8005 'el puerto ya está abierto
            DoEvents
            estado.BackColor = &HFF0000
        Case 8012 '8012 el dispositivo no está abierto
            DoEvents
            estado.BackColor = &HFF&
        Case 8015
            DoEvents    ' para evitar retardos en bucles
            estado.BackColor = &HFF&
    End Select
End Sub
Private Sub Form_Unload(Cancel As Integer)
If MSComm1.PortOpen = True Then
    MSComm1.PortOpen = False
End If 
End Sub
 

Adjuntos

  • ejercicio_n2_127.rar
    55.4 KB · Visitas: 2,732
Última edición por un moderador:
Moyano Jonathan dijo:
meta , si tenés tiempo y ganas te pediría si por favor podrías pasar el ejecutable del programa para la pc a otro lenguaje como visual c# que es el que vos tenés más experiencia.

No entiendo exactamente a que te refieres. ¿Te refieres que pase tu código fuente del Visual Basic al Visual C#?

Esto podría ayudar.

http://www.developerfusion.com/tools/convert/csharp-to-vb/

EDITO:
Por fin información para aprender USB.
 
y todavía hay más información sobre usb pero habrá que esperar que valla tragando toda la información recopilada y valla posteando los ejemplos.
Con respecto de pasar de un leguaje a otro me queda estudiarme el tuto que hiciste de visual c y ver que sale.
 
Ejemplo n° 3:

Este ejemplo trata sobre conectar/desconectar en caliente el dispositivo del host.

El firmware del pic es el del ejemplo n°2 al igual que las librerías, el esquema y el driver.

El código fuente del programa nuevo es el siguiente:

Código:
Private Sub conectar_Click()
'comprueva que el puerto este cerrado para poder abrirlo
    If MSComm1.PortOpen = False Then
        'determina el puerto que hemos seleccionado.
        If puerto.ListIndex = 0 Then
            MSComm1.CommPort = 1
            End If
        If puerto.ListIndex = 1 Then
            MSComm1.CommPort = 2
            End If
        If puerto.ListIndex = 2 Then
            MSComm1.CommPort = 3
            End If
        If puerto.ListIndex = 3 Then
            MSComm1.CommPort = 4
            End If
        If puerto.ListIndex = 4 Then
            MSComm1.CommPort = 5
            End If
        If puerto.ListIndex = 5 Then
            MSComm1.CommPort = 6
            End If
        If puerto.ListIndex = 6 Then
            MSComm1.CommPort = 7
            End If
        If puerto.ListIndex = 7 Then
            MSComm1.CommPort = 8
            End If
        If puerto.ListIndex = 8 Then
            MSComm1.CommPort = 9
            End If
        If puerto.ListIndex = 9 Then
            MSComm1.CommPort = 10
            End If
        If puerto.ListIndex = 10 Then
            MSComm1.CommPort = 11
            End If
            End If
            
MSComm1.OutBufferSize = 1 'tamaño del dato a transmitir.
MSComm1.PortOpen = True
End Sub

Private Sub Form_Load()
puerto.AddItem "COM1" ' Añadimos diferentes numeraciones para el puerto serie.
puerto.AddItem "COM2"
puerto.AddItem "COM3"
puerto.AddItem "COM4"
puerto.AddItem "COM5"
puerto.AddItem "COM6"
puerto.AddItem "COM7"
puerto.AddItem "COM8"
puerto.AddItem "COM9"
puerto.AddItem "COM10"
puerto.AddItem "COM11"
puerto.ListIndex = 0   ' Configuramos COM1, como predeterminado.
Timer1.Interval = 50
Timer1.Enabled = True 'activamos el ciclo de escan.
End Sub

Private Sub Form_Unload(Cancel As Integer)
    If MSComm1.PortOpen = True Then
        MSComm1.PortOpen = False
    End If
End Sub

Private Sub Timer1_Timer()
Dim a As String
On Error GoTo tratamiento_de_errores
DoEvents
If MSComm1.PortOpen = True Then
    DoEvents
    estado.BackColor = &HFF00&
    Debug.Print "Conectado"
    MSComm1.PortOpen = False
    Exit Sub
Else
    DoEvents
    MSComm1.PortOpen = True
    Exit Sub
End If
tratamiento_de_errores: Debug.Print Err.Number & ": " & Err.Description
     Select Case Err.Number
        Case 8002   'Número de puerto no válido
            DoEvents
           estado.BackColor = &HFF&
        Case 8005 'el puerto ya está abierto
            DoEvents
           estado.BackColor = &HFF0000
        Case 8012 '8012 el dispositivo no está abierto
            DoEvents
           estado.BackColor = &HFF&
        Case 8015
            DoEvents
            estado.BackColor = &HFF&
    End Select
      Exit Sub
End Sub

Lo que hace este código , es mirar continuamente el estado de la conexión usb:
Si está conectado , prende un led verde en el programa.
Si desconectamos el cable prende un led rojo. (los leds son los del programa)

Espero que les sirva , cualquier cosa pregunten.
 

Adjuntos

  • software_de_control_600.rar
    6.6 KB · Visitas: 3,315
ya me voy a descargar el vb 2008 .net y te pregunto dudas.

pd: estoy haciendo un programa de control de 8 relés por puerto usb utilizando lo aprendido en los 3 ejemplos anteriores.
 
Ojo que no se Visual Basic. :cry:

Pero si puedo pasarlo a C# buscando información. Si tienes dudas grandes, las puedes consultar aquí.

http://forums.microsoft.com/MSDN-ES/ShowForum.aspx?ForumID=303&SiteID=11

Muy bueno para aprender Visual Basic en el foro oficial.

PD: Lo de los 8 Relés es loq ue quiero hacer yo, ejejjeje. El manual que hice te da las ideas necesarias para hacer lo mismo pero en puerto serie.

https://www.forosdeelectronica.com/about29162.htmlhttps://www.forosdeelectronica.com/...ie-rs232-pic16f84a-controlado-visual-c-17414/

Saludos.
 
ok , ahora veo de bajar el programa y para la semana que viene hago más ejemplos y posteo más información, ya que se me acaba la batería de la laptop y las ganas de escribir ejejej. Gracias por la información de vb y visual c ya me voy a poner con eso tambien.

pd: se me rompió el soldador , que mala leche
 
El proyecto esta interesante salgo de mis últimos exámenes y me pongo a probarlo me gusta el tema si por favor puedes colgar información de la comunicación por USB te lo agradecería, tratare de realizarlo con otros Pic y en lenguaje BASIC en unos días ya debo tener resultados.
 
ya voy a poner información más específica sobre el control por puerto usb , lo que pasa es que yo también estoy aprendiendo y cuesta sacarle la vuelta, pero de a poco lo estoy logrando . ahora estoy me estoy metiendo un poco más en el tema de saber que hacen las famosas librerías de control y como logran comunicarse con el host.
 
Moyano Jonathan dijo:
meta dijo:

No entiendo exactamente a que te refieres. ¿Te refieres que pase tu código fuente del Visual Basic al Visual C#?

Esto podría ayudar.

http://www.developerfusion.com/tools/convert/csharp-to-vb/

muy buena herramienta

Ojo, es para C# vs VB .net, no para VB 6.

EDITO:
Aquí hay otro de cambiar a Visual C# a Mono, no lo he probado pero voy a investigar a pasar el código a ver que tal.
http://www.mono-project.com/Moma
 
Visual C#:
Código:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO.Ports;

namespace PicRS232
{
    public partial class Form1_Principal : Form
    {
        public Form1_Principal()
        {
            InitializeComponent();
            // Abrir puerto mientra se ejecute la aplicación
            if (!serialPort1.IsOpen)
            {
                try
                {
                    serialPort1.Open();
                }
                catch (System.Exception ex)
                {
                    MessageBox.Show(ex.ToString());
                }
            }
        }

        private void button_t_Click(object sender, EventArgs e)
        {
            byte[] mBuffer = new byte[1];
            mBuffer[0] = 0x74; //ASCII letra "t".
            serialPort1.Write(mBuffer, 0, mBuffer.Length);
        }

        private void button_b_Click(object sender, EventArgs e)
        {
            byte[] miBuffer = new byte[1];
            miBuffer[0] = 0x62; //ASCII letra "b".
            serialPort1.Write(miBuffer, 0, miBuffer.Length);
        }

        private void button_a_Click(object sender, EventArgs e)
        {
            byte[] mBuffer = new byte[1];
            mBuffer[0] = 0x61; //ASCII letra "a".
            serialPort1.Write(mBuffer, 0, mBuffer.Length);
        }

        private void button_l_Click(object sender, EventArgs e)
        {
            byte[] mBuffer = new byte[1];
            mBuffer[0] = 0x6C; //ASCII letra "l".
            serialPort1.Write(mBuffer, 0, mBuffer.Length);
        }

        private void button_Espacio_Click(object sender, EventArgs e)
        {
            byte[] mBuffer = new byte[1];
            mBuffer[0] = 0x20; //ASCII letra "Espacio".
            serialPort1.Write(mBuffer, 0, mBuffer.Length);
        }
    }
}

Transformado a VS .net con http://www.developerfusion.com/tools/convert/csharp-to-vb/
Código:
    * Imports System
    * Imports System.Collections.Generic
    * Imports System.ComponentModel
    * Imports System.Data
    * Imports System.Drawing
    * Imports System.Linq
    * Imports System.Text
    * Imports System.Windows.Forms
    * Imports System.IO.Ports
    *
    * Namespace PicRS232
    *     Public Partial Class Form1_Principal
    *         Inherits Form
    *         Public Sub New()
    *             InitializeComponent()
    *             ' Abrir puerto mientra se ejecute la aplicación
    *             If Not serialPort1.IsOpen Then
    *                 Try
    *                     serialPort1.Open()
    *                 Catch ex As System.Exception
    *                     MessageBox.Show(ex.ToString())
    *                 End Try
    *             End If
    *         End Sub
    *        
    *         Private Sub button_t_Click(ByVal sender As Object, ByVal e As EventArgs)
    *             Dim mBuffer As Byte() = New Byte(0) {}
    *             mBuffer(0) = &H74
    *             'ASCII letra "t".
    *             serialPort1.Write(mBuffer, 0, mBuffer.Length)
    *         End Sub
    *        
    *         Private Sub button_b_Click(ByVal sender As Object, ByVal e As EventArgs)
    *             Dim miBuffer As Byte() = New Byte(0) {}
    *             miBuffer(0) = &H62
    *             'ASCII letra "b".
    *             serialPort1.Write(miBuffer, 0, miBuffer.Length)
    *         End Sub
    *        
    *         Private Sub button_a_Click(ByVal sender As Object, ByVal e As EventArgs)
    *             Dim mBuffer As Byte() = New Byte(0) {}
    *             mBuffer(0) = &H61
    *             'ASCII letra "a".
    *             serialPort1.Write(mBuffer, 0, mBuffer.Length)
    *         End Sub
    *        
    *         Private Sub button_l_Click(ByVal sender As Object, ByVal e As EventArgs)
    *             Dim mBuffer As Byte() = New Byte(0) {}
    *             mBuffer(0) = &H6c
    *             'ASCII letra "l".
    *             serialPort1.Write(mBuffer, 0, mBuffer.Length)
    *         End Sub
    *        
    *         Private Sub button_Espacio_Click(ByVal sender As Object, ByVal e As EventArgs)
    *             Dim mBuffer As Byte() = New Byte(0) {}
    *             mBuffer(0) = &H20
    *             'ASCII letra "Espacio".
    *             serialPort1.Write(mBuffer, 0, mBuffer.Length)
    *         End Sub
    *     End Class
    * End Namespace
 
Muchisimas gracias meta voy a revisar tu código. A ver como es la nueva forma de programar de vb.net ya que nunca lo he utilizado al igual que visual c (sharp).

pd: Estoy preparando una explicación más detallada de lo que hacen las librerías de CDC (comunication device class) para que se le saque más provecho y ahora que estoy de vacaciones , le voy a meter mano a esto del USB. Tambíen estoy terminando con los toques finales al clon del pickit2 y a la placa de desarrollo para micros de 28 pines , que me parece que al final va estar enfocada más al PIC18F2550 que a otra cosa.
 
Atrás
Arriba