Manual de Formación de USB
Universal Serial Bus Specification 2.0
INGENIERÍA EN MICROCONTROLADORES - Protocolo USB un paseo por usb
Osciloscopio USB. Documentación autores: Pablo Hoffman y Martín Szmulewicz
este último viene de:
w w w . u n p o c o d e l e c t r o n i c a . n e t a u . n e t Página 104 http://pablohoffman.com/oscusb/
Osciloscopio USB abierto
w w w . u n p o c o d e l e c t r o n i c a . n e t a u . n e t Página 105
Estudio de mpusbapi.dll (parte II)
para hacer este estudio vamos a ver unos ejemplos de Slalen(programa1) y Ernesto Mozota Navarro(programa2). Este último lo pueden bajar de http://www.hobbypic.com/ ambos sirven para el firmware que escribió Jaime J1M, el programa2 también añade otras posibilidades (PWM, CAD)
lo primero, probar el código. ¡Claro! jeje y grabar el firmware PICusb en el PIC. Esto ya lo hice varios post atrás, pero no lo expliqué y ahora le toca el turno al Visual Basic usando el programa1.
como mencioné anteriormente, para usar nuestra aplicación corriendo en VB, tenemos que hacer uso de unas llamadas a la librería mpusbapi.dll (apis).
1 2 3 4 5 6 7
Public Declare Function MPUSBGetDLLVersion Lib "mpusbapi.dll" () As Long
Public Declare Function MPUSBGetDeviceCount Lib "mpusbapi.dll" (ByVal pVID_PID As String) As Long
Public Declare Function MPUSBOpen Lib "mpusbapi.dll" (ByVal instance As Long, ByVal pVID_PID As String, ByVal pEP As String, ByVal dwDir As Long, ByVal dwReserved As Long) As Long
Public Declare Function MPUSBClose Lib "mpusbapi.dll" (ByVal handle As Long) As Long
Public Declare Function MPUSBRead Lib "mpusbapi.dll" (ByVal handle As Long, ByVal pData As Long, ByVal dwLen As Long, ByRef pLength As Long, ByVal dwMilliseconds As Long) As Long
Public Declare Function MPUSBWrite Lib "mpusbapi.dll" (ByVal handle As Long, ByVal pData As Long, ByVal dwLen As Long, ByRef pLength As Long, ByVal dwMilliseconds As Long) As Long
Public Declare Function MPUSBReadInt Lib "mpusbapi.dll" (ByVal handle As Long, ByVal pData As Long, ByVal dwLen As Long, ByRef pLength As Long, ByVal dwMilliseconds As Long) As Long
aquí aparecen 7 ,yo conté unas 10 en el código fuente. parece que estas 7 son las necesarias para hacer transacciones a la función.
nota: función = dispositivo = módulo USB del PIC, en adelante me referiré a “dispositivo” para no confundir cuando hable de funciones en C.
la api mas sencilla aquí, parecer ser la de mostrar la versión veamos que dice la traducción que nos pasó Slalen:
1 2
MPUSBGetDLLVersion(Void)
Lee el nivel de revision del MPUSAPi.dll. Es un nivel de revision de 32bits. Esta funcion no devuelve la version del codigo, no realiza nada con el USB.
yo le agregaría que devuelve un dato de 32 bits, la versión de la dll en formato MMMMmmmm.
w w w . u n p o c o d e l e c t r o n i c a . n e t a u . n e t Página 106 1 2 3 4 5
Private Sub Command2_Click() Dim version_dll As Long
version_dll = Hex(MPUSBGetDLLVersion) MsgBox Str(version_dll)
End Sub
Mostrar la versión de mpusbapi.dll
nos arroja 10000, y pienso que como hay 8 dígitos, ya que la versión es en hexa (8 nibbles = 32bits) -> versión dll = 1.0.0.0.0
si quieren mas información acerca de estas funciones, visitar estas direcciones: - La mpusbapi.dll desencadenada: PC <-> PIC vía USB en Delphi
- Traducción de mpusbapi.doc
de lo que si voy hablar es como podemos usar esas apis en VB. veamos:
cuando arrancamos esta aplicación, primero se debe ejecutar el form_load 1
2 3
Private Sub Form_Load()
OpenMPUSBDevice 'abre comunicaciones End Sub
¿quién es openMPUSBDevice?
R: éste llama a MPUSBOpen:
1 2 3 4
Sub OpenMPUSBDevice()
myOutPipe = MPUSBOpen(0, vid_pid, out_pipe, 0, 0) 'como salida
myInPipe = MPUSBOpen(0, vid_pid, in_pipe, 1, 0) 'como entrada
w w w . u n p o c o d e l e c t r o n i c a . n e t a u . n e t Página 107 configura el conducto(pipe) de acceso a cada endpoint, uno de salida y uno de entrada.
para outpipe tenemos operación de escritura -> MP_WRITE=0 y para inpipe -> MP_READ=1. El resultado de esta llamada se guardará en my(In/Out)Pipe si para ambos tenemos como resultado -1 -> entonces quiere decir que no se pudo establecer el enlace lógico con el dispositivo.
INVALID_HANDLE_VALUE = -1
si observan el programa2 notaran que hay comprobaciones en casi todas partes, preguntando si hay enlace.
para terminar la aplicación, debemos cerrar el enlace (igual como se hace en RS-232) mediante: 1 2 3 4 Sub CloseMPUSBDevice() MPUSBClose (myOutPipe) MPUSBClose (myInPipe) End Sub
esto es parecido al sistema de mensajeria de windows, donde el resultado de una api, es utilizada por otra (handle) para ejecutar otros procesos.
nota: es bueno añadirle el método debug.print a cada api para poder analizar cada línea ejecutada: 1 2 3 4 5 6 7 Sub OpenMPUSBDevice()
myOutPipe = MPUSBOpen(0, vid_pid, out_pipe, 0, 0) 'como salida
Debug.Print "myOutPipe= " & myOutPipe
myInPipe = MPUSBOpen(0, vid_pid, in_pipe, 1, 0) 'como entrada
Debug.Print "myInPipe= " & myInPipe End Sub
vamos a escribir un código para abrir y cerrar un enlace virtual con el dispositivo. ¿les parece? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 Option Explicit
Private Declare Function MPUSBOpen Lib "mpusbapi.dll" (ByVal instance As Long, ByVal pVID_PID As String, ByVal pEP As String, ByVal dwDir As Long, ByVal dwReserved As Long) As Long
Private Declare Function MPUSBClose Lib "mpusbapi.dll" (ByVal handle As Long) As Long Const INVALID_HANDLE_VALUE = -1 Const MPUS_FAIL = 0 Const MPUSB_SUCCESS = 1
w w w . u n p o c o d e l e c t r o n i c a . n e t a u . n e t Página 108 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 Periferico id
Const out_pipe = "\MCHP_EP1" ' endpoint 1 Const in_pipe = "\MCHP_EP1" ' endpoint 1
Const MP_WRITE = 0 ' Const MP_READ = 1
Public myInPipe As Long ' para guardar el manejador Public myOutPipe As Long
Private Sub cmdabrir_Click() ' abrir enlace o pipe
myOutPipe = MPUSBOpen(0, vid_pid, out_pipe, 0, 0) 'como salida
Debug.Print "myOutPipe= " & myOutPipe ' para monitoreo
If myOutPipe = INVALID_HANDLE_VALUE Then ' si es -1 lblpipeout = "Fallo el enlace de salida"
Else
lblpipeout = "Enlace salida establecido" End If
myInPipe = MPUSBOpen(0, vid_pid, in_pipe, 1, 0) 'como entrada
Debug.Print "myInPipe= " & myInPipe
If myInPipe = INVALID_HANDLE_VALUE Then lblpipein = "Fallo el enlace de entrada" Else
lblpipein = "Enlace entrada establecido" End If
End Sub
Private Sub cmdcerrar_Click() ' cerrar enlace pipe Dim resul_o As Long: Dim resul_i As Long
resul_o = MPUSBClose(myOutPipe)
Debug.Print "MPUSBClose(myOutPipe)= " & resul_o If resul_o = MPUSB_SUCCESS Then
lblpipeout.Caption = "Enlace salida cerrado" Else
lblpipeout.Caption = "Error al cerrar el enlace salida, puede que este cerrado"
End If
resul_i = MPUSBClose(myInPipe)
Debug.Print "MPUSBClose(myInPipe)= " & resul_i If resul_i = MPUSB_SUCCESS Then
lblpipein.Caption = "Enlace entrada cerrado" Else
lblpipein.Caption = "Error al cerrar el enlace entrada, puede que este cerrado"
End If End Sub
w w w . u n p o c o d e l e c t r o n i c a . n e t a u . n e t Página 109 Casos de abrir y cerrar PiPES
w w w . u n p o c o d e l e c t r o n i c a . n e t a u . n e t Página 110 Casos de abrir y cerrar PiPES
Casos de abrir y cerrar PiPES
w w w . u n p o c o d e l e c t r o n i c a . n e t a u . n e t Página 111
Estudio de mpusbapi.dll (parte III)
veremos las apis mas importantes de la biblioteca mpusbapi.dll. Me refiero a: MPUSBRead
MPUSBWrite
- ¿como hizo el programa1 para encender un led? R: en el botón verde, tenemos:
1 2 3 4 5
Private Sub Command1_Click(Index As Integer)
Send_Buf(0) = 1 'Para que reconozca que se encienden o apagan Leds
Send_Buf(1) = Index Send Send_Buf, 2 End Sub
ajá ya empezaron las dudas, vamos a ver quien es Send_Buf:
1 2 3 4 5 6 7 8 9
Dim Send_Buf(0 To 2) As Byte ...
' Función enviar
Function Send(ByRef SendData() As Byte, bytes As Integer) As Long Dim SentDataLength As Long
Call MPUSBWrite(myOutPipe, VarPtr(SendData(0)), bytes, VarPtr(bytes), 1000) 'VarPtr()= puntero a la variable End Function
es lógico pensar que como se trabaja con bytes, entonces para varios datos es necesario crear arrays de bytes. y eso es precisamente lo que hace Send_Buf()
aquí hay una sentencia curiosa VarPtr(), yo nunca la había visto, además no pertenece al VB en sí, leyendo por aquí, por acá, conseguí:
1 2 3 4
Declare Function VarPtrAny Lib "vb40032.dll" Alias "VarPtr" (lpObject As Any) As Long
'The VarPtr-function retrieves the memory handle of an object. '· lpObject
' Handle that identifies the object ¡-ahh- conque viene del runtime!
hurgando en la biblioteca MSDN, aparecen tres métodos NO documentados sobre usar direccionamiento en VB, VarPtr, ObjPtr y StrPtr
esto si es un descubrimiento para mi, el uso de punteros en basic (bajo ciertas condiciones).
w w w . u n p o c o d e l e c t r o n i c a . n e t a u . n e t Página 112 pData -> salida: puntero al buffer que contiene los datos que se van a escribir
para explicar un momento el uso del puntero en este caso, este argumento lo que necesita es la dirección donde está alojado el dato que queremos enviar
el problema que tiene visual basic es que no podemos usar punteros, pero con el método varptr podemos tomar dicha dirección, y esto no es lo mejor de todo, léase bien. Lo mejor es que gracias a que en un array de bytes las direcciones de esos datos son contiguos, entonces con solo tener la dirección del primer byte de datos es lo necesario que debe tener la api para hacer el recorrido en memoria.
para demostrar esto que estoy diciendo, voy a escribir un código donde:
- guardaré un dato (byte) en 2 variables
- tomaré la dirección de esas 2 variables mediante varptr
- luego llamando una api CopyMemory, recuperaré el valor que hay en esas direcciones que vienen siendo el mismo dato.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
' mediante el uso de Varptr y CopyMemory
' Varptr(dato): devuelve la direccion (Long) donde se almacena la variable dato
' con CopyMemory podemos recuperar el dato en memoria a partir de su direccion
' por: Pedro - PalitroqueZ. 23-feb-2007 10:19AM
Option Explicit
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (pDst As Any, pSrc As Long, ByVal ByteLen As Long)
Dim d(0 To 1) As Byte, dato(0 To 1) As Byte, r1 As Long, r2 As Long
Private Sub Command1_Click()
d(0) = 25 ' un valor cualquiera Debug.Print "d(0)= " & d(0)
d(1) = 97 ' un valor cualquiera Debug.Print "d(1)= " & d(1)
r1 = VarPtr(d(0)) ' en r1 se guarda la direccion donde esta almacenado d(0)
Debug.Print "r1= " & r1
r2 = VarPtr(d(1))
Debug.Print "r2= " & r2
' ahora se procede a recuperar el dato, usando CopyMemory CopyMemory ByVal VarPtr(dato(0)), ByVal r1, 2
' debe usarse byval OBLIGATORIO para que se pueda copiar el dato en vez de la direccion
' el ultimo argumento corresponde a la longitud del dato en bytes
w w w . u n p o c o d e l e c t r o n i c a . n e t a u . n e t Página 113 36 37 38 39 40 41
' si se coloca 2, es para que tome la direccion del dato contiguo
' es decir, dato(1).
' como dato(0), dato(1) -> se almacenan en direcciones contiguas ' entonces CopyMemory almacenara el par de bytes de datos, en dato(0)
' y dato(1) mediante sus direcciones respectivas
Debug.Print "dato(0)= " & dato(0) Debug.Print "dato(1)= " & dato(1)
MsgBox "se recuperó d(0)=" & Str(dato(0)) & " y d(1)=" & Str(dato(1))
Unload Me End Sub
una imagen del debugger:
Usando punteros en Visual Basic 6
así pues, donde veamos el varptr ya sabemos a que se está refiriendo, además el argumento de la api también lo delata con la letra „p‟ ej: pData, pLenght
esto es la parte complicada de entender el uso de la api, para MPUSBRead es similar y al revés, el segundo argumento es el puntero de una variable previamente declarada por nosotros para que se alojen los datos que vayan llegando del USB.
como verán esta es otra aplicación del concepto del puntero, por un lado tenemos la casilla(dirección de almacenamiento) y por el otro tenemos el valor del dato
w w w . u n p o c o d e l e c t r o n i c a . n e t a u . n e t Página 114 el resto de los argumentos es fácil de entender, como la longitud del dato (en bytes).
esto depende de como configuremos el envío desde el dispositivo
el tiempo en milisegundos: es para que la api no se quede en un bucle infinito si llegara a ocurrir un problema
y por supuesto el pipe, o mejor dicho el handle del pipe, que se puede decir que es un puntero representado en VB como un long (ver fuentes consultadas)
bueno volviendo al uso de la función Send
1 2 3
Send_Buf(0) = 1 'Para que reconozca que se encienden o apagan Leds
Send_Buf(1) = Index Send Send_Buf, 2
esto interpretado desde el punto de vista del micro, es un paquete de datos, donde hay 2 bytes. en el primer byte se guarda el modo (modo_led) y el en otro byte se guarda el paraml que es la acción para ambos led´s (apagado, on, off -> led rojo y verde) luego el array de bytes se envía a la función send
1 2 3 4
Function Send(ByRef SendData() As Byte, bytes As Integer) As Long Dim SentDataLength As Long
Call MPUSBWrite(myOutPipe, VarPtr(SendData(0)), bytes, VarPtr(bytes), 1000) 'VarPtr()= puntero a la variable End Function
observen el VarPtr(SendData(0)), es lo mismo que hablé hace rato, se toma la dirección del primer byte es lo único que necesita pData para tomar el resto del array de datos el que falta, la suma:
1 2 3 4 5 6 7 8 9 10 11 12
Dim a As Byte 'buffer de datos intermedio
Send_Buf(0) = 0 'Para que reconozca que es una suma a = CByte(sumando(0).Text) 'convierte el texto a byte Send_Buf(2) = a
Send_Buf(0) = 0
a = CByte(sumando(1).Text) Send_Buf(1) = a
Send_Buf(0) = 0
Send Send_Buf, 3 'envía los sumandos recibir (a) 'recibe el resultado
resultado.Caption = CStr(rec) 'convierte el dato a string el Send ya lo hablamos, falta la función recibir:
1 2 3
Dim SentDataLength As Long
Call MPUSBRead(myInPipe, VarPtr(s), 1, 1, 1000)
rec = s 'guardo el dato recibido en una variable intermedia
w w w . u n p o c o d e l e c t r o n i c a . n e t a u . n e t Página 115 aquí sucede lo contrario, es decir, la api MPUSBRead necesita la dirección del byte ‟s‟ para almacenar el dato que viene del PIC (que en este caso es 1 byte de longitud). esto fue el análisis realizado al programa1 y programa2.
vamos a usar el estupendo SnoopyPro para ver los búferes del USB jijiji abrimos y ejecutamos las siguientes acciones en secuencia:
1.- led rojo = ON 2.- led verde = ON 3.- apaga led´s 4.- 1 + 0 = 1 5.- 1 + 7 = 8 6.- 12 + 7 = 19
Capturas con SnoopyPro a ver que tenemos allí:
w w w . u n p o c o d e l e c t r o n i c a . n e t a u . n e t Página 116 Transacción Recibida
tenemos un paquete de 2 bytes, en el primer el modo = 1 (modo led). y en el segundo paraml = 2 (led rojo ON)
Transacción Recibida
tenemos un paquete de 2 bytes, en el primer el modo = 1 (modo led). y en el segundo paraml = 1 (led verde ON)
Transacción Recibida
tenemos un paquete de 2 bytes, en el primer el modo = 1 (modo led). y en el segundo paraml = 0 (led rojo y verde off)
Transacción Recibida
tenemos un paquete de 3 bytes, en el primer el modo = 0 (modo suma). y en el segundo y tercer byte tenemos 0 y 1 que son los operandos de la suma. ojo vean que esto es un paquete down , que transmite HOST -> PIC.
w w w . u n p o c o d e l e c t r o n i c a . n e t a u . n e t Página 117 Contenido paquete
tenemos un paquete de PIC -> HOST de 1 byte ¿y que trae? nada mas y nada menos que el resultado de la suma.
el par de sumas que faltan:
w w w . u n p o c o d e l e c t r o n i c a . n e t a u . n e t Página 118 analizando paquetes
observaciones:
- después de haber visto varias veces el código de Jaime hasta ahora es que me doy cuenta que el led verde es RB6 y led rojo RB7 yo lo tenía invertido. pero lo extraño de todo es que con el programa PicUSBDelphi.exe de Diego se ejecuta OK con los led´s invertido. ¿¿??
- faltaría implementar un algoritmo de validación, porque si ocurre un problema, hay que resetear tanto al programa como al pic para normalizar.
- tengo que instalar el driver wdmstub.sys cada vez que conecto el cable USB en un puerto distinto, ¿no se supone que esos conectores son compartidos?
esto también sucede con la clase CDC.
Fuentes consultadas:
-Interacting with Microchip Full-Speed USB Demo Board using Visual Studio Tools (Part II)
- API-Guide - MSDN Library
w w w . u n p o c o d e l e c t r o n i c a . n e t a u . n e t Página 119
Estudio de mpusbapi.dll (parte IV)
quisiera hacer unas observaciones, varios mensaje atrás hablando sobre la api MPUSBGetDLLVersion() escribí:
cita:
1 nos arroja 10000, y pienso que como hay 8 dígitos, ya que la versión es en hexa (8 nibbles = 32bits) -> versión dll = 1.0.0.0.0
bueno, ahora no estoy tan seguro que eso sea cierto (después de todo es una suposición), ahora me baso en lo siguiente:
- que dicha api, devuelve un puntero que contiene la versión de la librería mpusbapi.dll - si esto es cierto, entonces la versión correcta es 0.0.1.0
aquí está un adjunto con un programa en visual basic que hace lo que digo. está planteado así al momento de escribir esto, pudiéndose cambiar por la versión correcta posteriormente (dado el caso).
voy a tomar el ejemplo del CDC explicado con anterioridad y lo voy a modificar para usarlo con la librería mpusbapi.dll
- lo primero, hacer la detección del lado del dispositivo - lo segundo hacer la detección del lado del Host Detección del lado del dispositivo:
es de la misma forma que para la clase CDC estudiada, mediante el USB_CON_SENSE_PIN
el código con la modificación: 1 2 3 4 5 6 7 8 9 1 0 1 1 1 /* ejemplo7_parte4.c
se pretende hacer la deteccion de conexion al puerto USB, mediante la mpusbapi.dll
mostrando en una pantalla LCD 2x16 el estado.
Este codigo es un hibrido del cual se tomo partes de: - PicUSB.c de J1M
- RRCdcUSB de RedPic
- probando_USB.c del ejemplo6_parte5 de PalitroqueZ
Pedro - PalitroqueZ 07-Mar-2007. Hora: 3:54 PM */
w w w . u n p o c o d e l e c t r o n i c a . n e t a u . n e t Página 120 2 1 3 1 4 1 5 1 6 1 7 1 8 1 9 2 0 2 1 2 2 2 3 2 4 2 5 2 6 2 7 2 8 2 9 3 0 3 1 3 2 3 3 3 4 3 5 3 6 3 7 3 8 3 9 4 0 4 1 4 2 #fuses XTPLL,NOMCLR,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL1,CPUDIV1,VREGE N,NOPBADEN #use delay(clock=48000000)
#define use_portb_lcd TRUE
#define USB_HID_DEVICE FALSE //deshabilitamos el uso de las directivas HID
#define USB_EP1_TX_ENABLE USB_ENABLE_BULK //turn on EP1(EndPoint1) for IN bulk/interrupt transfers
#define USB_EP1_RX_ENABLE USB_ENABLE_BULK //turn on EP1(EndPoint1) for OUT bulk/interrupt transfers
#define USB_EP1_TX_SIZE 1 //size to allocate for the tx endpoint 1 buffer
#define USB_EP1_RX_SIZE 1 //size to allocate for the rx endpoint 1 buffer
#define USB_CON_SENSE_PIN PIN_E3
#include <pic18_usb.h> //Microchip PIC18Fxx5x Hardware layer for CCS's PIC USB driver
#include "PicUSB.h" //Configuración del USB y los descriptores para este dispositivo
#include <usb.c> //handles usb setup tokens and get descriptor reports #include <lcd.c> void mostrar_estado_usb(); void main(){ int envia[1]; int recibe[1]; envia[0]='a';
usb_init_cs(); // inicializa el USB y lo desactiva
lcd_init(); // llamadas necesarias para iniciar la LCD while(true){
usb_task(); //habilita periferico usb e interrupciones mostrar_estado_usb();
if(usb_enumerated()){ // primer if if(usb_kbhit(1)){ // segundo if
//si el endpoint de salida contiene datos del host usb_get_packet(1, recibe, 1);
//cojemos el paquete de tamaño 1bytes del EP1 y almacenamos en recibe
if(recibe[0]=='a'){ // tercer if
usb_put_packet(1, envia, 1, USB_DTS_TOGGLE);
//enviamos el paquete de tamaño 1byte del EP1 al PC lcd_gotoxy(1,1);
lcd_putc("llego una a "); delay_ms(500);
} // fin del tercer if } // fin del segundo if } // fin del primer if lcd_gotoxy(1,1);
lcd_putc("otros procesos"); delay_ms(500);
} // fin del ciclo while
}
/************************************************
w w w . u n p o c o d e l e c t r o n i c a . n e t a u . n e t Página 121 4 3 4 4 4 5 4 6 4 7 4 8 4 9 5 0 5 1 5 2 5 3 5 4 5 5 5 6 5 7 5 8 5 9 6 0 6 1 6 2 6 3 6 4 6 5 6 6 6 7 6 8 6 9 7 0 7 1 7 2 7
// y desconectado del USB dependiendo de la bandera // estado_usb //***********************************************/ void mostrar_estado_usb(){ lcd_gotoxy(10,2); if(usb_attached()){ lcd_putc(" USB:On"); }else{ lcd_putc("USB:Off"); } // delay_ms(500); }
w w w . u n p o c o d e l e c t r o n i c a . n e t a u . n e t Página 122 3 7 4 7 5 http://www.youtube.com/watch?v=2OdNir5O9bo
voy a hacer unas observaciones sobre este programa, porque pasé un buen rato tratando de que funcionara.
- en usb_kbhit(1), el 1 es el endpoint de datos (el argumento es requerido). - sustituí a usb_init por usb_init_cs ¿porque?
R: aquí entra el simulador paso a paso del MPLAB. la función: 1 2 3 4 5 6 7
void usb_init(void) { usb_init_cs();
do {
usb_task();
} while (usb_state != USB_STATE_POWERED); }
se queda en un bucle eterno a menos que el dispositivo sea conectado, pero mi interes es hacer que el pic haga otras actividades independientemente si está presente ó no, el HOST.
usb_init_cs() -> inicializa el módulo USB y lo desactiva, está bien así que se desactive por defecto (menos consumo para el circuito).
- entonces ¿como enciendo el módulo?
para eso está usb_task() dentro del bucle eterno del while(true), en cada instante él preguntará por el USB_CON_SENSE_PIN y dependiendo del Vusb en este pin, él activará/desactivará.
ven lo importante que es el USB_CON_SENSE_PIN, basicamente es una detección por hardware, se está sensando si llega voltaje del HOST (Vusb).
- eliminé la bandera estado_usb, porque es igual que preguntar por usb_attached(), me ahorro 1 bit de memoria (que mezquino jaja). Además que no hay que modificar el driver original pic18_usb.h
- el resto del código queda igual, solo ajustar los paquetes de datos a 1 byte, usando un eco. el HOST le envía un carácter (a) y el dispositivo se lo devuelve.
w w w . u n p o c o d e l e c t r o n i c a . n e t a u . n e t Página 123
volver arriba