Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                

Introducción Al Bus Usb

Descargar como pdf o txt
Descargar como pdf o txt
Está en la página 1de 25

Ing. Carlos A. Narváez V.

INTRODUCCIÓN AL BUS USB


El Bus Universal Serie (en inglés: Universal Serial Bus), más conocido por la sigla
USB, es un bus serial de alta velocidad que también puede proporcionar energía a
los dispositios conectados a él. Su especificación define los cables, conectores y
protocolos usados para conectar, comunicar y proveer de alimentación eléctrica
entre computadoras, periféricos y dispositivos electrónicos.
Su desarrollo partió de un grupo de empresas del sector que buscaban unificar la
forma de conectar periféricos a sus equipos, por aquella época poco compatibles
entre sí, entre las que estaban Intel, Microsoft, IBM, Compaq, DEC, NEC y Nortel. La
primera especificación completa 1.0 se publicó en 1996, pero en 1998 con la
especificación 1.1, comenzó a usarse de forma masiva.
El USB es utilizado como estándar de conexión de periféricos como: teclados,
ratones, memorias USB, joysticks, escáneres, cámaras digitales, teléfonos móviles,
reproductores multimedia, impresoras, dispositivos multifuncionales, sistemas de
adquisición de datos, módems, tarjetas de red, tarjetas de sonido, tarjetas
sintonizadoras de televisión y grabadoras de DVD externa, discos duros externos y
disqueteras externas entre otros.

Los dispositivos USB se clasifican en cuatro tipos según su velocidad de


transferencia de datos:

• Baja velocidad (1.0): Soportado por las especificaciones 1.1, 2.0 y 3.0.Tasa
de transferencia de hasta 1,5 Mbit/s (188 Kb/s). Utilizado en su mayor parte
por dispositivos de interfaz humana (Human Interface Device), o HID en
inglés) como los teclados, los ratones (mouse), las cámaras web, etc.

• Velocidad completa (1.1): Soportado por USB 1.1, USB 2.0 y USB 3.0. Tasa
de transferencia de hasta 12 Mbit/s (1,5 MB/s). Ésta fue la versión más
rápida antes de la especificación USB 2.0.

 Alta velocidad (2.0): Solo USB 2.0 y USB 3.0. Tasa de transferencia de hasta
480 Mbit/s (60 MB/s) pero con una tasa real práctica máxima de 280
Mbit/s (35 MB/s). Ejemplo transmisiones de video.

 Superalta velocidad (3.0): Sólo soportado en dispositivos USB 3.0 Tiene una
tasa de transferencia de hasta 4,8 Gbit/s (600 MB/s). La velocidad del bus es
diez veces más rápida que la del USB 2.0, debido a que han incluido 5
contactos adicionales, desechando el conector de fibra óptica propuesto
inicialmente, y es compatible con los estándares anteriores. En octubre de
2009 la compañía taiwanesa ASUS lanzó la primera placa base que incluía
puertos USB 3.0, tras ella muchas otras le han seguido y actualmente se ve
cada vez más en placas base y portátiles nuevos, conviviendo junto con el
USB 2.0. Otra de las características de este puerto es su "regla de
inteligencia": los dispositivos que se enchufan y después de un rato quedan
en desuso, pasan inmediatamente a un estado de bajo consumo.

Un bus USB soporta hasta 127 dispositivos (limitado por un campo de direcciones
de 7 bits teniendo en cuenta que la dirección 0 no se utiliza, ya que tiene un
propósito especial) conectado a través de una cable serie de cuatro hilos de hasta
tres o incluso cinco metros de longitud. Muchos dispositivos USB pueden ser
conectados al mismo bus usando hubs, los cuales pueden tener 4, 8, o incluso 16
puertos.
Un dispositivo puede ser conectado a un hub que se conecta a otro hub, y así
sucesivamente. El número máximo de niveles permitido es de seis. De acuerdo con
la especificación, la distancia máxima de un dispositivo a su host es de unos treinta
metros, realizada usando cinco hubs. Para la comunicaciones de mayor distancia,
se recomienda otros métodos como el uso de Ethernet.
USB es una interfaz de cuatro hilos implementada usando un cable blindado con
impedancia de 90 Ω ± 15% . Las señales USB se transmiten utilizando un par de
hilos denominados D+ y D-, utilizando señalización diferencial en half duplex
excepto el USB 3.0 que utiliza un segundo par de hilos para realizar una
comunicación en full Duplex. La razón por la cual se realiza la comunicación en
modo diferencial es simple, reduce el efecto del ruido electromagnético en
enlaces largos.
Cuenta con tecnología "Plug&Play" la cuál permite conectar, desconectar y
reconocer dispositivos sin necesidad de reiniciar ó apagar la computadora. Este
puerto sólo admite la conexión de dispositivos de bajo consumo, es decir, que
tengan un consumo máximo de 100 mA por cada puerto; sin embargo, en caso de
que estuviese conectado un dispositivo que permite 4 puertos por cada salida USB
(extensiones de máximo 4 puertos), entonces la energía del USB se asignará en
unidades de 100 mA hasta un máximo de 500 mA por puerto. Con la primera
fabricación de un PC con USB 3.0 en 2009, ahora tenemos 1 A por puerto, lo cual da
5 W en lugar de 0,5 A o 2,5Wcomo máximo.

CONECTORES USB

Los puertos USB 1.0 y USB 2.0 tienen 4 contactos, mientras que el puerto USB 3.0
cuenta con 9; usan tres tipos de conectores especificados como tipo A, tipo B y
MiniUSB.

Conectores tipo A, B y MiniUSB

Asignación de Pines Conectores tipo A, B y MiniUSD

Pin Nombre Color de cable Descripción

1 VCC Rojo +5 V

2 D− Blanco Data −

3 D+ Verde Data +

4 GND Negro Tierra


Conectores tipo A y B USB 3.0

Conectores Hembra Tipo A y B USB 1.0 y 2.0

USB tipo A USB tipo B USB mini

Variante del
Puerto USB integrado en la Variante del puerto USB
puerto USB integrado en
tarjeta principal integrado en dispositivos
dispositivos grandes
("Motherboard") pequeños

USB UTILIZA CODIFICACIÓN NRZI

En esta técnica de codificación de datos, NRZI (Non return to zero invert), el nivel
de la señal es invertida por cada cambio a un 0 lógico. El nivel de la señal para cada
1 lógico no es cambiada. Existe un bit de relleno (stuffing bit) para comprobar que
se está manteniendo una comunicación adecuada y depurar errores, este bit
stuffing consiste en generar una cambio en la señal cuando esta se mantenga en
uno "1" durante seis periodos consecutivos. En la siguientes figuras se observan la
codificación de datos en NRZI.

Codificación NRTZI
TERMINOLOGÍA USB

Stream Pipes: se trata de un flujo sin formato USB definido, esto significa qLos
acostumbrados a utilizar interfaces de comunicación más simples, como el RS-232,
se encuentra que en la comunicación USB aparecen una serie de términos nuevos
como: Endpoint, Pipes, Transacciones, Clases, Enumeración, Descriptores etc. que
al principio pueden resultar difíciles de entender, por lo que abordaremos
primeramente algunos de estos término:

