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

Cualquier cosa que necesites , acá estamos. Si necesitas ayuda con algo de programación para el pic y para la pc lo vemos juntos y a ver que sale de todo esto.
 
Bueno acá vengo con la parte 3 del ejemplo de detección por parte del pic de la conexión del host.

luego de que vimos que hacía la función usb_attached(), queda ver que hace el pic cuando lo desconectamos del host. Vueno lo que hace es entrar nuevamente en ese bucle infinito
Código:
 while(!usb_cdc_connected())
.

Viendo las siguientes líneas:

UIE=__USB_UIF_IDLE | __USB_UIF_RESET; // Habilita las interrupciones IDLE and RESET.


tenemos unos defines:

#define __USB_UIF_IDLE 0x10 -> bit 4
#define __USB_UIF_RESET 0x01 -> bit 0

Si vemos en el datashet del PIC18F2550:

Las 2 banderas de las 2 interrupciones antes vistas IDLE y RESET registro UIR
Código:
bit 0 URSTIF: USB Reset Interrupt bit
                    1 = Valid USB Reset occurred; 00h is loaded into UADDR register
                    0 = No USB Reset has occurred
bit 4 IDLEIF: Idle Detect Interrupt bit(1)
                    1 = Idle condition detected (constant Idle state of 3 ms or more)
                    0 = No Idle condition detected

Y las habilitaciones de las 2 interrupciones en el registro UIE

Código:
bit 0 URSTIE: USB Reset Interrupt Enable bit
                     1 = USB Reset interrupt enabled
                     0 = USB Reset interrupt disabled
bit 4 IDLEIE: Idle Detect Interrupt Enable bit
                     1 = Idle detect interrupt enabled
                     0 = Idle detect interrupt disabled

Con este par de bits lo que hacemos es seleccionar el par USB Reset Interrupt y Idle Detect Interrupt Enable bit.

Ahora nos vamos a la descripción de lo que hacen esas 2 interrupciones:

Código:
/*******************************************************************************
/* usb_isr_rst() // USB Reset Interrupt.
/*
/* Summary: El host nos envía una señal de reset al dispositivo.  Resetea el periférico USB del pic y
/*                  pone el flag de la interrupción en su estado inicial.
/*
/********************************************************************************/

Para el estado IDLE:
/*******************************************************************************
/* usb_isr_uidle()
/*
/* Summary: Periferico USB no utilizado (desconectado del host).  Pone el periférico en modo slepp.
/*
/********************************************************************************/

Entonces vemos que ambos casos sirven para detectar el estado HOST<->PIC.

Pero luego de hacer un par de pruebas vi que era más facil detectar el estado de conexión con el host por otro lado: usando la función usb_task()

Vamos a modificar un par de cosas en las funciones usb_attach() y usb_detach() para que nos indique cuando está conectado/desconectado del host mediante 2 led's indicadores: un led verde (conectado) y un led rojo (desconectado). (Modificaciones hechas en la librería pic18_usb.c )

Código:
/******************************************************************************
/* usb_detach()
/*
/* Summary: Remove the D+/D- lines from the USB bus.  Basically, disable USB.
/*
/*****************************************************************************/
void usb_detach(void) {  //done
   output_high(PIN_B0) // Enciende LED rojo.
   output_low(PIN_B1) // Apaga LED verde.
   UCON=0;  //disable USB hardware
   UIE=0;   //disable USB interrupts
   UCFG = __UCFG_VAL_DISABLED__;
   set_tris_c(*0xF94 | 0x30);
   usb_state=USB_STATE_DETACHED;
   usb_token_reset();              //clear the chapter9 stack
   __usb_kbhit_status=0;
}

/******************************************************************************
/* usb_attach()
/*
/* Summary: Attach the D+/D- lines to the USB bus.  Enable the USB peripheral.
/*
/* You should wait until UCON_SE0 is clear before enabling reset/idle interrupt
/*
/*****************************************************************************/
void usb_attach(void) {
    usb_token_reset();
    output_high(PIN_B1) // Enciende LED verde.
    output_low(PIN_B0) // Apaga LED rojo.
    delay_ms(100)
    UCON = 0;
    UCFG = __UCFG_VAL_ENABLED__;
    UIE = 0;                                // Mask all USB interrupts
    UCON_USBEN = 1;                     // Enable module & attach to bus
    usb_state = USB_STATE_ATTACHED;      // Defined in usbmmap.c & .h
}

bueno hasta acá hemos visto como detectar la conexión / desconexión del host desde el pic. Luego pongo el ejemplo para grabar en el PIC18F2550 y ver como encienden los led's según se conecte al host o no.
 
Muchas gracias por estos ejemplos Jonathan, la verdad es que este tema me interesa bastante, no comento nada básicamente porque no conozco la programación en C, aunque he estado siguiendo el tema para ver como se desarrolla esto.
 
tengo un par de manuales de programación en c , pero para mi lo principal fue conocer la estructura del programación en c y de ahí luego ver el manual de usuario de CCS (en inglés) , no hace falta aprenderse todos los comandos , vas de apoco aprendiendo los que te hacen más falta o usas más. Eso estoy haciendo yo. Aunque te digo me falta muchisimo todavía para aprender a programar de forma eficiente en c.

si querés te paso algunos manuales pero va a tener que ser por otro medio ya que son un poco pesados, igual acá en el foro se han posteado tutoriales de programación en c de ccs para pic.

Otro consejo es mirar códigos de programación ajenos y ver los programas de ejemplo que trae el compilador.

Acordate que para lo que necesites acá estamos.
 
Gracias. Yo ya tengo algo de experiencia en ensamblador, he programado en C muy poco, solo para aplicaciones muy específicas en las que la vida se me hubiera complicado en ensamblador (como proyecto que hice hace un año en el que implementé una red neuronal sencilla en un pic 18f452), lo que he hecho lo he hecho siempre con ese manual de CCS en la mano.

Me interesa mucho el tema de USB, espero esta semana terminar un proyecto para ponerme con ese tema, y entonces con mucho gusto colaboraré en este post.

Te contactaré por mensaje privado porque si me interesan los manuales.
 
Bueno ya probé el ejemplo para "Detección de conexión/desconexión del host por parte del pic"

