Академический Документы
Профессиональный Документы
Культура Документы
www.unpocodelectronica.netau.net
Pgina 2
Introduccin:
Mis Primeros pasos son una serie de artculos que describen la introduccin al mundo de los uC-PIC 18F de Microchip, a travs del 18F4550. el enfoque est orientado a aprender desde cero de alguien (el autor) que viene de conocer y utilizar la serie uC-PIC 16F e intenta conocer poco a poco las nuevas funcionalidades, caractersticas y mdulos que ofrece la serie 18F. se empieza hablando sobre el aspecto fsico y analogas con el uC-PIC 16F877, particularidades en pines, para despus entrar hablar, sobre el mdulo convertidor analgico digital (ADC) y el mdulo estrella de 18F4550 como lo es Bus Serial Universal (USB), donde se hace un estudio paso a paso para hacer las primeras transmisiones, basndose en las libreras que provee el compilador de C de CCS. como nota adicional, quisiera decir que esta serie de artculos de mis primeros pasos con el 18F4550, fu escrita hace mas de 2 aos por lo que las ideas expresadas en sus contenidos pueden estar estar obsoletas o fuera de carril. He querido dejar casi intacto esta serie de artculos desde su origen, ya que la intencin es mirar con la perspectiva de un novato la introduccin a los 18F tal como yo lo hice cuando tuve en mis manos el primer 18F. el enfoque de estos artculos, fu usando una redaccin un poco coloquial, mis excusas para aquellos que sientan que no hay una redaccin propia de un artculo.
www.unpocodelectronica.netau.net
Pgina 3
Pinout del 18F4550 ya sabemos que el 18F4550 posee 40 pines, bien y por lo que se ve en la imagen, tiene cierta similitud con el 16F877 (la misma ubicacin del pin vdd, vss, mclr entre otros) el siguiente paso es saber como trabaja la configuracin del oscilador, en verdad a primera vista con el diagrama del clock que aparece en la Pg. 26, parece complicado, pero no es tan difcil, si se ve como si fuera el juego del laberinto, se pueden activar los bits de los registros necesarios y as configurar el oscilador para el cristal que usemos y el tiempo del ciclo de instruccin. En la pgina de PicMana de Diego (RedPic) hay un artculo llamado: Consiguiendo 4 Mhz para los 48 Mhz necesarios en los PICs con USB 2.0, siguiendo las instrucciones podemos configurar el CPU del 18F4550 a 48Mhz con solo seleccionar los word configuration correctos. como yo tengo un cristal de 4MHZ, lo usar para poner a trabajar el CPU a 48MHZ, y porque 48 MHZ? claro! si se puede llegar hasta ah, entonces a trabajar al mximo!
segn la eleccin de mi cristal dibuj el camino a tomar para que la etapa del oscilador tenga 48Mhz a la entrada del cpu, partiendo de los 4MHZ que le entran
www.unpocodelectronica.netau.net
Pgina 4
esto es necesario porque lo primero que debemos tomar en cuenta son los fuses que se van a usar y la configuracin del oscilador forma parte de ello para colocar el fuse de configuration y ya que es la primera vez, tomar prestado de la que he visto en ex_usb_serial2.c que trae de ejemplo del compilador PCWH de CCS
1 ... 2 //configure a 20MHz crystal to operate at 48MHz 3 #fuses 4 HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN 5 #use delay(clock=48000000) 6 ...
www.unpocodelectronica.netau.net
Pgina 5
[PRIMEROS PASOS CON EL 18F4550] 14 de abril de 2010 esto hay que analizarlo, hay algunos conocidos y otros nuevos (que se van a explicar), as que vayamos a la pgina 288 de la datasheet y al archivo cabecera 18F4550.h HSPLL: para cristales >4MHZ usando el PLL, en el cdigo ejemplo como XTAL=4MHZ -> se cambiar a XTPLL MCLR: significa que el pin 1 cumplir la funcin de Master CLeaR (y como arranca el PIC cuando no hay MCLR?) USBDIV: significa que el clock del usb se tomar del PLL/2, para nuestro cdigo es irrelevante, ya que no usaremos el mdulo USB, pero lo dejaremos (o es 1 es 0) PLL5: significa que el PLL prescaler dividir en 5 la frecuencia del cristal, si uso el cristal de 4MHZ no habr falta dividir por lo que se usar PLL1 CPUDIV1: el PLL postscaler decide la divisin en 2 de la frecuencia de salida del PLL de 96MHZ, si queremos 48MHZ, lo dejaremos como est. VREGEN: habilita el regulador de 3.3 volts que usa el mdulo USB, no lo usaremos por los momentos, se cambiar por NOVREGEN existen mas fuses para configurar, y habra que determinar como el compilador configura el resto si miran el la pgina 288, notaran que existe mas de un configuration word (especficamente 7), no como en 16F877 que haba solo uno. bueno, nuestro fuse quedar as:
1 #fuses 2 XTPLL,MCLR,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL1,CPUDIV1,NOVREGEN
ahora viene escribir un cdigo sencillo para poner arrancar el PIC, el programita lo que va a hacer es, encender y apagar el PORTB en intervalos de 1 seg. y para ello hay que averiguar como est configurado por defecto cada pin, me refiero a esto, ya que he manejado un poco el 16F877 y por ejemplo el pin RB3 siempre hay que configurarlo en el fuse si se va a utilizar como i/o digital
PBADEN: PORTB A/D Enable bit Cmo!?, el portb tiene funciones de entrada analgica?, pues sip, as que tambin hay que meter esa opcin en el fuse. Vamos hacer una prueba, vamos a dejar tal cual qued nuestro fuse, para ver como lo hace el compilador y lo sabremos cuando carguemos el .hex en el winpic800
www.unpocodelectronica.netau.net
Pgina 6
[PRIMEROS PASOS CON EL 18F4550] 14 de abril de 2010 vamos a escribir este cdigo en lenguaje C de CCS (para facilitar el aprendizaje pero sigo con el dilema si lo hago en C en asm, para conocer mejor al micro) y el simulador ser el MPLAB-SIM, que podemos hacer, hasta la fecha en que escrib esto el proteus todava no trae el 18F4550
1 2 3 4 5 6 7 8 9 1 0 1 1 1 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
// cdigo ejemplo para hacer funcionar por primera vez al PIC18F4550 mediante encendido // y apagado de 8 leds conectado al PORTB en intervalos de 1 Seg // 16-Dic-2006 #include <18f4550.h> //archivo de cabecera #fuses XTPLL,MCLR,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL1,CPUDIV1,NOVREGE N // el fuse que configuramos anteriormente #use delay(clock=48000000) // el clock que tendremos a la entrada del CPU void main() { set_tris_a(0x0); // configura los puertos como salidas set_tris_b(0x0); set_tris_c(0x0); set_tris_d(0x0); set_tris_e(0x0); //---------------------------------disable_interrupts(global); disable_interrupts(int_timer1); disable_interrupts(int_rda); disable_interrupts(int_ext); disable_interrupts(int_ext1); disable_interrupts(int_ext2); setup_adc_ports(NO_ANALOGS); setup_adc(ADC_OFF); setup_spi(FALSE); setup_psp(PSP_DISABLED); setup_comparator(NC_NC_NC_NC); setup_vref(FALSE); port_b_pullups(FALSE); //--------------------------output_a (0); // saca un nivel bajo de salida en los puertos output_c (0); output_d (0); output_e (0); while(1){ output_b (0); // saca un nivel bajo en el portb delay_ms(1000); // retardo de 1 Seg output_b (0xff); // saca un nivel alto en el portb delay_ms(1000); // retardo de 1 Seg } }
www.unpocodelectronica.netau.net
Pgina 7
las lineas que estn delimitadas, las saqu del cdigo _rtc.c que escribi RedPic, en estas lineas se desactivan otros modulos, como por ejemplo el CAD, SPI, PSP, las interrupciones y las resistencias de amarre que estn en el PORTB, para este PIC hay que averiguar como estn configurados por defectos cada pin y all veremos si hace falta habilitar deshabilitar ciertos modulos (esto se aplica tambin para los fuses) Esto ltimo lo digo porque el simulador es una cosa y el funcionamiento real es otra, en el caso de los fuses, nosotros podemos determinar la configuracin porque el winpic800 nos lo dir, pero en el caso de los mdulos activados o desactivados por defecto, no siempre el simulador acertar, as que para estar seguros es mejor escribir las configuraciones en el programa. (esperemos que con esas sea suficiente) bueno, compilemos y simulemos a ver que tal.
www.unpocodelectronica.netau.net
Pgina 8
[PRIMEROS PASOS CON EL 18F4550] 14 de abril de 2010 que bien nos compil exitosamente, vamos a cargar el MPLAB-SIM y abrimos tambin la ventana de los SFR, para ir viendo como estn los registros que nos interesa y los que nos pueden interferir. nota: se me pas por alto, con los pasos que indica el wizard crean el proyecto para el cdigo que estamos probando y despus configuran la frecuencia del CPU (los fuses no hacen falta configurarlo, porque el MPLAB los carga del que ya habamos programado) vamos a ver como qued el configuration bits
Bits de Configuracin en MPLAB epa! aqu dice que el portb tiene algunas entradas analgicas, vamos a ver que dice el temp18.lst (el listado que genera el compilador)
Configuration Fuses: 1 Word 1: 0220 XTPLL NOIESO NOFCMEN PLL1 CPUDIV1 USBDIV 2 Word 2: 1E1E BROWNOUT NOWDT BORV20 PUT WDT32768 NOVREGEN 3 RESERVED 4 Word 3: 8300 PBADEN CCP2C1 MCLR NOLPT1OSC RESERVED 5 Word 4: 0081 STVREN NODEBUG NOLVP NOXINST NOICPRT RESERVED 6 Word 5: C00F NOPROTECT NOCPD NOCPB 7 Word 6: E00F NOWRT NOWRTD NOWRTC NOWRTB 8 Word 7: 400F NOEBTR NOEBTRB
efectivamente est la opcin PBADEN, pues ya comprobamos que se debe colocar NOPBADEN en fuse, si es que queremos que RB[4-0] funcione como salida digital. el fuses quedar:
1 #fuses 2 XTPLL,MCLR,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL1,CPUDIV1,NOVREGEN ,NOPBADEN
www.unpocodelectronica.netau.net
Pgina 9
[PRIMEROS PASOS CON EL 18F4550] 14 de abril de 2010 compilamos y vemos nuevamente la ventana configuration bits
Bits de Configuracin Corregido ahora si nos aparece los pines RB[4-0] como i/o digitales. Si por ejemplo simulamos con la opcin PBADEN, vern como en el portb no habr problemas, har lo que el cdigo le dice, pero cuando vayamos a probar el PIC, no ser as. Se dan cuenta? hay que estar pendiente de esos detallitos que nos pueden causar dolor de alma. viendo los registros PORTB y uno nuevo, el LAT., vern que cambiarn de estado:
Simulacin Mplab
www.unpocodelectronica.netau.net
Pgina 10
Tiempo en Mplab-SIM en la ventana stopwatch, se observa que por cada lnea ejecutada ocurren mas de un ciclo de reloj, esto es tpico del C, si queremos ver que ocurre en cada ciclo, nada mas carguemos Disassembly Lisa y veremos el cdigo en C con su correspondiente asm
Listado en Ensamblador
www.unpocodelectronica.netau.net
Pgina 11
[PRIMEROS PASOS CON EL 18F4550] 14 de abril de 2010 una vez ya simulado y verificado, viene la parte crtica, y es la de programar el PIC, montarlo en el protoboard y rezar para que funcione, podemos llegar a 2 resultados: -Que si funciona y realmente nos llena de alegra y podemos dar el siguiente paso Que no funciona y hay que volver a revisar todo nuevamente :-s la segunda opcin es la frecuente y que no nos gusta mucho, pero es la que nos d el conocimiento. Manos a la obra! amigos, de buena suerte que todo funcion al primer arranque!! y es que se tomaron las previsiones una y otra vez, antes de conectar el PIC, verifiqu niveles de tensin, posicin de los pines, etc. http://www.youtube.com/watch?v=Wlpz-R9b0pY en realidad con este primer ejemplo lo que se pretende, es aprender a configurar el oscilador y a configurar los fuses, que es lo bsico a la hora de programar un PIC.
www.unpocodelectronica.netau.net
Pgina 12
vaya, vaya, como haremos. Bueno lo que se puede hacer es usar el resto de los pines que si funcionan como salida digital. RC[7-6,2-0]
1 2 3 4 5 6 7 8 // cdigo ejemplo para hacer funcionar por segunda vez al PIC18F4550 mediante encendido // y apagado de 8 leds conectado al PORTB y RE3 en intervalos de 1 Seg (sin usar el MCLR) // 20-Dic-2006 #include <18f4550.h> //archivo de cabecera #fuses
www.unpocodelectronica.netau.net
Pgina 13
www.unpocodelectronica.netau.net
Pgina 14
en los pines no usados del portc, del ejemplo1, no le dimos importancia, pero RC[5-4] estaban como entrada digital (segn el MPLAB el mdulo USB est deshabilitado por defecto) y no nos dimos cuenta y dejamos esos pines al aire, para resolver esto, coloqu unas resistencias de 1k a VSS
despus de compilar exitosamente (gracias Dios, jeje) y verificar los fuses veremos en la simulacin en MPLAB a ver que pinta tiene:
http://www.youtube.com/watch?v=anfwe__gnYc
www.unpocodelectronica.netau.net
Pgina 15
[PRIMEROS PASOS CON EL 18F4550] 14 de abril de 2010 yo creo que no importa si limpiamos el TRISC, porque de todas manera RC[5-4] quedaran como entradas, observen que en la simulacin aparecen esos pines como salidas activndose (aunque el LATC aparece RC[5-3]<-0 raro no?), ya hice la prueba y no encienden los leds para esos pines. nota: el circuito para este ejemplo est en el adjunto, en el circuito del ejemplo1 omit un componente que haba puesto en el protoboard, es un condensador de 100nF entre VDD y VSS. el montaje funcionando:
http://www.youtube.com/watch?v=YPHsHsEao10
el objetivo de este ejemplo fue el como trabajar el pin 1 del PIC 18F4550 y los detalles que trae el portc el adjunto con el cdigo fuente, circuito elctrico, etc.
PORTx vs LATx
-Qu es eso de LATA, LATB,..?- si miran en la pgina 71 de 39632c.pdf, tenemos del LATA-LATE. La segunda que vemos el LAT es en la pgina 113 y ya empiezan a especificar su funcionamiento, el LAT significa output latch salida del latch, si comparamos una salida de este pic con uno del 16F877
www.unpocodelectronica.netau.net
Pgina 16
El pin RC3 del 18F4550 la diferencia principal que se ve all es el buffer RD LAT cuya funcin es leer el estado de la salida del LAT (que funcin puede tener el leer la salida del LAT?) y WRLAT or PORT en el clock, bueno amigos como el datasheet no d mayores explicaciones porque dice que puede ser cualquiera de los 2. Puedo escribir en el pin usando LATx,pin PORTB. As que consultando los links de arriba, todos coinciden: el registro existe por cuestiones de rapidez al cambiar un flanco en un pin. yo recuerdo que para evitar escrituras errneas en la familia 16F manejando bits se recomienda colocar un nop entre pines:
1 bsf porta,0 2 nop 3 bsf porta,1
obviamente que la existencia del registro LATx es una mejora ya que en un ciclo de instruccin garantizas la escritura en un pin del puerto, pero esto habra que comprobarlo con un ejemplo quera pegar este cdigo en ensamblador pero dentro de entorno C
1 2 3 4 #asm bsf PORTB,0,1 bsf PORTB,1,1 #endasm
www.unpocodelectronica.netau.net
Pgina 17
[PRIMEROS PASOS CON EL 18F4550] 14 de abril de 2010 pero sospecho que el pcwh, mete sus narices an en asm, porque en la ayuda del ccs, dice:
BSF f,b
BSF f,b,a
donde a es un operando que tiene que ver con el tipo de acceso al banco de memoria RAM (bueno, pero no se supone que la memoria RAM es lineal?), esa duda la dejaremos pendiente por los momentos. entonces lo mejor es ensamblar desde el mpasmwin y ya que vamos a usar el 100% ensamblador, es bueno saber saber la configuracin de los puertos, para ello veremos la inicializacin de los puertos que salen a partir de la Pag 113 (corresponde al captulo 10 I/O PORTS) y en la plantilla 4550temp.asm que est en la carpeta code dentro de MPASM Suite el archivo hlpPIC18ConfigSet.chm ensea como configurar los fuses una nota curiosa vean la direccin sealada (viendo el listado en asm generado por el CCS del ejemplo2)
Coincidencia
www.unpocodelectronica.netau.net
Pgina 18
[PRIMEROS PASOS CON EL 18F4550] 14 de abril de 2010 as ser de fea la programacin en asm para los 18F que el propio MPLAB me lo dice, jaja pero volviendo en serio, aqu vamos a tener que repetir un poco el ejemplo1, configurar los fuses que ya no se llamaran fuses, sino word configuration, configuratin bits. (ver Pag . 287) La directiva de configuracin de palabras se puede escribir CONFIG y seguido los bits involucrados (en 16F se escribe __CONFIG xx & yy &..) para mayor comodidad se puede escribir CONFIG CP = OFF, OSC = LP,.. tomando el fuse del ejemplo1 nuestra palabra de configuracin quedar as:
CONFIG FOSC = XTPLL_XT, PLLDIV = 1,CPUDIV = OSC1_PLL2,USBDIV = 2,PWRT = ON,BOR = SOFT, VREGEN = OFF , WDT = OFF ,WDTPS = 1,MCLRE = ON,PBADEN = OFF CONFIG LVP = OFF,XINST = OFF,DEBUG = OFF
aqu hay que escribirlos toditos, porque no se sabe como estan por defectos, pero sin complicar mucho la explicacin lo que se hizo fu ver como el CCS configuraba los 7 word y llevarlos al asm, y eso fu lo que est arriba. este ejemplo3 har lo siguiente: -RB0 es un switche (normalmente en 0) -si hay un cero en RB0-> se encendern los leds de RB[6,4,2] -si hay un 1 en RB0-> se encendern los leds de RB[7,5,3,1] -en cada caso se apagarn los leds no mencionados.
para la escritura del PORTB, primero se utilizar el clsico PORTB, a ver que sucede y despus el LATB
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ; cdigo ejemplo para hacer funcionar por tercera vez al PIC18F4550 mediante encendido ; y apagado de 8 leds conectado al PORTB dependiendo del estado del pulsador en RB0 ; que encender leds pares e impares ; 21-Dic-2006 LIST P=18F4550 ;directive to define processor #include <P18F4550.INC> ;processor specific variable definitions CONFIG FOSC = XTPLL_XT, PLLDIV = 1,CPUDIV = OSC1_PLL2,USBDIV = 2,PWRT = ON,BOR = SOFT, VREGEN = OFF CONFIG WDT = OFF ,WDTPS = 1,MCLRE = ON,PBADEN = OFF,LVP = OFF,XINST = OFF,DEBUG = OFF CBLOCK 0x0 ENDC org 0
www.unpocodelectronica.netau.net
Pgina 19
como pueden ver, en este cdigo se va a comprobar que pasa si usamos la instruccin PORTB para manejar datos de salida y LATx notas: -por darmelas de vivo, trat de configurar el TRISB, as:
www.unpocodelectronica.netau.net
Pgina 20
movff 01,TRISB
pero no sirve, porque para esa instruccin los argumentos deben ser registros en ambos (ver pagina 334), nos vamos por el tradicional registro de trabajo, (que ahora se llama WREG) -hay otra instruccin nueva el BRA, suena al salto que se utiliza en BASIC (que sera BRANCH) y porque no usamos el goto? bueno tambin sirve, una diferencia que le, es que el goto puede saltar mas lejos, para nuestro ejemplo el BRA sirve, lo dejaremos. ahora compilaremos el ejemplo3 y simularemos con el MPLAB (mirar con atencin la ventana de la derecha, es la de Registros Funciones eSpeciales):
http://www.youtube.com/watch?v=uhYkxjsU6wU
el warning se debe a que la instruccin limpia un registro de solo 6 bits, los menos significativos, pero no hay rollo. en la simulacin vemos que ningn pin del puertoB cambia, ni el LATB, pero como yo soy necio, voy a grabar ese mismo cdigo en el pic, haber que hace. nota: la palabra de configuracin la compar con el del ejemplo1, e hice un cambio el BOR=ON el watchdog, aunque cambi, no altera el programa. el video en protoboard:
http://www.youtube.com/watch?v=tAMmVcAKKGk
Qu! y porque se quedan prendidos esos 3? vamonos a revisar el cdigo, parece que hay un error en las instrucciones B(s/c)F, especificamente en el ltimo argumento, yo les puse 1. Ese argumento tiene que ver con el acceso al banco de memoria, si vemos un momento el listado que genera el dissasembler:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ... 0004 6A92 CLRF 0xf92, ACCESS 29: clrf TRISA ; configuar el port como salida que bueno!, no hay que estar cambiando de bancos ;-) 0006 0E01 MOVLW 0x1 30: movlw 0x1 0008 6E93 MOVWF 0xf93, ACCESS 31: movwf TRISB ; configura RB0<- entrada, el resto -> salida 000A 6A94 CLRF 0xf94, ACCESS 32: clrf TRISC 000C 6A95 CLRF 0xf95, ACCESS 33: clrf TRISD 000E 6A96 CLRF 0xf96, ACCESS 34: clrf TRISE 35: ;//-----------------------------------------------------
www.unpocodelectronica.netau.net
Pgina 21
www.unpocodelectronica.netau.net
Pgina 22
vemos que hay varias instrucciones que tienen un tercer argumento, este argumento define como se va a accesar al banco de memoria RAM. En la pagina 66 aparece el mapa de la memoria de datos
www.unpocodelectronica.netau.net
Pgina 23
mapa de la memoria la memoria se divide en bancos y dependiendo de un tal BSR(registro selector de banco) se puede accesar a diferentes direcciones. como esto es un tema aparte(que apenas estoy conociendo), solo dir, que por defecto el tercer argumento es 0 como lo llama el mpasmwin (y el CCS tambin): ACCESS. Es vlido si no se coloca nada, el MPLAB, lo asume como a=0 (ver pagina 67) se colocar 0 en todas los B(s/c)F y el cdigo quedar as:
1 ; cdigo ejemplo para hacer funcionar por tercera vez al PIC18F4550 2 mediante encendido 3 ; y apagado de 8 leds conectado al PORTB dependiendo del estado del
www.unpocodelectronica.netau.net
Pgina 24
www.unpocodelectronica.netau.net
Pgina 25
haciendo la simulacin (mirar con atencin la ventana de la derecha, es la de Registros Funciones eSpeciales):
http://www.youtube.com/watch?v=m-7uVP1ji6w all muestra que el PORTB cambia los estados de acuerdo a la programacin escrita, ahora procedemos a grabar el pic y ver el comportamiento http://www.youtube.com/watch?v=AwaivT3Fg3g
ahora si hace lo que tiene que hacer, encender los leds pares e impares dependiendo del switcheo. pero entonces quiere decir que si se puede trabajar con el PORTB como salida. vamos a tomar el otro caso, sustituiremos el PORTB por LATB en la escritura de los pines de salida (llamemos ejemplo3_lat). el cdigo cambiar as:
1 2 3 4 5 6 7 8 9 1 0 1 1 1 2 1 3 1 4 1 5 1 6 1 7 1 8 ; cdigo ejemplo para hacer funcionar por tercera vez al PIC18F4550 mediante encendido ; y apagado de 8 leds conectado al PORTB dependiendo del estado del pulsador en RB0 ; que encender leds pares e impares ; 21-Dic-2006 LIST P=18F4550 ;directive to define processor #include <P18F4550.INC> ;processor specific variable definitions ;#fuses XTPLL,MCLR,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL1,CPUDIV1,NOVREGE N,NOPBADEN // el fuse que configuramos anteriormente (CORREGIDO) ;#use delay(clock=48000000) // el clock que tendremos a la entrada del CPU CONFIG FOSC = XTPLL_XT, PLLDIV = 1,CPUDIV = OSC1_PLL2,USBDIV = 2,PWRT = ON,BOR = ON, VREGEN = OFF CONFIG WDT = OFF ,WDTPS = 1,MCLRE = ON,PBADEN = OFF,LVP = OFF,XINST = OFF,DEBUG = OFF CBLOCK 0x0 ENDC org 0 goto inicio
www.unpocodelectronica.netau.net
Pgina 26
www.unpocodelectronica.netau.net
Pgina 27
www.unpocodelectronica.netau.net
Pgina 28
haciendo de nuevo la simulacin: (mirar con atencin la ventana de la derecha, es la de Registros Funciones eSpeciales)
http://www.youtube.com/watch?v=6ysIB7npYao el puerto B se escribe como debe ser, muy bien. Ahora a quemar el pic y probar en el protoboard http://www.youtube.com/watch?v=S559xGjpR6g
obtenemos el mismo resultado. La conclusin de este tercer ejemplo, bueno la verdad es que no se pudo demostrar el uso/comportamiento del PORTX frente al LATx, como escritura a los pines, creo que eso lo dir la experiencia, ensayando y programando con el pic como ya lo han hecho los que saben sobre el tema.
www.unpocodelectronica.netau.net
Pgina 29
www.unpocodelectronica.netau.net
Pgina 30
de acuerdo a la imagen anterior: -existen unos pines que se pueden configurar como entrada analgica, del cual se toma uno a la vez. -dado un arreglo R-C,que existe dentro, o a la entrada del mdulo CAD se toma un nivel de tensin en un tiempo discreto, ese voltaje se almacenar en el condensador interno (Chold) -el tiempo que tarde ese condensador en cargarse, lo determinaremos nosotros de 2 maneras: -mediante un retardo por software (configurando un timer, generando ciclos de instruccin. -mediante un retardo por hardware (configurando los bits ACQT2:ACQT0 en ADCON2) este tiempo, es el tiempo de adquisicin Tacq (acquire), y es fundamental para obtener precisin en el resultado digital. Ojo no confundir con Tad, como lo hice alguna vez, (las iniciales en ingls se asemejan a las iniciales en espaol). en el caso del 16F877, mediante clculos tericos era Tacq ~ 20uS
www.unpocodelectronica.netau.net
Pgina 31
[PRIMEROS PASOS CON EL 18F4550] 14 de abril de 2010 en el caso del 18F4550, el tiempo mnimo que sacan es Tacq ~ 2,45uS
Tiempo de Adquisicin 18F4550 esto aparece en la pgina 266. Se nota que disminuy el tiempo y aumentando as la velocidad en el CAD el retardo por hardware (que as lo quise llamar) programmable acquisition time es algo nuevo, es posible configurar el Tacq:
Diferencias de ciclos de Tacq en la figura 21-4 es como siempre lo habiamos visto, antes de activar el GO_DONE haba que introducir el Tacq. Ahora usando la configuracin por hardware, tenemos la figura 21-5 donde sucede despus de haber seteado al GO_DONE (no algodn, )), hacindolo automtico.
www.unpocodelectronica.netau.net
Pgina 32
[PRIMEROS PASOS CON EL 18F4550] 14 de abril de 2010 -luego viene el proceso de hacer la conversin, es decir, tomar el valor analgico de lo que est cargado en el condensador Chold y llevarlo a un nmero binario. -en este proceso de conversin hay otros parmetros, uno de ellos es el reloj de conversin, esto quiere decir que el mdulo CAD, trabaja con un reloj distinto del CPU y que puede depender o no de ste. Eso lo dir la debida configuracin de los bits ADCS2:ADCS0 del registro ADCON2 Cuando digo que puede ser independiente del CPU, es porque puede trabajar con un reloj interno (un oscilador RC) cuya aplicacin sera poner a dormir el PIC mientras se est haciendo una conversin, y que utilidad puede tener esto?, bueno al estar trabajando solo el mdulo CAD, se reduce el ruido de conmutacin de los otros perifricos y puede aumentar la precisin del valor digital obtenido. Desventajas: usando el oscilador interno se tarda mas la conversin (en el orden de los mS, que podra sera mucho tiempo para algunos eventos) cuando inicia la conversin, lo primero que hace es desconectar el condensador Chold de la entrada analgica, y mediante una aproximacin sucesiva, se v guardando bit a bit de los 10 bits que hay, el resultado digital (ver figura 21-4) esto tambin tiene su tiempo y es el tiempo (retardo) de conversin analgico digital por bit, llamado Tad. Segn la pagina 267 se requiere de un tiempo de 11Tad para realizar una conversin, el Tad mnimo para el CAD del 18F4550 es 700nS(pagina 400) pero haciendo algunos clculos de acuerdo a la tabla 21-1
Frecuencia Operacin Tad usando un clock del CPU de 48Mhz se obtiene hasta 64/48Mhz = 1.33uS
www.unpocodelectronica.netau.net
Pgina 33
Secuencia Conversin A/D Nota: el Tacq sacado por hardware depende de Tad
Bits seleccin Tacq posteriormente viene todo lo que se venia aplicando anteriormente, esperar a que GO_DONE =0 esperar la interrupcin del CAD y tomar el valor que est en la pareja de bytes ADRESH:ADRESL (limpiar la bandera ADIF si es es por interrupcin) en general, los pasos para un CAD, serian (Pg. 265):
www.unpocodelectronica.netau.net
Pgina 34
pasos requeridos para realizar una conversin desde luego que todo esto es pura teora, as que vamos a darle con un ejemplo para nuestro ejemplo (ejemplo4): -usaremos un reloj de conversin de 64Tosc = Fosc/64 ya que seguiremos usando un clock de 48Mhz y esto es lo que recomienda la tabla 21-1 -usaremos el Tacq por hardware, as que si nuestro Tad= 1.33uS, entonces usando un tacq= 2Tad= 2*1.33uS = 2.66uS -seleccionaremos el canal AN0, el resto como i/o digital. -haremos la conversin AD y despus indicaremos el resultado en 10 leds. aunque yo no se para que tanta precisin, si estoy trabajando en C, y no se que como har eso el compilador. clculo preciso + clculo(terico)= clculo preciso + error ( prctico) clculo preciso + error ( terico)= clculo preciso + error ( prctico) + error ( terico)
1 // usando el CAD en el 18F4550 2 // 30-Dic-2006
www.unpocodelectronica.netau.net
Pgina 35
www.unpocodelectronica.netau.net
Pgina 36
buscando en el CCS no consegu alguna constante declarada para los bits ACQTx as que tuve que crearlos y hacer una OR incluyente con las dems constantes dentro de la funcin setup_adc().
int ADC_ACQT_2TAD=01;
para comprobar si esto es correcto, voy a compilar y mirar en la ventana SFR del MPLAB para ver como qued el registro ADCON2 http://www.youtube.com/watch?v=wI9DlXFLGEI Pero fue en vano, el CCS no me deja cambiar los bits 3,4,5 de ADCON2, as que me voy por ensamblador, sustituyo la lnea setup_adc(ADC_CLOCK_DIV_64 || ADC_ACQT_2TAD ); por:
1 2 3 4 #asm movlw 0b10001110 ;justificacion_derecha,2Tad,Fosc/64 movwf 0xFC0 ; direccion de ADCON2 #endasm
www.unpocodelectronica.netau.net
Pgina 37
ahora si acept el cambio, entonces se hace la simulacin nuevamente, pero antes introduzco el cambio de ADRESx mediante estmulos, en una de las fuentes consultadas ( ver arriba) el amigo Maunix explica como hacerlo, ahora si arrancamos con el MPLAB-SIM http://www.youtube.com/watch?v=Fzf2_wvbiQU el estmulo no est funcionando, de verdad que pas un rato creyendo que estaba mal configurado el Register Injection, pero despus me di cuenta que faltaba la instruccin setup_adc(), si as como lo leen, como se hace entonces si lo haba quitado?, bueno, lo coloque de nuevo y le aad el pedacito en assembler para que aceptara el cambio en ADCON2
1 2 3 4 5 setup_adc(ADC_CLOCK_DIV_64 );//|| ADC_ACQT_2TAD ); #asm movlw 0b10001110 ;justificacion_derecha,2Tad,Fosc/64 iorwf 0xFC0,1 ; direccion de ADCON2 #endasm
claro, que cambi el movwf por iorwf, para que me aceptara los nuevos bits sin alterar el estado anterior de ADCON2, tambin es bueno decir que por aqu se puede cambiar la justificacin, hay otra cosa interesante, en CCS hay una directiva #DEVICE ADC=xx , sera bueno analizar que pasa si cambio ADC=10 por ADC=16, esto har la justificacin hacia la izquierda?, sera otro estudio. vamos a simular de nuevo, nota: el archivito llamado adresito.txt tiene estas lneas guardadas:
www.unpocodelectronica.netau.net
Pgina 38
esas lneas corresponden al supuesto valor de ADRESH:ADRESL y sern cargadas por el estmulo en un bucle http://www.youtube.com/watch?v=H4ozbfY1PGY me dio curiosidad y v el listado en ensamblador, met un breakpoint en el momento de escoger el canal y hasta que se cargan la pareja ADRESH:ADRESL
Tiempo muestra medido en MPLAB-SIM calculando el tiempo terico: Tacq= 2*Tad + 11*Tad= 2*(64/48Mhz) +11*(64/48Mhz)=17.33uS bastante aproximado con los 18.33 uS que d el MPLABSIM. el siguiente paso es programar el PIC y probarlo en el protoboard, hay un detallito que se est olvidando,la resistencia Rs, que es la que v a la entrada AN0, segn los clculos tericos mximo de 2.5k, yo usar un potencimetro que le med 2k que es lo que tengo a mano, habr algn cambio? eso habr que verlo en el protoboard. ja ja con tanta cablamenta, me imagino el ruido que debe haber all. Lo importante es que hicimos arrancar el mdulo CAD y que hicieras las respectivas conversiones. hice unas mediciones con el tester, y me di cuenta que al insertar la punta en AN0 parece que introduce variaciones, as que conect un TL082 como seguidor de voltaje, para poder medir sin interferencias. peeeero me top con un problemita, hay un detalle
www.unpocodelectronica.netau.net
Pgina 39
[PRIMEROS PASOS CON EL 18F4550] 14 de abril de 2010 cuando intentas medir niveles cercano a 0 volts usando el TL082. Buscando por ah consegu una pgina donde explican el fenmeno (llamado latch-up), a mi me sucede esto porque alimento al operacional con +Vcc=+5 y -Vcc=0. Solucin: aliment al operacional con +Vcc=+12 y -Vcc= -12 y listo!. volv hacer mediciones, esta vez arreglando mejor las conexiones: - una especie de apantallamiento a la entrada AN0 - acerqu mas el C=100nF de alimentacin del PIC. y varios resultados obtenidos:
datos obtenidos tabulados segn estos datos obtenidos, la precisin es mas o menos uhmmm, ser por el montaje en protoboard, si ya se que todo es relativo voy hacer otra prueba, voy a aumentar el Tacq al mximo permitido por ADCON2, esto es 20Tad = 20 * 1.33uS = 26.6 uS bastante tiempo de sobra que sumndole 11Tad = 11* 1.33uS =14.63uS dara una conversin aproximada de 41.23uS para Tacq=20Tad -> ADCON2<-0b10111110, entonces el cdigo cambiar:
1 2 3 4 #asm movlw 0b10111110 ;justificacion_derecha,20Tad,Fosc/64 iorwf 0xFC0,1 ; direccion de ADCON2 #endasm
repitiendo todo el procedimiento anterior, compilando y simulando y despus grabar el micro, llegamos a revisar el montaje en el protoboard: y unos datos nuevos que recopil
www.unpocodelectronica.netau.net
Pgina 40
Segunda recopilacin datos Conclusin: Bueno seores, esos resultados como que mejoraron un poco, uhmmmm la verdad es que nunca he podido obtener valores calculados en la prctica, quizs un montaje mejor elaborado en baquelita y bien filtrado pueda aumentar la precisin. espero que les pueda instruir en algo.
Colocar condensador 100nF en AN0 all recomiendan colocar un condensador de 100nF a la entrada de AN0 si la seal no cambia tan rapidamente, a mi me sirve pues estoy variando con un destornillador y eso es mas lento que inyectar una seal de baja frecuencia. -para la alimentacin en AN0, us un 7805 aparte, para separar los voltajes. -not una variacin de Vdd, no se porque la alimentacin del 7805 cambia cuando varo el potencimetro en AN0, as que en las mediciones tom en cuenta ese valor de Vdd que es mi Vref, en cada dato que sacaban los leds. los nuevos datos obtenidos:
www.unpocodelectronica.netau.net
Pgina 41
nuevos datos
valor prctico vs calculado segn la grfica se nota una mejora en la precisin, pero yo sigo obstinado a conseguir mas precisin, despus de un buen rato debugeando con el MPLAB SIM, observ la pestaa MPLAB SIM que est adentro de la ventana OUTPUT y me sala este mensaje:
ADC-W0001: Tad time is less than 1.60us 1 ADC-W0010: A Minimum of 2 TADs are required before another conversion 2 should be started.
-el primer mensaje es cierto porque el ADCON2 est para FOSC/64 = 1.33uS, pero recuerden que me estoy guiando por las recomendaciones de la datasheet. -con el segundo mensaje, el MPLAB SIM me di un regao, muy cierto me salt esos tiempos:
www.unpocodelectronica.netau.net
Pgina 42
Tiempo mnimo Tad esto sale en la pgina 265 3Tad = 3*(64/48MHZ)=3.99uS entonces modifiqu el programa, metiendo un delay_us(5) y grab el pic, y volv a tomar datos, pero un momento! en la pgina 268 dice que pueden ser 2Tad:
Tiempo mnimo 2Tad yo con mi mana lo saqu para ambos valores(2Tad y 3Tad) y aqu estan los resultados: para tiempo entre muestras >= 2Tad:
www.unpocodelectronica.netau.net
Pgina 43
Muestra 3uS prctico vs calculado para tiempo entre muestras >= 3Tad:
www.unpocodelectronica.netau.net
Pgina 44
[PRIMEROS PASOS CON EL 18F4550] 14 de abril de 2010 Muestra 5uS prctico vs calculado Ahhh!!! se dan cuenta seoras y seores, los valores son cercanos a lo calculado, o sea, que ese tiempito entre conversin y conversin es MUUY IMPORTANTE y yo voy a seguir sacandole punta a este ejemplo (que ahora se llama ejemplo4_parte2). nota: -esto ya se sale de la iniciacin con el 18F4550, formara parte de la configuracin bsica de un mdulo CAD. -observen en los resultados que la variacin de Vdd fu muy poca !?!? voy a modificarlo como quera en un principio, tratar que el CAD se tarde lo mnimo en hacer una conversin, es decir, con Tacq=2Tad y un 2Tad entre muestras, para ellos cambiamos por estas lineas:
1 2 3 4 5 6 #asm movlw 0b10001110 //justificacion_derecha,2Tad,Fosc/64 ... ... delay_us(3); // para pasar >= 2Tad a la sig CAD ...
www.unpocodelectronica.netau.net
Pgina 45
datos obtenidos Tacq y 2Tad para 3uS de estos ultimos resultados tengo varias conclusiones: -que si es posible hacer un conversin con aceptable precisin, usando el mnimo tiempo de la Adquisicin por hardware. -que el Vdd variaba (y esto es una sospecha) debido a incremento de corriente de parte de los leds, noten en los datos que a medida que mas leds se encendian, Vdd iba disminuyendo, esto no tiene que ver con la configuracin del CAD. -que hay que estar pendiente con los minimos detalles que dicen en la datasheet, tal es el caso del mnimo Tad entre muestras. -que no se le puede exigir demasiado a un montaje en protoboard.
www.unpocodelectronica.netau.net
Pgina 46
Programa PiCUSB de RedMania este archivo se encuentra en PicUSBDelphi.zip, y funciona con la librera mpusbapi.dll que debe estar en el mismo directorio. - seguido conectar todo. Hay que revisar los contactos del conector USB. Yo us el plug estndar tipo A (visto de la parte de abajo)
www.unpocodelectronica.netau.net
Pgina 47
Conector USB tipo A cuyos pines van as: (tomado de especificaciones USB2.0 captulo 6 pgina 99)
ese plug lo conect a una extensin, por si acaso med la tensin de Bus=5.1 volts. - ahora si viene la parte de conectar y enchufar al puerto de la PC, y. el windows me detect un nuevo dispositivo USB, hay que elegir la carpeta donde estn los controladores que estn en el mismo picusb.zip, son 4 archivitos:
www.unpocodelectronica.netau.net
Pgina 48
despus el windows hace todo lo que tiene que hacer (configurar dispositivo, etc.)
Propiedades del Dispositivo USB y listo, se encendi el circuito en el protoboard. parece que la misma alimentacin del puerto alimenta al circuito -ahora falta cargar el programa en la PC y hacer las respectivas pruebas: http://www.youtube.com/watch?v=XZN4L9kimr0 como podrn ver en este ejemplo, aqu no se habla de programacin ni de funcionamiento, simplemente me lanc a probar ese cdigo y siento especial alegra porque ya pude hacer mi primera transmisin de datos a un PIC va USB! Gracias a J1M y RedPic.
www.unpocodelectronica.netau.net
Pgina 49
Invocando el control mscomm.ocx en vb pegamos varios controles hasta que nos queda esta pantalla:
www.unpocodelectronica.netau.net
Pgina 50
Programa ejemplo CDC-VB como vern hay 2 botones cada uno para enviar la orden al PIC y despus ste, nos envi la respectiva cadena, dicha orden ser un byte un carcter, posteriormente esa cadena se guardar en la caja de texto.
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 36 37 38 39 40 41 42 43 44 ' ejemplo6_parte2 comunicacin al PIC mediante el puerto virtual COM4 cuya transmisin ' real ser por el USB enviando un caracter para confirmarle al PIC, la transmisin ' de una cadena de acuerdo al caracter enviado ' 12-ene-07 ' Pedro - PalitroqueZ Option Explicit Private Sub Command1_Click() If MSComm1.PortOpen = False Then MSComm1.PortOpen = True End If MSComm1.Output = "x" End Sub Private Sub Command2_Click() If MSComm1.PortOpen = False Then MSComm1.PortOpen = True End If MSComm1.Output = "a" End Sub Private Sub Form_Load() MSComm1.CommPort = 4 MSComm1.OutBufferSize = 1 'tamao 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 "presionaste el nmero 1" End Sub Private Sub Form_Unload(Cancel As Integer) If MSComm1.PortOpen = True Then MSComm1.PortOpen = False End If End Sub
www.unpocodelectronica.netau.net
Pgina 51
de este cdigo hay varias cosas que decir, lo primordial es tener bien configurado al MSCOMM, como por ejemplo RThreshold y para evitar caracteres extraos o los famosos chr(10) y chr(13) recortar la cadena a 23 caracteres como en este caso. Otra cosa que coloqu fue cerrar el puerto despus de ejecutar el evento comEvReceive, entre otras cosas para limpiar el buffer, en fin es cuestin de que hagan los respectivos ensayos de acuerdo a cada situacin. ahora viene escribir el cdigo para el PIC:
1 2 3 4 5 6 7 8 9 1 0 1 1 1 2 1 3 1 4 1 5 1 6 1 7 1 8 1 9 2 0 2 1 2 /* ejemplo6_parte2.c este ejemplo hace uso del mdulo USB en modo CDC transmitiendo datos hacia un puerto COMx emulado en Windows adaptacin del cdigo original de RRCdcUSB de RedPic Pedro-PalitroqueZ 12/01/07 */ #include <18F4550.h> #fuses XTPLL,MCLR,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL1,CPUDIV1,VREGEN, NOPBADEN #use delay(clock=48000000) #include "usb_cdc.h" void main() { usb_cdc_init(); usb_init(); while(!usb_cdc_connected()) {} // espera a detectar una transmisin de la PC (Set_Line_Coding) do{ usb_task(); if (usb_enumerated()){ if(usb_cdc_kbhit()){ //en espera de nuevo(s) caracter(es) en el buffer if(usb_cdc_getc()=='x'){ //lo que lleg fu el caracter x? printf(usb_cdc_putc, "el 11111111111111111111\n\r"); //si, entonces enva una cadena hacia el PC } if(usb_cdc_getc()=='a'){ //lo que lleg fu el caracter a? printf(usb_cdc_putc, "el 22222222222222222222\n\r");
www.unpocodelectronica.netau.net
Pgina 52
all se puede apreciar que si el byte que llega es una x, entonces se prepara para transmitir ese montn de unos, y si llega una a manda ese montn de does ahora se procede a compilar,grabar el PIC, revisar conexiones, etc. y probar la transmisin, pero ANTES hay que instalar la aplicacin para la clase CDC, solo hay que clicar en un archivito llamado mchpcdc.inf . como en este ejemplo, no se utilizar componentes adicionales, no har falta alimentacin externa y se puede hacer directamente desde Vusb http://www.youtube.com/watch?v=uCn2wOmnv2M observen que si no hay COM4 el VB tira el error porque no encuentra dicho puerto, pero cuando conectamos el cable todo funciona, bueno ah habra que aplicar una validacin para saltar ese error usando un On Error GoTo.
Conclusiones: - con este ejemplo se pretende hacer transmisiones de PIC<->PC usando el puerto USB real pero mediante el COM virtual - usando la clase CDC es una manera fcil y rpida de hacer comunicacin con la computadora, ya que podemos tomar programas de VB ya hechos para el MSCOMM y que mediante una pequea adaptacin podemos transmitir por el USB. La programacin para el PIC vara ligeramente.
www.unpocodelectronica.netau.net
Pgina 53
recordemos que usb_cdc_connected() detecta si el controlador host est enviando datos y usb_enumerated() es para que el PC detecte nuestro dispositivo ( funcin), pero eso no quiere decir que el pic har otras actividades si el cable est enchufado no. modificando el cdigo de ejemplo anterior
1 2 3 4 5 6 7 8 9 1 0 1 1 1 2 1 3 1 4 1 5 1 6 1 7 1 8 1 9 /* ejemplo6_parte3.c en este ejemplo se tratar de concocer la configuracin del dispositivo, cuando hay/no hay conexin con el PC mediante los comandos usb_enumerated() usb_cdc_kbhit() usb_cdc_getc() usb_cdc_connected() adaptacin del cdigo original de RRCdcUSB de RedPic Pedro-PalitroqueZ 14/01/07 */ #include <18F4550.h> #fuses XTPLL,MCLR,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL1,CPUDIV1,VREGEN, NOPBADEN #use delay(clock=48000000) #define use_portb_lcd TRUE #include <lcd.c> #include "usb_cdc.h" void main(){ usb_cdc_init(); // llamadas necesarias para iniciar el mdulo USB usb_init(); // llamadas necesarias para iniciar el mdulo USB lcd_init(); // llamadas necesarias para iniciar la LCD while(!usb_cdc_connected()) {lcd_putc("\fUSB NO detectadO"); delay_ms(100);} // para evitarme un retardo y que no parpadee la
www.unpocodelectronica.netau.net
Pgina 54
all inclu una pantalla LCD, el cul me mostrar que sucede en determinado momento dentro del cdigo, la idea es conocer que hace el pic cuando: - no hay conexin - conectado el cable USB
www.unpocodelectronica.netau.net
Pgina 55
[PRIMEROS PASOS CON EL 18F4550] 14 de abril de 2010 - ejecutando la aplicacin VB - enviando el dato hacia el dispositivo y todo eso me lo mostrar en pantalla con unos lcd_putc que coloqu en lugares estratgicos, el cdigo en VB lo modifiqu ligeramente, para que enve un carcter y no reciba ninguno. vamos a grabar el pic y a probar:
http://www.youtube.com/watch?v=iqxsPdhOUUc
estos son los mensajes del LCD y las acciones que llev a cabo:
MENSAJES -> CASOS POSIBLES - USB no detectado -> el cable USB SI est NO est enchufado al PC - USB detectado, ya enumerado USB conectado, en el bucle USB -> sucede cuando ejecuto la aplicacin en VB - dato recibido de la PC -> sucede cuando clco en el botn enviando a al pic recomendacin: pegar un switche doble para desconectar a D- D+, para no estar a cada rato sacando la extensin y hacer una reconexin fcil. esto est correcto solo en funcin del cdigo, pues una vez que entra dentro del bucle no sale, y siempre mostrar que est conectado aunque no sea cierto. si cierro la aplicacin de VB y la vuelvo a abrir har todo OK, porque seguir en el mismo bucle. hay una cosa curiosa que sucedi cuando apliqu un reset al PIC, en administrador de dispositivos reaparece el COM, pero en el programita de VB, se cuelga y no me detecta jams el puerto a menos que reconecte el cable USB de nuevo, ?? la solucin a este inconveniente se encuentra en el siguiente tpico Monitorear el puerto COM virtual. Esto se llamara: conexin en caliente del lado del software, (ya est arreglado en el video). el cdigo en VB:
1 2 3 4 5 6 7 8 9 10 11 ' ejemplo6_parte2 comunicacin al PIC mediante el puerto virtual COM4 cuya transmisin ' real ser por el USB enviando un caracter para confirmarle al PIC, la transmisin ' de una cadena de acuerdo al caracter enviado ' 12-ene-07 ' Pedro - PalitroqueZ ' el uso de bandera permite averiguar varios datos para confirmar el estado real ' de la conexin
www.unpocodelectronica.netau.net
Pgina 56
www.unpocodelectronica.netau.net
Pgina 57
lecturas recomendadas:
AN956 Migrating Applications to USB from RS-232 UART with Minimal Impact on PC Software Emulating RS-232 over USB with PIC18F4550
volver arriba
www.unpocodelectronica.netau.net
Pgina 58
Private Sub Form_Unload(Cancel As Integer) If MSComm1.PortOpen = True Then MSComm1.PortOpen = False End If End Sub Private Sub Timer1_Timer() Dim a As String On Error GoTo paca DoEvents If MSComm1.PortOpen = True Then DoEvents lblestado.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 'Nmero de puerto no vlido DoEvents lblestado.Caption = "Desconectado" Case 8005 'el puerto ya est abierto DoEvents lblestado.Caption = "puerto abierto" Case 8012 '8012 el dispositivo no est abierto DoEvents lblestado.Caption = "Desconectado" Case 8015 DoEvents lblestado.Caption = "Desconectado" End Select Exit Sub End Sub
si quisiera enviar datos al PIC, lo primero que tengo que hacer es detener el escaneo, mediante Timer1.Enabled = False y pego un cdigo similar al del evento timer (para que ocurra solo una vez) dentro del evento donde quiero enviar datos, despus que envie/reciba datos, arranco el escaneo Timer1.Enabled = True es decir, mientras no est haciendo operaciones de transmisiones por el USB, el timer estar encendido y solo se dentendr cuando se realice un envo/recepcin de datos.
www.unpocodelectronica.netau.net
Pgina 59
Detectando el HOST
Despus de varios das de descanso y para poner a trabajar al subconsciente en esto del USB seguimos con este mdulo, y porqu? es que este mdulo es la joya de la corona de este PIC, as que seguir echndole mano hasta abarcar todo lo necesario para realizar una comunicacin PIC<->PC bsica. ya en el ejemplo anterior dimos cuenta de como detectar una conexin por software, desde el punto de vista de un programa en la PC, ahora le toca el turno al hardware del PIC, es decir, que el pic debe detectar al host USB. hay algo que pas por alto, desde que empec con estos ejemplitos del CDC, hay una constante:
#include <18F4550.h> 1 #fuses 2 XTPLL,MCLR,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL1,CPUDIV1,VREGEN,N 3 OPBADEN 4 #use delay(clock=48000000) 5 6 #include "usb_cdc.h" 7 8 void main() { ...
la constante es el llamado al driver usb_cdc.h y no crean que es el nico archivo usado, si miran dentro de ste vern despus de varias lneas:
#if __USB_PIC_PERIF__ #if defined(__PCM__) #error CDC requires bulk mode! PIC16C7x5 does not have bulk mode #else #include <pic18_usb.h> //Microchip 18Fxx5x hardware layer for usb.c #endif #else #include <usbn960x.c> //National 960x hardware layer for usb.c #endif #include "rr2_USB_Cdc_Monitor.h" //USB Configuration and Device descriptors for this UBS device #include <usb.c> //handles usb setup tokens and get descriptor reports
1 2 3 4 5 6 7 8 9 10 11
como estamos usando el 18F4550 entonces se utilizar el driver pic18_usb.h y adems el rr2_USB_Cdc_Monitor.h y el usb.c caramba se usan varias libreras y estas a su vez llaman a otras. por ejemplo la rr2_USB_Cdc_Monitor.h es la usb_desc_cdc.h que est en la carpeta driver en PICC, solo que est modificada para identificar nuestro dispositivo como queramos (esto lo explica el amigo RedPic en su pgina) de la que me interesa hablar es la librera pic18_usb.h
www.unpocodelectronica.netau.net
Pgina 60
[PRIMEROS PASOS CON EL 18F4550] 14 de abril de 2010 si observamos el cdigo del ejemplo anterior hay unas funciones de inicializacin que hay que llamar para poder empezar a transmitir datos, una de ellas es
usb_init( );
www.unpocodelectronica.netau.net
Pgina 61
uuhmmm esa funcin est hecha mediante definicin y llama a su vez a un tal USB_CON_SENSE_PIN haciendo una pausa, esto que estoy haciendo es analizando el cdigo inversamente, es decir, mediante una simulacin en el MPLAB voy observando donde cae cada llamado para as determinar esa parte del cdigo que me interesa. quin es ese USB_CON_SENSE_PIN? y porque en mi simulacin del MPLAB salta sin preguntar por l?. En la nota de arriba dice que si no se est usando, automticamente se habilitar el mdulo USB.
http://www.youtube.com/watch?v=Tg_KTJ-8WfE
la lnea BTFSC 0xf6d, 03 est preguntando si USBEN=0, mientras que para el primer condicional no aparece su respectiva lnea en asm. ahora que recuerdo en el cdigo que escribi el amigo J1M, aparece una descripcin de ese USB_CON_SENSE_PIN (tambin aparece en el ejemplo ex_usb_serial2.c que trae el CCS)
1 2 3 4 5 6 7 8 9 1 0 1 1 1 2 1 3 1 4 //////////////////////////////////////////////////////////////////// ///////// // // 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) // //////////////////////////////////////////////////////////////////// ///////// //#define USB_CON_SENSE_PIN PIN_B2 //CCS 18F4550 development kit
www.unpocodelectronica.netau.net
Pgina 62
y se hace llamar antes que los drivers, quiere decir entonces que hay una forma de detectar (mediante hardware) cuando el host est conectado al PIC y es al sensar un voltaje en un pin establecido, especficamente el voltaje del bus USB (VBUS) vamos a probar pues! usemos el pin RE3 se acuerdan? el del MCLR que solo puede funcionar como entrada digital.
#define USB_CON_SENSE_PIN PIN_E3 //pin de MCLR hay una cosa que es digna de hacerle un estudio, me refiero a la funcin usb_task() que est dentro de usb_init(), si hacen la prueba y se ponen hacer la simulacin con el MPLAB descubrirn 2 diferencias habilitando/deshabilitando el conection sense pin, otra cosa importante hablando del ejemplo anterior sabemos que el cdigo se encierra dentro de un while
1 ... 2 while(!usb_cdc_connected()){ 3 ... 4}
pero y porque el HOST puede seguir reconociendo a la funcin an dentro de ese bucle? si miran dentro de usb_task vern este cdigo:
... 1 enable_interrupts(INT_USB); 2 enable_interrupts(GLOBAL); 3 UIE=__USB_UIF_IDLE | __USB_UIF_RESET; 4 USB interrupt 5 usb_state=USB_STATE_POWERED;
all se est seleccionado/habilitando la fuente de interrupcin USB y cuando se conecta la funcin al host, se ejecuta uno de los 2 servicios de interrupcin de rutina (SRI) :
usb_isr_rst() -> para el flag __USB_UIF_RESET usb_isr_uidle() -> para el flag __USB_UIF_IDLE esto de alguna manera reconecta a la funcin para que sea reconocida por el HOST. est interesante esta parte, vamos a ver adonde llegamos. leyendo en la ayuda del CCS tenemos que:
1 2 3 4 usb_task(): If you use connection sense, and the usb_init_cs() for initialization, then you must periodically call this function to keep an eye on the connection sense pin.
www.unpocodelectronica.netau.net
Pgina 63
usando el pin RE3 (no olviden cambiar el fuse a NOMCLR) como sense pin, vamos hacer unas simulaciones a ver que pasa
http://www.youtube.com/watch?v=7-8jEVfqZC8
noten que ahora si aparecen las lneas en asm que corresponden a if(usb_attached()){. all est preguntando por el estado de RE3 prosigamos con el MPLAB-SIM, vamos a tener que averiguar que ocurre si hay una interrupcin
1 void usb_cdc_init(void) { 2 usb_cdc_line_coding.dwDTERrate=9600; 3 usb_cdc_line_coding.bCharFormat=0; 4 usb_cdc_line_coding.bParityType=0; 5 usb_cdc_line_coding.bDataBits=8; 6 (int8)usb_cdc_carrier=0; 7 usb_cdc_got_set_line_coding=FALSE; 8 usb_cdc_break=0; 9 usb_cdc_put_buffer_nextin=0; 10 usb_cdc_get_buffer_status.got=0; 11 usb_cdc_put_buffer_free=TRUE; 12 }
me huele a que en esta llamada se hace una especie de configuracin tipo USART. despus de activar el estmulo de RE3 caigo en este segmento de cdigo:
1 2 3 4 5 6 7 8 9 ... 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");
este cdigo ya lo haba puesto antes, pues bien, despus de un largo rato no pude simular esa interrupcin. queda una cosa por averiguar: que esa interrupcin debe ocurrir cuando hay un detached, es decir, se desconecta el HOST de la funcin, porque digo esto?, porque si sigo simulando me doy cuenta que llego al bucle main y all caigo en el bucle eterno
www.unpocodelectronica.netau.net
Pgina 64
UIE=__USB_UIF_IDLE | __USB_UIF_RESET; //enable IDLE and RESET USB interrupt tenemos unos defines:
#define __USB_UIF_IDLE 010 -> bit 4 #define __USB_UIF_RESET 001 -> bit 0 si nos vamos a la datasheet del 18F4550, Pg. 180 nos encontramos un SFR llamado UIR
Registro Estado interrupcin USB este SFR contiene los flags de los estados de interrupcin seleccionados por UIE
www.unpocodelectronica.netau.net
Pgina 65
Registro habilitacin Interrupcin USB con este par de bits lo que hacemos es seleccionar el par USB Reset Interrupt y Idle Detect Interrupt Enable bit otro dato importante, si nos vamos a la descripcin de ambos servicio de interrupcin, veremos para el RESET:
/******************************************************************** *********** 1 /* usb_isr_rst() 2 /* 3 /* Summary: The host (computer) sent us a RESET command. Reset USB 4 device 5 /* and token handler code to initial state. 6 /* 7 /******************************************************************** ************/
www.unpocodelectronica.netau.net
Pgina 66
nuevamente deduzco lo siguiente: - que ambos casos sirven para detectar el estado HOST<->PIC. como lamentablemente no puedo hacer la simulacin, no me queda de otra que probar el cdigo en el protoboard, pero haciendo unas modificaciones, el cdigo quedar as:
1 2 3 4 5 6 7 8 9 1 0 1 1 1 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
/* ejemplo6_parte4_temp.c en este ejemplo se tratar se ordenar al PIC reconocer la deteccin del HOST USB de la PC adaptacin del cdigo original de RRCdcUSB de RedPic Pedro-PalitroqueZ 4/feb/07 */ #include <18F4550.h> #fuses XTPLL,NOMCLR,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL1,CPUDIV1,VREGE N,NOPBADEN #use delay(clock=48000000) #define use_portb_lcd TRUE #define USB_CON_SENSE_PIN PIN_E3 #include <lcd.c> #include "usb_cdc.h" void main(){ lcd_init(); // llamadas necesarias para iniciar la LCD usb_cdc_init(); // llamadas necesarias para iniciar el mdulo USB usb_init(); // llamadas necesarias para iniciar el mdulo USB while(!usb_cdc_connected()) { //bucle eterno delay_us(500); } do{ usb_task(); delay_us(500); }while (TRUE); // bucle eterno }
www.unpocodelectronica.netau.net
Pgina 67
despus de revisar bien las conexiones, el .lst para ver si estn OK los fuses, se procede a grabar el PIC y a ensayar: con el HOST:
www.unpocodelectronica.netau.net
Pgina 68
USB Desconectado en LCD arrg! que mala pata, se queda activado el USB CONECTADO an despus de desconectar al HOST obviamente hay que revisar nuevamente a pic18_usb.h vamos a repasar, segn mi hiptesis para que el mdulo USB arranque la funcin usb_task() debe esperar por el nivel alto en RE3 (proveniente de Vusb) y si ocurre selecciona/habilita la interrupcin para los casos USB Reset e Idle Detect hasta aqu vamos bien, ahora que debe ocurrir para que ocurra una de esas 2 interrupciones? primero que nada si ocurre una interrupcin el contador de programa se v para:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 #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();} has been detected if (UIR_URST && UIE_URST) {usb_isr_rst();} has been detected if (UIR_IDLE && UIE_IDLE) {usb_isr_uidle();} time, we can go to sleep if (UIR_SOF && UIE_SOF) {usb_isr_sof();} if (UIR_STALL && UIE_STALL) {usb_isr_stall();} stall handshake was sent //error //usb reset //idle //a
www.unpocodelectronica.netau.net
Pgina 69
ah est otra vez el debug_usb(), me intriga saber como se usa??. esa lnea es crucial porque se puede averiguar quien demonios fue el flag que se activ. voy a ser prctico, sustituir a debug_usb por printf as:
[1]conectando al HOST: UIR= 10 y luego cambia a 01 [2]desconectando el HOST: UIR=54 y luego cambia a 44
y para rematar al poco tiempo me sale un mensaje del windows diciendo que no reconoce al dispositivo.
54-> 01010100 44-> 01000100 [1]: el flag correcto es USB reset [2]: los flags involucrados son: start of frame, idle detect y bus activity
seores, esto se complic! lo mejor es entrarle por otro lado, la experiencia que he tenido me dice que cuando algo se complica, es que por ah no es la solucin. mirando por ensima vez el cdigo principal veo que aparte de que hacen la llamada usb_task() dentro de usb_init() la hacen afuera , es decir, se puede usar estas funciones dentro de nuestro cdigo como queramos. esta usb_init es importante porque habilita o no el mdulo USB, y que tal si usamos esa funcin en vez de meternos con el driver? para ello tendremos que quitar la lnea:
while(!usb_cdc_connected()) { //bucle eterno eso no nos importa por ahora, yo no voy a enviar datos al pic, lo nico que quiero es que el pic me diga si o no!
www.unpocodelectronica.netau.net
Pgina 70
[PRIMEROS PASOS CON EL 18F4550] 14 de abril de 2010 vamos a intentar ooootra vez:
1 2 3 4 5 6 7 8 9 1 0 1 1 1 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
/* ejemplo6_parte4_temp.c en este ejemplo se tratar se ordenar al PIC reconocer la deteccin del HOST USB de la PC adaptacin del cdigo original de RRCdcUSB de RedPic Pedro-PalitroqueZ 4/feb/07 */ #include <18F4550.h> #fuses XTPLL,NOMCLR,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL1,CPUDIV1,VREGE N,NOPBADEN #use delay(clock=48000000) #define use_portb_lcd TRUE #define USB_CON_SENSE_PIN PIN_E3 #include <lcd.c> #include "usb_cdc.h" void main(){ lcd_init(); // llamadas necesarias para iniciar la LCD usb_cdc_init(); // llamadas necesarias para iniciar el mdulo USB usb_init(); // llamadas necesarias para iniciar el mdulo USB do{ usb_task(); delay_us(500); }while (TRUE); // bucle eterno }
http://www.youtube.com/watch?v=nHt3RWJeoT4 en el video anterior quit lo relacionado a la pantalla LCD para resaltar la parte importante, pero al grabar el PIC se las puse de nuevo: http://www.youtube.com/watch?v=Ht2T5T7v8Ao
www.unpocodelectronica.netau.net
Pgina 71
[PRIMEROS PASOS CON EL 18F4550] 14 de abril de 2010 ahora si funcion, aunque fuera por poleo (no veo ninguna interrupcin aqu) pero algo es algo, ya sabemos que: con la funcin usb_task() podemos determinar el estado de conexin. observacin: el error que me apareci en el windows al no detectar el dispositivo en cierto tiempo se debi al retardo de 500mS que met en #int USB seguro alguien preguntar: bueno pero si no habilito el sense pin har lo mismo?. y yo le responder que no, puesto que con esa deshabilitacin, el mdulo USB siempre estar encendido. (comprobado) el problema no termina aqu, la idea principal es escribir un cdigo donde se muestre el estado y que aparte realice otras actividades.
www.unpocodelectronica.netau.net
Pgina 72
noten la diferencia de usb_init() con usb_init_cs(), si queremos ejecutar otros procesos en el micro usb_init() no nos servira, porque se quedara en un bucle esperando al HOST (COMPROBADO), y esto no es lo que se quiere, entonces se usar la otra funcin.
www.unpocodelectronica.netau.net
Pgina 73
[PRIMEROS PASOS CON EL 18F4550] 14 de abril de 2010 Esta otra llamada usb_init_cs() va de la mano con usb_task(), porque una vez detectada Vbus a travs 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 travs de usb_attached() de usb_task(). hay otra llamada adicional (aqu se llama a un gento) y es usb_enumerated(), en el concepto dice que su resultado es un boolean y depender de lo que diga el HOST
usb_enumerated(): // proviene de USB.C 1 returns TRUE if device has been enumerated (configured) by host, 2 FALSE if it has not Do not try to use the USB peripheral until you are enumerated.
es cierto porque si quiero hacer transaccin de datos con la PC, ambos tienen que estar de acuerdo. nota: hay que entender bien porque estn estas funciones y porque se deben ejecutar. bueno, ya entendido estos conceptos, vamos hacer otro ejemplo. Recuerden: el PIC debe ejecutar otros procesos independientemente si est o no est el HOST.
1 2 3 4 5 6 7 8 9 1 0 1 1 1 2 1 3 1 4 1 5 1 6 1 7 1 8 1 9 2 0 2 1 2 /* probando_USB.c es una modificacin del ejemplo6_parte4, aqu se usa una bandera global que determinar el estado de conexin del USB, mediante las llamadas usb_attach y usb_detach en pic18_usb.h Modificacin del cdigo original de RRCdcUSB de RedPic Pedro-PalitroqueZ 11-feb-07 */ #include <18F4550.h> #fuses XTPLL,NOMCLR,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL1,CPUDIV1,VREGE N,NOPBADEN #use delay(clock=48000000) #define use_portb_lcd TRUE short estado_usb; // boolean global, se debe declarar antes de llamar a usb_cdc.h #define USB_CON_SENSE_PIN PIN_E3 #include <lcd.c> #include "usb_cdc.h" void mostrar_estado_usb(short bandera); void main(){ estado_usb=false; usb_cdc_init(); // llamadas necesarias para iniciar el mdulo USB usb_init_cs(); // inicia el USB y sale. va a la par con usb_task() lcd_init(); // llamadas necesarias para iniciar la LCD while(true){ usb_task(); // configura el USB mostrar_estado_usb(estado_usb);
www.unpocodelectronica.netau.net
Pgina 74
www.unpocodelectronica.netau.net
Pgina 75
www.unpocodelectronica.netau.net
Pgina 76
MSComm1.InputLen = 16 ' BUFFER DE ENTRADA SE PUEDE DEJAR AL MAXIMO MSComm1.RThreshold = 16 ' Timer1.Interval = 10 Timer1.Enabled = True 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 Text1.Text = "" Text1.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 Text1.Text = "" End Select End Sub Private Sub Timer1_Timer() On Error GoTo paca DoEvents If MSComm1.PortOpen = True Then DoEvents lblestado.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 'Nmero de puerto no vlido DoEvents lblestado.Caption = "Desconectado" Case 8005 'el puerto ya est abierto DoEvents lblestado.Caption = "puerto abierto" Case 8012 '8012 el dispositivo no est abierto DoEvents lblestado.Caption = "Desconectado" Case 8015 DoEvents ' para evitar retardos en bucles
www.unpocodelectronica.netau.net
Pgina 77
a verdad que este ejemplo est bastante completo, se puede decir que logramos el objetivo, a pesar que en el video se observa cierta retraso en la respuesta y esto es debido a los retardos que introduc tanto en cdigo del PIC, como en VB para que pudiera observar la ejecucin un poco mas lenta, se cumplen todos los casos (en los ensayos que hice)
casos: funcin conectada/desconectada al HOST: el programa en VB funciona OK (ya lo habamos comprobado en el ejemplo6_parte3) programa en VB: - de parte del micro, detecta al HOST y lo muestra en pantalla LCD, y ejecuta la transmisin HOST->PC, aparte que continua ejecutando otros procesos, y todo ello independiente del mdulo USB!
www.unpocodelectronica.netau.net
Pgina 78
[PRIMEROS PASOS CON EL 18F4550] 14 de abril de 2010 - el resultado del CAD se mostrar en un pantalla LCD de 2 modos, justificacin a la izquierda a la derecha, dependiendo del cambio de un switche. pero vamos por partes, primero hay que construir el cdigo del CAD y la LCD, es decir, sin involucrar al USB. Para ello emplearemos al proteus (esto es para agilizar el proceso de depuracin y simulacin) y usaremos un pic similar al 18F4550, me refiero al 18F4525.
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 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 #include <18f4525.h> //archivo de cabecera #DEVICE ADC=10 // cad a 10 bits, justificacin a a la derecha #fuses XT,NOWDT,NOPROTECT,NOLVP,NODEBUG // el fuse que configuramos anteriormente #use delay(clock=4000000) // el clock que tendremos a la entrada del CPU #define use_portb_lcd TRUE #include <LCD.c> #define DERECHA 0 #define IZQUIERDA 1 long value; void config_adcon2(short justificacion); void main(){ int i; OUTPUT_A(0); // todos salidas OUTPUT_B(0); OUTPUT_C(0); OUTPUT_D(0); OUTPUT_E(0); lcd_init(); // inicia la LCD set_tris_a(0x3); // ra0=entradas, los demas=salida set_tris_b(0x0); set_tris_c(0x0); set_tris_d(0x0); set_tris_e(0x0); setup_adc_ports( AN0 || VSS_VDD ); // canal AN0, Vref+ = Vdd, Vref- = Vss config_adcon2(DERECHA); lcd_putc("\f"); // para evitarme un retardo y que no parpadee la LCD while(1){ // bucle infinito value = read_adc(); if(input_state(PIN_A1)){ //pregunta por el switche config_adcon2(DERECHA); }else{ config_adcon2(IZQUIERDA); } for(i=0;i<16;i++){ lcd_gotoxy(16-i,1); lcd_putc((char)(bit_test(value,i)+0x30)); } printf(lcd_putc,"\n0x%Lx",value); } } //---------------------------------------------------------------------------------------// cumple la funcin de configurar el bit ADFM para hacer
www.unpocodelectronica.netau.net
Pgina 79
otro video:
http://www.youtube.com/watch?v=5Bbe_kR7sFA
notas: la directiva #DEVICE ADC=16 realiza la justificacin a la izquierda, no la usar en este ejemplo, porque solamente se puede usar una vez (el compilador te lo dir). ya sabemos que el cdigo funciona perfectamente, no tenemos que preocuparnos por esa parte, ahora tenemos que concatenar la seccin de la transmisin USB tomando del ejemplo anterior, nuestro cdigo quedara as:
www.unpocodelectronica.netau.net
Pgina 80
long value; void config_adcon2(short justificacion); void mostrar_estado_usb(short bandera); void main(){ int i; set_tris_a(0x3); // ra[1,0]=entradas, los demas=salida estado_usb=false; usb_cdc_init(); // llamadas necesarias para iniciar el mdulo USB usb_init_cs(); // inicia el USB y sale. va a la par con usb_task() lcd_init(); // llamadas necesarias para iniciar la LCD setup_adc_ports( AN0 || VSS_VDD ); // canal AN0, Vref+ = Vdd, Vref- = Vss config_adcon2(DERECHA); while(true){ usb_task(); // configura el USB mostrar_estado_usb(estado_usb); value = read_adc(); if(input_state(PIN_A1)){ //pregunta por el switche config_adcon2(DERECHA); }else{ config_adcon2(IZQUIERDA); } for(i=0;i<16;i++){ lcd_gotoxy(16-i,1); lcd_putc((char)(bit_test(value,i)+0x30)); } printf(lcd_putc,"\n0x%Lx",value);
www.unpocodelectronica.netau.net
Pgina 81
www.unpocodelectronica.netau.net
Pgina 82
[PRIMEROS PASOS CON EL 18F4550] 14 de abril de 2010 hay otro detalle que nunca he mencionado, a que velocidad transmite esto? cuando se ejecuta la funcin usb_cdc_init() aparece:
1 2 3 4 usb_cdc_line_coding.dwDTERrate=9600; usb_cdc_line_coding.bCharFormat=0; usb_cdc_line_coding.bParityType=0; usb_cdc_line_coding.bDataBits=8;
esto forma parte de una estructura en la que sera 9600 bits/sec, 1 bit de parada, sin paridad, 1 byte de datos. Esto es conocido por el MSCOMM: 9600,n,8,1 hasta este punto lo que resta es checar bien el programa compilar, grabar, y probar
http://www.youtube.com/watch?v=97l6IcbL5EE
en el video anterior us el Siow que trae el CCS, bien ya comprobamos que el pic est haciendo correctamente todo lo que tiene que hacer. ahora hay que hacer el programa en VB para darle un toque de elegancia a los datos obtenidos:
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 36 ' ejemplo6_parte2 comunicacin al PIC mediante el puerto virtual COM4 cuya transmisin ' real ser por el USB enviando un caracter para confirmarle al PIC, la transmisin ' del resultado del CAD ' 13-feb-07 Pedro - PalitroqueZ Option Explicit Dim value As Long Const color_verde = &HFF00& Const color_rojo = &HFF& Dim bandera As Boolean Function cambiar(valor As Long) Dim t As Integer: Dim asa As String: Dim pepe As String pepe = HEXA_BIN(CStr(Hex(valor))) 'Debug.Print "pepe= " & Len(pepe) 'MsgBox pepe For t = 1 To 16 ' Debug.Print pepe asa = Mid$(pepe, t, 1) ' Debug.Print asa Label1(t - 1).Caption = asa ' es t-1 porque la matriz cuenta desde 0 Next t End Function Private Sub Check1_Click() On Error GoTo palla DoEvents If Check1.value = 1 Then DoEvents Timer1.Enabled = False Check1.ForeColor = &H8000& Check1.Caption = "Recibiendo datos..."
www.unpocodelectronica.netau.net
Pgina 83
www.unpocodelectronica.netau.net
Pgina 84
www.unpocodelectronica.netau.net
Pgina 85
www.unpocodelectronica.netau.net
Pgina 86
'
Exit Sub End Sub Private Sub Timer2_Timer() On Error GoTo palla1 MSComm1.Output = "a" Exit Sub palla1: 'Timer2.Enabled = False 'Check1.value = 0 Timer1.Enabled = True Exit Sub End Sub
PiC USB CDC CAD un par de videos de los resultados prcticos en el protoboard:
www.unpocodelectronica.netau.net
Pgina 87
observaciones y conclusiones: - Este ejemplo demostr una transmisin HOST<->PIC permitiendo al PIC hacer una actividad aparte. - se us 2 timer en vez de uno, debido a que en ambos se trabaja en intervalos de tiempos distintos. - el conector USB de mi PC ya est algo agrandado de tanto reconectar, esperemos que aguante un poco mas. - hay una bandera que yo us llamada: short estado_usb; // boolean global, se debe declarar antes de llamar a usb_cdc.h este flag debe ser declarado antes de usb_cdc.h porque hay una funcin all que hace uso de ella y sirve para mostrar los estados de: USB -> conectado/desconectado. Especficamente dentro de usb_attach() y usb_detach(). - en el ltimo ejemplo, us 2 videos en vez de uno. porque el camtasia studio interfera de manera extraa en la transmisin de datos cuando iniciaba una grabacin (el programa en VB se colgaba durante la grabacin)
www.unpocodelectronica.netau.net
Pgina 88
Conociendo al SnoopyPRO
saban que existen unas aplicaciones (software y software+hardware) que hacen de analizadores de protocolos para puertos USB.? existen muchos, hay uno llamado SnoopyPro. (licencia GPL) me di curiosidad y lo baj. lo primero ver las instrucciones:
1 2 3 4 5 6 7 8 9 1 0 1 1 1 2 1 3 1 4 1 5 1 6 1 7 SnoopyPro is a tool for advanced USB programmers. It allows you to record each URB sent to and received from a USB device. This traces can be saved, loaded, edited, printed and combined into new traces. WARNING: You might damage your system with this tool. Don't use it if you don't know what you're doing!!!! We're not responsible for anything that happens to you, your system, your devices, your marriage, etc. etc. ... ==================================================================== ====== INSTALLATION/USE: ==================================================================== ====== 1. Run SnoopyPro.exe from whereever you have saved it. 2. Open up the USB devices window with F2. 3. Choose 'Unpack Drivers' from the 'File' menu. 4. Choose 'Install Service' from the 'File' menu. 5. Locate the device you want to sniff. 6. Right-click on it and choose 'Install and Restart'. 7. Wait for the magic to happen... ...
www.unpocodelectronica.netau.net
Pgina 89
[PRIMEROS PASOS CON EL 18F4550] 14 de abril de 2010 siguiendo los pasos1,2,3 y buscamos el COM4 de nuestro ejemplo anterior
www.unpocodelectronica.netau.net
Pgina 90
[PRIMEROS PASOS CON EL 18F4550] 14 de abril de 2010 Probando el SnoopyPro despus de clicar varias veces en el botn Enviando a al PIC detenemos el escaneo:
Escaneando el puerto USB empezamos a husmear. Despus de unas decenas de lneas nos encontramos con esta:
www.unpocodelectronica.netau.net
Pgina 91
[PRIMEROS PASOS CON EL 18F4550] 14 de abril de 2010 abrimos a ver que hay:
leyendo parmetros capturados coincide con el carcter a que se enva al PIC en hexa coincidencia?. si miramos unas lneas mas abajo, no encontramos con un par de caracteres mas y una cadena:
Comparacin entre parmetros la coincidencia a la que me refiero es que la cadena que enva el PIC al PC es: Lleg la letra a cuya interpretacin en hexa sera: 4C 6C 65 67 F3 20 6C 61 20 6C 65 74 72 61 20 61 muy interesante!
www.unpocodelectronica.netau.net
Pgina 92
Mitos y verdades acerca del USB una cosa que hay que tener en consideracin y sobre todo para lo que estudiamos esto en lenguaje de alto nivel, el protocolo de transmisin USB tambin lo llaman la pila USB
www.unpocodelectronica.netau.net
Pgina 93
reas Implementadas de la pila USB tomado de usb_20.pdf, figura 5-2, pg26 observen que tiene cierto parecido al modelo OSI. en las capas superiores tenemos las funciones bsicas que el usuario puede realizar (comunicacin lgica). esto a su vez va a parar a la segunda capa y luego a la tercera capa(comunicacin fsica) que involucra el aspecto elctrico. En nuestro caso estaramos directamente metidos en la capa superior, pero algunas veces entrando en las otras dos: primera capa(superior): programacin bsica en C. segunda capa(intermedio): llamados a los drivers que trae el compilador de C. tercera capa(inferior): llamados a los drivers que trae el compilador de C (procesos dentro de los drivers) y conexin del mdulo USB al HOST. esta tema es fascinante pero a la vez extenso, as que hay que ir por partes para no perdernos. - ESTUDIO DEL LADO DEL PIC: por lo pronto lo que hay que hacer, es estudiar los drivers que trae el CCS (que es el compilador de C que uso), estos son:
www.unpocodelectronica.netau.net
Pgina 94
[PRIMEROS PASOS CON EL 18F4550] 14 de abril de 2010 tratando de meter un poco de teora a cada lnea que nos encontremos y siguiendo el mismo mtodo anterior: analizando el cdigo a la inversa. veamos el cdigo reza as:
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 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 //// PicUSB.c //// //// //// //// Este ejemplo muestra como desarrollar un sencillo dispositivo //// //// USB con el PIC18F2550, aunque puede ser facilmente adaptado //// //// para la serie 18Fxx5x. Se suministra el PicUSB.exe, as como //// //// su cdigo fuente para Visual C# 2005, podris encontrar tb //// //// los drivers para el dispositivo. No se suministra esquema de //// //// conexin puesto que est pensado para ser usado en el GTP USB, //// //// cualquiera de las tres versiones disponibles, si aun no teneis //// //// el programador, podeis utilizar el esquema de ese proyecto. //// //// //// //// Cuando el dispositivo sea conectado al PC, saldr el asistente //// //// para la instalacin del driver. Instala el suministrado junto //// //// a este ejemplo, lo encontrareis dentro de la carpeta Driver. //// //// Una vez instalado podreis usar el PicUSB.exe para encender o //// //// apagar el led bicolor del GTP USB, y para realizar la suma de //// //// dos nmeros introducidos. //// //// //// //// Realizado con el compilador CCS PCWH 3.227 //// //// //// //// Por: Jaime Fernndez-Caro Belmonte hobbypic@hotmail.com //// //// //// //// http://www.hobbypic.com //// /////////////////////////////////////////////////////////////////// ////// #include <18F4550.h> //#fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL3,CPUDIV1,VREGEN #fuses XTPLL,MCLR,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL1,CPUDIV1,VREGEN ,NOPBADEN // el fuse // modificado para USB -> VREGEN
www.unpocodelectronica.netau.net
Pgina 95
www.unpocodelectronica.netau.net
Pgina 96
/////////////////////////////////////////////////////////////////// ////////// // // Al conectar el PicUSB al PC encendemos el Led Rojo hasta que el dispositivo // halla sido configurado por el PC, en ese momento encederemos el Led Verde. // Esperaremos hasta que se reciba un paquete proveniente del PC. Comprobaremos // el primer byte del paquete recibido para comprobar si queremos entrar en el // modo Suma, donde se realizar una suma de dos operandos, que corresponderan // con los dos bytes restantes del paquete recibido; una vez realizada la suma // enviaremos el paquete con el resultado de vuelta al PC. Si entramos en el // modo Led comprobaremos el segundo byte del paquete recibido para comprobar // si deberemos apagar los leds, encender el verder o el rojo. // /////////////////////////////////////////////////////////////////// ////////// #define LEDV PIN_B6 #define LEDR PIN_B7 #define LED_ON output_high #define LED_OFF output_low #define #define #define #define modo param1 param2 resultado recibe[0] recibe[1] recibe[2] envia[0]
void main(void) { int8 recibe[3]; int8 envia[1]; LED_OFF(LEDV); LED_ON(LEDR); usb_init(); usb_task(); interrupciones usb_wait_for_enumeration(); sea configurado por el host LED_OFF(LEDR); LED_ON(LEDV); while (TRUE) { if(usb_enumerated()) { if (usb_kbhit(1)) contiene datos del host { //declaramos variables //encendemos led rojo //inicializamos el USB //habilita periferico usb e //esperamos hasta que el PicUSB
www.unpocodelectronica.netau.net
Pgina 97
//hacemos la suma
usb_put_packet(1, envia, 1, USB_DTS_TOGGLE); //enviamos el paquete de tamao 1byte del EP1 al PC } if (modo == 1) // Modo_Led { if (param1 == 0) {LED_OFF(LEDV); LED_OFF(LEDR);} //apagamos los leds if (param1 == 1) {LED_ON(LEDV); LED_OFF(LEDR);} //encendemos led verde if (param1 == 2) {LED_OFF(LEDV); LED_ON(LEDR);} //encendemos led rojo } } } } }
all estn las funciones usb_task(), usb_init() que ya las vimos por encimita, la novedad son las funciones: usb_wait_for_enumeration(), usb_get_packet y usb_put_packet tambin estn las definiciones USB_EP1_TX_ENABLE USB_ENABLE_BULK comencemos por el principio (lgico no? )
Qu significa HID?
HID es acrnimo en espaol de Dispositivo de Interfaz Humana como bien lo describe Diego en su artculo EL USB DESENCADENADO : HID USB y resulta que en los drivers del CCS viene activado por defecto. si lo vamos a usar, no colocamos nada. si NO lo usaremos, lo negamos en el define (est programado al revs, digo yo ) #define USB_EP1_TX_ENABLE USB_ENABLE_BULK //turn on EP1(EndPoint1) for IN bulk/interrupt transfers que es eso de endpoint? bulk/interrup transfers? voy a colocar aqu una explicacin que me pareci excelente tomada de un proyecto especial de grado link Capitulo 3: Bus Serie Universal, funcionamiento Pg. 38
www.unpocodelectronica.netau.net
Pgina 98
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
Se puede decir que los endpoint son buffer temporales de datos de entrada/salida en cada tipo. En el mdulo USB existen 16 de salida (OUT) y 16 de entrada (IN) pero agrupados en forma bidirecional, de acuerdo a un par de bits de configuracin (ver Pg. 171). Ojo un endpoint es unidireccional. para quien tenga dudas con el pipe, una imagen representativa:
www.unpocodelectronica.netau.net
Pgina 99
[PRIMEROS PASOS CON EL 18F4550] 14 de abril de 2010 respecto a la otra pregunta, existen 4 tipos de transferencias: transferencias de control: usado para comandos (y respuestas) cortos y simples. Es el tipo de transferencia usada por el pipe 0 transferencias iscronas: proveen un ancho de banda asegurado pero con posibles prdidas de datos. Usado tpicamente para audio y video en tiempo real transferencias interruptivas: para dispositivos que necesitan una respuesta rpida (poca latencia), por ejemplo, mouse y otros dispositivos de interaccin humana. transferencias masivas (BULK): para transferencias grandes y espordicas utilizando todo el ancho de banda disponible, pero sin garantas de velocidad o latencia. Por ejemplo, transferencias de archivos. entonces nosotros debemos definir que tipo de transferencia vamos a realizar. en el ejemplo de Jaime se estn declarando 2 endpoints (1 bidirecionales) como transferencia masiva o BULK. #define USB_EP1_TX_SIZE 1 //size to allocate for the tx endpoint 1 buffer podemos definir el tamao del buffer en bytes, el lmite lo tendremos que buscar en el driver correspondiente (con FS hasta 64 bytes por transaccin). nota: no confundir FS con HS, con High Speed se llega hasta 480Mbps, el mdulo USB del pic soporta Full Speed = 12Mbps usb_wait_for_enumeration() segn el concepto que dan en el driver, hace lo mismo que usb_enumerated(). La diferencia est en que el primero se queda en un bucle indefinido hasta que el HOST le d la orden de habilitacin. para propsitos donde queramos hacer otras actividades en el PIC, usaremos el segundo. ahora hablaremos de como se hace para transmitir y recibir datos. para eso estn usb_put_packet(,,) y usb_get_packet(,,) ambas necesitan de 3 argumentos. vamos con put_packet:
1 2 3 4 5 6 7 8 9 10 11 12 ... /* 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
www.unpocodelectronica.netau.net
Pgina 100
el 1 argumento endpoint ya se explic. - el 2 argumento apunta a la direccin del dato a enviar (es una variable declarada por nosotros). - el 3 argumento es el tamao del paquete en bytes. - el 4 argumento habla sobre DATA1, DATA2, toggle. y eso que es? como parte de su protocolo, nos encontraremos entre otras cosas que USB maneja la transmisin de datos por paquetes, llamados TOKEN en la cul el HOST es el iniciador de todas las transferencias que se producen en el BUS [2]
Los paquetes de datos ver Pg. 206 usb_20.pdf pues bien en la parte de transmisin de datos USB, los paquetes de datos se encuentran en grupos de paquetes de datos, y dentro de estos, existen unos llamados DATA0, DATA1. hay un proceso llamado sincronizacin del data toggle. a grandes rasgos esto no es mas que un mtodo de validacin de paquetes, y lo que hace es enviar alternadamente a DATA0 y DATA1 en una secuencia seguido de su ACK respectivo. todo con el objetivo de mantener la sincronizacin transmisor <-> receptor.
www.unpocodelectronica.netau.net
Pgina 101
Transacciones Consecutivas ver Pg. 233 usb_20.pdf ese tercer argumento definido en el cdigo ejemplo: USB_DTS_TOGGLE
1 enum USB_DTS_BIT {USB_DTS_DATA1=1, USB_DTS_TOGGLE=2, USB_DTS_DATA0=0, 2 USB_DTS_STALL=3, USB_DTS_USERX=4};
segn la pgina 174 de 39632c.pdf el data toggle est definido por un bit llamado DTSEN y es mas, all lo explican.
Bit DTSEN en recepcin de paquetes hay toda una teora en lo relacionado a los grupos de paquetes, no lo mencionar para no salirme del objetivo principal. seguro alguien preguntar, y si yo no quiero usar la sincronizacin del data toggle? esto depende del tipo de transferencia a usar, hay casos donde es recomendable usarlo. ej: transferencias de mltiples transacciones y casos donde no se puede usar. para mayor informacin ver paginas 56 y 232 de usb_20.pdf
usb_get_packet()
www.unpocodelectronica.netau.net
Pgina 102
/******************************************************************* ************ /* 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. ...
el argumento 1 es el buffer de datos de entrada, donde llega el paquete de datos. el argumento 2 es el apuntador adonde guardaremos ese dato. el argumento 3 es el tamao de paquete en bytes. -vaya- se fue todo en pura teora, entonces en la prxima parte veremos si hacemos el estudio del lado del HOST mediante mpusbapi.dll y como hacerla funcionar por ej: en VB a travs de una Interfaz de Programacin de Aplicaciones API
www.unpocodelectronica.netau.net
Pgina 103
[PRIMEROS PASOS CON EL 18F4550] 14 de abril de 2010 http://pablohoffman.com/oscusb/ Osciloscopio USB abierto Protocolo USB aplicado a placas con microcontroladores
www.unpocodelectronica.netau.net
Pgina 104
1 2 3 4 5 6 7
aqu aparecen 7 ,yo cont unas 10 en el cdigo fuente. parece que estas 7 son las necesarias para hacer transacciones a la funcin. nota: funcin = dispositivo = mdulo 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 versin veamos que dice la traduccin que nos pas Slalen:
MPUSBGetDLLVersion(Void) 1 Lee el nivel de revision del MPUSAPi.dll. Es un nivel de revision de 2 32bits. Esta funcion no devuelve la version del codigo, no realiza nada con el USB.
yo le agregara que devuelve un dato de 32 bits, la versin de la dll en formato MMMMmmmm. vamos agregar un procedimiento para ver que hace:
www.unpocodelectronica.netau.net
Pgina 105
Mostrar la versin de mpusbapi.dll nos arroja 10000, y pienso que como hay 8 dgitos, ya que la versin es en hexa (8 nibbles = 32bits) -> versin dll = 1.0.0.0.0 si quieren mas informacin acerca de estas funciones, visitar estas direcciones: - La mpusbapi.dll desencadenada: PC <-> PIC va USB en Delphi - Traduccin de mpusbapi.doc de lo que si voy hablar es como podemos usar esas apis en VB. veamos: cuando arrancamos esta aplicacin, primero se debe ejecutar el form_load
1 Private Sub Form_Load() 2 OpenMPUSBDevice 'abre comunicaciones 3 End Sub
quin es openMPUSBDevice?
www.unpocodelectronica.netau.net
Pgina 106
[PRIMEROS PASOS CON EL 18F4550] 14 de abril de 2010 configura el conducto(pipe) de acceso a cada endpoint, uno de salida y uno de entrada. para outpipe tenemos operacin 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 lgico 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 aplicacin, debemos cerrar el enlace (igual como se hace en RS-232) mediante:
1 Sub CloseMPUSBDevice() 2 MPUSBClose (myOutPipe) 3 MPUSBClose (myInPipe) 4 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 aadirle el mtodo debug.print a cada api para poder analizar cada lnea ejecutada:
Sub OpenMPUSBDevice() 1 myOutPipe = MPUSBOpen(0, vid_pid, out_pipe, 0, 0) 2 salida 3 Debug.Print "myOutPipe= " & myOutPipe 4 5 myInPipe = MPUSBOpen(0, vid_pid, in_pipe, 1, 0) 6 entrada 7 Debug.Print "myInPipe= " & myInPipe End Sub 'como
'como
vamos a escribir un cdigo 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 Const vid_pid = "vid_04d8&pid_0011" ' Vendor id (Microchip) y
www.unpocodelectronica.netau.net
Pgina 107
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
www.unpocodelectronica.netau.net
Pgina 108
www.unpocodelectronica.netau.net
Pgina 109
Casos de abrir y cerrar PiPES ya tenemos una idea de como se usa la api MPUSBOpen.
www.unpocodelectronica.netau.net
Pgina 110
es lgico 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 haba visto, adems no pertenece al VB en s, leyendo por aqu, por ac, consegu:
Declare Function VarPtrAny Lib "vb40032.dll" Alias "VarPtr" (lpObject 1 As Any) As Long 2 'The VarPtr-function retrieves the memory handle of an object. 3 ' lpObject 4 ' Handle that identifies the object
-ahh- conque viene del runtime! hurgando en la biblioteca MSDN, aparecen tres mtodos 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). volviendo a la api MPUSBWrite, el segundo argumento:
www.unpocodelectronica.netau.net
Pgina 111
[PRIMEROS PASOS CON EL 18F4550] 14 de abril de 2010 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 direccin donde est alojado el dato que queremos enviar el problema que tiene visual basic es que no podemos usar punteros, pero con el mtodo varptr podemos tomar dicha direccin, y esto no es lo mejor de todo, lase 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 direccin 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 cdigo donde:
- guardar un dato (byte) en 2 variables - tomar la direccin 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. 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 23-feb-2007 10:19AM
www.unpocodelectronica.netau.net
Pgina 112
Usando punteros en Visual Basic 6 as pues, donde veamos el varptr ya sabemos a que se est refiriendo, adems el argumento de la api tambin 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 revs, 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 vern esta es otra aplicacin del concepto del puntero, por un lado tenemos la casilla(direccin de almacenamiento) y por el otro tenemos el valor del dato almacenado.
www.unpocodelectronica.netau.net
Pgina 113
[PRIMEROS PASOS CON EL 18F4550] 14 de abril de 2010 el resto de los argumentos es fcil de entender, como la longitud del dato (en bytes). esto depende de como configuremos el envo 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 funcin Send
Send_Buf(0) = 1 'Para que reconozca que se encienden o apagan 1 Leds 2 Send_Buf(1) = Index 3 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 accin para ambos leds (apagado, on, off -> led rojo y verde) luego el array de bytes se enva a la funcin send
Function Send(ByRef SendData() As Byte, bytes As Integer) As Long 1 Dim SentDataLength As Long 2 Call MPUSBWrite(myOutPipe, VarPtr(SendData(0)), bytes, 3 VarPtr(bytes), 1000) 'VarPtr()= puntero a la variable 4 End Function
observen el VarPtr(SendData(0)), es lo mismo que habl hace rato, se toma la direccin del primer byte es lo nico que necesita pData para tomar el resto del array de datos el que falta, la suma:
1 Dim a As Byte 'buffer de datos intermedio 2 3 Send_Buf(0) = 0 'Para que reconozca que es una suma 4 a = CByte(sumando(0).Text) 'convierte el texto a byte 5 Send_Buf(2) = a 6 Send_Buf(0) = 0 7 a = CByte(sumando(1).Text) 8 Send_Buf(1) = a 9 Send_Buf(0) = 0 10 Send Send_Buf, 3 'enva los sumandos 11 recibir (a) 'recibe el resultado 12 resultado.Caption = CStr(rec) 'convierte el dato a string
www.unpocodelectronica.netau.net
Pgina 114
[PRIMEROS PASOS CON EL 18F4550] 14 de abril de 2010 aqu sucede lo contrario, es decir, la api MPUSBRead necesita la direccin del byte s para almacenar el dato que viene del PIC (que en este caso es 1 byte de longitud). esto fue el anlisis realizado al programa1 y programa2. vamos a usar el estupendo SnoopyPro para ver los bferes del USB jijiji abrimos y ejecutamos las siguientes acciones en secuencia:
1.- led rojo = ON 2.- led verde = ON 3.- apaga leds 4.- 1 + 0 = 1 5.- 1 + 7 = 8 6.- 12 + 7 = 19
www.unpocodelectronica.netau.net
Pgina 115
[PRIMEROS PASOS CON EL 18F4550] 14 de abril de 2010 Transaccin Recibida tenemos un paquete de 2 bytes, en el primer el modo = 1 (modo led). y en el segundo paraml = 2 (led rojo ON)
Transaccin Recibida tenemos un paquete de 2 bytes, en el primer el modo = 1 (modo led). y en el segundo paraml = 1 (led verde ON)
Transaccin 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)
Transaccin 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. un poco mas abajo:
www.unpocodelectronica.netau.net
Pgina 116
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:
analizando paquetes
www.unpocodelectronica.netau.net
Pgina 117
analizando paquetes observaciones: - despus de haber visto varias veces el cdigo de Jaime hasta ahora es que me doy cuenta que el led verde es RB6 y led rojo RB7 yo lo tena invertido. pero lo extrao de todo es que con el programa PicUSBDelphi.exe de Diego se ejecuta OK con los leds invertido. ?? - faltara implementar un algoritmo de validacin, 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 tambin 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
www.unpocodelectronica.netau.net
Pgina 118
bueno, ahora no estoy tan seguro que eso sea cierto (despus de todo es una suposicin), ahora me baso en lo siguiente: - que dicha api, devuelve un puntero que contiene la versin de la librera mpusbapi.dll - si esto es cierto, entonces la versin 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, pudindose cambiar por la versin correcta posteriormente (dado el caso).
voy a tomar el ejemplo del CDC explicado con anterioridad y lo voy a modificar para usarlo con la librera mpusbapi.dll - lo primero, hacer la deteccin del lado del dispositivo - lo segundo hacer la deteccin del lado del Host Deteccin del lado del dispositivo: es de la misma forma que para la clase CDC estudiada, mediante el USB_CON_SENSE_PIN el cdigo con la modificacin:
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 */ #include <18F4550.h>
www.unpocodelectronica.netau.net
Pgina 119
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 tamao 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 tamao 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 } /************************************************ // esta llamada imprime en la LCD los estados de conectado
www.unpocodelectronica.netau.net
Pgina 120
www.unpocodelectronica.netau.net
Pgina 121
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 funcin:
1 void usb_init(void) { 2 usb_init_cs(); 3 4 do { 5 usb_task(); 6 } while (usb_state != USB_STATE_POWERED); 7}
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 mdulo USB y lo desactiva, est bien as que se desactive por defecto (menos consumo para el circuito).
- entonces como enciendo el mdulo? 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 deteccin 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). Adems que no hay que modificar el driver original pic18_usb.h - el resto del cdigo queda igual, solo ajustar los paquetes de datos a 1 byte, usando un eco. el HOST le enva un carcter (a) y el dispositivo se lo devuelve.
www.unpocodelectronica.netau.net
Pgina 122
Option Explicit Dim Send_Buf(0) As Byte Const verde = &HFF00& Const rojo = &HFF& Private Sub cmdversiondll_Click() Dim version_dll As Long, digitos(4) As Byte, cad As String, t As Integer version_dll = VarPtr(MPUSBGetDLLVersion) 'toma el puntero de la version For t = 0 To 3 digitos(t) = 0 ' limpiar variables Next t CopyMemory ByVal VarPtr(digitos(0)), ByVal version_dll, 5 ' recupera de la memoria los digitos de la version y lo copia en digitos() cad = "" For t = 0 To 3 ' concatena los digitos en una cadena cad = cad & Str(digitos(t)) & "." Next t lblversiondll.ForeColor = &HFFFF& lblversiondll.Caption = Left$(cad, Len(cad) - 1) ' muestra la version End Sub Private Sub Command2_Click() Dim eco As Byte, dato As Long Timer1.Enabled = False Send_Buf(0) = Asc("a") 'envia la "a" OpenMPUSBDevice 'abre comunicaciones Send Send_Buf, 1 dato = recibir(eco) If eco = 97 Then lblrespuesta.Caption = "El dispositivo respondio Exitosamente" Else lblrespuesta.Caption = "No hubo respuesta del Dispositivo" End If CloseMPUSBDevice 'cierra comunicaciones Timer1.Enabled = True End Sub Private Sub Form_Load() Timer1.Interval = 50
www.unpocodelectronica.netau.net
Pgina 123
http://www.youtube.com/watch?v=N1xHoPay-LA como ven lo adapt para transferencias de paquetes de datos de 1 byte, y como siempre mi empeo en agregarle un sensor de estado del dispositivo, muy similar que con la clase CDC: un timer abriendo y cerrando el pipe cada 50 mS y preguntando si hubo enlace. cabe decir que el cdigo del PIC es el mismo del ejemplo anterior y funciona igual. en los ensayos en el protoboard - reconexin de la extensin USB. - abriendo y cerrando el programa en VB - incluso se desconect/conect la alimentacin al PIC y los resultados fueron satisfactorios.
www.unpocodelectronica.netau.net
Pgina 124
www.unpocodelectronica.netau.net
Pgina 125
void main(){ int i; int envia[1]; int recibe[1]; set_tris_a(0x1); // Ra[0]=entradas, los demas=salida
usb_init_cs(); // inicializa el USB y lo desactiva lcd_init(); // llamadas necesarias para iniciar la LCD setup_adc_ports( AN0 || VSS_VDD ); // canal AN0, Vref+ = Vdd, Vref- = Vss config_adcon2(DERECHA); // justificacin derecha, Tacq= 2Tad while(true){ usb_task(); //habilita periferico usb e interrupciones mostrar_estado_usb(); envia[0]= read_adc(); for(i=0;i<16;i++){// muestra resultado del CAD en binario, linea1 LCD lcd_gotoxy(16-i,1); lcd_putc((char)(bit_test(envia[0],i)+0x30)); } printf(lcd_putc,"\n0x%Lx",envia[0]); // muestra el resultado del CAD en Hexa, linea2 LCD 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 tamao 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 tamao 1 bytes del EP1 al PC } // fin del tercer if } // fin del segundo if } // fin del primer if } // fin del ciclo while } /*********************************************************** // esta llamada imprime en la LCD los estados de conectado // 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); } //------------------------------------------------------------------
www.unpocodelectronica.netau.net
Pgina 126
la resolucin del CAD es a 8 bits y aunque el paquete de datos es de 1 byte, se debe declarar las variables como tipo array:
porque sino no les funcionar (comprobado) del resto todo es igual como en el ejemplo mencionado anteriormente. el programa del lado del HOST:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ' programa para explotar el uso del picturebox realizando graficas en ' tiempo de ejecucion. ' para una aplicacion practica se recibiran paquetes de 1 bytes ' del dispositivo (18F4550) con el resultado del CAD a 8 bits y se mostrara ' la onda en el picturebox ' ' ' la parte del codigo de transferencia de datos por USB, pertenece a Slalen ' ' Saludos a foro TodoPic http://www.todopic.com.ar/foros/index.php ' ' por: Pedro - PalitroqueZ 10-Mar-2007 Hora: 09:34 PM
www.unpocodelectronica.netau.net
Pgina 127
Option Explicit Dim Dim Dim Dim Dim Dim Dim Dim cx As Integer, cy As Integer cx1 As Integer, cy1 As Integer i As Integer, j As Long x As Long, y As Integer dato(1000) As Long pcx As Long, pcy As Long fcx As Long, fcy As Long n As Integer ' n define la base de tiempo o time-division
Dim Send_Buf(0) As Byte Const verde = &HFF00& Const rojo = &HFF& Dim valor As Single, maximo As Integer Dim te As Byte Private Sub Form_Load() valor = 0 'VScroll1.Value ' el resultado del CAD en un tiempo discreto maximo = 255 'VScroll1.Max ' viene siendo el maximo numero de pasos del CAD (8 bits=255, 10 bits=1023) n = 30 ' wl time-division cy = Picture1.ScaleHeight ' 117 cx = Picture1.ScaleWidth ' 253 cy1 = Picture1.ScaleHeight ' 117 cx1 = Picture1.ScaleWidth ' 253 pcx = Picture1.Width pcy = Picture1.Height fcx = Me.Width fcy = Me.Height ajustar_tiempo (n) Timer1.Enabled = False Timer2.Enabled = False Timer3.Interval = 50 Timer3.Enabled = True 'Timer3.Enabled = False HScroll1.Value = n End Sub Private Sub Form_Resize() Timer1.Enabled = False Timer2.Enabled = False Picture1.Height = Form1.Height / (fcy / pcy) Picture1.Width = Form1.Width / (fcx / pcx) Picture1.ScaleHeight = Picture1.Height / (pcy / cy1) Picture1.ScaleWidth = Picture1.Width / (pcx / cx1) cy = Picture1.ScaleHeight cx = Picture1.ScaleWidth
www.unpocodelectronica.netau.net
Pgina 128
www.unpocodelectronica.netau.net
Pgina 129
If (myOutPipe <> INVALID_HANDLE_VALUE) And (myInPipe <> INVALID_HANDLE_VALUE) Then shpestado.FillColor = verde Else shpestado.FillColor = rojo End If Send Send_Buf, 1 recibir (te) If rec = 0 Then valor = 1 ' para ajustar el grfico Else valor = rec End If CloseMPUSBDevice 'cierra comunicaciones
End Sub Private Sub cmdayuda_Click() Dim mensaje As String mensaje = "Este programa recoge los datos enviado desde un" & vbCrLf mensaje = mensaje & "dispositivo (PIC18F4550) y grafica la seal correspondiente" & vbCrLf mensaje = mensaje & "al resultado de una conversion analogicadigital" & vbCrLf mensaje = mensaje & "a 8 bits de resolucin" MsgBox mensaje, vbInformation, "Informacion" End Sub
el Timer3_Timer() es primordial, porque cumple triple propsito: enva el dato de confirmacin (el ECO). recibe el dato del dispositivo. sensa el estado de conexin del dispositivo, ya que ante cada ejecucin y transferencia abre y cierra el pipe.
www.unpocodelectronica.netau.net
Pgina 130
un ventanazo en accin:
ventana del programa final http://www.youtube.com/watch?v=l9AdEIxAzgo en el video, se hizo ensayos variando un potencimetro, y reconectando el dispositivo, y TODO VA DE LUJO! en base a mis experiencias, debo decir que trabajar con mpusbapi.dll como que es la mejor opcin, mucho mas rpido y prctico (conociendo la programacin). pero para no subestimar a la clase CDC, entonces: - de acuerdo a la situacin dada, se debe escoger que es conveniente: CDC mpusbapi.dll - eso depender del programador que tendr que decidir cul es mejor. como dira Neo: todo es cuestin de eleccin (tomado de la pelcula Matrix, Revolutions) y este fue el estudio realizado al mdulo USB si se quiere decir por encima ya que queda mucha informacin a nivel de capas inferiores por estudiar.
www.unpocodelectronica.netau.net
Pgina 131
Agradecimientos y Mritos
Agradecimiento especial a los integrantes del foro TodoPic por su colaboracin y expongo los links mas relevantes que me sirvieron de gua para la creacin de esta bitcora. Foro Todopic Diego (RedPic) en PicMana Jaime (J1M) en hobbypic.com Microchip Manolo Nocturno con la Wikipic Sisco por su software WinPic800 Guillermos (Slalen) en Electronics Strange World
www.unpocodelectronica.netau.net
Pgina 132
www.unpocodelectronica.netau.net
www.unpocodelectronica.netau.net
Pgina 133