Host: Dispositivo maestro que inicia la comunicación (Generalmente la


computadora).

Hub: Dispositivo que contiene uno o mas conectores o conexiones internas hacia
otros dispositivos usb, el cual habilita la comunicación entre el host y con diversos
dispositivos. Cada conector representa un puerto USB.

Dispositivo compuesto: Es aquel dispositivo con múltiples interfaces


independientes. Cada una tiene una dirección sobre el bus pero cada interface
puede tener un driver diferente en el host.

Puerto USB: Cada host soporta sólo un bus, cada conector en el bus representa un
puerto USB por lo tanto sobre el bus puede haber varios conectores , pero sólo
existe una ruta y sólo un dispositivo puede transmitir información a un tiempo.

Driver: Es un programa que habilita aplicaciones para poderse comunicar con el


dispositivo. Cada dispositivo sobre el bus debe tener un driver, algunos periféricos
utilizan los drivers que trae Windows.

Puntos terminales (Endpoints): Los endpoint son simplemente buffer de memoria


RAM que son utilizados para el envío y recepción de datos o comandos de control
durante una comunicación USB. Cada endpoint puede ser de entrada o salida de
datos o bidireccional, el endpoint 0 está reservado para comandos de control, el
proceso de enumeración se realiza a través del endpoint número 0. Este concepto
sólo se aplica al dispositivo, en el host existen también buffer para el envío y
recepción de datos pero no se les denomina con este nombre.

Tuberías (Pipes): Es una conexión lógica o virtual entre un Endpoint del dispositivo
USB y el software del controlador del host (la PC) que se produce tras el proceso de
enumeración. Este enlace configura los parámetros asociados con el ancho de
banda, que tipo de transferencia se va a utilizar (Control, Bulk, Isocrona o Interrupt)
dirección del flujo de datos IN OUT y el máximo y/o mínimo tamaño de los
paquetes/buffers. Cada enlace está caracterizado por su banda de paso (Token), su
tipo de servicio, el número de punto terminal (EndPoint) y el tamaño de los
paquetes. Estos enlaces se definen y crean durante la inicialización del USB.
Siempre existe un enlace virtual 0 que permite tener acceso a la información de
configuración del periférico USB (estado, control e información). Los Pipes se usan
mucho en Sistemas Operativos como UNIX/LINUX para enlazar la salida de un
proceso con la entrada de otro, en este caso el concepto es el mismo. La norma
USB define 2 tipos de enlaces virtuales; stream y message.ue se puede enviar
cualquier tipo de dato. Este tipo de pipe soporta las transferencias bulk, isocronas, y
interrupt.
Message Pipes: este tipo de enlace virtual tiene un formato USB definido y sólo
puede soportar la transferencia Control.

COMUNICACIÓN USB

USB es un sistema de conectividad centrado en el host, en decir, el anfitrión dirije el


uso del bus USB. Cada dispositivo en el bus se le asigna una dirección única USB, y
ningún dispositivo esclavo puede usar el bus hasta que el anfitrión no se lo solicite.
Cuando se conecta un nuevo dispositivo USB al bus, el anfitrión USB utiliza la
dirección 0 para pedir información básica del dispositivo. Entonces el anfitrión le
asigna una dirección única USB. Después el anfitrión pide y recibe mayor
información sobre el dispositivo, como el nombre del fabricante, las capacidades
del dispositivo, y la identificación del producto, Luego de esto, las transacciones
bidireccionales en el bus pueden comenzar.

TRANSFERENCIAS USB

Isochronous o Flujo en tiempo real: Modo utilizado para la transmisión de


audio o video comprimido. Este tipo de transmisión funciona en tiempo real. Este
es el modo de mayor prioridad. La transmisión de la voz es Una transferencia se
puede definir como el conjunto global de los datos que forman una comunicación
USB, una transferencia está formada a su vez por una o varias transacciones que a
su vez están formadas por diferentes paquetes de datos que contienen las tramas
de una comunicación USB. No existe un formato único de transferencia, la
especificación USB permite cuatro tipos de transferencias:

Control: Modo utilizado para realizar configuraciones. Existe siempre sobre el Punto
terminal 0 (EndPoint 0). Todos los dispositivos USB deben soportar este tipo de
transferencia.

Se utiliza para configurar y obtener información sobre el dispositivo, envío o


recuperación de informes sobre la situación del dispositivo. Los datos enviados son
generalmente de pequeño tamaño. Cada dispositivo USB tiene un tipo de
transferencia de control denominado "endpoint 0" que es utilizado por el núcleo
para configurar el dispositivo USB cuando es insertado. Estas transferencias están
garantizadas a través del protocolo USB que siempre va a disponer de suficiente
ancho de banda.
Interrupt: Modo utilizado para transmisiones de pequeños paquetes, rápidos,
orientados a percepciones humanas (ratón, punteros). Este tipo de transferencia
son para dispositivos que deben recibir atención periódicamente y lo utilizan los
dispositivos de baja velocidad. Este tipo de transmisión garantiza la transferencia
de pequeñas cantidades de datos. El tiempo de respuesta no puede ser inferior al
valor especificado por la interfaz. El ratón o cualquier otro dispositivo apuntador es
una aplicación típica de este modo de transmisión.

Bulk: Este tipo transfiere grandes cantidades de datos. Estos datos son
normalmente mucho más numerosos que los transmitidos por la transmisión tipo
interrupción. Es usado normalmente por los dispositivos que necesitan transferir
cualquier cantidad de información sin pérdida de datos. Estas transferencias no
están garantizadas por el protocolo USB. Si no hay suficiente espacio en el bus para
enviar el paquete en su totalidad, se separan a través de múltiples transferencias
hacia o desde el dispositivo. Estos tipos son comunes en las impresoras,
almacenamiento y dispositivos de red.un ejemplo de esta aplicación. Si ésta no se
transmite correctamente, pueden llegar a oírse parásitos (glich) y la aplicación
puede detectar ciertos errores de los llamados underruns.
PAQUETES

Existen cuatro tipos de paquetes de datos como unidades de transacion básico en


el USB: "SOF", "token", "data", y "handshake". Cada paquete incluye un campo ID
(PID) de 8 bits. Un paquete de comienzo de trama (SOF) de 24 bits incluyendo el
PID, un numero de Frame de 11 bits, y un CRC de 5 bits. Un paquete token es
también de 3 bytes y es usado para pasar temporalmente el control a cada
dispositivo. El paquete de datos tiene además del PID un CRC de 16 bits, y un
campo de datos de longitud variable ente 0 y 1023 bytes. El paquete de Handshake
tiene solamente el campo PID. Es usado para informar sobre el estado de las
transferencias de todos los tipos excepto la isocrónica.

Toda transacción tiene un paquete de token. El host es siempre la fuente de este


paquete Configura la transacción identificando: El dispositivo que lo recibe, el
endpoint y el sentido de cualquier dato que la transacción vaya a transferir

Dependiendo del tipo de transferencia y si es el host o el dispositivo que tiene


información a enviar, un paquete de datos precede al paquete de token. El sentido
especificado en el paquete de token determina cuando el host o el dispositivo envía
el paquete de datos. En todos los tipos de transferencias exceptuando las
isochronous, el receptor de el paquete de datos retorna un paquete de handshake
conteniendo un código indicando si la transacción fue exitosa o falló.