Las librerías y drivers usados son los mismos, menos la librería pic18_usb, que fue modificada.
Código:
/////////////////////////////////////////////////////////////////////////
////                          pic18_usb.c                            ////
////                                                                 ////
//// Hardware layer for CCS's USB library.  This hardware layer      ////
//// supports the USB peripheral on the PIC18 family chips.  Current ////
//// supported families are:                                         ////
////     PIC18F2455/2550/4455/4550                                   ////
////     PIC18F2450/4450                                             ////
////     PIC18F65J50/66J50/66J55/67J50/85J50/86J50/86J55/87J50       ////
////                                                                 ////
//// This file is part of CCS's PIC USB driver code, which includes: ////
////   usb_desc_*.h - an example set of config and device descriptor ////
////   usb.c - USB token and request handler code                    ////
////   usb.h - definitions, prototypes and global variables          ////
////                                                                 ////
//// The following examples are provided by CCS:                     ////
////   ex_usb_mouse.c - A HID Mouse.                                 ////
////   ex_usb_hid.c - A custom application using HID protocol.       ////
////   ex_usb_kbmouse.c - A HID Mouse/Keyboard combo using multiple  ////
////                      interfaces.                                ////
////   ex_usb_kbmouse2.c - A HID Mouse/Keyboard combo using multiple ////
////                      HID Reports.                               ////
////   ex_usb_scope.c - A digital oscilloscope using a custom        ////
////                    protocol requiring custom Windows drivers.   ////
////   ex_usb_serial.c -                                             ////
////   ex_usb_serial2.c - Two examples of using the CDC driver for   ////
////     a virtual COM port.                                         ////
////                                                                 ////
////   *********** NOTE ABOUT 18F2450/4450 LIMITATIONS **********    ////
////  Due to the limited USB RAM of this family, a limitation of     ////
////  this driver is that there are only 3 endpoints (0, 1 and 2).   ////
////  The HW actually supports more endpoints, but to simplify       ////
////  driver development this driver will only support the first 3   ////
////  so there is an easier memory block to work with.               ////
////                                                                 ////
////  USB_MAX_EP0_PACKET_LENGTH will also be set to 8 regardless     ////
////  of USB speed, to save RAM.                                     ////
////                                                                 ////
////   ************** NOTE ABOUT HW REQUIREMENTS ****************    ////
////  If you are not using internal pullups, you will need to put    ////
////  an internal pullup resistor on C4 or C5 depending on if you    ////
////  want to use slow speed or full speed.  This code configures    ////
////  the device to use internal pullups, see usb_init() if you      ////
////  want to change that.                                           ////
////                                                                 ////
////  You need approximately 470nF cap on C3, even if you are using  ////
////  the internal 3.3V USB regulator.                               ////
////                                                                 ////
////  To run at full speed, you must use the oscillator              ////
////  configuration (PLLx) to set the PLL divide to 4MHz.  You can   ////
////  configure the MCU clock to any speed (up to 48MHz) but the     ////
////  PLL must run at 4Mhz to provide the USB peripheral with a      ////
////  96MHz clock.  See the datasheet for details.                   ////
////                                                                 ////
////  To run at slow speed you must configure your MCU to run at     ////
////  24Mhz.  See the datasheet for details.                         ////
////                                                                 ////
////   ****************  NOTE ABOUT INTERRUPTS  ******************   ////
//// This driver uses INT_USB.  It requires INT_USB to interrupt the ////
//// PIC when an event has happened on the USB Bus.  Therfore        ////
//// this code enables interrupts.  A user modification can be made  ////
//// to poll the USB interrupt flag instead of relying on an         ////
//// interrupt.                                                      ////
////                                                                 ////
////    ****************   USER FUNCTIONS  ***********************   ////
////                                                                 ////
//// usb_init() - Initializes the USB stack, the USB peripheral and  ////
////              attaches the unit to the usb bus.  Enables         ////
////              interrupts.                                        ////
////                                                                 ////
//// usb_init_cs() - A smaller usb_init(), does not attach unit      ////
////              to usb bus or enable interrupts.                   ////
////                                                                 ////
//// usb_put_packet() - Sends one packet to the host.                ////
////                    If you need to send a message that spans     ////
////                    more than one packet then see usb_puts() in  ////
////                    usb.c                                        ////
////                                                                 ////
//// usb_kbhit() - Returns true if OUT endpoint contains data from   ////
////               host.                                             ////
////                                                                 ////
//// usb_rx_packet_size() - Returns the size of packet that was      ////
////               received.  usb_kbhit() must return TRUE else      ////
////               this is not valid.  Don't forget in USB there     ////
////               are 0 len packets!                                ////
////                                                                 ////
//// usb_get_packet() - Gets one packet that from the host.          ////
////                    usb_kbhit() must return true before you call ////
////                    this routine or your data may not be valid.  ////
////                    Once usb_kbhit() returns true you want to    ////
////                    call this as soon as possible to get data    ////
////                    out of the endpoint buffer so the PC can     ////
////                    start sending more data, if needed.          ////
////                    This only receives one packet, if you are    ////
////                    trying to receive a multi-packet message     ////
////                    see usb_gets() in usb.c.                     ////
////                                                                 ////
//// usb_detach() - De-attach USB from the system.                   ////
////                                                                 ////
//// usb_attach() - Attach USB to the system.                        ////
////                                                                 ////
//// usb_attached() - Returns TRUE if the device is attached to a    ////
////                  USB cable.  A macro that looks at the defined  ////
////                  connection sense pin.                          ////
////                                                                 ////
//// usb_task() - Keeps track of connection sense, calling           ////
////              usb_detach() and usb_attach() when needed.         ////
////                                                                 ////
//// For more documentation on these functions read the comments at  ////
//// each function.                                                  ////
////                                                                 ////
//// The other functions defined in this file are for use by the     ////
//// USB code, and is not meant to be used by the user.              ////
////                                                                 ////
/////////////////////////////////////////////////////////////////////////
////                                                                 ////
//// Version History:                                                ////
////                                                                 ////
////   07-17-07: Added 18F4450,2450 support                          ////
////                                                                 ////
////   07-13-07: Added 87J50 family support                          ////
////                                                                 ////
////   11-01-05: usb_detach(), usb_attach() and usb_init_cs()        ////
////               changed for the better.                           ////
////                                                                 ////
////   10-28-05: Added usb_rx_packet_size()                          ////
////                                                                 ////
////   07-13-05: usb_put_packet() changed for 16bit packet sizes     ////
////             usb_flush_in() changed for 16bit packet sizes       ////
////             usb_get_packet() changed for 16bit packet sizes     ////
////             usb_flush_out() changed for 16bit packet sizes      ////
////             usb_set_configured() changed for 16bit packet sizes ////
////                                                                 ////
////   06-30-05: usb_tbe() added                                     ////
////             The way endpoint 0 DTS is set has been changed.     ////
////                                                                 ////
////   06-20-05: Initial Release                                     ////
////                                                                 ////
////   05-13-05: Beta Release (Full Speed works)                     ////
////                                                                 ////
////   03-21-05: Initial Alpha 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.              ////
/////////////////////////////////////////////////////////////////////////

#IFNDEF __USB_HARDWARE__
#DEFINE __USB_HARDWARE__

//let the USB Stack know that we are using a PIC with internal USB peripheral
#DEFINE __PIC__   1

#if ((getenv("DEVICE")=="PIC18F87J50") || (getenv("DEVICE")=="PIC18F86J55") || (getenv("DEVICE")=="PIC18F86J50") || (getenv("DEVICE")=="PIC18F85J50") || (getenv("DEVICE")=="PIC18F67J50") || (getenv("DEVICE")=="PIC18F66J55") || (getenv("DEVICE")=="PIC18F66J50") || (getenv("DEVICE")=="PIC18F65J50"))
 #define __USB_87J50__
 #define USB_TOTAL_BUFFER_SPACE  ((int16)getenv("RAM")-0x500)
 #define USB_MAX_NUM_ENDPOINTS  16
#elif ((getenv("DEVICE")=="PIC18F2450") || (getenv("DEVICE")=="PIC18F4450"))
 #define __USB_4450__
 #if (USB_EP3_TX_SIZE+USB_EP3_RX_SIZE+USB_EP4_TX_SIZE+USB_EP4_RX_SIZE+USB_EP5_TX_SIZE+USB_EP5_RX_SIZE+
USB_EP6_TX_SIZE+USB_EP6_RX_SIZE+USB_EP7_TX_SIZE+USB_EP7_RX_SIZE+USB_EP8_TX_SIZE+USB_EP8_RX_SIZE+
USB_EP9_TX_SIZE+USB_EP9_RX_SIZE+USB_EP10_TX_SIZE+USB_EP10_RX_SIZE+USB_EP11_TX_SIZE+USB_EP11_RX_SIZE+
USB_EP12_TX_SIZE+USB_EP12_RX_SIZE+USB_EP13_TX_SIZE+USB_EP13_RX_SIZE+USB_EP14_TX_SIZE+USB_EP14_RX_SIZE+
USB_EP15_TX_SIZE+USB_EP15_RX_SIZE)>0
   #error This driver only supports endpoints 0, 1 and 2 for this chip.
 #endif
 #define USB_MAX_NUM_ENDPOINTS  3
 #define USB_TOTAL_BUFFER_SPACE  (0x100 - USB_MAX_NUM_ENDPOINTS*8)
#else
 #define __USB_4550__
 #define USB_TOTAL_BUFFER_SPACE  ((int16)0x300)
 #define USB_MAX_NUM_ENDPOINTS  16
#endif

#ifndef USB_USE_FULL_SPEED
 #define USB_USE_FULL_SPEED   TRUE
#endif

#ifndef USB_CON_SENSE_PIN
#define USB_CON_SENSE_PIN  0
#endif

#if defined(__USB_4450__)
   #define USB_MAX_EP0_PACKET_LENGTH   8
#else
   #if USB_USE_FULL_SPEED==FALSE
      //slow speed requires 8byte max packet size for endpoint 0
      #DEFINE USB_MAX_EP0_PACKET_LENGTH   8
   #else
      //for full speed you can still use 8bytes, but 64 will be faster
      #DEFINE USB_MAX_EP0_PACKET_LENGTH   64
   #endif
#endif

#INCLUDE <usb.h>

#define USB_BUFFER_NEEDED (USB_EP0_TX_SIZE+USB_EP0_RX_SIZE+USB_EP1_TX_SIZE+USB_EP1_RX_SIZE+USB_EP2_TX_SIZE+
USB_EP2_RX_SIZE+USB_EP3_TX_SIZE+USB_EP3_RX_SIZE+USB_EP4_TX_SIZE+USB_EP4_RX_SIZE+
USB_EP5_TX_SIZE+USB_EP5_RX_SIZE+USB_EP6_TX_SIZE+USB_EP6_RX_SIZE+USB_EP7_TX_SIZE+
USB_EP7_RX_SIZE+USB_EP8_TX_SIZE+USB_EP8_RX_SIZE+USB_EP9_TX_SIZE+USB_EP9_RX_SIZE+
USB_EP10_TX_SIZE+USB_EP10_RX_SIZE+USB_EP11_TX_SIZE+USB_EP11_RX_SIZE+USB_EP12_TX_SIZE+
USB_EP12_RX_SIZE+USB_EP13_TX_SIZE+USB_EP13_RX_SIZE+USB_EP14_TX_SIZE+USB_EP14_RX_SIZE+
USB_EP15_TX_SIZE+USB_EP15_RX_SIZE)

#if (USB_BUFFER_NEEDED > USB_TOTAL_BUFFER_SPACE)
 #error You are trying to allocate more memory for endpoints than the PIC can handle
#endif

#if defined(__USB_4450__)
 #reserve 0x400:0x4FF
#else
 #reserve 0x400:0x4FF+USB_BUFFER_NEEDED
#endif

#define debug_usb(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z)
//#define debug_usb printf
//#define debug_putc putc_tbe
#define debug_display_ram(x,y)
/*
void debug_display_ram(int8 len, int8 *ptr) {
   int8 max=16;
   debug_usb(debug_putc,"%U - ",len);
   if (max>len) {max=len;}
   while(max--) {
      debug_usb(debug_putc,"%X",*ptr);
      len--;
      ptr++;
   }
   if (len) {debug_usb(debug_putc,"...");}
}
*/

//if you are worried that the PIC is not receiving packets because a bug in the
//DATA0/DATA1 synch code, you can set this to TRUE to ignore the DTS on
//receiving.
#ifndef USB_IGNORE_RX_DTS
 #define USB_IGNORE_RX_DTS FALSE
#endif

#ifndef USB_IGNORE_TX_DTS
 #define USB_IGNORE_TX_DTS FALSE
#endif

//if you enable this it will keep a counter of the 6 possible errors the
//pic can detect.  disabling this will save you ROM, RAM and execution time.
#ifndef USB_USE_ERROR_COUNTER
   #define USB_USE_ERROR_COUNTER FALSE
#endif

#define USB_PING_PONG_MODE_OFF   0  //no ping pong
#define USB_PING_PONG_MODE_E0    1  //ping pong endpoint 0 only
#define USB_PING_PONG_MODE_ON    2  //ping pong all endpoints