ENUMERACION

Cuando un dispositivo USB es conectado al bus USB del Host, este es reconocido
por el Host a través de un proceso llamado Enumeración. Los pasos que se siguen
en el proceso de enumeración son los siguientes:

• Cuando un dispositivo es conectado, el Host se da cuenta de ello, debido a


que una de las líneas de datos (D+ o D-) pasa a lógico alto .
• El host envía una señal de reinicio USB al dispositivo para colocarlo en un
estado conocido. El dispositivo responde a la dirección 0.
• El host envía una solicitud en la dirección 0 al dispositivo para averiguar su
tamaño máximo de paquete mediante un comando Get Descriptor.El
dispositivo responde enviando una pequeña parte del descriptor del
dispositivo.
• El host envía restablecer USB (reset) nuevamente.
• El host asigna una dirección única para el dispositivo y envía una solicitud set
address request al dispositivo. Después de que la solicitud se ha completado,
el dispositivo asume la nueva dirección. En este punto, el host es libre para
resetear cualquier otro dispositivo que haya sido recién conectado.
• El host envía una solicitud Get Descriptor Device para recuperar por completo la
información del descriptor de dispositivo, obteniendo así datos como,
fabricante, tipo de dispositivo, y tamaño máximo de paquete de control.
• El host envía una solicitud GET descriptores de configuración para recibir del
dispositivo los datos de configuración, tales como los requisitos de energía y
los tipos y número de las interfaces compatibles.
• El host puede solicitar cualquier descriptor adicional al dispositivo.

La comunicación inicial entre el host y el dispositivo se lleva a cabo usando


transferencia tipo control. Inicialmente, el dispositivo está direccionado, pero en
estado no configurado. Después de que el host obtiene suficiente información sobre
el dispositivo, carga un controlador de dispositivo adecuado que configura el
dispositivo mediante el envío de una solicitud de Set configuration. En este punto,
el dispositivo ha sido configurado, y está listo para responder a peticiones
específicas (es decir , puede recibir datos desde y enviar datos al host ).

DESCRIPTORES
Todo dispositivo USB tiene una jerarquia de descriptores que describen varias
características del dispositivo: la identificación del fabricante, la versión de USB que
soporta, que dispositivo es, sus requerimiento de energía, el número y tipo de
endpoints, etc.
Los descriptores USB más comunes son:
• Descriptores de dispositivos: Contiene información sobre el máximo
tamaño de paquete que soporta el Endpoint0, cuántas configuraciones
soporta el Esclavo, y otra información. Es el primero que lee el Host.
• Descriptores de configuracion: Existe uno por cada posible forma de
operar del Esclavo (solo puede haber una configuración activa en un
determinado momento). Tiene información sobre cuántas Interfaces existen
por configuración.
• Descriptores de Interfaces: Tiene información sobre el número de
Endpoints (excepto el Endpoint0) que utiliza al Interface y sobre la Clase a la
que pertenece.
• Descriptores HID: Ideada con el propósito de englobar a dispositivos que
permitan la interacción del usuario (ser humano) con el Host. Mouse,
teclado.
• Descriptores de Endpoints: Existe uno por cada Endpoint de una Interface.
Tiene información sobre el número de Endpoint. También sobre el tipo de
Transferencia que realiza (Control, Interrupt, Bulk o Isochronous). Y también
tiene información sobre el tamaño máximo de paquete del Endpoint.

Los descriptores forman una estructura jerarquica como se muesta en la siguiente


figura.

Las Clases USB


Una clase es un modelo o plantilla que describe el estado y el comportamiento de
los objetos que la comparten. La clase provee de propiedades y métodos
(funciones) reutilizables por los objetos o miembros que comparten la clase. Esta
definición general de clase utilizada en la programación orientada a objetos es la
mejor manera dedefinir este concepto utilizado en USB. La especificación USB
provee de propiedades y funciones que pueden ser utilizadas por los dispositivos
que tengan características similares. Por ejemplo, un teclado y un ratón por sus
características pertenecerán a la misma clase la llamada Human Interface Device
(HID), pues bien si yo diseño el firware de un dispositivo con las especificaciones
que me exige esta clase podré beneficiarme de esas propiedades y funciones
comunes a la clase, una ventaja de utilizar esta clase por ejemplo es que no se
necesita instalar ningún driver para el dispositivo ya que el sistema operativo
utilizará uno genérico para todos.

La Clase de dispositivo HID


El nombre HID es la abreviatura de “Human Interface Devices”. Esta Clase, cuya
versión actual es el estándar HID 1.11 fue ideada con el propósito de englobar a
dispositivos que permitan la interacción del usuario (ser humano) con el Host. Por lo
tanto, los requerimientos de ancho de banda son mínimos, y la transferencia de
datos debe ser confiable. Los datos que los dispositivos HID envían al Host son
interpretados por el HID Class Driver del sistema operativo, para luego poder ser
utilizados por la aplicación que los requiera (Client Software). Los dispositivos HID
se comunican con el HID Class Driver mediante la (Default) Control Pipe o mediante
Interrupt Pipes. Los requisitos para la implementación de un dispositivo HID son:
– Control Endpoint (Endpoint0): obligatorio
– Interrupt IN Endpoint: obligatorio
– Interrupt OUT Endpoint: opcional

Los ejemplos típicos de dispositivos de clase HID son: Teclados y dispositivos


señaladores (tales como ratones, joysticks y trackballs) controles del panel frontal
(por ejemplo botones, perillas, deslizadores, y los interruptores) dispositivos de
simulación (como volantes, pedales, otros dispositivos de entrada VR) controles y
teclas del teléfono remoto. Otros dispositivos de baja velocidad de datos que
proporcionan, por ejemplo, los datos ambientales (tales como termómetros,
medidores de energía o incluso los lectores de códigos de barras).

La Clase de dispositivo CDC


CDC (Communications Device Class): La velocidad máxima al utilizar esta clase es
de 80 kBytes/s y el tipo de transferencias soportadas son del tipo interrupción y
Bulk. Ejemplo de dispositivos que utilizan esta clase son los Modems. Utiliza
también driver estándar incluidos ya en el sistema operativo, según el sistema
operativo utilizado precisará o no de la instalación del archivo .INF, cuando
utilizamos esta clase en el PC nos creará un puerto serie virtual y la comunicación
entre el dispositivo y la aplicación de escritorio se hará a través de el al igual que se
haría con un puerto serie físico, esto supone una gran ventaja a la hora de diseñar
la aplicación de escritorio, ya que cualquier IDE de programación sea del lenguaje
que sea, dispone de un componente o librería que permite el acceso al puerto serie
fácilmente.

La Clase MSD

MSD (Mass Storage Device Class): Como su propio nombre indica es usada en
dispositivos de almacenamiento masivo como discos duros, memorias flash,
cámaras digitales, dispositivos ópticos externos como lectores y grabadoras de CD
y DVD, etc. Esta clase se puede utilizar solo en dispositivos que soporten
velocidades Full y High Speed. El tipo de transferencias utilizadas es Bulk o una
combinación formada por transferencias del tipo Control, Bulk y Interrupt. El CCS C
también implementa ejemplos sobre esta clase. No se necesita la instalación de un
driver específico, se utilizan drivers genéricos instalados ya en los Sistemas
Operativos, en Windows se utiliza el driver llamado usbstor.sys ubicado en
C:\Windows\Sistem32\drivers.

Existe una clase genérica llamada "Custom Class" que se utiliza cuando el
dispositivo no se asemeja a las características de ninguno de los miembros
pertenecientes a otras clases. un ejemplo de dispositivo que utiliza esta clase es el
ICD2 o ICD3 de Microchip.

USB EN WINDOWS
Si el firware de nuestro dispositivo no cumple con las especificaciones de alguna de
las clases que se benefician del uso de drivers genéricos ya instalados en el sistema
operativo, no queda otra que diseñar un driver para nuestro dispositivo, sino el
dispositivo no será reconocido por el PC. Diseñar un driver desde cero es muy
complicado ya que se requiere profundos conocimientos tanto de la arquitectura del
PC como del Sistema Operativo que tenga instalado. Afortunadamente ya hay
drivers personalizados que podemos utilizar en nuestros proyectos, algunos de ellos
son los siguientes:

Microchip proporciona los siguientes archivos:

mchpusb.sys es el driver en si y sólo está disponible en formato binario.


mchpusb.ini este archivo contiene información del driver y es requerido por el
sistema operativo, cuando el dispositivo se conecta por primera al PC, de manera
que este último sepa que driver asignarle. El S.O. también obtiene información de
este archivo para configurar correctamente el dispositivo. Es un archivo de texto
que se puede editar y modificar algunas cosas en el, como los valores del VID y PID
que deben de coincidir con los definidos en los descriptores del dispositivo.
También se pueden modificar algunas cadenas de texto que se mostraran como
información del dispositivo una vez instalado el driver en el S.O; lo demás es mejor
no tocarlo si queremos que nuestro dispositivo funcione.

La DLL mpusbapi: una dll es una capa software que en este caso facilita por medio
de funciones la comunicación entre la aplicación de escritorio y el driver del
dispositivo. Esta dll está compilada con el compilador de Borland C++ Builder 6.
Microchip facilita su código fuente, por lo que hay dos formas de utilizarla. Si
utilizamos el mismo IDE de Borland para crear nuestra aplicación de escritorio,
simplemente tendremos que añadir la librería (el archivo mpusbapi.lib) a nuestro
proyecto como una librería más. Si se utiliza otro compilador, se debe compilar de
nuevo los fuentes de la librería para obtener una nueva versión del archivo
mpusbapi.lib que sea compatible con el compilador utilizado. La otra opción de
utilización de la librería es añadirla a nuestro proyecto de forma dinámica, para ello
solo se necesita el archivo con extensión .dll (mpusbapi.dll) proporcionado también
por Microchip, de esta forma si utilizamos un compilador diferente como los que nos
proporciona Microsoft en su plataforma .NET u otros como LabVIEW, Matlab,
RealBAsic, etc. No tendremos que modificar el código fuente de la DLL,
simplemente la utilizaremos importando las funciones públicas de la DLL desde
nuestra aplicación de escritorio.

Microchip proporciona ejemplos de ambas formas. Como veis todo esto del USB da
pie a realizar las cosas de diferentes formas, más adelante en otro ejemplo veremos
estás dos posibilidades. Pero ¿por que utilizar esta opción y no utilizar siempre las
clase CDC, MSD o HID que a priori parece más fácil su utilización? Simplemente
porque utilizando un driver personalizado en vez de los genéricos que proporciona
Windows obtenemos una comunicación USB más versátil y con mayores
prestaciones. Por ejemplo, en cuanto a velocidad podremos alcanzar velocidades de
hasta 1MB/s frente a los 64 KB/s de la clase HID y los 80 kBytes/s de la clase CDC,
además el driver de Microchip soporta todos los tipos de transferencia (Control,
Isócronas, Interrup y Bulk), cosa que no ocurre igual si utilizamos las otras clases
como ya hemos visto.

En su última versión este driver está soportado por los siguientes sistemas
operativos: Windows 2000, Windows Server 2003, Windows XP, Windows XP 64,
Windows Vista, Windows Vista 64 y Windows 7.
cuando utilizamos el driver personalizado de Microchip los datos se transmiten en
raw (crudo) y la aplicación de escritorio intercambia información con el PIC
directamente a través de los enpoints utilizados por este, en este caso se usa un
protocolo de comunicación que a priori no está definido. Es importante que
copiemos del archivo .INF el valor del campo definido como GUI (Global Unique
Identifier), que es un número que sirve para que la aplicación pueda acceder al
dispositivo, luego accederemos a la dll desde el IDE que hallamos elegido para
desarrollar la aplicación de escritorio editaremos las propiedades y funciones
publicas de la dll buscando un campo que se llame GUI (o algo así) y si no coincide
tendremos que pegar ese número, si no lo hacemos no se podrá crear la tubería de
conexión (pipe) entre nuestra aplicación y el driver.
Cuando utilizamos la clase CDC esto no es necesario ya que la comunicación está
definida a través del puerto serie virtual creado y la información se transmite por
defecto en forma de caracteres ASCII al igual que un puerto serie físico.

Otros drivers que podemos utilizar para nuestro PIC 18fx550 son:

WinUSB: es el driver genérico para USB que propone utilizar Microsoft cuando
nuestro dispositivo no puede ser manejado directamente por los drivers que ya
incluye por defecto en su sistema operativo. Para ello al igual que Microchip
proporciona los siguientes archivos: Winusb.sys, Winusb.ini y la librería dinámica
Winusb.dll que al igual que la dll de Microchip nos proporciona una serie de
funciones públicas para acceder fácilmente al driver y a las APIs win32 de Windows
desde nuestra aplicación de escritorio.
Toda la información que proporcionada Microsof sobre este driver se puede
encontrar en el siguiente enlace.

USB del PIC 18F4550

Los pines 23 y 24 denominados RC4/D-/VP y RC5/D+/VP presentan las señales D- y


D+ respectivamente del puerto USB.
PIN VUSB del PIC4550
Los dispositivos PIC18FX455 / X550 han incorporado un regulador de 3.3V para
proporcionar potencia al transceiver USB interno y proporcionar una fuente para los
pull-ups internos/externos. Se requiere un condensador externo de 220 nF (± 20 %)
para la estabilidad. El regulador está activado de forma predeterminada y se puede
desactivar a través del bit de configuración VREGEN. En CCS C existe un FUSES
para activarlo VREGEN y otro para desactivarlo NOVREGEN. Cuando está activado,
la tensión es visible en el pin VUSB, pin 18 en el PIC18F4550. Cuando el regulador
está desactivado, una fuente de 3.3V debe ser proporcionada a través del pin VUSB
para el transceiver interno. Si el transceiver está desactivado, el pin VUSB no se
utiliza.

UTILIZANDO USB CON UN CRISTAL EXTERNO DE 20MHZ