//NOTE - PING PONG MODE IS NOT SUPPORTED BY CCS!
#ifndef USB_PING_PONG_MODE
   #define USB_PING_PONG_MODE USB_PING_PONG_MODE_OFF
#endif

#if USB_USE_ERROR_COUNTER
   int ERROR_COUNTER[6];
#endif

//---pic18fxx5x memory locations
#if defined(__USB_4550__)
   #byte UFRML   =  0xF66
   #byte UFRMH   =  0xF67
   #byte UIR     =  0xF68
   #byte UIE     =  0xF69
   #byte UEIR    =  0xF6A
   #byte UEIE    =  0xF6B
   #byte USTAT   =  0xF6C
   #byte UCON    =  0xF6D
   #byte UADDR   =  0xF6E
   #byte UCFG    =  0xF6F
   #define  UEP0_LOC 0xF70
#else
   #byte UFRML   =  0xF60
   #byte UFRMH   =  0xF61
   #byte UIR     =  0xF62
   #byte UIE     =  0xF5C
   #byte UEIR    =  0xF63
   #byte UEIE    =  0xF5D
   #byte USTAT   =  0xF64
   #byte UCON    =  0xF65
   #byte UADDR   =  0xF5E
   #byte UCFG    =  0xF5F
   #define  UEP0_LOC 0xF4C
#endif

#byte UEP0    =  UEP0_LOC

#if defined(__USB_4450__)
 #define USB_BUFFER (0x400 + (USB_MAX_NUM_ENDPOINTS*8))
 //#define USB_BUFFER 0x418   //if you have an old compiler you will need to use this
#else
 #define USB_BUFFER 0x500
#endif

#byte BD0STAT  =  0x400
#byte BD0CNT  =  0x401
#byte BD0ADRL  =  0x402
#byte BD0ADRJ  =  0x403

#define BD0STAT_LOC 0x400
#define BD0CNT_LOC  0x401
#define BD0ADRL_LOC 0x402
#define BD0ADRH_LOC 0x403

#define UEP(x) *(UEP0_LOC+x)

#BIT UIR_SOF = UIR.6
#BIT UIR_STALL = UIR.5
#BIT UIR_IDLE = UIR.4
#BIT UIR_TRN = UIR.3
#BIT UIR_ACTV = UIR.2
#BIT UIR_UERR = UIR.1
#BIT UIR_URST = UIR.0

#BIT UIE_SOF = UIE.6
#BIT UIE_STALL = UIE.5
#BIT UIE_IDLE = UIE.4
#BIT UIE_TRN = UIE.3
#BIT UIE_ACTV = UIE.2
#BIT UIE_UERR = UIE.1
#BIT UIE_URST = UIE.0

#bit UCON_PBRST=UCON.6
#bit UCON_SE0=UCON.5
#bit UCON_PKTDIS=UCON.4
#bit UCON_USBEN=UCON.3
#bit UCON_RESUME=UCON.2
#bit UCON_SUSPND=UCON.1

#if (USB_PING_PONG_MODE==USB_PING_PONG_MODE_OFF)
 #define EP_BDxST_O(x)    *(BD0STAT_LOC + x*8)
 #define EP_BDxCNT_O(x)    *(BD0CNT_LOC + x*8)
 #define EP_BDxADR_O(x)   *(int16 *)(BD0ADRL_LOC + x*8)
 #define EP_BDxST_I(x)    *(BD0STAT_LOC + 4 + x*8)
 #define EP_BDxCNT_I(x)    *(BD0CNT_LOC + 4 + x*8)
 #define EP_BDxADR_I(x)   *(int16 *)(BD0ADRL_LOC + 4 + x*8)
#else
#error Right now this driver only supports no ping pong
#endif

//See UEPn (0xF70-0xF7F)
#define ENDPT_DISABLED   0x00   //endpoint not used
#define ENDPT_IN_ONLY   0x02    //endpoint supports IN transactions only
#define ENDPT_OUT_ONLY   0x04    //endpoint supports OUT transactions only
#define ENDPT_CONTROL   0x06    //Supports IN, OUT and CONTROL transactions - Only use with EP0
#define ENDPT_NON_CONTROL 0x0E  //Supports both IN and OUT transactions

//Define the states that the USB interface can be in
enum {USB_STATE_DETACHED=0, USB_STATE_ATTACHED=1, USB_STATE_POWERED=2, USB_STATE_DEFAULT=3,
    USB_STATE_ADDRESS=4, USB_STATE_CONFIGURED=5} usb_state=0;

//--BDendST has their PIDs upshifed 2
#define USB_PIC_PID_IN       0x24  //device to host transactions
#define USB_PIC_PID_OUT      0x04  //host to device transactions
#define USB_PIC_PID_SETUP    0x34  //host to device setup transaction

#define USTAT_IN_E0        4
#define USTAT_OUT_SETUP_E0 0

#define __USB_UIF_RESET    0x01
#define __USB_UIF_ERROR    0x02
#define __USB_UIF_ACTIVE   0x04
#define __USB_UIF_TOKEN    0x08
#define __USB_UIF_IDLE     0x10
#define __USB_UIF_STALL    0x20
#define __USB_UIF_SOF      0x40

#if USB_USE_ERROR_COUNTER
 #define STANDARD_INTS 0x3F
#else
 #define STANDARD_INTS 0x3D
#endif

#define __USB_UCFG_UTEYE   0x80
#if defined(__USB_4550__)
 #define __USB_UCFG_UOEMON  0x40
#endif
#define __USB_UCFG_UPUEN   0x10
#define __USB_UCFG_UTRDIS  0x08
#define __USB_UCFG_FSEN    0x04

#if USB_USE_FULL_SPEED
   #define __UCFG_VAL_ENABLED__ (__USB_UCFG_UPUEN | __USB_UCFG_FSEN | USB_PING_PONG_MODE)
#else
   #define __UCFG_VAL_ENABLED__ (__USB_UCFG_UPUEN | USB_PING_PONG_MODE);
#endif

#define __UCFG_VAL_DISABLED__ 0x08

char usb_ep0_rx_buffer[USB_MAX_EP0_PACKET_LENGTH];
#locate usb_ep0_rx_buffer=USB_BUFFER

char usb_ep0_tx_buffer[USB_MAX_EP0_PACKET_LENGTH];
#locate usb_ep0_tx_buffer=USB_BUFFER+USB_MAX_EP0_PACKET_LENGTH

char usb_data_buffer[USB_TOTAL_BUFFER_SPACE-USB_MAX_EP0_PACKET_LENGTH-USB_MAX_EP0_PACKET_LENGTH];
#locate usb_data_buffer=USB_BUFFER+USB_MAX_EP0_PACKET_LENGTH+USB_MAX_EP0_PACKET_LENGTH

int8 __setup_0_tx_size;

//interrupt handler, specific to PIC18Fxx5x peripheral only
void usb_handle_interrupt();
void usb_isr_rst();
void usb_isr_uerr();
void usb_isr_sof(void);
void usb_isr_activity();
void usb_isr_uidle();
void usb_isr_tok_dne();
void usb_isr_stall(void);
void usb_init_ep0_setup(void);

//following functions standard part of CCS PIC USB driver, and used by usb.c
void usb_init();
void usb_detach();
int1 usb_put_packet(int endpoint, int * ptr, int16 len, USB_DTS_BIT tgl);
int1 usb_flush_in(int8 endpoint, int16 len, USB_DTS_BIT tgl); //marks the transmit buffer as ready for transmission
int16 usb_get_packet(int8 endpoint, int8 * ptr, int16 max);
int16 usb_rx_packet_size(int8 endpoint);
int16 usb_get_packet_buffer(int8 endpoint, int8 *ptr, int16 max);
void usb_flush_out(int8 endpoint, USB_DTS_BIT tgl);
void usb_stall_ep(int8 endpoint);
void usb_unstall_ep(int8 endpoint);
int1 usb_endpoint_stalled(int8 endpoint);
void usb_set_address(int8 address);
void usb_set_configured(int config);
void usb_disable_endpoints(void);

//// BEGIN User Functions:

/******************************************************************************
/* usb_attached()
/*
/* Summary: Returns TRUE if the device is attached to a USB cable
/*
/*****************************************************************************/
#if USB_CON_SENSE_PIN
 #define usb_attached() input(USB_CON_SENSE_PIN)
#else
 #define usb_attached() TRUE
#endif
 // parte modificada:
/******************************************************************************
/* usb_detach()
/*
/* Summary: Remove the D+/D- lines from the USB bus.  Basically, disable USB.
/*
/*****************************************************************************/
void usb_detach(void) {  //done
   output_high(PIN_B1); // Enciendo LED rojo
   output_low(PIN_B0);  // Apago LED verde.
   delay_ms(50); // espero 50ms.
   UCON=0;  //disable USB hardware
   UIE=0;   //disable USB interrupts
   UCFG = __UCFG_VAL_DISABLED__;
   set_tris_c(*0xF94 | 0x30);
   usb_state=USB_STATE_DETACHED;
   usb_token_reset();              //clear the chapter9 stack
   __usb_kbhit_status=0;
}

/******************************************************************************
/* usb_attach()
/*
/* Summary: Attach the D+/D- lines to the USB bus.  Enable the USB peripheral.
/*
/* You should wait until UCON_SE0 is clear before enabling reset/idle interrupt
/*
/*****************************************************************************/
void usb_attach(void) {
   usb_token_reset();
    output_high(PIN_B0); // Enciendo LED VERDE.
    output_low(PIN_B1);  // Apago LED rojo.
    delay_ms(50); // espero 50ms.
    UCON = 0;
    UCFG = __UCFG_VAL_ENABLED__;
    UIE = 0;                                // Mask all USB interrupts
    UCON_USBEN = 1;                     // Enable module & attach to bus
    usb_state = USB_STATE_ATTACHED;      // Defined in usbmmap.c & .h
}