El USB trabaja con una frecuencia de 48MHZ y el CPU del PIC18F4550 también
puede trabajar a esta frecuencia. Si utilizamos como oscilador externo un cristal de
20MHz, la datasheet especifica los bits de configuración necesarios para ello. El PIC
recibe la señal de su cristal externo y usa un preescalador que divide su frecuencia
(dependiendo de sus registros de configuración), entre alguno de los siguientes
valores: 1, 2, 3, 4, 5, 6, 10, ó 12. La entrada al circuito PLL debe ser siempre de 4
Mhz. En el caso de funcionamiento a 20 Mhz, la división del preescalador es entre 5
(PLL5).
Estos 4 Mhz pasan a través del PLL y generan a su salida 96 Mhz, los cuales a su
vez se dividen entre 2 (USBDIV) para dar finalmente la señal de 48 Mhz, con la cual
se obtiene un funcionamiento del puerto USB a la velocidad máxima de 12 Mbps.
Esta velocidad permite la comunicación del puerto USB del microcontrolador
18F4550, con cualquier Host. Para que el CPU trabaje a 48MHZ se requiere además
dividir los 96Mhz del PLL entre 2 (CPUDIV1).
Existen multiples configuraciones dependiendo del valor del oscilador externo por lo
que remitimos al lector a la datasheet del dispositivo.
Las siguientes líneas de código de CCS C son válidas para un oscilador externo de
20MHZ.

#include <18F4550.h>
#fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN

#use delay(clock=48000000)

USB en CCS C
CCS suministrar librerías para comunicar PIC con el PC utilizando el bus USB,
mediante perifericos internos (PIC18F4550 o el PIC16C765) o mediante dispositivos
externos al pic (del tipo USBN9603).
Las librerías suministradas son:

ex_usb_common.h //Common hardware definitions and configuration for all of


//CCS's USB example programs (ex_usb_*.c)
pic18_usb.h //Microchip PIC18Fxx5x hardware layer for usb.c
usb_desc_hid.h //USB Configuration and Device descriptors for
// this UBS device
usb.c //handles usb setup tokens and get descriptor reports

El VID (Vendor ID) y el PID (Product ID) son dos números de 16 bits representados
en Hexadecimal. Si se utiliza la clase CDC (Communications Device Class) de CCS
para la comunicación USB estos valores los podemos modificar en el archivo
"usb_desc_cdc.h", y si se utiliza la clase HID en el archivo “usb_desc_hid.h”. Según
el sistema operativo instalado en el Host, se debe modificar también en el archivo
.inf del driver utilizado.

Programa Ejemplo para el PIC utilizando HID

/////////////////////////////////////////////////////////////////////////
//// ////
//// ex_usb_hid.c ////
//// ////
//// A simple demo that shows how to use the HID class to send ////
//// and receive custom data from the PC. Normally HID is used ////
//// with pre-defined classes, such as mice and keyboards, but ////
//// can be used for vendor specific classes as shown in this ////
//// example. ////
//// ////
//// The first byte sent by the PIC is the ADC reading ////
//// on channel 0 (AN0), the second byte is the status of the ////
//// pushbutton. The two bytes sent by the PC are LED on/off ////
//// toggle status. ////
//// ////
//// Hemos realizado un programa ejemplo para windows usando ////
//// visual basic express 10 que lee y escribe el dispositivo HID ////
//// de este ejemplo y que denominamos USBHID.exe, usa el controlador////
//// EasyHid mcHID.dll ////
/// ////
//// Normally this program sends and receives 2 bytes. These ////
//// sizes can be changed with USB_CONFIG_HID_TX_SIZE and ////
//// USB_CONFIG_HID_RX_SIZE. Changing these values will cause ////
//// hiddemo.exe to not work. ////
//// ////
//// This file is part of CCS's PIC USB driver code. See USB.H ////
//// for more documentation and a list of examples. ////
//// ////
/////////////////////////////////////////////////////////////////////////
//// ////
//// ABOUT HID: ////
//// ////
//// HID devices are useful because HID drivers are generally ////
//// installed and supplied with modern operating systems. ////
//// However, since HID is a general device with general drivers ////
//// there are limitations to what a HID device can do: ////
//// ////
//// - A report (message) can't be larger than 255 bytes. ////
//// (A report or message != A packet) ////
//// ////
//// - On slow speed devices the max packet size is 8. ////
//// On a full speed device the max packet size is 64. ////
//// ////
//// - Data is obtained on the host / PC through polling the HID ////
//// device (PC polls the PIC) ////
//// ////
//// - On a full speed device, max polling rate is 1 transaction ////
//// per 1ms. This is 64000 bytes per second (64 byte packets ////
//// every 1ms). ////
//// ////
//// - On a slow speed device, max polling rate is 1 transaction ////
//// per 10ms. This is 800 bytes per second (8 byte packets every ////
//// 10ms) ////
//// ////
//// - No guarantee that polls will happen at a guaranteed rate. ////
//// If you want guaranteed transfer rate you must use Isochronous ////
//// transfers, which HID is not. ////
//// ////
/////////////////////////////////////////////////////////////////////////
//// ////
//// WINDOWS DRIVERS: ////
//// ////
//// USB HID drivers come included with all Windows, starting ////
//// with Windows 98 and up. Windows 95 does not include USB ////
//// support, unless you are running Windows 95 Gold (aka OSR2, or ////
//// Windows 95b). ////
//// ////
//// If you plug in the USB device, and it is working, a "Found new ////
//// device" window should pop-up. The Add Device wizard then will ////
//// install the HID drivers automatically. ////
//// ////
//// If you plug in the USB device and do not get this window then ////
//// the device is not working, or USB does not work on your ////
//// computer. Goto the Device Manager (Right Click on my Computer, ////
//// it is located under one of the Tabs. It is located under the ////
//// Hardware tab of Windows2000), and make sure that "Universal ////
//// Serial Bus controllers" is installed. Open "Universal Serial ////
//// Bus controllers" and you should see 1 or more "USB Root Hubs". ////
//// If you see these then that's a good indication that USB is ////
//// working on your computer. If you see a question mark and ////
//// an unkown USB device then this is quite possibly your USB ////
//// device that is not working. ////
//// ////
/////////////////////////////////////////////////////////////////////////
//// ////
//// NOTE ABOUT ENDPOINT BUFFER SIZE: ////
//// ////
//// Although this application sends and receives only 2 bytes from ////
//// the PC, this demo defines USB_EP1_TX_SIZE and USB_EP1_RX_SIZE ////
//// to 8 to allocate 8 bytes for these endpoint. These constants ////
//// are also used in the endpoint descriptor to specify the ////
//// endpoint max size. If you were concious of RAM savings you ////
//// could redefine these to 2 (or even 1!), but you would lose ////
//// throughput. The reason for throughput loss is that if you send ////
//// a packet that is the same size as the max packet size then ////
//// you need to send a 0 len packet to specify end of message ////
//// marker. The routines usb_puts() and usb_gets() send and ////
//// receive multiple packet message, waiting for a 0 len packet ////
//// or a packet that is smaller than max-packet size. ////
//// ////
/////////////////////////////////////////////////////////////////////////
//// ////
//// VERSION HISTORY ////
//// ////
//// Oct 15th, 2010: ////
//// Potential bug in CDC that causes lost PIC->PC chars resolved? ////
//// Added initial 18F47J53 family support. ////
//// Added USB_ISR_POLLING support. Define this and interrupts ////
//// will not be used. usb_task() must be called periodically ////
//// in your main loop. If it is not called faster than once ////
//// per millisecond, USB may not work (PIC18 and PIC24 only). ////
//// ////
//// April 28th, 2010: ////
//// Added ex_usb_common.h. ////
//// Initial support for CCS PIC24USB board. ////
//// ////
//// March 5th, 2009: ////
//// Cleanup for Wizard. ////
//// PIC24 Initial release. ////
//// ////
//// June 20th, 2005: 18fxx5x initial release. ////
//// ////
//// March 22nd, 2005: Cleanup to work with PIC18Fxx5x ////
//// ////
//// June 24th, 2004: Cleanup to work with updated USB API ////
//// ////
/////////////////////////////////////////////////////////////////////////