/*****************************************************************************
/* usb_init_cs()
/*
/* Summary: Resets and initalizes USB peripheral.  Does not attach the peripheral
/*          to the USB bus.  See usb_attach() and usb_task() on how to
/*          attach to the USB bus.
/*
/*          You must call this before any other USB code.
/*
/*          NOTE: an alternative function, usb_init(), is provided that
/*                initializes the USB and then connects.
/*
/*****************************************************************************/
#define usb_init_cs usb_detach

/*****************************************************************************
/* usb_task()
/*
/* Summary: Keeps an eye on the connection sense pin to determine if we are
/*          attached to a USB cable or not.  If we are attached to a USB cable,
/*          initialize the USB peripheral if needed.  If we are disconnected
/*          from the USB cable, disable the USB peripheral.
/*
/*          NOTE: If you are not using a connection sense pin, will automatically
/*                enable the USB peripheral.
/*
/*          NOTE: this enables interrupts once the USB peripheral is ready
/*
/*****************************************************************************/
void usb_task(void) {
   if (usb_attached()) {
      if (UCON_USBEN==0) {
         debug_usb(debug_putc, "\r\n\nUSB TASK: ATTACH");
         usb_attach();
      }
   }
   else {
      if (UCON_USBEN==1)  {
         debug_usb(debug_putc, "\r\n\nUSB TASK: DE-ATTACH");
         usb_detach();
      }
   }

   if ((usb_state == USB_STATE_ATTACHED)&&(!UCON_SE0)) {
      UIR=0;
      UIE=0;
      enable_interrupts(INT_USB);
      enable_interrupts(GLOBAL);
      UIE=__USB_UIF_IDLE | __USB_UIF_RESET;  //enable IDLE and RESET USB interrupt
      usb_state=USB_STATE_POWERED;
      debug_usb(debug_putc, "\r\n\nUSB TASK: POWERED");
   }
}

/*****************************************************************************
/* usb_init()
/*
/* Summary: Resets and initalizes USB hardware.  You must call this first before
/*          using code.  Will attach the USB periperhal to the USB bus.
/*
/*          NOTE: If you are using a connection sense pin, this will wait in
/*                an infinite loop until the device is connected to a USB cable.
/*
/*          NOTE: If you are not using a connection sense pin, this will wait
/*                in an infinte loop until the SE0 condition clears, which usually
/*                doesn't take long
/*
/*          NOTE: this enables interrupts.
/*
/*****************************************************************************/
void usb_init(void) {
   usb_init_cs();

   do {
      usb_task();
   } while (usb_state != USB_STATE_POWERED);
}


/**************************************************************
/* usb_flush_in()
/*
/* Input: endpoint - which endpoint to mark for transfer
/*        len - length of data that is being tramsferred
/*        tgl - Data toggle synchronization for this packet
/*
/* Output: TRUE if success, FALSE if error (we don't control the endpoint)
/*
/* Summary: Marks the endpoint ready for transmission.  You must
/*          have already loaded the endpoint buffer with data.
/*          (IN is PIC -> PC)
/***************************************************************/
int1 usb_flush_in(int8 endpoint, int16 len, USB_DTS_BIT tgl) {
   int8 i;

   debug_usb(debug_putc,"\r\nPUT %X %U %LU",endpoint, tgl, len);

   i=EP_BDxST_I(endpoint);
   if (!bit_test(i,7)) {

      EP_BDxCNT_I(endpoint)=len;

     debug_display_ram(len, EP_BDxADR_I(endpoint));

     #if USB_IGNORE_TX_DTS
      i=0x80;
     #else
      if (tgl == USB_DTS_TOGGLE) {
         i=EP_BDxST_I(endpoint);
         if (bit_test(i,6))
            tgl=USB_DTS_DATA0;  //was DATA1, goto DATA0
         else
            tgl=USB_DTS_DATA1;  //was DATA0, goto DATA1
      }
      else if (tgl == USB_DTS_USERX) {
         i=EP_BDxST_O(endpoint);
         if (bit_test(i,6))
            tgl=USB_DTS_DATA1;
         else
            tgl=USB_DTS_DATA0;
      }
      if (tgl == USB_DTS_DATA1) {
         i=0xC8;  //DATA1, UOWN
      }
      else if (tgl == USB_DTS_DATA0) {
         i=0x88; //DATA0, UOWN
      }
     #endif

      //set BC8 and BC9
      if (bit_test(len,8)) {bit_set(i,0);}
      if (bit_test(len,9)) {bit_set(i,1);}

      debug_usb(debug_putc," %X",i);

      EP_BDxST_I(endpoint)=i;//save changes

      return(1);
   }
    else {
         debug_usb(debug_putc,"\r\nPUT ERR");
    }
   return(0);
}

/*******************************************************************************
/* usb_put_packet(endpoint,*ptr,len,toggle)
/*
/* Input: endpoint - endpoint to send packet to
/*        ptr - points to data to send
/*        len - amount of data to send
/*        toggle - whether to send data with a DATA0 pid, a DATA1 pid, or toggle from the last DATAx pid.
/*
/* Output: TRUE if data was sent correctly, FALSE if it was not.  The only reason it will
/*         return FALSE is if because the TX buffer is still full from the last time you
/*         tried to send a packet.
/*
/* Summary: Sends one packet out the EP to the host.  Notice that there is a difference
/*          between a packet and a message.  If you wanted to send a 512 byte message you
/*          would accomplish this by sending 8 64-byte packets, followed by a 0 length packet.
/*          If the last (or only packet) being sent is less than the max packet size defined
/*          in your descriptor then you do not need to send a 0 length packet to identify
/*          an end of message.
/*
/*          usb_puts() (provided in usb.c) will send a multi-packet message correctly.
/*
/********************************************************************************/
int1 usb_put_packet(int8 endpoint, int8 * ptr, int16 len, USB_DTS_BIT tgl) { //done
   int16 j;
   int8 i;
   int8 * buff_add;    

   i=EP_BDxST_I(endpoint);
   if (!bit_test(i,7)) {

      buff_add=EP_BDxADR_I(endpoint);

      for (j=0;j<len;j++) {
         *buff_add=*ptr;
         buff_add++;
         ptr++;
      }

      return(usb_flush_in(endpoint, len, tgl));
    }
    else {
        debug_usb(debug_putc,"\r\nPUT ERR");
    }
    return(0);
}

/// END User Functions


/// BEGIN Hardware layer functions required by USB.C

/**************************************************************
/* usb_flush_out()
/*
/* Input: endpoint - which endpoint to mark for transfer
/*        tgl - Data toggle synchronization to expect in the next packet
/*
/* Output: NONE
/*
/* Summary: Clears the previously received packet, and then marks this
/*          endpoint's receive buffer as ready for more data.
/*          (OUT is PC -> PIC)
/***************************************************************/
void usb_flush_out(int8 endpoint, USB_DTS_BIT tgl) {
   int8 i;
   int16 len;

     #if USB_IGNORE_RX_DTS
      if (tgl == USB_DTS_STALL) {
         debug_usb(debug_putc, '*');
         i=0x84;
         EP_BDxST_I(endpoint)=0x84;
         return;
      }
      else
         i=0x80;
     #else
      i=EP_BDxST_O(endpoint);
      if (tgl == USB_DTS_TOGGLE) {
         if (bit_test(i,6))
            tgl=USB_DTS_DATA0;  //was DATA1, goto DATA0
         else
            tgl=USB_DTS_DATA1;  //was DATA0, goto DATA1
      }
      if (tgl == USB_DTS_STALL) {
         i=0x84;
         EP_BDxST_I(endpoint)=0x84; //stall both in and out endpoints
      }
      else if (tgl == USB_DTS_DATA1) {
         i=0xC8;  //DATA1, UOWN
      }
      else if (tgl == USB_DTS_DATA0) {
         i=0x88; //DATA0, UOWN
      }
     #endif

   bit_clear(__usb_kbhit_status,endpoint);

   len=usb_ep_rx_size[endpoint];
   EP_BDxCNT_O(endpoint)=len;
   if (bit_test(len,8)) {bit_set(i,0);}
   if (bit_test(len,9)) {bit_set(i,1);}


   EP_BDxST_O(endpoint)=i;
}

int16 usb_rx_packet_size(int8 endpoint) {
   return(EP_BDxCNT_O(endpoint));
}

/*******************************************************************************
/* usb_get_packet_buffer(endpoint, *ptr, max)
/*
/* Input: endpoint - endpoint to get data from
/*        ptr - where to save data to local PIC RAM
/*        max - max amount of data to receive from buffer
/*
/* Output: the amount of data taken from the buffer.
/*
/* Summary: Gets a packet of data from the USB buffer and puts into local PIC RAM.
/*          Does not mark the endpoint as ready for more data.  Once you are
/*          done with data, call usb_flush_out() to mark the endpoint ready
/*          to receive more data.
/*
/********************************************************************************/
int16 usb_get_packet_buffer(int8 endpoint, int8 *ptr, int16 max) {
   int8 * al;
   int8 st;
   int16 i;

   al=EP_BDxADR_O(endpoint);
   i=EP_BDxCNT_O(endpoint);
   st=EP_BDxST_O(endpoint);

   //read BC8 and BC9
   if (bit_test(st,0)) {bit_set(i,8);}
   if (bit_test(st,1)) {bit_set(i,9);}

   if (i<max) {max=i;}

   i=0;

   while (i<max) {
       *ptr=*al;
       ptr++;
       al++;
       i++;
   }

   return(max);
}