#include <ex_usb_common.h>

// you can change the tx and rx packet sizes here.


// in order to be compatbile with hiddemo.exe, these values must be 2.
#define USB_CONFIG_HID_TX_SIZE 2
#define USB_CONFIG_HID_RX_SIZE 2
/////////////////////////////////////////////////////////////////////////////
//
// Include the CCS USB Libraries.
//
////////////////////////////////////////////////////////////////////////////
#include <pic18_usb.h> //Microchip PIC18Fxx5x hardware layer for usb.c
#include <usb_desc_hid.h> //USB Configuration and Device descriptors for
// this UBS device
#include <usb.c> //handles usb setup tokens and get descriptor reports
/////////////////////////////////////////////////////////////////////////////
//
// usb_debug_task()
//
// When called periodically, displays debugging information over serial
// to display enumeration and connection states. Also lights LED1 based upon
// enumeration and status.
//
/////////////////////////////////////////////////////////////////////////////
void usb_debug_task(void)
{
static int8 last_connected
static int8 last_enumerated;
int8 new_connected;
int8 new_enumerated;

new_connected=usb_attached();
new_enumerated=usb_enumerated();

if (new_enumerated)
LED_ON(LED1);
else
LED_OFF(LED1);

if (new_connected && !last_connected)


uart_printf("\r\n\nUSB connected, waiting for enumaration...");
if (!new_connected && last_connected)
uart_printf("\r\n\nUSB disconnected, waiting for connection...");
if (new_enumerated && !last_enumerated)
uart_printf("\r\n\nUSB enumerated by PC/HOST");
if (!new_enumerated && last_enumerated)
uart_printf("\r\n\nUSB unenumerated by PC/HOST, waiting for enumeration...");

last_connected=new_connected;
last_enumerated=new_enumerated;
}

void display_array(unsigned int8 *p, unsigned int8 n)


{
while(n--)
{
uart_printf(" 0x%X", *p++);
}
}
void main(void)
{
int8 out_data[USB_CONFIG_HID_TX_SIZE];
int8 in_data[USB_CONFIG_HID_RX_SIZE];
int8 send_timer=0;

HW_INIT();

LED_OFF(LED1);
LED_OFF(LED2);
LED_OFF(LED3);

uart_printf("\r\n\nCCS Vendor Specific HID Example");

#ifdef __PCH__
uart_printf("\r\nPCH: v");
uart_printf(__PCH__);
#elif defined(__PCD__)
uart_printf("\r\nPCD: v");
uart_printf(__PCD__);
#else
uart_printf("\r\nPCM: v");
uart_printf(__PCM__);
#endif

usb_init_cs();

#if !(__USB_PIC_PERIF__)
uart_printf("\r\nUSBN: 0x%X", usbn_get_version());
#endif
uart_printf("\r\n");

setup_adc_ports(HW_ADC_PORTS);
setup_adc(HW_ADC_CONFIG);
set_adc_channel(HW_ADC_CHANNEL);

memset(in_data, 0x00, USB_CONFIG_HID_RX_SIZE);


memset(out_data, 0x00, USB_CONFIG_HID_TX_SIZE);

while (TRUE)
{
usb_task();
usb_debug_task();
if (usb_enumerated())
{
if (!send_timer)
{
send_timer=250;
out_data[0]=read_adc();
out_data[1]=BUTTON_PRESSED();
if (usb_put_packet(1, out_data, USB_CONFIG_HID_TX_SIZE, USB_DTS_TOGGLE))
{
uart_printf("\r\n<-- Sending %u bytes:", USB_CONFIG_HID_TX_SIZE);
display_array(out_data, USB_CONFIG_HID_TX_SIZE);
}
}
if (usb_kbhit(1))
{
usb_get_packet(1, in_data, USB_CONFIG_HID_RX_SIZE);
uart_printf("\r\n--> Received %u bytes:", USB_CONFIG_HID_RX_SIZE);
display_array(in_data, USB_CONFIG_HID_RX_SIZE);
if (in_data[0]) {LED_ON(LED2);} else {LED_OFF(LED2);}
if (in_data[1]) {LED_ON(LED3);} else {LED_OFF(LED3);}
}
send_timer--;
delay_ms(1);
}
}
}
Programa Ejemplo para el PC utilizando HID

Public Class frmUSB


' HID controller DLL mcHID.dll
' EasyHID
' vendor and product IDs
Private Const VendorID As Integer = &H461 'Microchip VID, PID
Private Const ProductID As Integer = &H20
' read and write buffers
Private Const BufferInSize As Integer = 8 'Size of the data buffer coming IN to the PC
Private Const BufferOutSize As Integer = 8 'Size of the data buffer going OUT from the PC
Dim BufferIn(BufferInSize) As Byte 'Received data will be stored here - the first
byte in the array is unused
Public BufferOut(BufferOutSize) As Byte 'Transmitted data is stored here - the first item
in the array must be 0
' ****************************************************************
' when the form loads, connect to the HID controller - pass
' the form window handle so that you can receive notification
' events...
'*****************************************************************
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles
MyBase.Load
' do not remove!
ConnectToHID(Me)
End Sub

'*****************************************************************
' disconnect from the HID controller...
'*****************************************************************
Private Sub Form1_FormClosed(ByVal sender As Object, ByVal e As
System.Windows.Forms.FormClosedEventArgs) Handles Me.FormClosed
DisconnectFromHID()
End Sub

'*****************************************************************
' a HID device has been plugged in...
'*****************************************************************
Public Sub OnPlugged(ByVal pHandle As Integer)
If hidGetVendorID(pHandle) = VendorID And hidGetProductID(pHandle) = ProductID Then
ConState.Text = "HID Device Connect"
End If
End Sub

'*****************************************************************
' a HID device has been unplugged...
'*****************************************************************
Public Sub OnUnplugged(ByVal pHandle As Integer)
If hidGetVendorID(pHandle) = VendorID And hidGetProductID(pHandle) = ProductID Then
hidSetReadNotify(hidGetHandle(VendorID, ProductID), False)
ConState.Text = "HID Device Disconnect"
End If
End Sub

'*****************************************************************
' controller changed notification - called
' after ALL HID devices are plugged or unplugged
'*****************************************************************
Public Sub OnChanged()
' get the handle of the device we are interested in, then set
' its read notify flag to true - this ensures you get a read
' notification message when there is some data to read...
Dim pHandle As Integer
pHandle = hidGetHandle(VendorID, ProductID)
hidSetReadNotify(hidGetHandle(VendorID, ProductID), True)
End Sub