/*******************************************************************************
/* usb_get_packet(endpoint, *ptr, max)
/*
/* Input: endpoint - endpoint to get data from
/*        ptr - where to save data to local PIC RAM
/*        max - max amount of data to receive from buffer
/*
/* Output: the amount of data taken from the buffer.
/*
/*         NOTE - IF THERE IS NO PACKET TO GET YOU WILL GET INVALID RESULTS!
/*                VERIFY WITH USB_KBHIT() BEFORE YOU CALL USB_GET_PACKET()!
/*
/* Summary: Gets a packet of data from the USB buffer and puts into local PIC RAM.
/*          Until you call usb_get_packet() the data will sit in the endpoint
/*          buffer and the PC will get NAKs when it tries to write more data
/*          to the endpoint.
/*
/********************************************************************************/
int16 usb_get_packet(int8 endpoint, int8 * ptr, int16 max) {

   max=usb_get_packet_buffer(endpoint,ptr,max);
   usb_flush_out(endpoint, USB_DTS_TOGGLE);

   return(max);
}

/*******************************************************************************
/* usb_tbe(endpoint)
/*
/* Input: endpoint - endpoint to check
/*        ptr - where to save data to local PIC RAM
/*        max - max amount of data to receive from buffer
/*
/* Output: returns TRUE if this endpoint's IN buffer (PIC-PC) is empty and ready
/*         returns FALSE if this endpoint's IN buffer is still processing the last
/*         transmit or if this endpoint is invalid.
/*
/********************************************************************************/
int8 usb_tbe(int8 endpoint) {
   int8 st;
   st=EP_BDxST_I(endpoint);
   if (!bit_test(st,7))
      return(TRUE);
   return(FALSE);
}

/*******************************************************************************
/* usb_stall_ep(endpoint,direction)
/*
/* Input: endpoint - endpoint to stall.
/*                   top most bit indicates direction (set is IN, clear is OUT)
/*
/* Summary: Stalls specified endpoint.  If endpoint is stalled it will send STALL packet
/*          if the host tries to access this endpoint's buffer.
/*
/*
/* NOTE: WE ASSUME ENDPOINT IS VALID.  USB.C SHOULD CHECK THIS
/*
/********************************************************************************/
void usb_stall_ep(int8 endpoint) {  //done
   int1 direction;
   direction=bit_test(endpoint,7);
   endpoint&=0x7F;
   if (direction) {
      EP_BDxST_I(endpoint)=0x84;
   }
   else {
      EP_BDxST_O(endpoint)=0x84;
   }
}

/*******************************************************************************
/* usb_unstall_ep(endpoint, direction)
/*
/* Input: endpoint - endpoint to un-stall.
/*                   top most bit indicates direction (set is IN, clear is OUT)
/*
/* Summary: Un-stalls endpoint.
/*
/* NOTE: WE ASSUME ENDPOINT IS VALID.  USB.C SHOULD CHECK THIS
/********************************************************************************/
void usb_unstall_ep(int8 endpoint) {   //done
   int1 direction;
   direction=bit_test(endpoint,7);
   endpoint&=0x7F;
   if (direction) {
      #if USB_IGNORE_RX_DTS
      EP_BDxST_I(endpoint)=0x80;
      #else
      EP_BDxST_I(endpoint)=0x88;
      #endif
   }
   else {
      EP_BDxST_O(endpoint)=0x00;
   }
}

/*******************************************************************************
/* usb_endpoint_stalled(endpoint)
/*
/* Input: endpoint - endpoint to check
/*                   top most bit indicates direction (set is IN, clear is OUT)
/*
/* Output: returns a TRUE if endpoint is stalled, FALSE if it is not.
/*
/* Summary: Looks to see if an endpoint is stalled, or not.  Does not look to
/*          see if endpoint has been issued a STALL, just whether or not it is
/*          configured to STALL on the next packet.  See Set_Feature and Clear_Feature
/*          Chapter 9 requests.
/*
/* NOTE: WE ASSUME ENDPOINT IS VALID.  USB.C SHOULD CHECK THIS
/********************************************************************************/
int1 usb_endpoint_stalled(int8 endpoint) {   //done
   int1 direction;
   int8 st;
   direction=bit_test(endpoint,7);
   endpoint&=0x7F;
   if (direction) {
      st=EP_BDxST_I(endpoint);
   }
   else {
      st=EP_BDxST_O(endpoint);
   }
   return(bit_test(st,7) && bit_test(st,2));
}


/*******************************************************************************
/* usb_set_address(address)
/*
/* Input: address - address the host specified that we use
/*
/* Summary: Configures the USB Peripheral for the specified device address.  The host
/*          will now talk to use with the following address.
/*
/********************************************************************************/
void usb_set_address(int8 address) {   //done
   UADDR=address;
   if (address) {
      usb_state=USB_STATE_ADDRESS;
   }
   else {
      usb_state=USB_STATE_POWERED;
   }
}


/*******************************************************************************
/* usb_set_configured(config)
/*
/* Input: config - Configuration to use.  0 to uncofigure device.
/*
/* Summary: Configures or unconfigures device.  If configuring device it will
/*          enable all the endpoints the user specified for this configuration.
/*          If un-configuring device it will disable all endpoints.
/*
/*          NOTE: CCS only provides code to handle 1 configuration.
/*
/********************************************************************************/
void usb_set_configured(int config) {
   int8 en;
   int16 addy;
   int8 new_uep;
   int16 len;
   int8 i;
      if (config==0) {
         //if config=0 then set addressed state
         usb_state=USB_STATE_ADDRESS;
         usb_disable_endpoints();
      }
      else {
         usb_state=USB_STATE_CONFIGURED; //else set configed state
         addy=(int16)USB_BUFFER+(2*USB_MAX_EP0_PACKET_LENGTH);
         for (en=1;en<16;en++) {
            new_uep=0;
            if (usb_ep_rx_type[en]!=USB_ENABLE_DISABLED) {
               new_uep=0x04;
               len=usb_ep_rx_size[en];
               EP_BDxCNT_O(en)=len;
               EP_BDxADR_O(en)=addy;
               addy+=usb_ep_rx_size[en];
               #if USB_IGNORE_RX_DTS
                  i=0x80;
               #else
                  i=0x88;
               #endif
               if (bit_test(len,8)) {bit_set(i,0);}
               if (bit_test(len,9)) {bit_set(i,1);}
               EP_BDxST_O(en)=i;
            }
            if (usb_ep_tx_type[en]!=USB_ENABLE_DISABLED) {
               new_uep|=0x02;
               EP_BDxADR_I(en)=addy;
               addy+=usb_ep_tx_size[en];
               EP_BDxST_I(en)=0x40;
            }
            if (new_uep==0x06) {new_uep=0x0E;}
            if (usb_ep_tx_type[en]!=USB_ENABLE_ISOCHRONOUS) {
               new_uep|=0x10;
            }
            UEP(en)=new_uep;
         }
      }
}

/// END Hardware layer functions required by USB.C


/// BEGIN USB Interrupt Service Routine

/*******************************************************************************
/* usb_handle_interrupt()
/*
/* Summary: Checks the interrupt, and acts upon event.  Processing finished
/*          tokens is the majority of this code, and is handled by usb.c
/*
/* NOTE: If you wish to change to a polling method (and not an interrupt method),
/*       then you must call this function rapidly.  If there is more than 10ms
/*       latency the PC may think the USB device is stalled and disable it.
/*       To switch to a polling method, remove the #int_usb line above this fuction.
/*       Also, goto usb_init() and remove the code that enables the USB interrupt.
/********************************************************************************/
#int_usb
void usb_isr() {
   if (usb_state==USB_STATE_DETACHED) return;   //should never happen, though
   if (UIR) {
      debug_usb(debug_putc,"\r\n\n[%X] ",UIR);
      if (UIR_ACTV && UIE_ACTV) {usb_isr_activity();}  //activity detected.  (only enable after sleep)

      if (UCON_SUSPND) return;

      if (UIR_UERR && UIE_UERR) {usb_isr_uerr();}          //error has been detected

      if (UIR_URST && UIE_URST) {usb_isr_rst();}        //usb reset has been detected

      if (UIR_IDLE && UIE_IDLE) {usb_isr_uidle();}        //idle time, we can go to sleep
      if (UIR_SOF && UIE_SOF) {usb_isr_sof();}
      if (UIR_STALL && UIE_STALL) {usb_isr_stall();}        //a stall handshake was sent

      if (UIR_TRN && UIE_TRN) {
         usb_isr_tok_dne();
         UIR_TRN=0;    // clear the token done interrupt., 0x190.3
      }    //a token has been detected (majority of isrs)
   }
}

//SOF interrupt not handled.  user must add this depending on application
void usb_isr_sof(void) {
   debug_usb(debug_putc,"\r\nSOF");
   UIR_SOF=0;
}

/*******************************************************************************
/* usb_disable_endpoints()
/*
/* Summary: Disables endpoints 1 thru 15
/*
/********************************************************************************/
void usb_disable_endpoints(void) {
   int8 i;
   for (i=1;i<16;i++) {
      UEP(i)=ENDPT_DISABLED;
   }
   __usb_kbhit_status=0;
}

/*******************************************************************************
/* usb_isr_rst()
/*
/* Summary: The host (computer) sent us a RESET command.  Reset USB device
/*          and token handler code to initial state.
/*
/********************************************************************************/
void usb_isr_rst() {
   debug_usb(debug_putc,"R");

   UEIR=0;
   UIR=0;
   UEIE=0x9F;
   UIE=STANDARD_INTS & ~__USB_UIF_ACTIVE;

   UADDR=0;

   usb_token_reset();

   usb_disable_endpoints();

   UEP(0)=ENDPT_CONTROL | 0x10;

   while (UIR_TRN) {
      UIR_TRN=0;    //do this to clear out the ustat fifo
   }

   UCON_PKTDIS=0; //SIE token and packet processing enabled

   usb_init_ep0_setup();

   usb_state=USB_STATE_DEFAULT; //put usb mcu into default state
}

/*****************************************************************************
/* usb_init_ep0_setup()
/*
/* Summary: Configure EP0 to receive setup packets
/*
/*****************************************************************************/
void usb_init_ep0_setup(void) {
    EP_BDxCNT_O(0) = USB_MAX_EP0_PACKET_LENGTH;
    EP_BDxADR_O(0) = USB_BUFFER;
   #if USB_IGNORE_RX_DTS
    EP_BDxST_O(0) = 0x80; //give control to SIE, data toggle synch off
   #else
    EP_BDxST_O(0) = 0x88; //give control to SIE, DATA0, data toggle synch on
   #endif

    EP_BDxST_I(0) = 0;
    EP_BDxADR_I(0) = USB_BUFFER + (int16)USB_MAX_EP0_PACKET_LENGTH;
}

/*******************************************************************************
/* usb_isr_uerr()
/*
/* Summary: The USB peripheral had an error.  If user specified, error counter
/*          will incerement.  If having problems check the status of these 8 bytes.
/*
/* NOTE: This code is not enabled by default.
/********************************************************************************/
void usb_isr_uerr() {
#if USB_USE_ERROR_COUNTER
   int ints;
#endif

   debug_usb(debug_putc,"E %X ",UEIR);

#if USB_USE_ERROR_COUNTER

   ints=UEIR & UEIE; //mask off the flags with the ones that are enabled

   if ( bit_test(ints,0) ) { //increment pid_error counter
      debug_usb(debug_putc,"PID ");
      ERROR_COUNTER[0]++;
   }

   if ( bit_test(ints,1) ) {  //increment crc5 error counter
      debug_usbdebug_putc,"CRC5 ");
      ERROR_COUNTER[1]++;
   }

   if ( bit_test(ints,2) ) {  //increment crc16 error counter
      debug_usb(debug_putc,"CRC16 ");
      ERROR_COUNTER[2]++;
   }

   if ( bit_test(ints,3) ) {  //increment dfn8 error counter
      debug_usb(debug_putc,"DFN8 ");
      ERROR_COUNTER[3]++;
   }

   if ( bit_test(ints,4) ) {  //increment bto error counter
      debug_usb(debug_putc,"BTO ");
      ERROR_COUNTER[4]++;
   }

   if ( bit_test(ints,7) ) { //increment bts error counter
      debug_usb(debug_putc,"BTS ");
      ERROR_COUNTER[5]++;
   }
#endif

   UEIR=0;
   UIR_UERR=0;
}

/*******************************************************************************
/* usb_isr_uidle()
/*
/* Summary: USB peripheral detected IDLE.  Put the USB peripheral to sleep.
/*
/********************************************************************************/
void usb_isr_uidle() {
   debug_usb(debug_putc,"I");

   UIE_ACTV=1;   //enable activity interrupt flag. (we are now suspended until we get an activity interrupt. nice)
   UIR_IDLE=0; //clear idle interrupt flag
   UCON_SUSPND=1; //set suspend. we are now suspended
}


/*******************************************************************************
/* usb_isr_activity()
/*
/* Summary: USB peripheral detected activity on the USB device.  Wake-up the USB
/*          peripheral.
/*
/********************************************************************************/
void usb_isr_activity() {
   debug_usb(debug_putc,"A");

   UCON_SUSPND=0; //turn off low power suspending
   UIE_ACTV=0; //clear activity interupt enabling
   UIR_ACTV=0;
}

/*******************************************************************************
/* usb_isr_stall()
/*
/* Summary: Stall handshake detected.
/*
/********************************************************************************/
void usb_isr_stall(void) {
   debug_usb(debug_putc,"S");

   if (bit_test(UEP(0),0)) {
      usb_init_ep0_setup();
      bit_clear(UEP(0),0);
   }
   UIR_STALL=0;
}


/*******************************************************************************
/* usb_isr_tok_dne()
/*
/* Summary: A Token (IN/OUT/SETUP) has been received by the USB peripheral.
/*          If a setup token on EP0 was received, run the chapter 9 code and
/*          handle the request.
/*          If an IN token on EP0 was received, continue transmitting any
/*          unfinished requests that may take more than one packet to transmit
/*          (if necessary).
/*          If an OUT token on any other EP was received, mark that EP as ready
/*          for a usb_get_packet().
/*          Does not handle any IN or OUT tokens on EP0.
/*
/********************************************************************************/
void usb_isr_tok_dne() {
   int8 en;

   en=USTAT>>3;

         debug_usb(debug_putc,"T ");
         debug_usb(debug_putc,"%X ", USTAT);

      if (USTAT==USTAT_OUT_SETUP_E0) {   //new out or setup token in the buffer
         debug_usb(debug_putc,"%X ", EP_BDxST_O(0));
         if ((EP_BDxST_O(0) & 0x3C)==USB_PIC_PID_SETUP) {
            EP_BDxST_I(0)=0;   // return the in buffer to us (dequeue any pending requests)

            debug_usb(debug_putc,"(%U) ", EP_BDxCNT_O(0));
            debug_display_ram(EP_BDxCNT_O(0), usb_ep0_rx_buffer);

            usb_isr_tok_setup_dne();

            //if setup_0_tx_size==0xFF - stall ep0 (unhandled request)
            //if setup_0_tx_size==0xFE - get EP0OUT ready for a data packet, leave EP0IN alone
            //else setup_0_tx_size=size of response, get EP0OUT ready for a setup packet, mark EPOIN ready for transmit
            if (__setup_0_tx_size==0xFF)
               usb_flush_out(0,USB_DTS_STALL);
            else {
               usb_flush_out(0,USB_DTS_TOGGLE);
               if (__setup_0_tx_size!=0xFE) {
                  usb_flush_in(0,__setup_0_tx_size,USB_DTS_USERX);
               }
            }
            UCON_PKTDIS=0;       // UCON,PKT_DIS ; Assuming there is nothing to dequeue, clear the packet disable bit
         }
         else if ((EP_BDxST_O(0) & 0x3C)==USB_PIC_PID_OUT) {
            usb_isr_tok_out_dne(0);
            usb_flush_out(0,USB_DTS_TOGGLE);
            if ((__setup_0_tx_size!=0xFE)&&(__setup_0_tx_size!=0xFF)) {
               usb_flush_in(0,__setup_0_tx_size,USB_DTS_DATA1);   //send response (usually a 0len)
            }
         }
      }

      else if (USTAT==USTAT_IN_E0) {   //pic -> host transfer completed
         __setup_0_tx_size=0xFF;
         usb_isr_tok_in_dne(0);
         if (__setup_0_tx_size!=0xFF)
            usb_flush_in(0,__setup_0_tx_size,USB_DTS_TOGGLE);
         else
            usb_init_ep0_setup();
      }

      else {
         if (!bit_test(USTAT,2)) {
            usb_isr_tok_out_dne(en);
         }
         else {
            usb_isr_tok_in_dne(en);
         }
      }
}

/**************************************************************
/* usb_request_send_response(len)
/* usb_request_get_data()
/* usb_request_stall()
/*
/* Input: len - size of packet to send
/*
/* Summary: After we process a SETUP request, we have 1 of three responses:
/*            1.) send a response IN packet
/*            2.) wait for followup OUT packet(s) with data
/*            3.) stall because we don't support that SETUP request
/*
/*          If we are sending data, the array usb_ep0_tx_buffer[] will hold
/*          the response and the USB Request handler code will call
/*          usb_request_send_response() to let us know how big the packet is.
/*
/*          If we are waiting for more data, usb_request_get_data() will
/*          be called by the USB request handler code to configure the EP0 OUT
/*          endpoint to be ready for more data
/*
/*          If we don't support a request, usb_request_stall() will be called
/*          by the USB request handler code to stall the endpoint 0.
/*
/***************************************************************/
void usb_request_send_response(int len) {
   __setup_0_tx_size=len;
}

void usb_request_get_data(void) {
   __setup_0_tx_size=0xFE;
}

void usb_request_stall(void) {
   __setup_0_tx_size=0xFF;
}

/// END USB Interrupt Service Routine

#ENDIF

la librería fue modificada en esta parte, funciones usb_attach() y usb_dettach():
Código:
/******************************************************************************
/* usb_detach()
/*
/* Summary: Remove the D+/D- lines from the USB bus.  Basically, disable USB.
/*
/*****************************************************************************/
void usb_detach(void) {  //done
   output_high(PIN_B1); // Enciendo LED rojo
   output_low(PIN_B0);  // Apago LED verde.
   delay_ms(50); // espero 50ms.
   UCON=0;  //disable USB hardware
   UIE=0;   //disable USB interrupts
   UCFG = __UCFG_VAL_DISABLED__;
   set_tris_c(*0xF94 | 0x30);
   usb_state=USB_STATE_DETACHED;
   usb_token_reset();              //clear the chapter9 stack
   __usb_kbhit_status=0;
}