'*****************************************************************
' on read event...
'*****************************************************************
Public Sub OnRead(ByVal pHandle As Integer)
' read the data (don't forget, pass the whole array)...
If hidRead(pHandle, BufferIn(0)) Then
' ** YOUR CODE HERE **
' first byte is the report ID, e.g. BufferIn(0)
TextBoxReceived.Text = Str$(BufferIn(1))
End If
End Sub

Private Sub send_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)


BufferOut(0) = 0
BufferOut(1) = Not (BufferOut(1))
BufferOut(2) = Not (BufferOut(1))

' white data(don´t forget pass the whole array)...


hidWriteEx(VendorID, ProductID, BufferOut(0))
End Sub

Private Sub FIN_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles


FIN.Click
' Form1_FormClosed()
End
End Sub

Private Sub LED1_Click(sender As System.Object, e As System.EventArgs) Handles LED1.Click


BufferOut(0) = 0
BufferOut(1) = Not (BufferOut(1))

' white data(don´t forget pass the whole array)...


hidWriteEx(VendorID, ProductID, BufferOut(0))
End Sub

Private Sub LED2_Click(sender As System.Object, e As System.EventArgs) Handles LED2.Click


BufferOut(0) = 0
BufferOut(2) = Not (BufferOut(2))

' white data(don´t forget pass the whole array)...


hidWriteEx(VendorID, ProductID, BufferOut(0))
End Sub

Private Sub TextBoxReceived_TextChanged(sender As System.Object, e As System.EventArgs)


Handles TextBoxReceived.TextChanged
' read the data (don't forget, pass the whole array)...
' If hidRead(pHandle, BufferIn(0)) Then
' ** YOUR CODE HERE **
' first byte is the report ID, e.g. BufferIn(0)
TextBoxReceived.Text = Str$(BufferIn(1))
'End If
If BufferIn(2) = 0 Then 'Element 2 contains the button state
lblButton.Text = "Pressed"
ElseIf BufferIn(2) = 1 Then
lblButton.Text = "Not Pressed"
End If
End Sub
End Class

Imports System
Imports System.Threading
Imports System.Runtime.InteropServices

Module HIDDLLInterface
' this is the interface to the HID controller DLL - you should not
' normally need to change anything in this file.
'
' WinProc() calls your main form 'event' procedures - these are currently
' set to..
'
' MainForm.OnPlugged(ByVal pHandle as long)
' MainForm.OnUnplugged(ByVal pHandle as long)
' MainForm.OnChanged()
' MainForm.OnRead(ByVal pHandle as long)

' HID interface API declarations...


Declare Function hidConnect Lib "mcHID.dll" Alias "Connect" (ByVal pHostWin As Integer) As
Boolean
Declare Function hidDisconnect Lib "mcHID.dll" Alias "Disconnect" () As Boolean
Declare Function hidGetItem Lib "mcHID.dll" Alias "GetItem" (ByVal pIndex As Integer) As
Integer
Declare Function hidGetItemCount Lib "mcHID.dll" Alias "GetItemCount" () As Integer
Declare Function hidRead Lib "mcHID.dll" Alias "Read" (ByVal pHandle As Integer, ByRef pData
As Byte) As Boolean
Declare Function hidWrite Lib "mcHID.dll" Alias "Write" (ByVal pHandle As Integer, ByRef
pData As Byte) As Boolean
Declare Function hidReadEx Lib "mcHID.dll" Alias "ReadEx" (ByVal pVendorID As Integer, ByVal
pProductID As Integer, ByRef pData As Byte) As Boolean
Declare Function hidWriteEx Lib "mcHID.dll" Alias "WriteEx" (ByVal pVendorID As Integer,
ByVal pProductID As Integer, ByRef pData As Byte) As Boolean
Declare Function hidGetHandle Lib "mcHID.dll" Alias "GetHandle" (ByVal pVendoID As Integer,
ByVal pProductID As Integer) As Integer
Declare Function hidGetVendorID Lib "mcHID.dll" Alias "GetVendorID" (ByVal pHandle As
Integer) As Integer
Declare Function hidGetProductID Lib "mcHID.dll" Alias "GetProductID" (ByVal pHandle As
Integer) As Integer
Declare Function hidGetVersion Lib "mcHID.dll" Alias "GetVersion" (ByVal pHandle As Integer)
As Integer
Declare Function hidGetVendorName Lib "mcHID.dll" Alias "GetVendorName" (ByVal pHandle As
Integer, ByVal pText As String, ByVal pLen As Integer) As Integer
Declare Function hidGetProductName Lib "mcHID.dll" Alias "GetProductName" (ByVal pHandle As
Integer, ByVal pText As String, ByVal pLen As Integer) As Integer
Declare Function hidGetSerialNumber Lib "mcHID.dll" Alias "GetSerialNumber" (ByVal pHandle
As Integer, ByVal pText As String, ByVal pLen As Integer) As Integer
Declare Function hidGetInputReportLength Lib "mcHID.dll" Alias "GetInputReportLength" (ByVal
pHandle As Integer) As Integer
Declare Function hidGetOutputReportLength Lib "mcHID.dll" Alias "GetOutputReportLength"
(ByVal pHandle As Integer) As Integer
Declare Sub hidSetReadNotify Lib "mcHID.dll" Alias "SetReadNotify" (ByVal pHandle As
Integer, ByVal pValue As Boolean)
Declare Function hidIsReadNotifyEnabled Lib "mcHID.dll" Alias "IsReadNotifyEnabled" (ByVal
pHandle As Integer) As Boolean
Declare Function hidIsAvailable Lib "mcHID.dll" Alias "IsAvailable" (ByVal pVendorID As
Integer, ByVal pProductID As Integer) As Boolean

' windows API declarations - used to set up messaging...

Public Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal


lpPrevWndFunc As Integer, ByVal hwnd As Integer, ByVal Msg As Integer, ByVal wParam As Integer,
ByVal lParam As Integer) As Integer
Public Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" _
(ByVal hwnd As Integer, ByVal nIndex As Integer, ByVal
dwNewLong As Integer) As Integer

Delegate Function SubClassProcDelegate(ByVal hwnd As Integer, ByVal msg As Integer, ByVal


wParam As Integer, ByVal lParam As Integer) As Integer
Public Declare Function DelegateSetWindowLong Lib "USER32.DLL" Alias "SetWindowLongA" _
(ByVal hwnd As Integer, ByVal attr As Integer, ByVal
lval As SubClassProcDelegate) As Integer

' windows API Constants


Public Const WM_APP As Integer = 32768
Public Const GWL_WNDPROC As Short = -4

' HID message constants


Private Const WM_HID_EVENT As Decimal = WM_APP + 200
Private Const NOTIFY_PLUGGED As Short = 1
Private Const NOTIFY_UNPLUGGED As Short = 2
Private Const NOTIFY_CHANGED As Short = 3
Private Const NOTIFY_READ As Short = 4

' local variables


Private FPrevWinProc As Integer ' Handle to previous window procedure
Private FWinHandle As Integer ' Handle to message window
Private Ref_WinProc As New SubClassProcDelegate(AddressOf WinProc)
Private HostForm As Object