/******************************************************************************
/* usb_attach()
/*
/* Summary: Attach the D+/D- lines to the USB bus.  Enable the USB peripheral.
/*
/* You should wait until UCON_SE0 is clear before enabling reset/idle interrupt
/*
/*****************************************************************************/
void usb_attach(void) {
   usb_token_reset();
    output_high(PIN_B0); // Enciendo LED VERDE.
    output_low(PIN_B1);  // Apago LED rojo.
    delay_ms(50); // espero 50ms.
    UCON = 0;
    UCFG = __UCFG_VAL_ENABLED__;
    UIE = 0;                                // Mask all USB interrupts
    UCON_USBEN = 1;                     // Enable module & attach to bus
    usb_state = USB_STATE_ATTACHED;      // Defined in usbmmap.c & .h
}

Este es el código fuente en C de CCS del programa del ejemplo n°4:

Código:
// Programa que detecta la conexión/desconexión del pic al host USB.
// USB_CONECTADO: prende led verde.
// USB_DESCONECTADO: prende led rojo.
// Programador: Moyano Jonathan.
// Fecha: 11/12/08

#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
NOPBADEN: Deshabilitamos el módulo de conversión ADC del puerto B.
*/

#use delay(clock=48000000) // Frecuencia máxima de trabajo 48 Mhz.
#define USB_CON_SENSE_PIN PIN_E3 // Definiendo este pin , detectamos si el host está conectado o no por hardware.
#include "usb_cdc.h" // Descripción de funciones del USB.
#include "usb_desc_cdc.h" // Descriptores del dispositivo USB.

void main(){
usb_cdc_init(); // llamadas necesarias para iniciar el módulo USB.
    usb_init();    // llamadas necesarias  para iniciar el módulo USB.
   do{
    usb_task(); // En esta función se detecta la conexión/desconexión del pic al host USB (por software).
   }while (TRUE); // bucle eterno
}
 

Adjuntos

  • ejercicio_n4_449.rar
    56.1 KB · Visitas: 1,099
Te han respondido ya en:
http://forums.microsoft.com/MSDN-ES/ShowPost.aspx?PostID=4227073&SiteID=11&mode=1

Código:
Bueno, lo que es convertir el código en sí es fácil. Abajo te lo copio convertido. Pero no te servirá de mucho. Es un código para manejar el objeto MSComm, que no tienes en .Net, y además son eventhandlers cuya conexión al evento no está indicada en el código a convertir.

 

Code Snippet

void conectar_Click()

//comprueva [sic] que el puerto este cerrado para poder abrirlo

{
    if (MSComm1.PortOpen == false) {
        //determina el puerto que hemos seleccionado.
        if (COM_sel.ListIndex == 0) {
            MSComm1.CommPort = 1;
        }
        if (COM_sel.ListIndex == 1) {
            MSComm1.CommPort = 2;
        }
        if (COM_sel.ListIndex == 2) {
            MSComm1.CommPort = 3;
        }
        if (COM_sel.ListIndex == 3) {
            MSComm1.CommPort = 4;
        }
        if (COM_sel.ListIndex == 4) {
            MSComm1.CommPort = 5;
        }
        if (COM_sel.ListIndex == 5) {
            MSComm1.CommPort = 6;
        }
        if (COM_sel.ListIndex == 6) {
            MSComm1.CommPort = 7;
        }
        if (COM_sel.ListIndex == 7) {
            MSComm1.CommPort = 8;
        }
        if (COM_sel.ListIndex == 8) {
            MSComm1.CommPort = 9;
        }
        if (COM_sel.ListIndex == 9) {
            MSComm1.CommPort = 10;
        }
        if (COM_sel.ListIndex == 10) {
            MSComm1.CommPort = 11;
        }
    }
   
    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 SE PUEDE DEJAR AL MAXIMO.
    MSComm1.PortOpen = true;
    MSComm1.RThreshold = 23;
    //son 23 caracteres.
}

 

void MSComm1_OnComm()

{

        string InBuff = null;
        switch (MSComm1.CommEvent) {
            case comEvReceive:
                InBuff = MSComm1.Input;
                Debug.Print();
                InBuff();
                Texto.Text = "";
                Texto.Text = Strings.Left(InBuff, 23);
                // se recorta los caracteres basura
                MSComm1.PortOpen = false;
                break;
            //cierra el puerto y vacia el buffer
        }
}

http://foros.solocodigo.com/viewtopic.php?f=53&t=37799

kaidok dijo:
En esta página se ofrece un conversor que realiza esa función, pero es de pago así que no creo que te interese. Creo que el Microsoft Visual Studio también incluye una herramienta para realizar la conversión que pides, pero el Microsoft Visual Studio tampoco es gratis.

Me temo que no hay nada gratuito que realice la conversión que pides, en todo caso te dejo esta información.
 
Hola a todos.

Utilización del micro, mientras el usb no está conectado: Parte 1

Viendo en la librería usb_pic18, vamos a ver a mediado que vamos bajando los comentarios (En inglés), de lo que hace cada función de dicha librería.

usb_init():
Inicializa el hardware USB. Luego espera de forma indefinida hasta que el puerto haya sido conectado (Aunque no importa si ha sido enumerado aún por el host). Luego de que es enumerado , se habilitan las interupciones del usb.
usb_init_cs():
Es lo mismo que la función anterior, aunque No espera indefinidamente a que el puerto haya sido conectado. Esta función es ideal , si el dispositivo no usa la alimentación del puerto, y puede funcionar sin la conexión a usb.
usb_task():
/***************************************************************************************
/* usb_task()
/*
/* Función: Mantiene un ojo puesto sobre el SENSE pin para saber si el cable usb está o no conectado.
/* Si está conectado inicializa el periferico si es requerido. Si no está conectado el cable desactiva el
/* puerto usb del PIC.
/* Nota: Si el SENSE pin no es definido en la programación del pic, el hardware usb se inicializa de forma
/* automática.
/*
/* Nota: Esta función también habilita las interrupciones si el hardware usb está conectado.
/*
/*
/***************************************************************************************
usb_detach():
Remueve al pic del bus usb. Esta función será llamada automáticamente si la conexión con el host se pierde, aunque puede ser llamada por el usuario.
usb_attach():
Conecta el pic al bus usb Esta función será llamada automáticamente si la conexión con el host, es realizada aunque puede ser llamada por el usuario.
usb_attached():
Si se usa el pin de sensado de conexión (USB_CON_SENSE_PIN), retorna con un 1 lógico, si el pin de sensado no es utilizado, retorna con un 1 lógico de igual forma.
usb_enumerated():
Retorna con un 1 lógico si el host enumera el dispositivo. En ese caso el pic puede enviar o recibir paquetes de datos por el puerto.


Vean la diferencia de la función usb_init() con usb_init_cs(), si queremos ejecutar otros procesos en el micro usb_init() no nos serviría, porque se quedaría en un bucle esperando al HOST, pero lo que nosotros queremos hacer es que el micro realize otras tareas mientras espera la conexión dels host. Entonces se usará la función
usb_init_cs().

Esta otra función usb_init_cs() trabaja de forma conjunta con con usb_task(), porque una vez detectado el Vbus a través de USB_CON_SENSE_PIN, en task se procede a conectar el bus.

Lo principal aquí es estar monitoreando continuamente a USB_CON_SENSE_PIN, ya sea a través de usb_attached() ó de usb_task().

Otra función muy importante es:
usb_enumerated():
Retorna con un 1 lógico si el host enumera el dispositivo. En ese caso el pic puede enviar o recibir paquetes de datos por el puerto.

Esta función lisa y llanamente , no permite comunicarnos con el host hasta que el mismo nos enumere el dispositivo. :eek:

Bueno hasta acá llega la primera parte , luego voy a presentar un ejemplo en donde apliquemos lo antes explicado.
 
Hola a todos.

Utilización del micro, mientras el usb no está conectado: Parte 2

Bueno , perdonen por la demora ajaj acá les traigo el ejemplo del que les estaba contando en el post anterior.

Es un ejemplo muy simple , pero sirve para ver como el PIC pude realizar otras actividades mientras el host no está conectado.

El Código fuente en CCS es el siguiente:
Código:
// Programa: Realiza procesos secundarios mientras el dispositivo está desconectado del HOST.
// Programador: Moyano Jonathan.
// 15/12/08
/********************************************************************************************/

#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
NOPBADEN: Deshabilitamos el módulo de conversión ADC del puerto B.
*/

#use delay(clock=48000000) // Frecuencia máxima de trabajo 48 Mhz.
short estado_usb;   // boolean global, se debe declarar antes de llamar a usb_cdc.h
#define USB_CON_SENSE_PIN PIN_E3 // Definiendo este pin , detectamos si el host está conectado o no por hardware.
#include "usb_cdc.h" // Descripción de funciones del USB.
#include "usb_desc_cdc.h" // Descriptores del dispositivo USB.

// Declaramos las funciones utilizadas.
void estado_conexion_usb(short bandera);

void main() {
estado_usb=false;
   usb_cdc_init(); // llamadas necesarias para iniciar el módulo USB.
   usb_init_cs();    // inicia el USB y sale. Va de la mano con usb_task().
while(true){
     usb_task(); // configura el USB.
     estado_conexion_usb(estado_usb); // Se fija en el estado de la conexión usb.
     if(usb_cdc_connected()){ // Si está conectado entonces....
   // Espera a detectar una transmisión de la PC (Set_Line_Coding).
       if (usb_enumerated()){ // aquí se enumera el dispositivo por el host y despúes sale.
          if(usb_cdc_kbhit()){ //en espera de nuevo(s) caracter(es) en el buffer.
             if(usb_cdc_getc()=='m'){ //¿lo que llegó fué el caracter m?

                printf(usb_cdc_putc, "Llegó la letra m.\n\r"); // Envia una respuesta al HOST.
                output_high(PIN_B7); // Indica que ha llegado un caracter.
                delay_ms(1000); // Espera 1 seg.
                output_low(PIN_B7); // Apaga el indicador de llegada de caracteres.
             }  
          }
       }
     }
//*************** aquí se ejecutan otros procesos*********************//
// Estos procesos son independientes de la conexión por usb.
output_high(PIN_B6); // enciende el LED, conectado al pin RB6.
delay_ms(500); // Espera 500 mseg.
output_low(PIN_B6); // Apaga el LED, conectado al pin RB6.
delay_ms(500); // Espera 500 mseg.
}
}
//***********************************************
// Esta función, nos indica mediante 2 diodos LED conectados al 
// puerto RB0 y RB1 respectivamente. El estado de conexión del puerto usb.
// Conectado: Enciende LED VERDE.
// Desconectado: Enciende LED ROJO.
//***********************************************
void estado_conexion_usb(short bandera){
 if(bandera){
 output_high(PIN_B0); // Enciende LED VERDE.
 output_low(PIN_B1);  // Apaga LED ROJO.
 }else{
 output_high(PIN_B1); // Enciende LED ROJO.
 output_low(PIN_B0);  // Apaga LED VERDE.
 }
}

Para detectar la conexión con el host usamos las funciones antes vistas : usb_attach() , usb_dettach() , pero además usamos una variable que nos indique la conexión/desconexión. Esta varible es
Código:
short estado_usb;   // boolean global, se debe declarar antes de llamar a usb_cdc.h

Esta variable se usa en la librería usb_pic18, en la que modifique un par de lineas para que me mostrara el estado de la conexión.

Código:
/******************************************************************************
/* usb_detach()
/*
/* Summary: Remove the D+/D- lines from the USB bus.  Basically, disable USB.
/*
/*****************************************************************************/
void usb_detach(void) {  //done
   // Definimos un boolean que nos dice el estado de la conexión.   
   estado_usb = false;
   delay_ms(50); // espero 50ms.
   UCON=0;  //disable USB hardware
   UIE=0;   //disable USB interrupts
   UCFG = __UCFG_VAL_DISABLED__;
   set_tris_c(*0xF94 | 0x30);
   usb_state=USB_STATE_DETACHED;
   usb_token_reset();              //clear the chapter9 stack
   __usb_kbhit_status=0;
}

/******************************************************************************
/* usb_attach()
/*
/* Summary: Attach the D+/D- lines to the USB bus.  Enable the USB peripheral.
/*
/* You should wait until UCON_SE0 is clear before enabling reset/idle interrupt
/*
/*****************************************************************************/
void usb_attach(void) {
   usb_token_reset();
    // Definimos un boolean que nos dice el estado de la conexión.   
   estado_usb = true;
    delay_ms(50); // espero 50ms.
    UCON = 0;
    UCFG = __UCFG_VAL_ENABLED__;
    UIE = 0;                                // Mask all USB interrupts
    UCON_USBEN = 1;                     // Enable module & attach to bus
    usb_state = USB_STATE_ATTACHED;      // Defined in usbmmap.c & .h
}

En el código fuente del firmware , use la función usb_init_cs(). Esta función es muy importante ya que como dijimos antes , me permite realizar otras tareas mientras el host no esté conectado.

Bueno las librerías usadas son las mismas , menos usb_pic18 que hay que hacerle la modificación que puse más arriba.

El código fuente del programa es el siguiente:

Código:
' Programa de ejemplo que envía un caracter al PIC. El mismo responde devolviendo
' una cadena de respuesta que hace heco del caracter recibido. Mientras el HOST no evíe
' ninguna cadena, el PIC cumplira otras funciones.
' el uso de bandera permite averiguar varios datos para confirmar el estado real
' de la conexión

Option Explicit
' Declaramos variables.
Dim value As Long
Dim bandera As Boolean ' Bandera para saber cuando el host está conectado.
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.InBufferSize = 16  '16 caracteres
MSComm1.InputLen = 16  ' Buffer de entrada.
MSComm1.RThreshold = 16
MSComm1.PortOpen = True
End Sub

Private Sub envio_Click()
    Timer1.Enabled = False

    If MSComm1.PortOpen = True Then
      MSComm1.Output = "m"
    End If
    Timer1.Enabled = 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 = 10
Timer1.Enabled = True 'activamos el ciclo de escan.
bandera = False
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
    recibo.Text = ""
    recibo.Text = Left$(InBuff, 16)  ' se recorta los caracteres basura
    MSComm1.PortOpen = False  'cierra el puerto y vacia el buffer
    Espera 2  ' Retardo de  2 segundos.
    recibo.Text = ""
End Select
End Sub
Private Sub Timer1_Timer()
On Error GoTo paca
DoEvents
If MSComm1.PortOpen = True Then
    DoEvents
    estado.Caption = "CONECTADO"
    Debug.Print "Conectado"
    MSComm1.PortOpen = False
    Exit Sub
Else
    DoEvents
    MSComm1.PortOpen = True
    Exit Sub
End If
paca: Debug.Print Err.Number & ": " & Err.Description
     Select Case Err.Number
        Case 8002   'Número de puerto no válido
            DoEvents
           estado.Caption = "DESCONECTADO"
        Case 8005 'el puerto ya está abierto
            DoEvents
            estado.Caption = "ABIERTO"
        Case 8012 '8012 el dispositivo no está abierto
            DoEvents
            estado.Caption = "DESCONECTADO"
        Case 8015
            DoEvents    ' para evitar retardos en bucles
            estado.Caption = "DESCONECTADO"
    End Select
      Exit Sub
End Sub
' Procedimiento de retardo.
Sub Espera(Segundos As Single)
  Dim ComienzoSeg As Single
  Dim FinSeg As Single
  ComienzoSeg = Timer
  FinSeg = ComienzoSeg + Segundos
  Do While FinSeg > Timer
      DoEvents
      If ComienzoSeg > Timer Then
          FinSeg = FinSeg - 24 * 60 * 60
      End If
  Loop
End Sub
 

Adjuntos

  • ejercicio_n5_347.rar
    76.3 KB · Visitas: 957
Lo único que hace falta es un ejemplo concreto , de como usar la clase CDC con toda la información hasta ahora recabada. Y luego podemos pasar de lleno a estudiar la mpusbapi.dll o también llamado comunicación por bulck tranfer (transferencia de paquetes de datos).
 
El ejemplo que vamos a desarrollar va a requerir de otros conocimientos. En concreto: Como funciona el CAD del microcontrolador PIC18F2550.

CAD: Conversor analógico digital.

Luego podremos seguir con los ejemplos.

PD: He decidido ponerme a estudiar bien la programación en Visual C# , mientras tanto los ejemplos los estoy desarrollando en Visual Basic 6.0 , cuando entienda bien la programación en Visual C# pasaré todos los ejemplos que hemos visto a ese lenguaje.
 
Moyano Jonathan dijo:
El ejemplo que vamos a desarrollar va a requerir de otros conocimientos. En concreto: Como funciona el CAD del microcontrolador PIC18F2550.

CAD: Conversor analógico digital.

Lo del CAD se usa mucho. Sería muy bueno ejemplos de estas cosas y controlado por USB.

Luego podremos seguir con los ejemplos.

PD: He decidido ponerme a estudiar bien la programación en Visual C# , mientras tanto los ejemplos los estoy desarrollando en Visual Basic 6.0 , cuando entienda bien la programación en Visual C# pasaré todos los ejemplos que hemos visto a ese lenguaje.

¿Y ahora como que te dio por pasar a ese lenguaje Visual C#?
 
Jajaja si meta lo estoy estudiando de a poco porque se me hizo .....como decir un cuello de botella de lenguajes. Lo del CAD tenés razón que se usa mucho por eso voy a tratar de que la información sea buena , voy a tratar de que se entienda lo mejor posible. Por la red hay proyectos muy buenos para realizar con el CAD. Luego de ver el tema del cad y del usb voy a ir viendo los otros módulos como el spi el i2c usart comparador/capturador/pwm en fin todo lo que esté a mi alcanze de conocimientos (y dinero).

PD: Elejí visual C# por que hay bastante información al respecto, incluso más que para visual basic 2008, pero voy a ir despacio.
También voy a ver si filmo algunos videitos como para que tengan de muestra.
 
una consulta jonathan...
estube viendo el codigo fuente del pic en este pedazo:

usb_init_cs(); // inicia el USB y sale. Va de la mano con usb_task().
while(true){
usb_task(); // configura el USB.
estado_conexion_usb(estado_usb); // Se fija en el estado de la conexión usb.
if(usb_cdc_connected()){ // Si está conectado entonces....
// Espera a detectar una transmisión de la PC (Set_Line_Coding).
if (usb_enumerated()){ // aquí se enumera el dispositivo por el host y despúes sale.
if(usb_cdc_kbhit()){ //en espera de nuevo(s) caracter(es) en el buffer.

ahi, en la linea donde esta "usb_task(); // configura el USB." es necesario que lo configures al puerto usb en cada iterasion del while?
y lo mismo me pregunto con el usb_enumerated, este ultimo no se enumera cuando el sistema operativo lo reconoce?
disculpa mi ignorancia pero nunca me puse a usar el usb, siempre intente pero nunca tube tiempo y ahora estoy un poco mas libre
 
Si el usb_task(), es necesario por que se fija continuamente en el estado de la conexión (por hardware) del pic con host, utilizando para esto el pin sense.
Usb_enumerated() es como decirte....un juego de preguntas y respuestas que hace el pic con el host en donde se preguntan mutuamente si están listos para recibir/trasmitir datos. Cuando el sistema operativo reconoce al pic, solo hace eso "reconocerlo" y luego establece un puerto de comunicaciones (lo explicare más adelante)

espero lo entiendas , cualquier cosa decime.
 
Atrás
Arriba