' Set up a windows hook to receive notification


' messages from the HID controller DLL - then connect
' to the controller
Public Function ConnectToHID(ByRef targetForm As Form) As Boolean
Dim pHostWin As Integer = targetForm.Handle.ToInt32
FWinHandle = pHostWin
pHostWin = hidConnect(FWinHandle)
FPrevWinProc = DelegateSetWindowLong(FWinHandle, GWL_WNDPROC, Ref_WinProc)
HostForm = targetForm
End Function

' Unhook from the HID controller and disconnect...


Public Function DisconnectFromHID() As Boolean
DisconnectFromHID = hidDisconnect
SetWindowLong(FWinHandle, GWL_WNDPROC, FPrevWinProc)
End Function

' This is the procedure that intercepts the HID controller messages...

Private Function WinProc(ByVal pHWnd As Integer, ByVal pMsg As Integer, ByVal wParam As
Integer, ByVal lParam As Integer) As Integer
If pMsg = WM_HID_EVENT Then
Select Case wParam

' HID device has been plugged message...


Case Is = NOTIFY_PLUGGED
HostForm.OnPlugged(lParam)

' HID device has been unplugged


Case Is = NOTIFY_UNPLUGGED
HostForm.OnUnplugged(lParam)

' controller has changed...


Case Is = NOTIFY_CHANGED
HostForm.OnChanged()

' read event...


Case Is = NOTIFY_READ
HostForm.OnRead(lParam)
End Select

End If

' next...
WinProc = CallWindowProc(FPrevWinProc, pHWnd, pMsg, wParam, lParam)

End Function
End Module

Programa Ejemplo para el PIC utilizando CDC

/////////////////////////////////////////////////////////////////////////
//// ////
//// ex_usb_serial.c ////
//// ////
//// A demonstration of the USB CDC API that is provided by CCS. ////
//// The USB CDC API that CCS provides will create a virtual UART ////
//// port. USB CDC drivers are included with most versions of ////
//// Microsoft Windows, and when properly loaded will create a COMx ////
//// port from which you can write and read to your PIC device ////
//// like any serial device that has a COMx port. ////
//// ////
//// This example creates a USB<->UART converter. Open ////
//// Hyperterminal to COM1 or putty(or whatever COM port is your ////
//// usual RS232 ////
//// serial COM port). Plug the PIC to USB. Open Hypertimernal to ////
//// the new COM port that is the USB<->UART COM port (for this ////
//// example say it is COM2). Typing a character in COM1 will cause ////
//// it to be sent out COM2, and vice-versa. ////
//// ////
//// See usb_cdc.h for API documentation. ////
//// ////
/////////////////////////////////////////////////////////////////////////
//// ////
//// VERSION HISTORY ////
//// ////
//// 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. ////
/////////////////////////////////////////////////////////////////////////

//set to 1 to use a PIC's internal USB Peripheral


//set to 0 to use a National USBN960x peripheral
#define __USB_PIC_PERIF__ 1

#if !defined(__PCH__)
#error USB CDC Library requires PIC18
#endif

#if __USB_PIC_PERIF__
#DEFINE LED1 PIN_A5
#include <18F4550.h>
#fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN
#use delay(clock=48000000)
#else //use the National USBN960x peripheral
#DEFINE LED1 PIN_B3
#include <18F452.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000)
#endif //endif check to see which peripheral to use

#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)

/////////////////////////////////////////////////////////////////////////////
//
// If you are using a USB connection sense pin, define it here. If you are
// not using connection sense, comment out this line. Without connection
// sense you will not know if the device gets disconnected.
// (connection sense should look like this:
// 100k
// VBUS-----+----/\/\/\/\/\----- (I/O PIN ON PIC)
// |
// +----/\/\/\/\/\-----GND
// 100k
// (where VBUS is pin1 of the USB connector)
//
/////////////////////////////////////////////////////////////////////////////
///only the 18F4550 development kit has this pin
#if __USB_PIC_PERIF__ && defined(__PCH__)
#define USB_CON_SENSE_PIN PIN_B2
#endif

#include <usb_cdc.h> //API

/////////////////////////////////////////////////////////////////////////////
//
// Configure the demonstration I/O
//
/////////////////////////////////////////////////////////////////////////////
#define LED2 PIN_B4
#define LED3 PIN_B5
#DEFINE BUTTON PIN_A4
#define LED_ON output_low
#define LED_OFF output_high

/////////////////////////////////////////////////////////////////////////////
//
// usb_debug_task()
//
// When called periodically, displays debugging information over serial
// to display enumeration and connection states. Also lights LED1 based upon
// enumeration and status.
//
/////////////////////////////////////////////////////////////////////////////
void usb_debug_task(void) {
static int8 last_connected;
static int8 last_enumerated;
int8 new_connected;
int8 new_enumerated;
static int8 last_cdc;
int8 new_cdc;

new_connected=usb_attached();
new_enumerated=usb_enumerated();
new_cdc=usb_cdc_connected();

if (new_enumerated)
LED_ON(LED1);
else
LED_OFF(LED1);

if (new_cdc)
LED_ON(LED2);
else
LED_OFF(LED2);

if (usb_cdc_carrier.dte_present)
LED_ON(LED3);
else
LED_OFF(LED3);

if (new_connected && !last_connected)


printf("USB connected, waiting for enumaration...\r\n\n");
if (!new_connected && last_connected)
printf("USB disconnected, waiting for connection...\r\n\n");
if (new_enumerated && !last_enumerated)
printf("USB enumerated by PC/HOST\r\n\n");
if (!new_enumerated && last_enumerated)
printf("USB unenumerated by PC/HOST, waiting for enumeration...\r\n\n");
if (new_cdc && !last_cdc) {
printf("Serial program initiated on USB<->UART COM Port\r\n\n");
printf(usb_cdc_putc, "\r\n\nCCS CDC (Virtual RS232) Example\r\n\n");
}

last_connected=new_connected;
last_enumerated=new_enumerated;
last_cdc=new_cdc;
}

void main(void) {
char c;

LED_OFF(LED1);
LED_OFF(LED2);
LED_OFF(LED3);

printf("\r\n\nCCS CDC (Virtual RS232) Example\r\n");

#ifdef __PCH__
printf("PCH: v");
printf(__PCH__);
#else
printf("PCM: v");
printf(__PCM__);
#endif
printf("\r\n");

usb_init_cs();

#if !(__USB_PIC_PERIF__)
printf("USBN: 0x%X", usbn_get_version());
printf("\r\n\n");
#endif

while (TRUE) {
usb_task();
usb_debug_task();

if (kbhit()) {
c=getc();
if (c=='\n') {usb_cdc_putc('\r'); usb_cdc_putc('\n');}
if (c=='\r') {usb_cdc_putc('\r'); usb_cdc_putc('\n');}
else {usb_cdc_putc(c);}
}
if (usb_cdc_kbhit()) {
c=usb_cdc_getc();
if (c=='\n') {putc('\r'); putc('\n');}
if (c=='\r') {putc('\r'); putc('\n');}
else {putc(c);}
}
}
}

programa ejemplo Visual basic 2010 express

PROGRAMAS SNIFER

USBDeview

SnoopyPro

También podría gustarte