PARA LAS ÚNICAS PERSONAS QUE ME INTERESAN EN EL MUNDO. PUES LO DEMÁS ES VANO. PARA MIS PADRES…. GRACIAS “ Y a ti . . . Porque estarás conmigo desde hoy, hasta el fin de los tiempos. Y he de tomar mi lugar, en las leyendas del pasado ” A mis padres, Cristóbal Orantes Verdugo y Rosa Osuna. Por ayudarme en lo que que sea y por sus esfuerzos que no han sido en vano. A mi asesor, Maestro en ciencias Javier Pérez, Por su apoyo y asesoría. A los maestros revisores, Mtro. Eduardo romero, Mtro. Othon y Mtro. Solís. Por su ayuda a la realización de este trabajo y por sus enseñanzas. A todos los maestros que a través del curso de mi carrera, dedicarón de su tiempo en mi aprendizaje. A mi compañero Gabriel Enríque Cázares enriquez, por su amistad y compañía. Y sobre todo a Isidro Murrieta Dorame, Por patrocinarme con la computadora, y darme su amistad a través del tiempo que hemos estado juntos y sin estar juntos también. i ÍNDICE Página LISTA DE FIGURAS............................................................................................... iv LISTA DE TABLAS................................................................................................. vii RESUMEN............................................................................................................... viii I INTRODUCCIÓN................................................................................................... 1 1.1 Antecedentes.......................................................................................... 1 1.2 Definición del problema........................................................................... 4 1.3 Justificación............................................................................................. 4 1.4 Objetivo.................................................................................................... 4 1.5 Delimitaciones.......................................................................................... 5 1.6 Referencias............................................................................................... 5 II MARCO TEÓRICO................................................................................................ 6 2.1 USB (universal serial bus)........................................................................ 6 2.1.1 Introducción............................................................................... 6 2.1.2 Conexiones................................................................................ 7 2.1.3 Comunicación............................................................................ 8 2.1.4 Paquetes.................................................................................... 10 2.1.5 Transacciones o Transferencias................................................ 11 2.1.6 HUB........................................................................................... 13 2.1.7 Descriptores.............................................................................. 15 2.1.8 Clases (Class) y subclases (Subclass)..................................... 16 2.1.9 Enumeración y Estados del dispositivo.................................... 19 2.1.10 Protocolo, Tramas y Campos de bits....................................... 23 2.1.11 Formato de paquetes............................................................... 24 2.1.12 Formato de transferencia......................................................... 26 2.1.13 Requisiciones........................................................................... 27 2.1.14 Formato de los descriptores..................................................... 29 ii 2.1.15 Descriptor reporte (Report descriptor)...................................... 32 2.1.16 Descriptor físico (physical report)............................................. 44 2.1.17 Dispositivo de interfaz humana (HID)....................................... 46 2.2 Microcontroladores................................................................................... 47 2.2.1 Introducción............................................................................... 47 2.2.2 Puertos de entrada y salida........................................................ 49 2.2.3 Módulo USART........................................................................... 50 2.2.4 Módulo ADC................................................................................ 52 2.2.5 Módulo USB................................................................................ 53 2.3 Freeware.................................................................................................. 57 2.3.1 Introducción................................................................................ 57 2.3.2 Código fuente en ensamblador del freeware.............................. 59 2.3.3 Funciones del código fuente de ensamblador............................ 59 2.3.4 API de Visual Basic (ACTIVEX).................................................. 60 2.3.5 Asiganación del controlador (Driver)........................................... 65 2.4 Referencias.............................................................................................. 66 III DESARROLLO..................................................................................................... 67 3.1 Introducción.............................................................................................. 67 3.2 Conexión de microcontroladores.............................................................. 71 3.3 Modos de funcionamiento........................................................................ 73 3.4 Adecuación del firmware.......................................................................... 75 3.5 Diseño del software para la PC................................................................ 76 3.5.1 Diseño modo de conexión con la PC.......................................... 76 3.5.2 Diseño modo de conexión con el PLC........................................ 82 3.6 Programación de microcontroladores....................................................... 86 3.6.1 Inicialización de microcontroladores (modo conexión PC)......... 86 3.6.2 Inicialización de microcontroladores (modo conexión PLC)....... 87 3.6.3 Generador de señales de activación (modo conexión PC)......... 89 3.6.4 Generador de señales de activación (modo conexión PLC)....... 93 3.6.5 Recepción de datos y claves de conmutación............................ 95 iii 3.6.6 Recepción y apilamiento de datos en RAM................................ 98 3.6.7 Detector de frecuencia válida.................................................... 101 3.6.8 Generador de señal de dato...................................................... 103 3.6.9 Medición de señales de frecuencia........................................... 108 IV PRUEBAS Y RESULTADOS.............................................................................. 113 V CONCLUSIONES Y RECOMENDACIONES....................................................... 120 BIBLIOGRAFÍA....................................................................................................... 122 ANEXOS...................................................................................................................123 Anexo1 Código completo de los programas………………............................ 124 Anexo2 Cuadros de diálogos en el proceso de enumeración....................... 167 Anexo3 Jumpers de configuración................................................................ 172 Anexo4 Fotografias completas de los módulos............................................. 173 Anexo5 Diagramas de los programas en ensamblador................................ 174 iv LISTA DE FIGURAS Página Figura 1.1 Tuberías superficiales........................................................................................................ 1 Figura 1.2 Tubería subterránea........................................................................................................... 1 Figura 1.3 Filtración de humedad........................................................................................................ 1 Figura 1.4 Sistema de riego automatizado (esquema general) …...................................................... 2 Figura 1.5 Sistema de monitoreo........................................................................................................ 3 Figura 2.1 Topología........................................................................................................................... 6 Figura 2.2 Cable.................................................................................................................................. 7 Figura 2.3 (Conector a, Conector b, Receptor a y Receptor b) .......................................................... 7 Figura 2.4 Pines correspondientes (1= Vbus, 2 = d-, 3 = d+, 4 = GND) ........................................... 7 Figura 2.5 Flujo de comunicación (lógica y física) .............................................................................. 8 Figura 2.6 Conexión lógica.................................................................................................................. 9 Figura 2.7 Transacciones (ejemplo) .................................................................................................. 12 Figura 2.8 Ancho de banda................................................................................................................ 12 Figura 2.9 Flujo de información en el hub.......................................................................................... 14 Figura 2.10 El host cuenta con un hub integrado llamado root hub..................................................... 14 Figura 2.11 Descriptores para una y dos interfaces............................................................................. 22 Figura 2.12 Formato de los tokens (IN, OUT y SETUP) ..................................................................... 25 Figura 2.13 Formato del token SOF..................................................................................................... 25 Figura 2.14 Formato del paquete de datos.......................................................................................... 25 Figura 2.15 Token handshake.............................................................................................................. 25 Figura 2.16 Transferencia síncrono y transferencia control................................................................. 26 Figura 2.17 Transferencia bulto (bulk) ................................................................................................. 26 Figura 2.18 Transferencia interrupción................................................................................................. 27 Figura 2.19 Formato para un endpoint específicamente...................................................................... 28 Figura 2.20 Formato para una interfaz específicamente...................................................................... 28 Figura 2.21 ítem Short.......................................................................................................................... 32 Figura 2.22 ítem Long.......................................................................................................................... 32 Figura 2.23 Estructura del descriptor reporte....................................................................................... 43 Figura 2.24 Mapa de memoria del PIC 16C745................................................................................... 48 Figura 2.25 Mapa de memoria del PIC 16F628................................................................................... 49 Figura 2.26 Comunicación serie síncrona............................................................................................ 51 Figura 2.27 Protocolo serie asíncrono.................................................................................................. 51 Figura 2.28 Registro TXSTA................................................................................................................ 51 Figura 2.29 Registro RXSTA................................................................................................................ 51 Figura 2.30 Registro PIR1 del PIC 16C745.......................................................................................... 52 Figura 2.31 Registro PIE1 del pic 16C745........................................................................................... 52 Figura 2.32 Registro ADCON0 del pic 16F873.................................................................................... 52 Figura 2.33 Registro ADCON1 del pic 16F873.................................................................................... 52 Figura 2.34 Registro UIR...................................................................................................................... 53 Figura 2.35 Registro UIE...................................................................................................................... 53 Figura 2.36 Registro UEIR................................................................................................................... 53 Figura 2.37 Registro UEIE.................................................................................................................... 53 Figura 2.38 Registro UCTRL................................................................................................................ 54 Figura 2.39 Registro UADDR............................................................................................................... 54 Figura 2.40 Registro USWSTAT.......................................................................................................... 54 Figura 2.41 Registro UEPn................................................................................................................... 54 Figura 2.42 Tabla de configuración de enpoints.................................................................................. 55 Figura 2.43 Registro BdndAL............................................................................................................... 55 Figura 2.44 Registro BDndBC.............................................................................................................. 56 Figura 2.45 Registro BDndST leído por el MCU.................................................................................. 56 Figura 2.46 Registro BDndBC escrito por el MCU............................................................................... 56 v Página Figura 2.47 Registro USTAT................................................................................................................ 56 Figura 2.48 Diagrama para la rutina de servicio de interrupción.......................................................... 57 Figura 2.49 Tipos de tokens que atiende el freeware.......................................................................... 58 Figura 2.50 Cuadro de dialogo en win98.............................................................................................. 65 Figura 3.1 Sistema de riego............................................................................................................... 67 Figura 3.2 Etapas de ambos módulos principales.............................................................................. 67 Figura 3.3 Etapas del módulo maestro............................................................................................... 69 Figura 3.4 Barra de LEDS.................................................................................................................. 69 Figura 3.5 Vista frontal y superior del conector PLC en el módulo maestro...................................... 69 Figura 3.6 Etapas del módulo esclavo............................................................................................... 70 Figura 3.7 Conexion a detalle de los microcontroladores 16f628 y 16c745....................................... 71 Figura 3.8 Conexion a detalle del microcontrolador 16f873............................................................... 72 Figura 3.9 Modo conexión con la PC................................................................................................. 74 Figura 3.10 Modo conexión con el PLC............................................................................................... 74 Figura 3.11 Conector db9 (pines correspondientes) ........................................................................... 74 Figura 3.12 Adecuación al firmware..................................................................................................... 75 Figura 3.13 Proceso de activación en el modo de conexión con la PC............................................... 76 Figura 3.14 Programa en vista de diseño............................................................................................. 77 Figura 3.15 Base de datos para los transductores............................................................................... 78 Figura 3.16 Base de datos para los tiempos de barridos..................................................................... 78 Figura 3.17 Interfaz para el barrido de lecturas manual....................................................................... 79 Figura 3.18 Temporizadores del programa.......................................................................................... 79 Figura 3.19 Funciones del programa.................................................................................................... 80 Figura 3.20 Funcion del timer2............................................................................................................. 81 Figura 3.21 Proceso de activación en el modo de conexión con el PLC............................................. 82 Figura 3.22 Programa en vista de diseño............................................................................................. 83 Figura 3.23 Programa en tiempo de ejecución...................................................................................... 83 Figura 3.24 Función del botón enviar................................................................................................... 85 Figura 3.25 Código para la inicialización del puerto USB y configuraciones de puertos..................... 86 Figura 3.26 Configuración del puerto serie síncrono e inicializaciones................................................ 87 Figura 3.27 Rutina para la configuración del puerto serie síncrono e inicializaciones......................... 88 Figura 3.28 Rutina para inicialización de variables, configuración de puerto y RSI (PIC16F873) …... 88 Figura 3.29 Rutina para el generador de frecuencia o señales de activación...................................... 89 Figura 3.30 Gráfica de la tabla 3.1....................................................................................................... 91 Figura 3.31 Comparación de la ecuación obtenida y los datos de la tabla 3.1.................................... 92 Figura 3.32 Rutina para el generador de señales................................................................................ 93 Figura 3.33 Caracterización del generador de señales de activación.................................................. 94 Figura 3.34 Comparación de la ecuación y los datos de la tabla 3.2................................................... 95 Figura 3.35 Clave1 (arriba línea de dato, abajo línea de reloj) ........................................................... 96 Figura 3.36 Led indicador.................................................................................................................... 96 Figura 3.37 Clave2 (arriba línea de dato, abajo línea de reloj) ........................................................... 97 Figura 3.38 Rutina de interrupción serie síncrona................................................................................ 97 Figura 3.39 Led indicador para cálculo de retardo............................................................................... 98 Figura 3.40 Rutina para la recepción y transmisión de datos.............................................................. 99 Figura 3.41 Rutina para la recepción serie síncrona de datos y su clasificación................................. 99 Figura 3.42 Rutina para el temporizador............................................................................................. 100 Figura 3.43 Ruido presente en estado de reposo (osciloscopio y acercamiento) .............................. 101 Figura 3.44 Rutina para el generador de datos o frecuencia.............................................................. 104 Figura 3.45 Cálculo del número necesario para generar la frecuencia de dato.................................. 105 Figura 3.46 Rutina para determinar el rango de error de la muestra de frecuencia............................ 106 Figura 3.47 Rutina para la adquisición de dato y proceso de cálculo................................................. 107 vi Página Figura 3.48 Rutina para el medidor de frecuencia.............................................................................. 108 Figura 3.49 Resultado de la medición de frecuencia.......................................................................... 110 Figura 3.50 Rutina de servicio de interrupción serie síncrona............................................................ 111 Figura 3.51 Recepción de datos de humedad y transmisión por el puerto USB................................. 112 Figura 4.1 Jumpers y push button para pruebas (1.- jumpers. 2.- Push button) ............................. 114 Figura 4.2 Rutina para configurar la frecuencia de activación del módulo esclavo.......................... 114 Figura 4.3 Sincronización del retardo para la adquisición del dato de humedad................................ 115 Figura 4.4 Etapa de adecuación para el PLC (1.- etapa de adecuación. 2.- cable de bus) ............... 115 Figura 4.5 Receptores de cables (1.- módulo de despliegue. 2.- cable de bus) ................................ 116 Figura 4.6 Módulo de despliegue para realizar pruebas..................................................................... 116 Figura 4.7 Conexión de cables para el interfaz con el PLC y módulo de despliegue......................... 117 Figura 4.8 Interpretación de la medición de frecuencia en porcentaje de humedad........................... 119 vii LISTA DE TABLAS Página Tabla 2.1 Tipos de paquetes.............................................................................................................. 10 Tabla 2.2 Resumen de transferencias................................................................................................ 13 Tabla 2.3 Subclases para la clase = 02h............................................................................................ 17 Tabla 2.4 Protocolo para la clase = 02h............................................................................................. 17 Tabla 2.5 Subclases para la clase = 08h............................................................................................ 18 Tabla 2.6 Protocolo para la clase = 08h............................................................................................. 18 Tabla 2.7 Protocolo para la clase = 09h............................................................................................. 19 Tabla 2.8 Requisiciones Standard y sus Códigos.............................................................................. 28 Tabla 2.9 Device descriptor................................................................................................................ 29 Tabla 2.10 String descriptor................................................................................................................. 29 Tabla 2.11 Configuration descriptor..................................................................................................... 30 Tabla 2.12 Interface descriptor............................................................................................................. 30 Tabla 2.13 Hid descriptor..................................................................................................................... 31 Tabla 2.14 Endpoint descriptor............................................................................................................ 31 Tabla 2.15 Prefijo de un byte del short ítem........................................................................................ 33 Tabla 2.16 Mapa de bits...................................................................................................................... 34 Tabla 2.17 Collections......................................................................................................................... 36 Tabla 2.18 ítems globales (nn indica el número de bytes que lo siguen) …........................................ 37 Tabla 2.19 Ejemplo de uso de los ítems Logical maximum y minimum............................................... 38 Tabla 2.20 Valores para el exponente de las unidades....................................................................... 39 Tabla 2.21 Tabla de unidades.............................................................................................................. 39 Tabla 2.22 Local ítems......................................................................................................................... 41 Tabla 2.23 Ejemplo de uso de Usage minimum y maximum............................................................... 42 Tabla 2.24 Descriptor físico cero.......................................................................................................... 44 Tabla 2.25 Descriptor físico.................................................................................................................. 45 Tabla 2.26 Valores de bias................................................................................................................... 45 Tabla 2.27 Descriptor físico agregado.................................................................................................. 45 Tabla 2.28 Valores para los designators.............................................................................................. 45 Tabla 2.29 Valores de qualifier............................................................................................................. 46 Tabla 3.1 Caracterización para el generador de frecuencia................................................................. 90 Tabla 3.2 Caracterización para el generador de frecuencia................................................................. 93 Tabla 3.3 Caracterización del generador de datos.............................................................................. 104 Tabla 3.4 Adecuación ADC................................................................................................................. 105 Tabla 3.5 Caracterización del medidor de frecuencia......................................................................... 109 Tabla 4.1 Resultado final (voltaje de referencia del ADC a 5.2 volts) ................................................ 118 viii RESUMEN El presente trabajo muestra el diseño de control para las etapas de radiofrecuencia, que se encuentran dentro de un sistema de monitoreo de humedad, aplicado en un sistema de riego por goteo. El control es aplicado por medio de microcontroladores PIC, para el encendido y apagado de las etapas de todos los dispositivos que intervienen en la medición de humedad, así como la generación de la banda base para las transmisiones inalámbricas. En el capítulo I, se muestra un antecedente de los trabajos anteriores a éste, así como la descripción de un sistema de monitoreo. Después, se plantea el problema a resolver, los objetivos a cumplir al terminar el presente trabajo y las ventajas con las que contará. En el capítulo II, se encuentran toda la teoria para comprender el funcionamiento del puerto USB y los módulos que se utilizaron de los PICs. En el capítulo III, se describen los primeros pasos del diseño, las especificaciones con las que cuenta las etapas de radiofrecuencia y el sensor de humedad. Para después definir los bloques que describen el proceso de control que se ejercerá sobre las demás etapas. Cada uno de estos bloques son descritos a detalle así como su diseño. En el capítulo IV, se muestran los resultados obtenidos aplicando dicho control sobre las etapas. Muestra resultados de las lecturas de humedad asi como los diseños realizados para llevar a cabo las pruebas. En el capítulo V, se mencionan las conclusiones sobre el presente trabajo así como algunas recomendaciones para mejorar este trabajo. Por último se muestran las referencia de algunos libros de apoyo. I INTRODUCCIÓN 1.1 Antecedentes En el valle del yaqui, que es una región de producción agrícola, se tiene el problema de la falta de agua [1], y es por eso que es importante economizar la poca que queda en esta área geográfica. Debido a la necesidad economizar el agua, algunos productores agrícolas han optado por cambiar a nuevas técnicas de riego, una de ellas es la técnica de riego por goteo, que riega uniformemente la tierra por medio de tuberías superficiales o subterráneas (figuras 1.1 y 2.2), ya que sólo humedece el área de absorción de la planta cultivada, sin necesidad de humedecer áreas donde el agua se filtra o se evapora (figura 1.3). Figura 1.1 Tuberías superficiales. Figura 1.2 Tubería subterránea. Figura 1.3 Filtración de humedad. 2 En un sistema de riego automatizado como se muestra en la figura 1.4. Las tuberías se controlan a través de electroválvulas para habilitar el riego o simplemente detenerlo cuando la tierra alcanza la humedad requerida, esta humedad depende del tipo de planta que se esté cultivando. Sistema De Riego Central Cultivo Figura 1.4 Sistema de riego automatizado (esquema general). Las electroválvulas son controladas por medio de una central, que tomará las decisiones de habilitar o no el sistema de riego por goteo, a la central es necesario informarle las lecturas de humedad (sistema de monitoreo de humedad) y así tomar la decisión, si al cultivo le falta o no más agua para llegar a la humedad requerida. En el 2002, el Instituto Tecnológico de Sonora (ITSON) realizó el proyecto de automatización de un sistema de riego por goteo en un cultivo ubicado en la manzana 940, lotes 19 y 20, a un costado del CIANO en el Valle del Yaqui, con el objetivo de aprovechar al máximo la poca agua con la que cuenta el valle [1]. En este proyecto se han implementado varios trabajos de tesis, que van desde software para el control del sistema de riego, hasta los transductores que miden la humedad. El último trabajo de tesis realizado es el de Enrique Cuadras [1], y se acerca mucho al presente proyecto. El sistema de comunicación con la que cuenta su monitoreo de humedad es vía RF, y lo componen 2 módulos de acoplamiento y radios comerciales para establecer esta comunicación, además, fue realizado para un solo transductor y la medición de humedad es continua. 3 El presente proyecto propone sustituir estos radios, hacer el sistema de monitoreo para más transductores y que se realice un mínimo de cambios en el hardware al agregar o quitar transductores en el sistema de riego. Con los cambios antes mencionados, el sistema de monitoreo de humedad tiene la siguiente forma: La central lo componen la PC o un PLC y el módulo maestro, este módulo se enlazará con un módulo esclavo, que a su vez estará conectado a un sensor de humedad en contacto con la tierra de cultivo. PC O PLC Módulo Maestro De transmisión Y Recepción Módulo Esclavo De transmisión Y Recepción Sensor Sistema De Riego Figura 1.5 Sistema de monitoreo. El sistema de monitoreo de humedad, consta de 2 dispositivos principales para llevar a cabo las lecturas (módulo maestro y módulo esclavo), y ambos dispositivos se dividen en 2 partes; parte digital y parte analógica. La parte analógica consiste en un sistema de comunicación de RF, como medio para realizar el enlace en forma inalámbrica. La parte digital la compone uno o varios microcontroladores, los cuales servirán para tomar el control de las etapas de la parte analógica además de otras funciones. Debido a la complejidad de este proyecto, ambas partes (digital y analógica) se separan en 2 trabajos de tesis, el presente trabajo se enfocará en la parte digital. La parte analógica representa otro trabajo en conjunto con este [2]. 4 1.2 Definición del problema Para llevar a acabo la parte digital, se necesita implementar un control al sistema de comunicación de RF en ambos módulos, esto es, para enviar las señales modulantes y que la interferencia de una etapa no afecte el desempeño de las otras. También es necesario crear un interfaz con la PC y PLC. 1.3 Justificación Debido a que no hay una basta experiencia en el desarrollo de transmisores y receptores, éstos serán manufacturados en los cubículos de los laboratorios de electrónica del ITSON [2], contribuyendo al desarrollo de tecnología propia de la universidad y a la realización de tecnología adaptable a las necesidades. Debido al control que se aplica al sistema de comunicación de RF, la batería que se encarga de alimentar a los dispositivos tendrá una duración mayor, ya que sólo alimentará parte de la circuiteria en estado de reposo y activará a las demás circuiterias a la hora de activarse las lecturas de humedad ya que las mediciones no serán continuas como en el proyecto de tesis de Enrique Cuadras [1]. El sistema de comunicación inalámbrica no sólo se puede aplicar a transductores de humedad sino también a transductores que manejen un rango de medición de 0 a 5 volts, o que puedan adecuarse a esa especificación. Este control permitirá trabajar con un PLC o una PC, abriendo más posibilidades de conexión. Con el software se podrá tener un mejor control de los transductores del sistema, realizando baja, altas y cambios de posiciones de los transductores. 1.4 Objetivo Diseñar una etapa de control para el sistema de comunicación de RF con microcontroladores PIC 16C745, 16F628 y 16F873, además crear una aplicación en Visual Basic para configurar el sistema por medio del puerto USB. 5 1.5 Delimitaciones -Las pruebas se realizarán con un solo transductor debido a que sólo se dispone de uno. -Cuando en la central se disponga de un PLC en vez de una PC, sólo se podrán ingresar 15 transductores como máximo en el sistema de monitoreo, debido a que se dispone sólo de 4 pines para indicar el número (binario) del transductor activado, siendo el cero un valor con el estado en reposo. -En la comunicación con el PLC la salida de información es a través de un conector DB9. -Se utilizarán microcontroladores PIC 16C745, 16F628 y 16F873. -Se utilizará el software Visual basic empresarial versión 6.0. 1.6 Referencias [1].- Hugo Enrique Cuadras Aguilar, Desarrollo de un sistema de comunicación para la transmisión inalámbrica de sensado de humedad. Tesis, México 2003. [2].- Gabriel Enrique Cázarez Enriquez. Tesis en desarrollo, México 2007. II MARCO TEÓRICO 2.1 USB (Universal Serial Bus) 2.1.1 Introducción La información de este capítulo proviene de varios documentos [1],[2],[3],[4]. En esta parte se presenta la idea principal o resumen de la información original, encontradas en los documentos fuentes. Esta tecnología fue desarrollada para incrementar el ancho de banda y el número de dispositivos que pueden ser conectados, así como una operación de usuario amigable, comunicación robusta y bajo costo. Los primeros promotores de USB fueron Intel, Compaq, Microsoft y NEC. La topología del bus es de tipo estrella, con el HOST en el nivel más alto, los HUBS en el medio y los diferentes dispositivos al final. Figura 2.1 Topología. 7 Hoy en día se encuentran dos especificaciones para este estándar, la revisión 1.1 y la 2.0. En las cuales se hablan de distintas velocidades, en la revisión 1.1 se manejan las velocidades baja-velocidad (low-speed) y velocidad-completa (fullspeed), las mismas que proporcionan velocidades de 1.5 y 12 mbps y en la especificación 2.0 alta-velocidad (high-speed) hasta 480 mbps. 2.1.2 Conexiones El cable que se utiliza para interconectar los dispositivos y hubs hacia el host contiene 4 hilos por el cuál 2 de ellos (d+ y d-) se transmiten los datos y los 2 restantes proporciona al dispositivo (si éste lo desea) una alimentación de 5 volts. Figura 2.2 Cable. En los extremos del cable se encuentran los 2 diferentes tipos de conectores, tipo A y tipo B. el tipo B es conector trama de subida (up-stream) y en el A es trama de bajada (down-stream), eso significa que lo dispositivos deberán tener conectores receptor trama de subida y el host un receptor trama de bajada. Figura 2.3 (Conector a, Conector b, Receptor a y Receptor b). Figura 2.4 Pines correspondientes (1= Vbus, 2 = d-, 3 = d+, 4 = GND). 8 2.1.3 Comunicación La comunicación que se realiza entre el host y el dispositivo se dividen en capas (como en el modelo OSI), esto es, que cada capa del host se comunica con su correspondiente capa en lado del dispositivo. Figura 2.5 Flujo de comunicación (lógica y física). La capa de funciones en el host, la compone el software cliente del dispositivo, y éste se encarga de conectarse con una interfaz en el dispositivo por medio de conexiones virtuales llamadas pipas (PIPES), cuando el software comunica los buffers de información y obtiene uno o varios puertos virtuales en el dispositivo llamados endpoints se dice que se ha conectado una pipa. En la capa lógica del host residen los controladores (drivers) y es aquí donde se asigna una pipa especial llamada PIPE0, default PIPE o control PIPE que es conectada a un endpoint especial llamado endpoint0 en el dispositivo. Los controladores sirven para informar al sistema operativo aspectos físicos del bus USB, el software cliente será el encargado de comunicarse con el controlador. Específicamente también se encuentra en esta capa el USB driver (USBD) que proporciona interfaz entre esta capa y el software cliente. 9 Otro controlador que se encuentra aquí es el host controler driver (HCD), proporciona interfaz entre la capa lógica del host y el concentrador que se encuentra en la capa bus. En la última capa del host está el concentrador de USB, éste se encarga de enviar físicamente el dato hacia el dispositivo. Existen dos modos de operación en las pipas: trama (stream) y mensaje (message). El modo trama no tiene una imposición de estructura definida, el flujo de paquetes es de una sola dirección. En el modo mensaje tienen asociadas con ellas las necesidades de ancho de banda, tipo de transferencia y características de los puertos virtuales del dispositivo (endpoints) donde además el flujo es bidireccional. Como se mencionó anteriormente, los endpoints son puertos virtuales que residen en el dispositivo, poseen un cierto número y son únicos. Estos sirven para transmitir y recibir datos en una sola dirección, por lo que si se requiere de una comunicación bidireccional se requiere de dos endpoints. Estos puertos son utilizados para una ruta de comunicación más avanzada como los son las pipas. Figura 2.6 Conexión lógica. 10 2.1.4 Paquetes El host siempre inicializa la transacción, y solamente un dispositivo es seleccionado por el host para comunicarse sobre el bus. Un dispositivo tiene permiso para hablar sobre el bus cuando éste recibe un token. Un token es un paquete especial que se utiliza para el control del bus, indicando el tipo y la dirección de la transacción, siendo el host el único capaz de generar un token. Así como el token existen otros tipos de paquetes. Tabla 2.1 Tipos de paquetes. Paquetes Token Data Handshake Especial Tipos Out, In, Sof y Setup. Data0 y Data1. Ack, Nak y Stall. Pre. Tipo SOF.- El inicio de trama (Start of frame) sirve para delimitar la trama y marcar un punto de inicio, como un mecanismo de sincronización. El host genera estos paquetes y el dispositivo deberá ser capaz de detectar un SOF cada 1 milisegundo en el bus, si no ocurre en el siguiente periodo de tiempo, se presenta un error. Este paquete no recibe respuesta alguna por parte de los dispositivos ni tampoco hay garantía que éstos los reciban, es responsabilidad de los dispositivos detectar la pérdida de estos paquetes. Tipo SETUP.- Se utiliza para que el host envíe información para la pipa de control. Tipo OUT.- Describen transacciones del host hacia funciones del dispositivo. Tipo IN.- Describen transacciones de las funciones del dispositivo hacia el host. 11 Los paquetes de datos sirven para lo que su nombre indica, se encargan de enviar los datos. Se dividen en 2 tipos: data0 y data1, estos tipos son semejantes, sólo que poseen una pequeña diferencia en el campo PID (los campos se explican en la sección 2.1.10). Tipo data0.- Paquete de datos par Tipo data1.- Paquetes de datos impar Los paquetes handshake son utilizados para indicar el estado de la transacción, proporciona al host la satisfactoria o fallo del envío de una transacción, da un control de flujo y reporta las condiciones de parada (stall). Se encuentran en las transacciones donde se permita el control de flujo. Tipo ACK.- Significa que el dato fue recibido sin errores. Tipo NAK.- Significa que el dispositivo no puede recibir datos del host, y que es una condición temporal, o lo que es lo mismo, el dato no fué recibido. Tipo STALL.- Significa que el dispositivo no puede recibir ni transmitir datos hacia el host, y que el host deberá ayudar al dispositivo a rectificar la situación. Los paquetes especiales se utilizan como preámbulos, habilita el tráfico de bus trama de bajada para dispositivos de baja velocidad. 2.1.5 Transacciones o transferencias Las transacciones sobre el bus son gobernadas por el protocolo. Un protocolo es simplemente el orden en el cual los paquetes satisfacen la transacción. Cada transacción consiste en el intercambio de 3 paquetes. 12 Figura 2.7 Transacciones (ejemplo). En las velocidades velocidad-completa y alta-velocidad soportan 4 tipos de transferencias: bulto (bulk), interrupción (interrupt), isócrono (isochronous) y control. Mientras que la velocidad baja-velocidad soporta 2 tipos: interrupción y control. El tipo isócrono.- Garantiza el tiempo pero no la integridad de la transferencia, no hay retransmisión ni paquetes de handshaking. En este tipo una porción del ancho de banda es reservado para la requisición de los dispositivos (si el ancho de banda del bus lo permite). Este tipo es usado para transmisiones multimedia, donde la pérdida de unos cuantos paquetes no es crítica, ya que los sentidos humanos no serán capaz de detectarlo. El tipo de pipa a utilizar en esta transferencia deberá ser de modo trama. Figura 2.8 Ancho de banda. 13 El tipo bulto.- Contrario al isócrono garantiza la integridad de la transferencia pero no el tiempo que le tome hacerlo, garantiza una tasa de transferencia pero se espera hasta que se presenten las condiciones en el bus. Este tipo se utiliza para transferencias de datos que no sean críticas. El tipo de pipa deberá ser del modo trama. El tipo control.- Es usado para reportar el estado y configuración de los dispositivos, esto es, que el host lea información, asigne direcciones y configuraciones, así como otras funciones. Para esto se utiliza el default PIPE y no es necesario crear otra pipa para el control, si es necesario crear una, se deberá crear una en modo mensaje por que el flujo de la pipa es bidireccional. El tipo interrupción.- Es usado para dispositivos que requieran una revisión periódica para el envío o recepción de pequeñas cantidades de datos. Este tipo no trabaja como una interrupción de un microcontrolador, sino que el host revisa en un periodo de tiempo el bus para que de ese modo se vea como una interrupción. El tipo de pipa de esta transferencia deberá ser del modo trama. Tabla 2.2 Resumen de transferencias. Modo de PIPE Sincronización Handshake Control Mensaje Ninguna Si Isócrono Trama Bus, Software Externo No Usado Interrupción Trama Ninguna Si Bulto Trama Ninguna Si 2.1.6 HUB El hub es otro dispositivo que proporciona un punto de conexión entre el host y los diferentes dispositivos finales, cuenta con funciones especiales como conectividad, proporcionar alimentación a los dispositivos conectados en él y detectar la conexión y desconexión de dispositivos. 14 Los hubs responden a las requisiciones de los controladores y al software cliente del host. También hace que el dispositivo hable solamente con el host y no con otros dispositivos conectados. Lo componen básicamente los receptores donde proporciona conectividad, un repetidor que se encarga de re-transmitir la información y un control que se encargará de las requisiciones, cambiar la conexión del repetidor y detectar los cambios de estados de si mismo. Cuando el hub detecta un SOP (start of packet) en un receptor tipo A, los otros receptores tipo A son cerrados, esto asegura que no cambie nada en el hub hasta que el paquete se halla enviado (ver figura 2.9). Figura 2.9 Flujo de información en el hub. Cuando se detecta un SOP en un receptor tipo B, el hub estabiliza conectividad con todos los receptores tipo A válidos, mandando los paquetes como una difusión (broadcast). Figura 2.10 El host cuenta con un hub integrado llamado root hub. 15 2.1.7 Descriptores (Descriptors) Los descriptores son una estructura de datos que contiene información como: tamaño máximo de paquete del endpoint0, número de configuraciones que el dispositivo soporta, y otras informaciones básicas del dispositivo. Se encuentran divididos en 2 grupos: estandarizados (Standard) y clases específicas (classespecific). Los estandarizados son los requeridos por todos los dispositivos HID (human interface device), y lo componen los siguientes descriptores: dispositivo (Device), configuración (Configuration), interfaz (Interface), Endpoint y cadena (String). Los descriptores de clase específica son usados para los dispositivos donde su clase (class) sea HID, este grupo contiene los descriptores HID, reporte (report ) y descriptores físicos (physical descriptors). Algunos descriptores son opcionales. Descriptor dispositivo.- Su información es usado en el proceso de enumeración del dispositivo, en este proceso, se compara la información con los controladores en el host, y esto ayuda al sistema operativo a seleccionar el controlador. Descriptor configuración.- Proporciona características de la alimentación que se proporciona al dispositivo. Descriptor interfaz.- Indica el tipo de protocolo a usar, en caso de un dispositivo HID. Descriptor Endpoint.- Indica la dirección y el tamaño máximo del endpoint. Descriptor cadena.- Contiene una lista de cadenas en las cuales se mencionan características del dispositivo. La especificación 2.0 menciona que puede tener indexados de varias cadenas. Éste descriptor es opcional. Descriptor HID.- Contiene información acerca de la longitud y tipo de todos los descriptores. 16 Descriptor reporte.- Es usado para indicar información acerca del tipo y formato de los datos que empiezan a ser enviados por el endpoint. Descriptor físico.- Proporciona información acerca de partes específicas o partes del cuerpo humano que están activando uno o varios controles, este descriptor es opcional. 2.1.8 Clases (class) y Subclases (subclass) Cuando un grupo de dispositivos comparten funciones similares, entran a un grupo llamado clases. Por ejemplo, todos los ratones envían el movimiento y los clicks, todas las impresoras reciben e imprimen el dato y envían el estado de la impresión. Las clases hacen más fácil escribir un controlador y un firmware, porque trabajan con atributos definidos. Cuando un dispositivo tiene funciones adicionales, el device-vendor, puede proveer un filtro para el controlador, que agrega capacidades al controlador del sistema operativo y es más fácil que escribir un controlador desde cero. A continuación se muestran algunos ejemplos de clases y subclases. Dispositivos de audio.- Para los dispositivos que envían audio. Class = 01h. Subclass: 01= audio control, 02 = audio streaming, 03 = midi streaming. Dispositivos chip/smart cart interface.- Tarjetas para transferir pequeñas cantidades de datos y acceso fácil. Class = 0Bh. Dispositivos de comunicación.- Modems y tarjetas de red. Este grupo contiene modems, teléfonos analógicos, terminal de adaptadores ISDN, teléfonos digitales, ADSL modems, cable modems, 10 base t ethernet adapters y hubs. Class=02h. Para esta clase se necesita especificar un protocolo. 17 Tabla 2.3 Subclases para la clase = 02h Código 00h Subclases Direct line control model 02h Abstract control model 03h 04h 05h 06h 07h 08-0Bh 0Ch 0D-7Fh 80-FEh Telephone control model Miltichannel control model CAPI control model Ethernet networking Control model ATM networking WMC models Ethernet emulation model (EEM) Reservado Reservado Aplicación Teléfono MODEM con el host enviando cualquier compresión de datos y corrección de error. El host o el dispositivo deberán de proveer modulación y demodulación del dato del MODEM. Teléfono MODEM con el dispositivo enviando cualquier compresión de datos, corrección de error, modulación y demodulación del dato del MODEM. Teléfono. Dispositivos ISDN con múltiple, y canales multiplexados. Dispositivos ISDN con soporte de comandos commond-ISDN-API (CAPI) y mensajes. Dispositivos que cambian datos ethernet framed. Dispositivos ATM. Comunicaciones inalámbricas móviles. Futuros usos. Futuros usos. Vendor específic. Tabla 2.4 Protocolo para la clase = 02h Código 00h 01h 02-06h 07-F0h FFh Protocolo La clase no especifica protocolo. Comandos AT. (Especificado en ITU v.250). Comandos AT. (Para dispositivos WMC). Futuros usos. Vendor especific. Dispositivos de control de seguridad.- Muestra el camino para contener nuestro propio control de acceso hacia los archivos. Puede ser por dos métodos. Autorización básica o transmisión digital de protección de contenido. Class = 0Dh. 18 Dispositivos con actualización de firmware.- Define un protocolo donde habilita al host para enviar secciones de código, para el firmware hacia el dispositivo. Recibiendo una señal conocida como (firmware upgrate), el dispositivo vuelve a realizar el proceso de enumeración (que será explicado más adelante), usando este nuevo firmware o sección del firmware. Para indicar un dispositivo de que es de este tipo se usan los siguientes valores: Class = FEh indica que es una clase muy específica. Subclass = 01 indica que es del tipo update firmware. Dispositivos HID.- Se describen en la sección 2.1.17. Class = 03h. Dispositivos puentes IRDA.- (infrared data association) define el hardware y el protocolo para el intercambio de datos sobre distancias cortas vía infrarrojo. Class = FEh indica que es de clase específica. Subclass = 02h índica IRDA brige. Dispositivos de memoria masiva.- Transfieren archivos (ambas direcciones) a dispositivos como floppys, discos duros, cd, dvd, flash. Class = 08h. Tabla 2.5 Subclases para la clase = 08h. Código 02h 03h 04h 05h 06h Subclases Dispositivos ATAPI/CD/DVD. Dispositivos QIC-157. Interfaz USB floppy (UFI). ATAPI removible media. Generis SCSI media. Tabla 2.6 Protocolo para la clase = 08h. Código 00h 01h 50h Protocolo CBI con comandos de transferencias de interrupción completas. CBI sin comandos. Transferencias BULK solamente. 19 Dispositivos impresoras.- Dispositivos para impresión de documentos. Class = 07h. Tabla 2.7 Protocolo para la clase = 09h. Código 00h 01h 03h Protocolo Unidireccional. Bidireccional. IEEE 1284.4 compatible bidireccional. Dispositivos Still image capture.- (cámaras y scanners). Dispositivos para capturar imágenes en video y en forma estática. Class = 06h. Subclase = 01h interfaz de Figura, protocol = 02h función still image capture. Dispositivos para test y mediciones.- (USBTMC) dispositivos de medición que no necesitan garantizar el tiempo de medición. Class = FEh indica clase específica, Subclass = 03h indica test y medición. Dispositivos de video.- (grabadoras de video, webcams y demás) la documentación para este tipo de dispositivos está en construcción todavía. Para indicar un dispositivo de este tipo Class = 0Eh. 2.1.9 Enumeración y Estados del dispositivo Cuando un dispositivo se conecta por primera vez al host, ocurre el proceso “enumeración”, y que se describirá a continuación: 1.- El usuario conecta el dispositivo.- El sistema alimenta al dispositivo y éste entra en el estado de powered (alimentado). 2.- El hub detecta el dispositivo.- El hub monitorea los voltajes en las líneas de señal de cada puerto USB, El hub tiene resistencias de pull up de 15000 ohms y el dispositivo de 1500 ohms. Las resistencias del dispositivo cambian la línea en estado alto permitiendo al hub detectar que fué conectado un dispositivo. 20 3.- El host conoce el nuevo dispositivo.- Cuando el hub detecta un evento éste lo reporta al host, esto se realiza cuando el host envía la requisición get_report_status. 4.- El hub detecta la velocidad del dispositivo.- En la especificación 1.x dice que se puede detectar la velocidad después del reset, pero en la especificación 2.0 dice que los dispositivos de alta velocidad deben detectarse antes del reset. Antes de que el host mande un reset al dispositivo, el hub detecta la especificación examinando el voltaje de las líneas de señal. El hub envía una respuesta al host en una requisición get_report_status. Ahora el dispositivo necesita saber si el host soporta alta velocidad. Para esto, el dispositivo soporta dos estados especiales llamados chirp J y k, en el estado J la línea d+ es usado solamente, en el estado K la línea d- es usado solamente, estos estados son cambios de niveles en la línea. Durante el reset, si el dispositivo soporta una alta velocidad envía un estado chirp K, el hub detecta el estado y responde con una serie de varias alteraciones de estados chirps K y J. Cuando el dispositivo detecta el patrón KJKJKJ, éste quita las resistencias de pull ups para la velocidad completa y cambia a comunicación de alta velocidad. Si el hub no responde a los estados K del dispositivo, el dispositivo cambia a comunicación velocidad completa, por lo que los dispositivos de alta velocidad deberán de comunicarse también en velocidad completa, que es la velocidad más alta en la especificación 1.x. Esto es si el host no soporta la especificación 2.0, mínimo deberá soportar la especificación 1.x. 5.- El host envía un reset al dispositivo.- El host envía un set_port_feature para resetear al puerto, la condición de reset pone las líneas del dispositivo (en 10 milisegundos) en un estado especial, las líneas d+ y d- están en lógica baja, el hub envía el reset solo al dispositivo nuevo, los demás dispositivos no detectarán el reset. 6.- El hub estabiliza una ruta de señal entre el dispositivo y el bus.- El host verifica que el dispositivo se encuentre en estado de reset enviando un get_report_status, un bit del dato regresado indica que el dispositivo esta ocupado en el estado de reset, si es necesario el host envía el get_report_status hasta que el dispositivo esté en 21 estado de reset, cuando el hub quita el reset al dispositivo, éste está en estado de default. Los registros de USB del dispositivo están listos para responder a las transferencias de control sobre la pipa de control o default PIPE conectado hacia el endpoint0. Ahora el dispositivo puede comunicarse con el host usando la dirección default address 00h y el dispositivo puede obtener hasta 100 miliamperes en el bus. El host solamente asigna un default address a la vez. 7.- Tamaño máximo del default PIPE.- El host envía un get_descriptor para conocer este dato del dispositivo, el octavo byte del descriptor dispositivo contiene el tamaño máximo del paquete, soportado por endpoint0. 8.- El host asigna una dirección.- el host asigna una dirección única enviando un set_address, el dispositivo lo recibe y envía un ACK y cambia a su nueva dirección, cambiando así, al estado address. Desde aquí, todas las comunicaciones se realizan con la nueva dirección. La dirección es válida hasta que el dispositivo es desconectado, esté en estado de reset o se caiga del sistema. En la próxima enumeración el dispositivo será asignado en una dirección diferente. 9.- El host conoce las habilidades del dispositivo.- El host envía requisiciones como: get_device_descriptor, get_configuration_descriptor, get_report_descriptor y get_string_descriptor a la nueva dirección. El dispositivo enviará la información en el siguiente orden: (dispositivo, configuración, interfaz, HID, endpoint en caso de de ser un HID). En caso de 2 interfaces el orden es el siguiente: dispositivo, configuración, interfaz1, HID1, endpoint1, interfaz2, HID2 y endpoint2. 22 Figura 2.11 Descriptores para una y dos interfaces. 10.- El host asigna y carga el controlador del dispositivo. 11.- El driver selecciona una configuración.- Los controladores requieren una configuración enviando un set_configuration con el número de configuración (para múltiples configuraciones), si hay varios, el controlador selecciona uno, si no se especifica selecciona uno por default. El dispositivo recibe la requisición y cambia al estado configurated, las interfaces del dispositivo son habilitadas y el dispositivo está listo para usarse. El estado attached ocurre si el hub no provee alimentación en el puerto o detecta una sobre corriente o simplemente que el host quite la alimentación. El estado suspendido (suspended) significa que el dispositivo no tiene actividad incluyendo SOFs, en este estado deberán consumir menos potencia y dispositivos configurados y no configurados deberán soportar este estado. para 23 Un hub normal se enumera exactamente igual a un dispositivo, y si tiene dispositivos conectados, los enumera una vez que el hub halla sido enumerado y reporte al host sobre sus conexiones. Cuando un dispositivo es desconectado, el hub cambia el reporte del estado, y cuando el host envía un get_report_status sabrá que se a desconectado cierto dispositivo. Cambiando así su mapa interno. El sistema operativo da de baja al dispositivo del administrador de dispositivos (device manager) y libera la dirección para que pueda ser usado por otro dispositivo. 2.1.10 Protocolo, Tramas y Campos de bits Los paquetes que se utilizan en las transferencias se dividen en secciones básicas llamadas campos donde los bits son enviados desde el menos significativo hasta el más significativo. Campo SYNC.- todos los paquetes inician con el campo de sincronización, el cuál es una secuencia codificada que genera la máxima densidad de transición. Éste campo aparece en el bus como un IDLE seguido por la cadena binaria “KJKJKJKK” esto es una codificación NRZI. Esto es usado por la circuiteria de entrada de dato y el reloj local como mecanismo de sincronización. Campo PID.- Llega después del campo SYNC. Éste le indica al dispositivo que hacer con el paquete y contiene una longitud de 8 bits, además, el campo PID se divide en dos subcampos que son tipo y checado. El subcampo tipo tiene la identificación del paquete, el subcampo checado es el complemento del subcampo tipo y es usado para comprobar la integridad del paquete, cuando resulta erróneo se ignora el resto del paquete. La función de los endpoints son direccionadas utilizando 2 campos: el campo ADDRESS y el campo ENDPOINT. Una función necesita codificar totalmente ambos campos. 24 Campo ADDRESS.- Este campo especifica la función y es el origen o destino del paquete dependiendo del valor que tenga en el campo PID (IN, OUT y SETUP solo estos tipos). Contiene una longitud de 7 bits por lo que puede tener hasta 127 direcciones válidas. Campo ENDPOINT.- Este campo permite más flexibilidad de direccionamiento de funciones en el cual más de un endpoint es requerido. Los números de los endpoint son funciones específicas y son usados sólo para los tipos IN, OUT y SETUP. Campo NUMBER FRAME.- Es de 11 bits de longitud. Representa un número que es incrementado por el host por cada trama (frame), regresa al valor de cero cuando alcanza el valor de 7FFh y son enviados solamente en los tokens SOF en el inicio de cada trama. Campo DATA.- El rango de este campo deberá ser de cero a 1023 bytes. Campo CRC.- Con una longitud de 5 bits, es usado para proteger la integridad de los campos que no sean PID en los paquetes tokens y datos. Los bits de este campo ayudan a un algoritmo a detectar cualquier error. El CRC cubre los campos ADDRESS y ENDPOINT de los tokens IN, OUT y SETUP. El generador polynomial es: G(x) = x5 + x2 + 1. Y en caso de un paquete de dato, el generador es el siguiente: G(x) = x16 + x15 + x2 + 1. y cuya longitud del campo CRC es de 16 bits. 2.1.11 Formato de paquetes El formato de los tokens (IN, OUT y SETUP) consiste en los campos PID – ADDRESS – ENDPOINT – CRC de 5 bits. 25 Figura 2.12 Formato de los tokens (IN, OUT y SETUP). El formato para el token SOF lo forman los campos PID – Frame Number – CRC de 5 bits. Figura 2.13 Formato del token SOF. El formato del paquete de datos lo forman los campos PID – DATA – CRC de 16 bits. Figura 2.14 Formato del paquete de datos. El formato de un paquete handshake lo compone únicamente el campo PID. Figura 2.15 Token handshake. 26 2.1.12 Formato de las transferencias Figura 2.16 Transferencia isócrono y transferencia control. Figura 2.17 Transferencia bulto (bulk). 27 Figura 2.18 Transferencia interrupción. 2.1.13 Requisiciones Las requisiciones son los datos estructurados que el host envía al hub para conocer o asignar funciones a los dispositivos conectados al hub, los cuales también se dividen en secciones básicas llamadas campos. Campo bmrequestType.- Este campo identifica las características de una requisición específica, en particular identifica la dirección de la transferencia y es ignorado si el valor del campo wLength es cero. Campo bRequest.- Especifica la requisición, los bits del campo bmRequestType modifica el significado de este campo. Campo wValue.- El contenido este campo varía de acuerdo a la requisición, esto es para pasar un parámetro al dispositivo. Campo wIndex.- El contenido de este campo también varía de acuerdo a la requisición y pasa un parámetro al dispositivo pero específicamente a un endpoint o una interfaz. 28 Figura 2.19 Formato para un endpoint específicamente. Figura 2.20 Formato para una interfaz específicamente. Campo wLength.- Indica la longitud del dato transferido, en una transferencia de entrada el dispositivo no deberá de transmitir un dato con una longitud superior al indicado en este campo, en una transferencia de salida deberá transferir la cantidad exacta de datos indicado por este campo. Tabla 2.8 Requisiciones Standard y sus Códigos. bRequest Value bmRequest type 10000OOOB 10000OO1B 10000 O1OB wValue wIndex wLength Zero Zero Interface Endpoint two 00000OOOB 00000OO1B 00000O1OB Feature Selector Zero Interface Endpoint Zero None 00000OOOB 00000OO1B 00000O1OB Feature Selector Zero Interface Endpoint Zero None Device Adress Descriptor Type and Index Descriptor Type and Index Zero Zero Zero or Language ID Zero or Language ID Zero Zero Descriptor Length None Configuration Value Zero Zero Zero Interface One Interface Zero Endpoint Two Get Status 0 Clear Feature 1 Reserved 2 Set Feature 3 Reserved Set Adress 4 5 000000OOB Get Descriptor 6 100000OOB Set Descriptor 7 000000OOB Get Configuration 8 100000OOB Set Configuration 9 000000OOB Get Interface 10 100000 O1B Set Interface 11 000000 O1B Zinc Frame 12 1000001OB Alternate Setting Zero Data Device Interface or Endpoint Status Descriptor Descriptor Length Descriptor One Configuration Value None Alternate Interface None Frame Number 29 2.1.14 Formato de los descriptores (Descriptors) Tabla 2.9 Device descriptor. Byte 0 1 Campo bLength bDescriptorType N. Bytes 1 1 Valor Número Constante 2 bcdUSB 2 BCD 4 bDeviceClass 1 Class 5 bDeviceSubClass 1 Subclass 6 bDeviceProtocol 1 Protocolo 7 bMaxPacketSize0 1 Número 8 10 idVendor idProduct 2 2 ID ID 12 14 bcdDevice iManufacturer 2 1 BCD Index 15 iProduct 1 Index 16 iSerialNumber 1 Index 17 bNumConfigurations 1 Número Byte 0 1 2 Campo bLength bDescriptorType bSTRING ó wLANGID[n] Descripción Tamaño del descriptor en bytes. Tipo del descriptor (1 = device descriptor). Especificación (1.x o 2.0) en BCD. Si este campo es cero, cada interfaz contiene una configuración específica y su propia información class y las distintas interfaces operan independientemente. Si contiene un valor entre 1 y FEh Las interfaces no operan independientemente. Si es FFh el class es especificado por el vendor. Este campo es afectado por el anterior. (0-FFh). Identifica el protocolo. Si está a cero no utiliza protocolo class específico, si es FFh el protocolo es especificado por el vendor. Tamaño máximo del paquete por el Endpoint0. Solamente 8, 16, 32 o 64 son números válidos. ID del vendor (asignado por el USB). ID del producto (asignado por la manufacturera). Número del dispositivo. (En BCD) Index del string descriptor describiendo la manofacturera. Index del string descriptor describiendo el producto. Index del string descriptor describiendo el número serial del producto. Número de configuraciones posibles Tabla 2.10 String descriptor. N. Byte Descripción 1 Tamaño del descriptor en bytes. 1 Tipo del descriptor 03 = String descriptor. Número Una cadena en formato unicode. Número Un arreglo de uno o más códigos de lenguajes. 30 Tabla 2.11 Configuration descriptor. Byte 0 1 Campo bLength bDescriptorType N. Bytes 1 1 Valor Número Constante 2 wTotalLength 2 Número 4 bNumInterfaces 1 Número 5 bConfigurationValue 1 Número 6 iConfiguration 1 Index 7 bmAttributes 1 Bitmap 8 MaxPower 1 mA Descripción Tamaño del descriptor en bytes. Tipo del descriptor (2 = configuration descriptor). Longitud total de datos regresados por esta configuración. Incluyendo los descriptors interface y endpoint, además las clases y especificaciones vendors. Número de interfaces de esta configuración. El valor utilizado como argumento en la requisición SetConfiguration() para seleccionar esta configuración. Index del string descriptor describiendo esta configuración. Características de configuración. D7: Reservado (puesto a uno). D6: Alimentado por si mismo. D5: Remote Wake up. D4-D0: reservado (puesto a cero). Poder máximo de consumo. Cada unidad representa 2 mA de alimentación. Por ejemplo 50= 100mA. Tabla 2.12 Interface descriptor. Byte 0 1 Campo bLength bDescriptorType N. Bytes 1 1 Valor Número Constante 2 3 bInterfaceNumber bAlternateSetting 1 1 Número Número 4 bNumEndpoints 1 Número 5 bInterfaceClass 1 Class 6 bInterfaceSubClass 1 SubClass 7 bInterfaceProtocol 1 Protocol 8 iInterface 1 Index Descripción Tamaño del descriptor en bytes. Tipo del descriptor (4 = interface descriptor). Número de interfaz. Valor usado para seleccionar asignaciones alternadas para la interfaz identificada en el campo prioridad. Número de endpoints usados en esta interfaz excluyendo el endpoint0, si este valor es cero, esta interfaz sólo usa el default PIPE. Código para clase del dispositivo. Por ejemplo 03h es un dispositivo HID (ver sección 2.1.17). Indica si el dispositivo soporta una interfaz de buteo (boot interface) (ver sección 2.1.17). Indica el protocolo a usar en caso de usar una interfaz de buteo (ver sección 2.1.17). Index del string descriptor describiendo esta interfaz. 31 Tabla 2.13 Hid descriptor. Byte 0 1 2 4 Campo bLength bDescriptorType bcdHID bCountryCode N. Bytes 1 1 2 1 5 bNumDescriptors 1 6 bDescriptorType 1 7 9 wDescriptorLength bDescriptorType 2 1 10 wDescriptorLength 2 Descripción Tamaño del descriptor en bytes. Tipo del descriptor (21 = HID descriptor) (29 = HUB). Especificación del HID (revisión). Número que identifica el país para localizar el hardware. Número de class descriptors que son subordinados a este descriptor. Tipo de descriptor que está subordinado al HID class descriptor (report = 22 o físico = 23). Longitud total del report descriptor. Tipo de descriptor (opcional). para dispositivos con mas de un descriptor. Longitud total del descriptor (opcional). Para dispositivos con más de un descriptor. Deberá ser seguido por un adicional wDescriptorType y un wDescriptorLength. Tabla 2.14 Endpoint descriptor. Bytes 0 1 Campo bLength bDescriptorType N. Bytes 1 1 Valor Número Constante 2 bEndpointAddress 1 Endpoint 3 bmAttributes 1 Bitmap 4 wMaxPacketSize 2 Número 6 bInterval 1 Número Descripción Tamaño del descriptor en bytes. Tipo del descriptor (5 = endpoint descriptor). B3-B0: número de endpoint. B6-B4: reservado. B7: dirección, ignorado por los endpoints de control. 0 = endpoint de salida. 1 = endpoint de entrada. Este campo describe los atributos de los endpoints, cuando esté configurado usando el campo bConfigurationvalue. B1-B0: tipo de transferencia. 00 = control 01 = isócrono 10 = bulto 11 = interrupción Los demás bits son reservados. Máximo tamaño de paquete de este endpoint capaz de enviar o recibir cuando esta configuración es seleccionado. Para endpoints isócronos este valor es usado para reservar el tiempo del bus en la agenda. Intervalo de poleo de endpoints para tranferencias de datos. Expresado en milisegundos. Este campo es ignorado para los endpoints bulto y control. Para el endpoint isócrono este campo deberá ser cero. Y para el endpoint interrupción el rango deberá de ser de 1 a 255. 32 2.1.15 Descriptor reporte (Report descriptor) Es un arreglo de bytes o un complejo ordenamiento de ítems con el cuál se asignan funciones y unidades. La ventaja de un descriptor complejo es que el dispositivo puede proveer información acerca del dato enviado y lo que se espera recibir. El descriptor puede especificar el uso de los valores y que unidades aplicar a los datos recibidos. La ventaja para la aplicación en el host es que conoce el tipo, tamaño y el orden de los datos en un reporte, como deberá interpretarlos o ejecutarlos. Por ejemplo el reporte de un teclado, la aplicación deberá interpretar el caracter si se encuentra en un procesador de texto. Un descriptor reporte contiene uno o más controles e ítems de datos, que describen valores para ser transferidos en uno o más reportes. Un control puede ser un botón, un switch u otra entidad física que opera o regula un aspecto de un dispositivo. Se han publicado varios documentos que definen los valores que los reportes deben de tener, los diferentes dispositivos se han agrupado en: controles generales de escritorio (general desktop controls), monitoreo (monitor), alimentación (power) y dispositivos de punto de ventas (point of sale devices). Este descriptor se transporta en ítems que se pueden ser en 2 formatos: short y long. El tipo short lo compone un byte de prefijo y dos bytes de dato opcionales (ver figura 2.21). El tipo long lo compone el mismo prefijo, un byte para el tamaño del dato y otro byte para el tag, seguido de hasta 255 bytes de datos opcionales (ver figura 2.22). Figura 2.21 ítem Short. Figura 2.22 ítem Long. 33 El tipo long no está definido en la especificación 1.1 y es reservado para usos futuros. Utiliza múltiples bytes para almacenar alguna información. El prefijo con un valor de FEh identifica el ítem como un long. El prefijo de un byte del short ítem describe: tamaño, tipo y tag. Tabla 2.15 Prefijo de un byte del short ítem. Número de bit 0 1 2 3 4 5 6 7 Contenido Descripción Size Número de bytes en el item. Type Alcance del Item : main, global o local. Tag Valor numérico que indica la Función del item. =>Donde los valores de size son 00 = 0 bytes, 01= 1 byte, 10 = 2 bytes, 11 = 4 bytes. =>Donde los valores de Type son 00 = Main, 01= Global, 10 = Local. Main define o agrupa campos de datos en el descriptor. Engloba 5 items principales: input, output, feature collection y end collection. Global describe los datos. Local define características de controles individuales de datos. =>Donde Tag indica funciones de los ítems. La parte alta del byte del prefijo indica si es un in, out o feature item. La parte baja indica si necesita 1 o 2 bytes para transportar el dato. Seguido del prefijo lo siguen 9 bits que describen el dato del ítem (ver tabla 2.16). 34 Tabla 2.16 Mapa de bits. Prefijo main item Input (100000nn, donde nn = al número de bytes de datos seguido por el prefijo). Usa 81h para 1 byte de item de dato o 82h para 2 bytes de item de dato. Output (100100nn, donde nn = al número de bytes de datos seguido por el prefijo). Usa 91h para 1 byte de item de dato o 92h para 2 bytes de item de dato. Feature (101100nn, donde nn = al número de bytes de datos seguido por el prefijo). Usa B1h para 1 byte de item de dato o B2h para 2 bytes de item de dato. N. de bit 0 1 2 3 4 5 6 7 8 9-31 0 1 2 3 4 5 6 7 8 9-31 0 1 2 3 4 5 6 7 8 9-31 Si el bit = 0 Data Array Absolute No wrap Linear Preferred state No null position Reserved Bit field Reserved Data Array Absolute No wrap Linear Preferred state No null position Non volatile Bit field Reserved Data Array Absolute No wrap Linear Preferred state No null position Non volatile Bit field Reserved si el bit = 1 Constant Variable Ralative Wrap Non – linear No prefered s. Null state Buffered bytes Constant Variable Ralative Wrap Non – linear No prefered s. Null state Volatile Buffered bytes Constant Variable Ralative Wrap Non – linear No prefered s. Null state Volatile Buffered bytes -Data-Constant. Data significa que el dato es modificable, constant significa que es sólo de lectura. -Array-Variable. Especifica si el dato reporta el estado de cada control o solo los activados. Reportar solo los controles activados compacta más el reporte, para dispositivos como teclados donde son muchos controles (teclas), pueden ser activados solo uno o pocos controles a la vez. Si un control (keypad) tiene 8 botones. Configurar en variable significa que el reporte del control deberá contener un bit para cada botón, en el tamaño del report deberá ser de 1 bit, el contador del report de 8 y la cantidad de dato a enviar de 8 bits. Configurar en arreglo (array) significa que cada 35 botón tiene asignado un index, el reporte contiene sólo los indexs de los botones que son activados, y el tamaño del reporte deberá ser de 3 bits debido a los 8 botones, el contador del reporte deberá ser igual al número máximo de botones que puedan ser activadas a la vez, y la cantidad total de datos de 3 bits. Un valor fuera de rango del array significa que ningún botón está activado. -Absolute-Relative. Absoluto significa que el valor está basado en un origen fijo, relativo significa que el dato indica los cambios desde la última lectura. -No wrap-Wrap. Wrap indica que el valor rota de su valor máximo al mínimo y viceversa. Un item no wrap deberá reportar un valor fuera de los límites especificados. Este bit no se aplica para un array de datos. -Linear-Non linear. Linear indica que el dato medido y el valor reportado tienen una relación lineal. No linear los datos del reporte forman una gráfica curva. Este bit no se aplica para un array de datos. -Preferred state-No preferred state. Preferred state indica que un control va a regresar a un estado de reposo cuando el usuario no interactúe con él. En un no preferred state recuerda el último estado en que se encuentra el control. Este bit no se aplica para un array de datos. -No null position-Null state. Null state significa que el control soporta un estado donde el control no esta enviando un dato significativo. Un control indica que está en estado nulo enviando un valor fuera del rango definido por los ítems logical minimum y maximum. Un no null position es que cualquier valor del dato puede ser significativo. Este bit no se aplica para un array de datos. -Non volatile-volatile. Éste bit solo se aplica para reportes de datos output y feature. Volatile significa que el dispositivo puede cambiar el valor por si mismo sin la interacción del host. Non volatile significa que el dispositivo cambia el valor 36 solamente cuando el host requiere un nuevo valor en un reporte. Este bit no se aplica para un array de datos. Un ejemplo para volatile, es que una función del dispositivo se ejecute con un botón en el software del host o con un botón en el dispositivo. -Bit field-Buffered bytes. Bit field significa que cada bit o grupo de bits en un bytes representan una pieza separada de dato y el byte no representa una simple cantidad. Buffered bytes significa que el dato consiste en uno o más bytes. El tamaño del reporte para buffered bytes deberá ser 8, este bit es el 8 si vas a utilizar este bit se necesitan 2 bytes de datos en el ítem. Un input ítem son datos que los dispositivos envían hacia el host y un output ítem del host hacia el dispositivo. Los feature ítems son usados típicamente en la información que el host envía hacia el dispositivo, esto habilita al host para leer feature ítems del dispositivo. Todos los reportes pueden contener los ítems collection y end collection. Que sirven para agrupar ítems relacionados. Tabla 2.17 Collections. Prefijo main ítem Valor 00h 01h Collection (A1h) 02h 03-7Fh 80-FFh End Collection (C0h) Ninguno Descripción Physical. Aplication. Logical. Reserved. Vendor definido. Cierra una collection. Aplication contiene ítems que tiene un propósito en común o que juntos tienen una simple función. Physical contiene ítems que representan datos en un simple punto geométrico. Para dispositivo que colecciona una variedad de sensores leyendo desde múltiples direcciones agrupando el dato para cada dirección en una colección physical, por ejemplo un ratón. Logical forma una estructura de datos que consiste en ítems de diferentes tipos. Todos los main ítems que se encuentren dentro de los item collection y end collection forman parte de la misma colección, donde cada colección 37 deberá tener el tag usage, que se describirá más delante de esta lectura. Un colection superior es un colection que no está jerarquizado con los otros colections. Un interfaz HID puede tener más de un colection superior, cada colection superior significaría un diferente HID. A diferencia de los HIDs con interfaces separados, éstos comparten los endpoints de interrupción. Si el reporte contiene un desconocido vendor o usage tag el host ignora todos los ítems del collection. Los Global ítems identifican reportes y describen los datos en ellos incluyendo características como la función de los datos, valores máximos y mínimos permitidos, tamaño y número del report item. Un ítem Global se aplica a cada uno de los ítems que lo siguen hasta encontrar un nuevo ítem global. Los diferentes ítems Global se muestran en la siguiente tabla. Tabla 2.18 ítems globales (nn indica el número de bytes que lo siguen). Global ítem Usage page Logical minimum Valor 000001nn 000101nn Logical maximum 001001nn Physical minimum 001101nn Physical maximum Unit exponent Unit Report size Report ID Report count Push 010001nn Pop 101101nn Reserved 110001nn to 111101nn 010101nn 011001nn 011101nn 100001nn 100101nn 101001nn Descripción Especifica el usage o función del dato. El valor más pequeño que el ítem va a reportar. El valor más grande que el ítem va a reportar. La lógica mínima expresada en unidades físicas. La lógica máxima expresada en unidades físicas. Unidades de exponente de base 10. Valores de unidad. Tamaño de un campo de bits de un ítem. Prefijo que identifica un report. Número de campos de dato para un ítem. Pone una copia de la tabla de estado del ítem en el snack. Remplaza la tabla de estado del ítem con la última estructura puesta en el stack. Para usos futuros. 38 -Report ID.- Este valor puede identificar un reporte específico. Un HID puede soportar múltiples reportes de algunos tipos, teniendo cada reporte su propio report ID, contenido y formato. No se deberá crear un report ID con el valor de cero. -Usage page. Es un ítem con un valor de 32 bits que identifica la función que el dispositivo realiza. Este usage contiene 2 valores: los 16 bits superiores son un global usage page ítem y los 16 bits inferiores es un local usage ítem. El valor en el local usage ítem es un usage ID. El término usage puede referirse a cualquier valor de 32 bits o al valor local de 16 bits. Para evitar la confusión algunas fuentes utilizan el término extendido usage para referirse a al valor de 32 bits. -Logical minimum y maximum. Definen los límites para los valores de los reportes. Son expresados en unidades lógicas. Por ejemplo si un dispositivo reporta lecturas de hasta 500 miliamperes en unidades de 2 miliamperes, el máximo lógico es 250. Si el bit más significativo del byte más significativo es 1, el valor es negativo, expresado como el complemento de 2. Usando el valor de 1 byte, 00h a 7Fh son valores positivos decimales 0 a 127, y FFh a 80h son los valores negativos decimales -1 a 128. La especificación HID dice que si logical maximum y minimum son positivos, no hay necesidad de signar el bit. Pero causará un error que se puede solucionar usando 2 bytes de valores (ver tabla 14). El item logical maximum es 0x26 para indicar de bytes de datos. Tabla 2.19 Ejemplo de uso de los ítems Logical maximum y minimum. 0x15 0x00 0x25 0xFF erroneo. //Logical minimum. 0x15 0x00 //Logical maximum 0x26 0x00FF correcto. //Logical minimum. //Logical maximum -Physical minimum y maximum. Definen los límites para un valor, cuando es expresado en unidades definido por el tag units. Por ejemplo, valores de 0 a 250 en unidades de 2 miliamperes, el physical minimum es 0 y el physical maximum es 500. La recepción del dispositivo utiliza los límites de valores de physical y logical para obtener el valor en las unidades deseadas. 39 -Unit exponent. Especifica el exponente de base 10 que se aplicará al valor obtenido después de usar los límites logical y physical. El exponente puede ranquear valores desde -8 hasta +7. Un valor de cero causa que el valor sea el mismo. Por ejemplo, si el valor obtenido es 1234 y el unit exponent es 0Eh, el valor final es 12.34. A continuación se muestran los valores posibles. Tabla 2.20 Valores para el exponente de las unidades. Exp. 0 1 2 3 4 5 6 7 -8 -7 -6 -5 -4 -3 -2 -1 Cod. 00h 01h 02h 03h 04h 05h 06h 07h 08h 09h 0Ah 0Bh 0Ch 0Dh 0Eh 0Fh -Unit. Especifica que unidades se aplicarán al dato del reporte después de que el valor es convertido usando los ítems physical y unit exponent. Tabla 2.21 Tabla de unidades. Número de Nibble 1 2 3 4 5 6 7 Sistema de Medición Lineal SI Inglés Inglés Rotación Lineal Rotación (2) (3) (4) Centímetros Radianes Pulgadas Grados Gramos Slugs Segundos Kelvin Fahrenheit Amperes Candelas Calidad de Medición Ninguna SI (0) (1) Longitud Masa Tiempo Temperatura Corriente Intensidad Luminosa Reservado Ninguna Ninguna Ninguna Ninguna Ninguna Ninguna Ninguna El valor puede ser de una longitud de 4 bytes, en el cual cada nibble tiene una función definida. El nibble 0 (el más significativo) especifica el sistema de medición (SI o Inglés), si la medición es lineal o en unidades angulares. Seguido de cada nibble representa la calidad de la medición, con el valor del nibble representando el exponente que se aplicará al valor. Por ejemplo, un nibble con el valor de 2 significa que el dato está en unidades cuadradas, si es 0Dh representa un -3 por lo que significa que el dato está en unidades cúbicas negativas. Esto es diferente al ítem unit exponent. 40 Por ejemplo, para especificar tiempo en segundos hasta un minuto, el descriptor reporte deberá incluir la siguiente información. Logical minimum = 0 Logical maximum = 60 Physical minimum = 0 Physical maximum = 60 Unit exponent = 0 Unit = 1003h Nibble 0 = 3 para seleccionar sistema de medición lineal inglés. Nibble 3 = 1 para seleccionar el tiempo en segundos. Si se necesita especificar en décimas de segundos se requiere aumentar los máximos y cambiar el ítem unit exponent. Para enviar un valor de 600 se requiere de 3 bytes, el cual se deberá especificar en el tag report size. Logical minimum = 0 Logical maximum = 600 Physical minimum = 0 Physical maximum = 600 Unit exponent = 0Fh Unit = 1003h Para enviar un valor de temperatura de 1 byte, que va desde -20 a 11 grados Fahrenheit, se requiere lo siguiente. Logical minimum = -128 o 80h Logical maximum = 127 o 7Fh Physical minimum = 0 o ECh Physical maximum = 110 o 6Eh Unit exponent = 0 Unit = 10003h -Report size. Especifica el tamaño en bits de un campo en un input, output o feature ítem. Cada campo contiene una pieza de dato. -Report count. Especifica cuantos campos en los ítems mencionados por report size. Por ejemplo, si un reporte tiene 2 campos de 8 bits el report size es 8 y el report count es 2. Si el reporte tiene un campo de 16 bits, el report size es 16 y el report count es 1. Si se cuenta con múltiples ítems cada uno tiene su propio report size y report count. 41 -Push. Asigna una copia de la tabla de estado del ítem global en la pila del CPU. La tabla de estado del global ítem contiene las actuales asignaciones para todos los global ítems previamente definidos. -Pop. Es el complemento de push, restaura los estados grabados previamente por el ítem push. Los valores de los Local ítems son aplicados a todos los ítems hasta que un nuevo valor es asignado. Estos no se encuentran sobre los main ítems. Los local ítems relacionan usages generales, designaciones de body-parts y cadenas. Un ítem delimitador habilita el grupo que asignará el local ítem. Los local ítems son mostrados en la siguiente tabla. Tabla 2.22 Local ítems. Lócal ítem Usage Valor 000010 Usage minimum 000110 Usage maximum 001010 Designator index 001110 Designator minimun 010010 Designator maximum 010110 String index String minimum 011110 100010 Strim Maximum 100110 Delimiter 101010 Reservado 101011 a 111110 Descripción Un index que describe el uso para un ítem o colecction. El inicio usage asociado con elementos en un arreglo o mapa de bits. El final usage asociado con elementos en un arreglo o mapa de bits. Un valor designador en un physical descriptor. Indica que parte del cuerpo aplica el control. El inicio designador asociado con elementos en un arreglo o mapa de bits. El final designador asociado con elementos en un arreglo o mapa de bits. Asociaciones a cadenas con un ítem o control. El primer string index cuando asignan a un grupo de cadenas subsecuentes para controles en un arreglo o mapa de bits. El último string index cuando asignan a un grupo de cadenas subsecuentes para controles en un arreglo o mapa de bits. El inicio (1) o final (0) de una asignación de local ítems. Para usos futuros. 42 -Usage. Es el usage ID que trabaja junto con el global usage page para definir la función de un control, dato, o colección. Al igual que el usage page, la documentación de tablas usages para HIDs listan usage IDs. Por ejemplo los botones usage page usan local usage IDs de 1 a FFFFh para identificar cuales botones se han presionado, el valor de cero significa no botones presionados. Un reporte deberá asignar un usage a múltiples ítems. Si un report ítem es precedido por un simple usage, ese usage se aplica a todos los ítems de datos. Si un report ítem es precedido por más de un usage y el número de controles o ítems de dato es igual al número de usages, cada usage es aplicado a un control o ítem de dato, con los usages y los ítems controles/datos emparejados en secuencia. Si el report ítem es precedido por más de un usage y el número de ítems control/dato es más grande que el número de usages, cada usage se aplica a un control/dato, hasta que el último usage se aplica a los controles/datos sobrantes. -Usage minimum y maximum. Pueden asignar una serie de usage IDs a elementos en un arreglo o mapa de bits. Por ejemplo, en la siguiente tabla muestra un reporte que contiene el estado de 3 botones (0 o 1), el usage minimum y maximum especifican que le primer botón tiene el usage ID de 1, y hasta el tercer botón que tiene el usage ID de 3. Tabla 2.23 Ejemplo de uso de Usage minimum y maximum. Usage page (valor para botón) Lógical minimum (0) Lógical maximum (1) Usage minimum (1) Usage maximum (3) Report count (3) Report size (1) Input (dato,variable, absoluto) -Designator index. Para ítems con descriptor físico (physical descriptors), asigna un valor designado este a su vez especifica que parte del cuerpo usa el control. -Designator minimum y maximum. Cuando un reporte tiene múltiples designator indexes éste es aplicado a los elementos en un campo de bits o arreglo, Un designator minimum y maximum puede asignar un designator index secuencial para cada ítem de bit o arreglo. 43 -String index. Un ítem o control que puede incluir un string index para asociar una cadena con el ítem o control. -String minimum y maximum. Cuando un reporte tiene múltiples string index éstos se aplican para los elementos de en un mapa de bits o arreglo, un string minimum y maximum pueden asignar un string index secuencial para cada ítem de bit o arreglo. -Delimiter. Define el inicio o final de un ítem local (0 o 1). Deberá contener usages alternados para un control, esto permite que diferentes aplicaciones definan controles de dispositivos de diferentes maneras. Por ejemplo, un botón deberá tener un uso genérico (button 1) y un específico uso (send, quit, etc). En resumen de la sección 2.1.15 se puede organizar los diferentes ítems de la siguiente forma: Figura 2.23 Estructura del descriptor reporte. 44 2.1.16 Descriptor físico (Physical descriptor) Especifica la parte o partes del cuerpo previsto para activar un control. Son agrupados dentro de asignaciones, cada descriptor set consiste de un corto encabezado seguido por uno o más descriptores físicos. Los encabezados definen las bías (si el descriptor set está apuntando a un usuario derecho o zurdo) y la preferencia de las asignaciones. Para un vendor se pueden definir descriptores físicos alternados. El descriptor físico se divide en 3 campos: Designator que identifica el actual parte del cuerpo que afecta a un ítem por ejemplo la mano. Qualifier a futuro define los designator por ejemplo mano derecha o izquierda. Effort valor cuantificando el esfuerzo que el usuario deberá emplear para afectar el ítem. Si múltiples ítem identifican alguna combinación designator/qualifier el valor de effort puede ser usado para resolver el asignamiento de la función. Un valor de cero en effort significa que un dedo está en descanso o cuando una mano está en una posición de descanso. Sólo una vez uno o más controles tendrán idénticos designator/qualifier/effort combinaciones porque ellos están físicamente conectados juntos. Por ejemplo cuando dos teclas son presionadas el descriptor deberá escoger solo una o ejecutar las dos en caso de que los botones operen como un joystick. El descriptor set cero, es un descriptor especial que indica el número de descriptor set adicionales y así el número del descriptor físico en cada asignación. Tabla 2.24 Descriptor físico cero. Parte bNumber Tamaño (bytes) 1 bLength 2 Descripción Expresión numérica que indica el número de physical descriptor. No incluye el physical descritor cero. Expresión numérica que indica la longitud de cada physical descriptor. 45 Tabla 2.25 Descriptor físico. Parte bPhysicalInfo Tamaño (bytes) 1 dPhysical dPhysical dPhysical Descripción Bits especificando información física: 7-5 Bias, 4-0 Preferencia (0 más preferido). Physical descriptor data, index1. Physical descriptor data, index2. Physical descriptor data, index2. 2 2 2 El campo bías indica a cual mano el descriptor set está caracterizando, éste no es aplicable para algunos dispositivos. Tabla 2.26 Valores de bias. Valor Descripción 0 No aplicable 1 Mano derecha 2 Mano izquierda Valor Descripción 3 Ambas manos 4 Cualquier mano 5 Reservado Valor Descripción 6 Reservado 7 Reservado Si se va a indicar preferencia otro descriptor físico como el que sigue será necesario. Tabla 2.27 Descriptor físico agregado. Parte bDesignator bFlags Tamaño (bytes) 1 1 Descripción Indica que parte del cuerpo afecta al ítem. Bits especificando banderas: 7-5 qualifier, 4-0 effort. Tabla 2.28 Valores para los designators. Valor 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F Descripción Ninguno Mano Globo ocular Ceja Párpado Oreja Nariz Boca Labio superior Labio inferior Quijada Cuello Brazo superior Codo Antebrazo Muñeca Valor 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F Descripción Palma Pulgar Dedo índice Dedo medio Dedo anillo Dedo meñique Cabeza Hombro Cadera Cintura Muslo Rodilla Calf Tobillo Pie Talón Valor 20 21 22 23 24 25 26 27 28-FF Descripción Bola de pie Dedo gordo Segundo dedo del pie Tercer dedo del pie Cuarto dedo del pie Dedo chico del pie Frente Mejilla Rservado 46 El campo qualifier indica cual mano (o mitad del cuerpo) el designator está definiendo. Éste no es aplicable para algunos dispositivos. Tabla 2.29 Valores de qualifier. Valor 0 1 2 3 Descripción No aplicable Derecha Izquierda Ambos Valor 4 5 6 7 Descripción Cualquiera Centro Reservado Reservado 2.1.17 Dispositivo de interfaz humana (HID) Son dispositivos de baja velocidad que tienen contacto directo con personas, estos dispositivos utilizan reportes para el intercambio de datos. Cuando un dispositivo tiene un interfaz de selección de inicio (boot), el dispositivo puede ser usado cuando los controladores de host no son cargados. Esto puede ocurrir cuando la PC inicia directamente a DOS o cuando estás en modo a prueba de errores en el sistema operativo. Un teclado o ratón con una interfaz de selección de inicio puede ser predefinido simplificando el protocolo soportado por el BIOS. El BIOS carga del ROM u otra memoria no volátil en el Boot up y este es valido en cualquier modo del sistema operativo. La especificación del HID define el protocolo de interfaz de selección de inicio para teclado y ratón. Si el dispositivo tiene una interfaz de selección de inicio, el campo protocolo indica si soporta una interfaz de teclado (1) o un ratón (2). Los valores de 3 – 255 son reservados. En el campo subclase, un cero significa que el dispositivo no soporta interfaz de buteo, los valores de 2 -255 son reservados. Cuando se llega a cargar el sistema operativo normal, el host envía un Set_protocol causa que el dispositivo cambie del protocolo de selección de inicio al protocolo del reporte. 47 2.2 Microcontroladores 2.2.1 Introducción Un controlador es un dispositivo que se emplea para el gobierno de uno o varios procesos, a medida que avanzó el tiempo todos los elementos del controlador se han podido incluir en un chip, este nuevo dispositivo es llamado microcontrolador . Un microcontrolador es un circuito integrado de alta escala de integración, que incorpora la mayor parte de sus elementos que configuran un controlador, su menor tamaño minimiza el número de componentes y el coste. Los PICs son microcontroladores de la compañía Microchip, donde sus siglas PIC significan controlador de interrupción programable. Éstos poseen una arquitectura Harvard, memoria de programa de varios tipos como; flash, OTP (programable una sola vez) y SQTP (programada desde fábrica con números de serie). También poseen registros de uso general (RAM), así como múltiples periféricos y módulos de diferentes propósitos como; ADCs, puertos digitales, comparadores, PWM, etc. Comunicaciones seriales como; I2C, serial síncrono y asíncrono, interfaz con el puerto USB y otras. El lenguaje de programación que utiliza es ensamblador para MPLAB (con 35 instrucciones aproximadamente), MPLAB es un programa para crear código hexadecimal y así programar el PICs, además es gratuito. Para mayor información sobre este programa visitar la página www.microchip.com. Y para mayor información sobre el conjunto de instrucciones ver el PDF de cualquier modelo de PIC. También es posible utilizar otros programas que manejan lenguaje C y obtener el código fuente para programar el PIC. Uno de ellos es el PIC C COMPILER. 48 Por mencionar un ejemplo, estos son los registros de configuración (ver figuras 2.24 y 2.25) de los diferentes periféricos y módulos de los microcontroladores 16C745 y 16F628, distribuidas en 4 bancos de memoria.Los de la gama baja solo poseen 2 bancos de memoria. Figura 2.24 Mapa de memoria del PIC 16C745. 49 Figura 2.25 Mapa de memoria del PIC 16F628. 2.2.2 Puertos de entrada y de salida Los microcontroladores poseen puertos programables de entrada o de salida, pero en varios de ellos, algunos pines son multifuncionales, esto es, que asignando valores a determinados registros (configurar), ese PIN podría ser la entrada de señal de un comparador, de un ADC, o la salida de un mismo comparador o la salida de un transmisor serie. 50 Por mencionar algún ejemplo, el PIN RC6/RX/DT del PIC 16C745 puede ser configurado como un pin de entrada o salida digital, como transmisor de comunicación serie asíncrona, o transmisor y receptor de datos en la comunicación serie síncrona. Generalmente sus funciones son separadas con una diagonal. Por mencionar otro ejemplo el pin RB0/INT que puede ser configurado como un pin de entrada o salida digital o como entrada para la interrupción de un flanco de subida o de bajada según sea el caso. En varios casos algunos puertos tienen que ser configurados y otros están configurados por default. Si es el caso de que un pin, sea configurado como una entrada o salida digital, ese pin es asociado a un determinado bit en un registro, para leer o escribir el dato y también se le asocia otro bit en otro registro, para determinar si ese pin es de entrada o de salida, en el ejemplo del PIC16C745 son los registros portc y trisc respectivamente para los pines RCn siendo n el número del pin. 2.2.3 Módulo USART (transmisor-receptor síncrono y asíncrono universal) Este módulo establece una interfaz de comunicación serie síncrona y asíncrona, configurando ciertos registros de los bancos de memoria. Si se configura la comunicación asíncrona, en el PIN TX/CK se usa como línea transmisión y el PIN RX/DT como de recepción, permitiendo así una comunicación full duplex. Si se configura como comunicación síncrona los respectivos pines se convierten en una línea de reloj y una de dato, permitiendo así una comunicación half duplex. En la comunicación síncrona, se puede configurar al dispositivo como maestro o como esclavo, esto es, un único maestro genera el reloj de sincronía para la transmisión de datos. Cada flanco de subida que genera el pin de reloj del maestro, en el pin de dato se debe de sacar un bit del dato a transmitir (ya sea que el maestro transmita o el esclavo), cuando el pin de reloj del maestro conmuta a flanco de bajada, éste le indica al dispositivo receptor (puede ser maestro o esclavo) que debe de leer el nivel lógico del pin de dato, así que, en cada flanco de subida se saca un bit de dato y en cada flanco de bajada se debe de leer el dato. 51 Figura 2.26 Comunicación serie síncrona. En la comunicación asíncrona, posee un protocolo para definir el dato, esto es, un bit de inicio seguido por los bits de datos y un bit de stop. Además el baudio le indica como leer los estados lógicos. Figura 2.27 Protocolo serie asíncrono. Para configurar este módulo serial es necesario asignar valores a los registros txsta y rcsta, además, se deben configurar los pines RX/DT y TX/CK como entrada, esto se logra poniendo sus correspondientes bits, en el registro tris con el valor de uno. Para transmitir un dato, sólo se necesita cargar al registro txreg el valor, o cuando se desea leer lo que se a recibido por el puerto serie se lee el registro rcreg, también se asocian a este módulo banderas que indica si hay un dato válido que leer o si el puerto serie está listo para transmitir otro dato, esas banderas son RCIF y TXIF respectivamente, que se leen con un valor de uno si ocurre una recepción o si está listo para transmitir. Figura 2.28 Registro TXSTA. Figura 2.29 Registro RXSTA. 52 Figura 2.30 Registro PIR1 del PIC 16C745. También se le puede habilitar una interrupción a las banderas, asignando el valor de uno a los bits RCIE y TXIE. Figura 2.31 Registro PIE1 del pic 16C745. 2.2.4 Módulo ADC (Convertidor analógico digital) En el PIC 16F873, el módulo posee 10 bits de resolución, 2 entradas para la referencia positiva y negativa, si se desea, se puede configurar con una referencia positiva de la alimentación y el tiempo de adquisición es programable. Todo lo mencionado se lleva a cabo asignando sus correspondientes valores a los registros de configuración de este módulo. Figura 2.32 Registro ADCON0 del pic 16F873. Figura 2.33 Registro ADCON1 del pic 16F873. El bit GO/DONE indica si la conversión está en progreso, el bit ADIF se pone a uno cuando termina la conversión, y también se le puede asociar una interrupción para cada fin de conversión, habilitando el bit ADIE. 53 2.2.5 Módulo USB El PIC16C745 proporciona varios registros para llevar a cabo la comunicación con el puerto USB. El registro UIR es un registro de banderas que proporciona información sobre los eventos que ocurren el el puerto. Figura 2.34 Registro UIR. Asociado a este registro se encuentra el registro UIE que habilita interrupciones si alguna de las banderas del registro UIR es puesto a uno. Figura 2.35 Registro UIE. También proporcina un registro para el control de errores sobre el bus del puerto usb, de esto se encarga el registro UEIR. Figura 2.36 Registro UEIR. A este registro también se le asocia un registro (UEIE), para habilitar interrupciones en caso de que el microcontrolador detecte un error sobre el bus. Figura 2.37 Registro UEIE. 54 El registro UCTRL es un registro de control que provee bits para asignar aspectos de señalización sobre el bus. Figura 2.38 Registro UCTRL. El registro UADDR posee la dirección única del dispositivo, éste toma la dirección cero durante el procesos de enumeración, después, el host le proporciona una dirección única. Figura 2.39 Registro UADDR. Para proporcionar información sobre los estados del dipositivo se encuentra el registro USWSTAT. Figura 2.40 Registro USWSTAT. Cada enpoint del PIC es controlado y configurado por un registro UEPn dónde la n significa el número de enpoint, el pic16C745 soporta los enpoints 0,1 y 2. Figura 2.41 Registro UEPn. 55 La figura 2.40 muestra la tabla de configuración para los 3 bit más significativos del registro UEPn, y que configura los tipos de transacciones que deberá soportar determinado enpoint, asignar un 06h al registro asegura que el enpoint pueda realizar transacciónes de tipo control. Figura 2.42 Tabla de configuración de enpoints. Para eficientar la comunicación de los enpoints se encuentra un buffer descriptor table (BDT) en espacio de registros, los buffers son compartidos entre el bus USB y el MCU (procesador y firmaware del pic) sólo uno de ellos puede actualizar estos registros a la vez, la bandera UOWN permite saber quien tiene permiso para modificar el BD (buffer descriptor). Cada endpoint tiene 4 bytes de BD y apuntan hacia el buffer de dato en los registros duales usb (dual port registers, banco 3, direcciones 1A0h-1DFh) , para asignar los BD a estos registros de datos se encuentra el registro BDndAL, dónde la n significa el número del endpoint y la d la dirección de la transacción. Por ejemplo al enpoint de control se le asocia los registros BD0OAL (salida), BD0IAL (entrada). Figura 2.43 Registro BDndAL. A este registros sólo se le puede asignar valores de B0h – DFh (dirección de los registros duales USB), los demás registros son reservados para los tokens. 56 Asociado a este registro esta el registro BDndBC (byte count), representa el número de bytes a transmitir en un token in (modificado por el MCU) o recibidos durante un token out o setup (modificados por el SIE). En caso de un token de entrada sólo son válidos los números del 1-8 en este registro. Figura 2.44 Registro BDndBC. Otro registro asociado es el registro BDndST, con sus datos reporta el estado de una transacción y su significado difiere dependiendo si el MCU lee o escribe el registro. Figura 2.45 Registro BDndST leído por el MCU. Figura 2.46 Registro BDndST escrito por el MCU. Cuando el bus a realizado una transacción, el registro USTAT es modificado para informar el endpoint y la dirección del token, este registro es utilizado por el MCU para determinar cual DBT fue modificado por la última transacción, las transacciones se apilan en un STAT FIFO de cuatro bytes, que conforme se limpia el bit TOK_ DNE del registro UIR los valores se actualizan en este registro. Figura 2.47 Registro USTAT. 57 Cuando el bus transmite o recibe dato el SIE va a checar que el bit UOWN sea igual a uno, si es así, el SIE obtiene la dirección del buffer y mueve el dato desde o hacia el correspondiente buffer, actualizará el BD status y el registro USTAT y al bit UOWN lo pondrá a cero, cuando el token es completado, el bit TOK_DNE se pone a uno. Al ponerse este último bit en uno, se crea una interrupción y el MCU dispone de los registros antes mencionados para servir la transacción y devolver la disponibilidad de los mismos al SIE. 2.3 Freeware 2.3.1 Introducción Freeware es un software que se regala sin cargo alguno. Microchip también proporciona un freeware para no tener que hacer código, que realice lo que a nivel bajo hace el dispositivo de USB, como atender las interrupciones de USB, realizar rutinas para checar los estados del dispositivo de USB (mencionado en la sección 2.1.9), así como otras tareas. Figura 2.48 Diagrama para la rutina de servicio de interrupción. 58 La figura 2.46 muestra un diagrama para visualizar la estructura de la rutina de servicio de interrupción (RSI), que es donde se lleva acabo la mayoría de las transacciones del puerto USB. Esta rutina identifica el encendido de bits para determinar quíen causó la interrupción, una vez determinada, se atiende la interrupción ya sea saltando o mandar a llamar una rutina, asignar una macro o atenderla una vez identificada. La figura 2.49 muestra los tipos de tokens que atiende el freeware. Al terminar de atender a cualquiera de estos tokens, regresa a la dirección de memoria de programa donde se vió interrupida. Figura 2.49 Tipos de tokens que atiende el freeware. 59 2.3.2 Código fuente en ensamblador del Freeware (proporcionado por Microchip) El freeware para ensamblador consiste en los siguientes archivos: • 16C745.lkr – Indica al compilador como ensamblará los archivos con código fuente. • usb_defs.inc – Define variables de USB y macros que se usarán en los siguientes archivos. • usb_main.asm – Aquí se encuentra el programa principal, esto es, lo que el usuario desea hacer o programar. También se encuentra la rutina de servicio de interrupción, la configuración inicial del dispositivo hasta que el reset llegue por parte del hub. • usb_ch9.asm – Aquí se encuentran las funciones que atienden a los diferentes estados del dispositivo (explicado en la sección 2.1.9), atiende los tokens y paquetes según sea la transacción y lectura/escritura por el puerto USB. • hidclass.asm – Contiene las funciones para un dispositivo HID. Como atender las requisiciones del host para un HID. • descript.asm – Contiene los descriptores que describirán nuestro proyecto. En la versión HI-TEC C, se encuentra los archivos: • usb.pjt, • usb.h, • usb_defs.h, • usb_main.c, • usb_ch9.c 2.3.3 Funciones del código fuente de ensamblador InitUSB. Se manda a llamar antes de que el proceso de enumeración empiece (aproximadamente en 16 microsegundos), habilita los periféricos de USB. 60 ConfiguresdUSB. Polea los bits de estados para ver que el dispositivo ya halla sido configurado. DeinitUSBint. Usado para que el dispositivo sea ignorado por el host y así pueda ser desconectado. ServiceUSB. Llamado para procesar transacciones como tokens y errores en el puerto USB. PutEPn. Envía datos al host vía endpoint n, dándole el número de bytes a enviar mientras que unos punteros indican el bloque de información a enviar. GetEPn. Recibe datos del host vía endpoint n, la dirección deseada para los datos deberá ser indicada con punteros. Hay en el freeware, más funciones para los demás estados, que sirven para crear un proyecto más avanzado. Para mayor información visitar la página de microchip. 2.3.4 API de Visual basic (Activex) Microchip proporciona también un API que nos comunica con el buffer de USB del host, para extraer los datos al interfaz final para el usuario o programa de aplicación. Se puede crear un API propio, si se es un experto en Visual Basic y obtienes la información del kernel, que es allí donde se puede comunicarte con el controlador de Windows. Un control Activex es un objeto que coloca un formulario para permitir o mejorar la interación de un usuario con una aplicación. Los controles Activex tienen eventos y se pueden incorporar a otros controles. Estos controles tienen una extensión ocx. Un componente de código Activex es una aplicación servidora que expone funcionalidad que otras aplicaciones pueden utilizar y reutilizar mediante automatización. Los componentes Activex permiten a los programadores combinar fragmentos de código 61 reutilizables para crear aplicaciones y servicios. Los componentes de código ofrecen una completa funcionalidad. Por ejemplo, puede empaquetar una rutina compleja en un componente simple que puedan utilizar otros programadores. Crear sus propios componentes Activex o bien adquirirlos a Microsoft o a otros fabricantes para proporcionar servicios genéricos. Cuando cree aplicaciones, puede combinar componentes Activex con componentes genéricos para crear robustas soluciones personalizadas. Con la versión 5.0 de Visual basic puede crear componentes de código Activex (antes llamados servidores OLE). Microchip proporciona un Control ACTIVEX para comunicar la aplicación cliente con nuestro microcontrolador. Se trata del HIDCOMM, en el cual contiene eventos y funciones que ayudarán a conocer el estado de nuestro dispositivo, a seleccionar (si es necesario) el dispositivo que deseamos comunicarnos, realizar operaciones de lectura/escritura del microcontrolador. Sus propiedades, eventos y funciones son las siguientes: PROPIEDADES: -MatchMethod As Integer. Es un switch de asignación de bits, para especificar cual será el criterio de búsqueda, que se usara para localizar el dispositivo HID. Por ejemplo, si se desea comunicarse a un HID, en el cual el ID del producto es 5 y el vendor ID es 6, el MatchPID y el MatchVID deberán de llenarse con esa información y poner MatchMethod = CheckPID o CheckVID. -MatchPID As Long. Es uno de los criterios de búsqueda, se puede especificar y localizar el dispositivo HID. Si se desea comunicarse a un HID el cual el ID del producto es 1234, especifica 1234 en esta propiedad. 62 -MatchVID As Long. Es uno de los criterios de búsqueda que se puede especificar para localizar el dispositivo HID. Si tu quieres comunicarte con un ID vendor 1234, especifica 1234 en esta propiedad. -MatchVersion As Long. Es uno de los criterios de búsqueda que puedes especificar para localizar el dispositivo HID. Si se quiere comunicar a un HID el cual su versión es 1.00, especifica 256 en esta propiedad, por que el número de la versión esta expresado en BCD, con los 2 últimos dígitos como parte decimal. La versión 1.10 deberá ser 272. -MatchManufacturer As String. Es otro de los criterios de búsqueda. Se deberá colocar una cadena de caracteres para encontrar la manufacturera. -MatchProduct As String. Es otro de los criterios de búsqueda. Se deberá colocar una cadena de caracteres para encontrar el producto. -MatchSerial As String. Es otro de los criterios de búsqueda. Se deberá colocar una cadena de caracteres para encontrar el serial del producto. - ReportID As Byte. Determina cual reporte HID esta la PC enviando y recibiendo. -TimeOut As Long. Indica el intervalo de tiempo en ms. de todas las operaciones de E/S al dispositivo HID. Si el intervalo del time out a sobrepasado antes de que la E/S esta completada, la operación habrá fallado, y el evento redfailure/writefailure va a ser activado. EVENTOS: - ConnectSuccess(ByVal Status As Long). Este es activado cuando el control activex se ha conectado bien al dispositivo. 63 -ConnectFailure(ByVal Status As Long). Este evento se activará cuando no haya criterio de búsqueda, cuando hay más de un criterio de búsqueda, o si el mismo método es abierto por otro programa. La razón de fallo está en la variable status. -Disconnected(ByVal Status As Long). Éste es activado si el dispositivo HID está desconectado. - ReadSuccess(ByVal Status As Long, ByVal ByteRead As Long). Éste es activado si la última lectura asíncrona fue satisfactoria. Los bytes leídos son pasados a través de byteread. -ReadFailure(ByVal Status As Long, ByVal ByteRead As Long). Éste es activado si la última lectura asíncrona ha fallado. La razón del error es pasado a la variable status y los bytes leídos pasados a byteread. -WriteSuccess(ByVal Status As Long, ByVal ByteWritten As Long). Éste es activado si la última escritura asíncrona fue satisfactoria. Los bytes leídos son pasados a través de byteread. - WriteFailure(ByVal Status As Long, ByVal ByteWritten As Long). Éste es activado si la última escritura asíncrona ha fallado. La razón del error es pasado a la variable status y los bytes leídos pasados a bytewritten. FUNCIONES: - Browse() As String. Escanea todos los dispositivos HID actualmente añadidos a la ruta. El usuario puede escoger un dispositivo desde la lista de todos los dispositivos añadidos, y la ruta escogida por el dispositivo es regresado. La ruta puede ser usada en la función ConnectToPath para la conexión directa y escoger el dispositivo HID. Si el usuario oprime el botón cancel, la ruta va a ser una cadena vacía. 64 - Connect() As Long. El dispositivo HID a comunicar está determinado por la propiedad matchxxxx y el bit swicheado de MatchMethod. El control activex HIDcomm deberá ser conectado al dispositivo HID para realizar cualquier operación de E/S. Si no hay dispositivos encontrados o se encuentran más de un criterio de búsqueda, la función fallará, un código de estado es regresado para indicar la razón de la falla o satisfactoria conexión. - ConnectToPath() As Long. Obtiene esta ruta. El control activex deberá ser comunicado al dispositivo HID para hacer cualquier operación de E/S. Un código de estado es regresado para indicar la razón del fallo o satisfactoria conexión. - GetFeature(ByVal Size As Long) As Byte(). Obtiene un informe de las características del dispositivo HID. Size es el número de bytes a leer, los reportes de características son regresadas como un arreglo de bytes. La variable reportID determina cual reporte de características se trata. -ReadFrom(ByRef Size As Long) As Byte(). Lee desde un dispositivo HID. Size es el tamaño del buffer intermediario de datos. El número de bytes actualmente leídos se ponen el la variable Size después de la operación de lectura y un arreglo de bytes es regresado, la variable reportID determina cual reporte de características se trata. - Sub WriteTo(ByRef Buffer() As Byte, ByRef Size As Long). Escribe a un dispositivo HID. Buffer tiene el dato a enviar, Size es el no. de bytes a enviar, primero se indica el tamaño a enviar y después se escribe. -Function SetFeature(ByRef Buffer() As Byte, ByVal Size As Long) As Boolean. Pone el reporte de características del HID a especificar valor. Buffer contiene el dato a enviar, Size es el número de bytes a enviar, si la operación es exitosa, la función regresa verdadero, de otra forma, falso. La variable reporID determina cual reporte de características se trata esta transacción. 65 -Sub Uninit(). Esta función descarga archivos DLLs subyacentes usados por el activex. Esto es necesario para llamar las funciones antes que el programa se cargue. Llama en tu programa el evento "terminate" o "unload". 2.3.5 Asignación del controlador (Driver) Microsoft Windows proporciona controladores para dispositivos estándar, en nuestro caso, proporciona un controlador para los dispositivos catalogados como HID. Cuando el sistema operativo detecta un dispositivo por primera vez, aparece un cuadro de diálogo preguntándonos por el controlador para el dispositivo. Figura 2.50 Cuadro de dialogo en win98. En caso del sistema operativo XP (si se encuentra actualizado con algún service pack) la asignación es automática. Un service pack es una actualización del sistema operativo (parche). Una vez asignado el driver, se puede ver en los registros y en los administradores de hardware, que nuestro dispositivo forma parte del grupo de componentes. Para revisar los cuadros de diálogos y registros (en diferentes versiones de windows) ver las páginas de anexo 2. 66 2.4 Referencias [1].- Martín Cuenca, J.M. Angulo Usategui, I. Angulo Martinez. Microcontroladores PIC. Quinta edición. EDITORIAL PARAINFO THOMSON LEARNING. [2].- Jan Axelson. USB COMPLETE. Second and Third Editions. LAKE VIEW RESEARCH LLC. [3].- Steven McDowell, Martin D. Seyer. USB EXPLAINED. EDITORIAL PRENTICE HALL. [4].- www.usb.org. Universal serial bus Specification. Rev 1.1, Noviembre de 2005. III DESARROLLO 3.1 Introducción El sistema de monitoreo a implementar lo componen dos dispositivos principales a los cuales se les llamó módulo maestro y módulo esclavo. Central Pc o PLC Módulo maestro Área de cultivo Electroválvulas Y equipo de bombeo Cultivo y N Transductores N Módulos esclavos Figura 3.1 Sistema de riego. Como muestra la figura 3.1, el módulo maestro se encuentra en la central y los módulos esclavos en el área de cultivo, ambos módulos principales se comunican entre si vía RF y son conectados a diferentes dispositivos; los esclavos se conectan a varios capacitores que sensan la humedad y el maestro a una PC o a un PLC. En el sistema de comunicación, el maestro transmite una señal de activación el cual será recibido por todos los esclavos, pero solo uno estará capacitado para activarse, una vez activado uno de los esclavos, éste deberá de realizar la lectura de humedad y transmitirlo al maestro y éste a su vez pueda transmitirlo a la PC o al PLC. Etapa TX de RF Etapa RX de RF Etapa de Control (microcontroladores) Figura 3.2 Etapas de ambos módulos principales. Circuiteria externa 68 La figura 3.2 muestra las etapas en que se dividen ambos módulos principales como un primer acercamiento al diseño de los módulos. La etapa de transmisión de RF, representa la sección por el cuál la etapa de control transmitirá la señal de un módulo a otro, la etapa de recepción es la encargada de recibir las señales y proporcionárcelas a la etapa de control, estas etapas de RF se tomarán como una caja negra, el cuál cuenta con una entrada y una salida para que la etapa de control transmita y reciba señales, también cuenta con una entrada para que la etapa de control pueda cambiar el estado de la comunicación de transmisión a recepción y viceversa. Este cambio de estado no es más que el intercambio de encendido y apagado entre las etapas de transmisión y recepción, también se intercambia la conexión de la antena entre las etapas de RF. La etapa de control es la encargada de encender y apagar varias etapas analógicas, generar señales para la transmisión, procesar la señal recibida y realizar otras actividades especiales para cada uno de los módulos principales; para realizar estas tareas se hará uso de microcontroladores PICs. El encendido y apagado de las etapas se hizo con el fin de ahorrar energía de la batería, y también, a que algunas etapas interferían con otras, esto debido a la radiofrecuencia que se está utilizando. El cálculo para estas tareas y todas las pruebas, se realizarón a prueba y error observando LEDS que se encendían y apagaban en ambos módulos, o en algunas ocasiones mirando las frecuencias en el osciloscopio. La etapa circuiteria externa representa el espacio que ocuparán los circuitos de excitación para el capacitor que sensa la humedad, esto es en el caso del ser un módulo esclavo, en un módulo maestro, representa el espacio que ocupará la circuiteria para la interfaz con la PC y PLC. En la figura 3.2 las flechas representan el flujo de información de una etapa a otra, las líneas sencillas representan las líneas de control que ejerce la etapa de control sobre las otras etapas. Una vez identificadas las necesidades de cada módulo, las etapas finales para cada uno de ellos son las siguientes: 69 El módulo maestro se divide en varias etapas, como lo muestra la figura 3.3 compuestas por: etapa de control, etapa de modulador FM, etapa de potencia, etapa receptor FM y adecuador. Etapa De Potencia Modulador FM Control PIC16C745 Receptor FM Adecuador PIC16F628 Barra de LEDs y conector USB conector PLC (db9) Figura 3.3 Etapas del módulo maestro. El indicador de barras de LEDS (figura 3.4) nos muestra que algunos de los estados del dispositivo USB (mencionados en la sección 2.1.9 del capítulo 2) se encuentren correctamente inicializadas, el primer LED (de izquierda a derecha) indica que se han configurado los registros de USB, el segundo, que el dispositivo ha sido reseteado por el host, el tercero, que el dispositivo ya tiene una dirección por parte del host, el cuarto, que el puerto está en modo sleep, el sexto indica actividad en el endpoint. Figura 3.4 Barra de LEDS. La figura 3.5 muestra la etapa que servirá de interfaz con el PLC a través de un conector db9 y una etapa de adecuación de voltaje. Figura 3.5 Vista frontal y superior del conector PLC en el módulo maestro. 70 El módulo esclavo se divide en las etapas que muestra la figura 3.6, compuestas por: etapa de control, circuito del transductor, modulador FM, la etapa de potencia, el receptor FM y el adecuador. Etapa De Potencia Modulador FM Circuito del Transductor Receptor FM Adecuador Control PIC16F873 Figura 3.6 Etapas del módulo esclavo. El circuito del transductor representa la etapa donde se encuentra la circuiteria de excitación para el capacitor que servirá de cómo sensor de humedad. Este capacitor estará conectado a esta etapa. A continuación se mencionan algunas especificaciones para el sistema de monitoreo ya que algunas de ellas son especificaciones de la etapa de RF. ►Se decidió que el sistema de comunicación sería half duplex, ya que con esto se utilizaría la misma frecuencia portadora para la activación y la transmisión de datos de humedad. ► También se decidió que se utilizaría un número mínimo de hardware, es por esa razón que no se usaron señales digitales para la transmisión de los datos. ► El ancho de banda de la señal moduladora es de 1 a 5 Khz en la etapa de transmisión de RF. 71 3.2 Conexión de microcontroladores La figura 3.7 muestra a detalle las conexiones que tiene la etapa de control en el módulo maestro hacia las demás etapas. Figura 3.7 Conexion a detalle de los microcontroladores 16f628 y 16c745. El generador de tonos representa el pin por donde saldrá la señal modulante hacia la etapa modulador FM. El indicador de estados del puerto USB representa la barra de leds que nos ayudará visualmente a checar los estados del dispositivo. El puerto USB representa el conector por el cual se colocará el cable USB y este último hacia la PC. La conexión entre el pin 17 del PIC16F628 y el pin 4 del PIC16C745, representa una línea de control entre los 2 pics para realizar una petición de transmisión de esclavo a maestro, en la comunicación serial síncrona. 72 Las conexiones de los pines 18 y 17 del PIC16C745 hacia los pines 7 y 8 del PIC16F628 muestran las lineas de dato y reloj de la comunicación serie síncrona. El medidor de frecuencia representa el pin por donde se recibirá la señal de dato por parte de la etapa de adecuación. El mute representa parte de la circuitería que se encuentra en la etapa de adecuación y cuya función es aterrizar la señales de ruido que entrega el receptor FM hacia el medidor de frecuencia, debido a que perturba en cierto proceso de comunicación serie síncrona, este mute se activa poniendo en estado alto el pin 9 del PIC16F628. El pin 11 del mismo PIC, representa el dectector de nivel del receptor FM, el cual indica en un estado en alto que se ha detectado portadora y por lo tanto dato de humedad. El pin 12 del PIC16F628, es el encargado de conmutar el encendido y apagado entre las etapas de potencia y receptor FM, además también conmuta la conexión de la antena entre dichas etapas; poniendo el nivel en estado alto se enciende la etapa de potencia y se apaga la etapa receptor FM además de conectar la antena a la etapa de potencia, en estado bajo hace exactamente lo contrario a lo mencionado. Los pines 18, del 1 al 3 representan los pines por los cuales le indicamos al PLC,el transductor activado. La figura 3.8 muestra a detalle las conexiones que tiene la etapa de control en el módulo esclavo hacia las demás etapas. Figura 3.8 Conexion a detalle del microcontrolador 16f873. 73 El generador de tonos representa el pin por donde saldrá la señal modulante hacia la etapa modulador FM. El pin 4 al igual que el pin 12 del PIC16F628, es el encargado de conmutar el encendido y apagado entre las etapas de potencia y receptor FM, además también conmuta la conexión de la antena entre dichas etapas, funciona exactamente igual que el pin 12 del PIC16F628. El pin 7 es el encargado de conmutar el encendido y apagado de la etapa circuito del transductor, poniendo en un estado en alto este pin se enciende la etapa antes mencionada, en estado bajo se apaga la etapa. Los pines 13 y 14 representan la entrada para los jumpers de configuración, esto es, modificar la frecuencia de activación, sin colocar los jumper el microcontrolador lee un estado alto, con los jumper colocados lee un estado en bajo. El detector de tonos representa el pin por donde se recibirá la frecuencia de activación por parte de la etapa de adecuación. El pin 15 es el receptor de un push buton, éste sirve para realizar una activación del módulo esclavo y realice una transmisión de dato. 3.3 Modos de funcionamiento Debido a los 2 diferentes destinos del dato de humedad (PC o PLC), el sistema de monitoreo soporta 2 modos de funcionamiento, uno para la conexión con el PLC y otro para la PC, estos modos de funcionamiento solo afecta al módulo maestro y se decidió que solo modificando unos jumpers de sus posiciones, se pueda configurar al módulo maestro en el modo de funcionamiento deseado (ver anexo 3). El primer modo se presenta cuando el módulo maestro es conectado hacia la PC, esta conexión se realiza por medio de un cable USB (figura 3.9), el programa residente en la PC indica en tiempo real cuando debe de activarse un módulo esclavo determinado, esto es, transmitiendo los datos necesários para la activación hacia el módulo maestro por medio del puerto USB. Por este mismo puerto se recibe los datos de humedad del módulo maestro, que a su vez, fue recibido por el módulo esclavo activado. El dato es almacenado en el disco duro y el programa activa uno a la vez cada módulo esclavo que esté dado de alta es su base de datos. 74 PC Cable USB Módulo Maestro Figura 3.9 Modo conexión con la PC. El segundo modo de funcionamiento es cuando el módulo maestro es conectado hacia un PLC (figura 3.10), en este modo se requiere que el módulo maestro envíe los datos a través de 5 pines conectados al PLC, de los cuales 4 de ellos determinan (en número binario) el módulo esclavo que se ha activado y en el quinto PIN se entrega la frecuencia o el dato de humedad que generó la activación (figura 3.11), el PLC deberá ser capaz de leer esta frecuencia o dato de humedad y almacenarlo por si mismo. En el conector db9 se encuentran los 5 pines de datos y 1 línea por donde el PLC proporcionará una alimentación de 24 volts, para los transistores que se encuentran en la etapa que servirá como interfaz con el PLC. PLC Módulo Maestro Figura 3.10 Modo conexión con el PLC. Donde los pines del 6 al 9 representan en número binario el transductor activado, y por lo tanto, a quien pertenece el dato de frecuencia que se presenta por el pin número 5, en el pin 1, el PLC entregará el voltaje de alimentación. Figura 3.11 Conector db9 (pines correspondientes). Debido a que la PC ya no estará conectada en este modo de funcionamiento se dispone de un temporizador, el cual realiza en un determinado tiempo el barrido de lecturas o activaciones, se tendrá en memoria RAM los datos necesarios para activar los módulos esclavos así como el tiempo para el temporizador, toda esta información 75 es transmitida por medio de un software especial en la PC hacia el módulo maestro a través del puerto USB. Debido a los 2 modos de funcionamiento, se crearon 2 programas para la PC (en visual basic) y 4 programas para los microcontroladores del módulo maestro (en ensamblador), el programa para el microcontrolador del módulo esclavo permanece independiente del modo de funcionamiento (en ensamblador). 3.4 Adecuación del Firmware La adecuación representa el cambio que se realizó al firmware original para adecuarlo a la necesidades de nuestro proyecto. Como se muestra acontinuación, se realizó el cambio en la sección de enpoints en el archivo “descript.asm”. Original Endpoint1 retlw retlw retlw retlw retlw retlw retlw Cambio Endpoint1 retlw retlw retlw retlw retlw retlw retlw Endpoint2 retlw retlw retlw retlw retlw retlw retlw Figura 3.12 Adecuación al firmware. 7 ENDPOINT 0x81 ;endpoint1 de entrada 3 ;de interrupción 4 ;tamaño de paquete 0 ;byte superior 0x0a ;intervalo de poleo 0x07 ENDPOINT 0x81 ;endpoint1 de entrada 0x03 ;de interrupción 0x08 ;tamaño de paquete 0x00 ;byte superior 0x0A ;intervalo de poleo 0x07 ENDPOINT 0x01 0x03 0x08 0x00 0x0A Con este cambio, podemos enviar 8 paquetes por cada transacción en vez de 4, tal y como lo indicaba el original, también se agregó un segundo endpoint y aunque no estriba mucho en el funcionamiento, con esto le indica al host que el dispositivo contiene un endpoint1 de entrada y otro de salida. 76 3.5 Diseño de software para la PC El software es el programa hecho en Visual basic. Éste es requerido para dar de alta los transductores que estarán dentro del sistema de monitoreo; con los 2 modos de funcionamiento, se crearon 2 programas diferentes. 3.5.1 Diseño modo de conexión con la PC A continuación se muestra un digrama para explicar el proceso de activación de un sensor de humedad con el modo de funcionamiento para la PC. Figura 3.13 Proceso de activación en el modo de conexión con la PC. 77 En este modo, se crea una base de datos para dar de altas los transductores, grabar las lecturas de humedad y los tiempos en los cuales se realizarán los barridos. La figura 3.14 se muestra la presentación en tiempo de diseño. Figura 3.14 Programa en vista de diseño. En la sección superior izquierda se editan, eliminan y agregan transductores, así como los tiempos de barridos. En la parte inferior izquierda se encuentra la activación del barrido de lecturas de forma automática (botón iniciar), esto es, se realizarán los barridos de lecturas según la base de datos. En la sección superior derecha se muestra la interfaz para enviar una sola activación (activación manual), se pueden dar de alta tantos transductores como el ancho de banda de la señal modulante lo permita, claro que, a mayor número de transductores el barrido de lectura tardará más tiempo en realizarse. Para dar de alta un transductor solo hay que oprimir el botón nuevo (figura 3.15), introducir la frecuencia de activación (se aconseja que las frecuencias de activación para cada transductor tenga una separación de 50 hertz y así dejar una banda de guarda de 30 hertz) y por 78 último, oprimir el botón guardar. También se pueden utilizar los botones de desplazamiento para realizar cambios o dar de baja transductores. Figura 3.15 Base de datos para los transductores. También es necesario dar de alta el tiempo específico en las que se realizarán los barridos de lecturas (figura 3.16), en la hora el valor va de 0 a 23 y en minuto 0-59 (como valores válidos). Su operación es idéntica a la sección “alta de transductores”. Figura 3.16 Base de datos para los tiempos de barridos. Para arreglos o calibraciones, se creó una interfaz para la activación de transductores de forma manual (figura 3.17), sólo hay que indicarle la frecuencia del transductor que se desea activar en la casilla. El botón calcular despliega los datos necesarios para que el PIC genere la frecuencia indicada en la casilla, y el botón enviar hace lo que el botón de calcular realiza y envia la información al PIC. El resultado de la activación es mostrado en la parte inferior, si se desea un barrido de lecturas de forma automática sólo hay que oprimir el botón iniciar. Esto hará que el sistema realice los barridos sin tener que realizar los pasos que se explicaron para la forma manual. 79 Figura 3.17 Interfaz para el barrido de lecturas manual. El botón calcular se encarga de generar los números que el PIC16C745 necesita para reproducir la frecuencia de activación, por medio del valor que se introduce en la casilla de frecuencia y a una ecuación, dicha ecuación se explicará en secciónes posteriores. El resultado de la ecuación es un número que es repartido en 6 bytes. El botón enviar se encarga de transmitir 8 bytes a dicho microcontrolador, de los cuales 6 contienen datos para los 6 registros de la función en ensamblador. Figura 3.18 Temporizadores del programa. Los temporizadores son funciones que se ejecutan en determinados intervalos de tiempo. El primer temporizador checa si se encuentran datos en el buffer USB después de haber activado un transductor, esto se realiza observando el contenido en una posición determinada del buffer de recepción de datos, si es un valor diferente de cero, se ha realizado una lectura válida, entonces procede a guardar el resultado en la base de datos. El segundo temporizador checa si ya puede realizar un barrido de lecturas de acuerdo con la base de datos, esto es, checa la hora (en 80 tiempo real) de la PC y la compara con la base de datos, si la comparación es positiva se realiza el barrido de lectura. Para poder entender el flujo de las funciones, timers y botones, se presentan las siguientes figuras, que explicarán los lugares y tiempos. El código (en Visual Basic) se presentará en las páginas de anexo 1. Timer1 no Recibir buffer del HID Hay algún Dato valido? si 1 no Fue activación manual? Condiciones para otra activación manual 1 si Crear registro nuevo en la base de datos Salir Obtener hora y fecha Botón Enviar Guardar información en la base de datos 6 registros al buffer Deshabilitar timer1 Transmitir buffer al HID Salir Botón Calcular Botón Limpiar Calcular número Limpia casillas Repartirlo en 6 registros Salir Figura 3.19 Funciones del programa. Habilito timer1 Botón Iniciar Habilitar Timer2 81 Timer2 Deshabilito Timer1 Primer registro de tiempo Primer registro de transductores Obtengo el tiempo real no si Tiempo real = Tiempo de registro? Obtengo frecuencia del Registro Transductores Siguiente registro De tiempo Ejecuto botón enviar Pasó último Registro De tiempo? no Dato guardado? si Salir si Siguiente registro De transductores Último registro De transductores? no si Figura 3.20 Funcion del timer2. no 82 El funcionamiento total del programa consiste en atender las rutinas cuando los timer lo indiquen, cada segundo (aproximadamente), el timer principal compara el tiempo real con cada uno de los tiempos de barrido dados de alta, si ya puede realizarse uno, se hace uso de los botones antes mencionados y se habilita un segundo timer, que nos indicará si ya se a realizado una lectura válida en el puerto usb, o lo que es lo mismo, si el dato de una activación ya se encuentra listo para ser dado de alta. Después de una activación se realizarán tantas como la base de datos indique. 3.5.2 Diseño modo de conexión con el PLC La siguiente figura muestra un digrama para explicar el proceso de activación de un sensor de humedad con el modo de funcionamiento para el PLC. Figura 3.21 Proceso de activación en el modo de conexión con el PLC. 83 En este modo de operación, al igual que la anterior, se deben de dar de alta los transductores que formarán el sistema de monitoreo y el tiempo entre cada barrido de lectura. En la figura 3.22 se muestra la presentación en tiempo de diseño. Figura 3.22 Programa en vista de diseño. En la sección superior izquierda se editan, eliminan y agregan transductores, su forma de operar es la misma que la interfaz anterior, sólo que en esta ya se asignan las frecuencias de los transductores automáticamente. En la parte superior derecha, se asigna el tiempo que habrá entre cada barrido de lectura. Para explicar el botón “cambiar a DB”, se muestra el programa en tiempo de ejecución (figura 3.23). Figura 3.23 Programa en tiempo de ejecución. 84 Esta presentación muestra los transductores que actualmente están dados de alta en la base de datos, para poder editar, dar de alta y eliminar transductores hay que cambiar a la presentación que la figura 3.22 nos muestra, esto se logra oprimiendo el botón “Cambiar a DB” y esa es su función en la interfaz. Debido a que la PC ya no estará calculando los datos necesarios para llevar a cabo las activaciones, ni tampoco revisará el tiempo (tiempo real) en que se deban realizar los barridos de lectura, estos se calcularán una vez que se oprima el botón “guardar”. Oprimiendo el botón “enviar”, esta función enviará paquetes de 8 bytes con la información necesaria para las activaciones y los tiempos de barridos, el método es el siguiente: en el primer paquete, el primer byte indica cuantos paquetes se enviarán por el puerto USB, el segundo byte representa la suma de dos número, dónde el primer número es el número de transductores dados de alta en el sistema, el segundo número es 5, debido a los bytes de información del protocolo, y los subsecuentes 3 bytes indican el tiempo de barrido, hacen un total de 5 bytes para el protocolo de envío, los demás bytes los representan los datos calculados para generar las activaciones, esta trama de información es necesaria, para que la transferencia de información se pueda llevar correctamente, sin depender del número de transductores que el usuario pueda dar de alta en el sistema. Para explicar mejor el funcionamiento del botón enviar se presenta la figura 3.24, ya que las demas funciones de los botones son similares al interfaz anterior (conexión con la PC), excepto que la función del botón “guardar”, calcula automáticamente los datos necesarios para generar la frecuencia asignada, del transductores recién ingresados en la base de datos. La figura 3.24 muestra el papel que toman 2 tipos de buffers, uno es el buffer de datos con toda la información necesária para las activaciones, y el otro, es un buffer de transmisión el cual tiene una capacidad de 8 bytes (máximo por cada transacción), se crea un ciclo en el cual se transfiere 8 bytes del buffer de datos al buffer de transmisión, una vez llenos se transmiten por el puerto USB, y se repite 85 este proceso hasta terminar con el buffer de datos. El código (en Visual Basic) se presentará en las páginas de anexo 1. Botón Enviar Calcula el número de paquetes y lo envía al buffer Calcula el número de transductores y lo envía al buffer Calcula el número de segundos del tiempo de barrido y lo envía al buffer Primer registro de transductores Dato del registro actual al buffer Siguiente registro de transductores no Último registro? si Buffer al buffer de Transmisión Siguiente index del buffer de transmisión no Salir Son 8 bytes? si Transmitir datos al HID no Último dato? Retardo si Siguiente index del buffer Index del buffer de transmisión = 0 Figura 3.24 Función del botón enviar. 86 3.6 Programación de microcontroladores En esta sección se mostrará el diseño para realizar las funciones de los bloques faltantes, mostrados en las figuras 3.13 y 3.21. tales funciones serán realizadas por los microntroladores, programados en lenguaje ensamblador. 3.6.1 Inicialización de microcontroladores (modo conexión pc) Desde que se alimenta al PIC16C745 con voltaje, se inicia las configuraciones del puerto USB así como las condiciones iniciales, hasta llegar a un ciclo de espera de datos que serán enviados por la PC (sección 3.5.1). Main banksel TRISA ;selecciona el banco donde se encuentra TRISA clrf TRISC ;todo el puerto como salida bsf TRISC,0x07 ;configura el puerto serie. RC7 como entrada bsf TRISC,0x06 ;configura el puerto serie. RC6 como entrada movlw 0x06 movwf ADCON1 ;puerto A como puerto digital clrf TRISA ;puerto A como salida bsf TRISA,0x02 ;pin 4,RA2 como de entrada clrf TRISB ;puerto B como salida banksel PORTA ;selecciona el banco donde se encuentra PORTA clrf PORTA ;pone la salida del puerto A puros ceros clrf PORTB ;pone la salida del puerto B puros ceros movlw .30 ;retardo para esperar el reset de USB movwf W_save decfsz W_save,f goto $-1 banksel OPTION_REG bcf OPTION_REG,NOT_RBPU ;quita pull ups en el puerto B pagesel InitUSB call InitUSB ;función para inicializar los registros de USB ConfiguredUSB ;macro para enmascarar las configuraciones de USB call inicializar ;inicialización de variables call ini_tx ;modo tx=on rx=off del puerto serie síncrono LoopForData ;bucle para saber si ya se encuentran datos en la RX USB Pagesel GetEP1 banksel outbuffer movlw outbuffer ;dirección de la pila donde la función GetEP1 pondrá los movwf FSR ;los datos que mandaron por el Puerto USB. call GetEP1 ;rutina para obtener los datos del enpoint0 pagesel tonos btfss STATUS,C ;por medio del carry la funcion GETEP1 goto LoopForData ;me indica si hay datos Figura 3.25 Código para la inicialización del puerto USB y configuraciones de puertos. 87 En el PIC16F628, se inicia la configuración del puerto serie síncrono así como las condiciones iniciales (figura 3.26), después entra en un ciclo ocioso en la espera de una clave por parte del PIC16C745. Inicio bcf pie1,TXIE bcf estado,RP0 bcf pir1,RCIF ciclo bcf pir1,TXIF movlw 0xAA serial movwf clave1 bsf estado,RP0 movlw 0xBB movlw b'00010000' movwf clave2 movwf txsta movlw 0xCC bcf estado,RP0 movwf clave3 movlw b'10010000' clrf porta movwf rcsta movlw 0x07 return movwf cmcon clrf w inicial movlw 0x01 bsf estado,RP0 movwf f movlw b'00100111' movwf cont movwf trisb movlw 0x30 clrf trisa movwf fsr bsf trisa,0x05 movlw 0x04 movlw b'11001000' movwf var1 movwf opcion clrf overflow movlw b'11000000' clrf portb movwf intcon bcf portb,0x03 bsf pie1,RCIE return Figura 3.26 Configuración del puerto serie síncrono e inicializaciones. call call goto inicial serial ciclo 3.6.2 Inicialización de microcontroladores (modo conexión plc) La inicialización para el PIC16C745 en este modo conexión es el mismo que el anterior modo de conexión. En el PIC16F628, se empieza con la configuración del puerto serie, se preparan las condiciones iniciales y después entra a un ciclo en espera de datos, que serán enviados por el puerto serie síncrono (figura 3.27). A diferencia del anterior modo de conexión, éste presenta cambios en las configuraciones de los puertos digitales y variables. 88 Inicio bsf pie1,RCIE bcf pie1,TXIE bcf estado,RP0 ciclo bcf pir1,RCIF bcf pir1,TXIF clrf porta serial movlw 0x07 bsf estado,RP0 movwf cmcon movlw b'00010000' clrf w movwf txsta movlw 0x01 bcf estado,RP0 Movwf f movlw b'10010000' movlw 0x30 movwf rcsta movwf fsr return movlw 0x1F movwf var2 inicial clrf overflow1 bsf estado,RP0 clrf overflow2 movlw b'00000110' clrf aux1 movwf trisb clrf aux2 clrf trisa clrf aux3 movlw b'11001000' clrf portb movwf opcion bsf portb,0x03 movlw b'11000000' clrf trans movwf intcon incf trans,f return Figura 3.27 Rutina para la configuración del puerto serie síncrono e inicializaciones. call call goto inicial serial ciclo En el PIC16F873, se inician las configuraciones de puertos así como las variables, para luego entrar a un ciclo ocioso (independiende del modo de conexión). Inicio bsf movlw movwf movlw movwf clrf clrf bsf clrf bsf bcf movlw movwf movwf estado,RP0 b'11001111' opcion b'10001110' adcon1 pie1 trisb trisb,0x00 trisa trisa,0x00 estado,RP0 0x01 f cont clrf movlw movwf clrf clrf clrf clrf clrf clrf movlw movwf movlw movwf movlw movwf w b'11010000' intcon adcon0 porta portb overf sobra veces 0xF9 cte 0x14 vuelta 0x05 palta ciclo goto Servicio btfss goto decf btfss goto clrf bcf goto ciclo intcon,INTF Tmr0int cont,f estado,Z Puerto tmr0 intcon,INTF Atajo Tmr0int btfss retfie incf intcon,TOIF overf,f Atajo bcf intcon,TOIF bsf intcon,TOIE retfie Figura 3.28 Rutina para inicialización de variables, configuración de puerto y RSI (PIC16F873). 89 Como la interrupción externa se encuentra habilitada, el ruido que entrega la etapa de adecuación (figura 3.43) interrumpe en cada momento, obligando al programa del PIC a saltar a la RSI (etiqueta servicio de interrupción), y a su vez entrar a la función de detección de frecuencia válida (sección 3.6.7). Hasta esta sección, se puede transmitir los datos desde la PC hacia los microcontroladores y éstos están configurados para recibirla. Ahora se mostrarán los diseños de los procesos que dependen de los datos transmitidos por la PC. 3.6.3 Generador de señales de activación (modo conexión pc) El microcontrolador PIC16C745 se encargará de realizar esta función, haciendo variar el estado lógico de un PIN a través de una función en lenguaje ensamblador (figura 3.29), en la cual se le deben de ingresar 6 números en los registros y así crear el retardo del semiperiodo, esto es, decrementando el valor de los 6 registros tanto para el tiempo en alto como para el tiempo en bajo. Tonos bsf lo banksel movf movwf movwf movf movwf movwf movf movwf movwf movf movwf movwf movf movwf movwf movf movwf movwf banksel outbuffer outbuffer,w over lower outbuffer+1,w over1 lower1 outbuffer+2,w over2 lower2 outbuffer+3,w over3 lower3 outbuffer+4,w over4 lower4 outbuffer+5,w over5 lower5 PORTA ok decf btfss goto ok1 decf btfss goto ok2 decf btfss goto ok3 decf btfss goto ok4 decf btfss goto ok5 decf btfss goto PORTA,00h over,f STATUS,2 ok over1,f STATUS,2 ok1 over2,f STATUS,2 ok2 over3,f STATUS,2 ok3 over4,f STATUS,2 ok4 over5,f STATUS,2 ok5 bcf o o1 o2 o3 o4 o5 btfss PORTA,00h decf lower,f btfss STATUS,2 goto o decf lower1,f btfss STATUS,2 goto o1 decf lower2,f btfss STATUS,2 goto o2 decf lower3,f btfss STATUS,2 goto o3 decf lower4,f btfss STATUS,2 goto o4 decf lower5,f btfss STATUS,2 goto o5 decf periodos,f STATUS,2 goto lo return Figura 3.29 Rutina para el generador de frecuencia o señales de activación. 90 Estos registros son rellenados con los datos recibidos por el puerto USB, y que a su vez fuerón enviados por el programa residente en PC. Poniendo a prueba esta función se generó la tabla 3.1. Tabla 3.1 Caracterización para el generador de frecuencia. registro1 registro2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 Registros registro3 registro4 registro5 registro6 1 1 1 125 1 1 1 150 1 1 1 175 1 1 1 200 1 1 1 225 1 1 1 250 1 1 1 255 1 1 25 255 1 1 50 255 1 1 75 255 1 1 100 255 1 1 125 255 1 1 150 255 1 1 175 255 1 1 200 255 1 1 223 255 1 1 225 255 1 1 239 255 1 1 250 255 1 1 255 255 1 2 255 255 1 21 255 255 1 25 255 255 1 40 255 255 1 50 255 255 1 62 255 255 1 75 255 255 1 85 255 255 1 100 255 255 1 110 255 255 1 125 255 255 1 137 255 255 1 150 255 255 1 167 255 255 1 175 255 255 1 199 255 255 1 200 255 255 1 225 255 255 1 234 255 255 Frecuencia (Khz) 5.6817 4.777 4.1208 3.6231 3.2327 2.9182 2.8625 2.6223 2.4115 2.2321 2.0775 1.9429 1.8248 1.7201 1.6268 1.55 1.5432 1.5 1.4677 1.4534 1.45 1.4 1.3888 1.35 1.3274 1.3 1.2712 1.25 1.2195 1.2 1.1718 1.15 1.1278 1.1 1.0869 1.05 1.0489 1.0535 1 Número 125 150 175 200 225 250 255 280 305 330 355 380 405 430 455 479 480 495 505 510 512 531 535 550 560 572 585 595 610 620 635 647 660 677 685 709 710 735 744 91 En la tabla 3.1, los registros con el número 1 dentro significan un cero en la función de ensamblador, esto es debido a que los retardos son generados con decrementos y aunque el número 1 es un valor mínimo, este genera ilapsos de tiempo (tiempo que no son tomados en cuenta por el programa) en los semiperiodos. La columna “número” es el resultado de la suma de los 6 registros representando el retardo del semiperiodo. Y la columna “‘frecuencia” representa la frecuencia que se generó con dicho retardo. Graficando la columna frecuencia contra la columna número se obtiene la figura 3.30. Figura 3.30 Gráfica de la tabla 3.1 Se puede ver claramente que la función no es lineal, debido a que los ilapsos son diferentes para cada frecuencia a generar, este problema se resuelve con una ecuación de sexto orden; con esto, es posible obtener un número y se podrá generar la frecuencia deseada con un mínimo de error. Con la ayuda del programa MATLAB se consigue la ecuación. 92 Introduciendo los datos y con la función polyfit se obtiene la siguiente ecuación: Y = 1.01983321076x6 - 21.76684340806x5 + 189.46208279318x4 867.57740836853x3 + 2246.43786488113x2 - 3275.43053009874x + 2474.90135900252 Siendo X la frecuencia generar en Khz y Y el número necesario para generarla. Graficando esta ecuación, da como resultado la línea que muestra la figura 3.30. Figura 3.31 Comparación de la ecuación obtenida y los datos de la tabla 3.1. La figura 3.31 nos muestra, que la ecuación nos ayudará a generar la frecuencia deseada con un error mínimo. Los asteriscos representan los datos de la tabla 3.1 y la línea continua representa la ecuación obtenida. 93 3.6.4 Generador de señales de activación (modo conexión plc) En este modo de funcionamiento, el generador de señales se encuentra en el PIC16F628. Para generar las frecuencias de activación se utiliza el mismo método (mencionado en la sección anterior), sólo que este PIC utiliza un cristal de 8 Mhz. y la rutina para generar la frecuencia se realizó de forma diferente, es por eso, que en esta rutina (figura 3.32) se utilizó solo un registro para el retardo del semiperiodo, y en consecuencia, se necesitó caracterizar de nuevo, obteniendo los resultados de la tabla 3.2 y la figura 3.33, en la tabla 3.2 la variable número representa el valor que debe de contener el registro para el retardo del semiperiodo en la rutina de la figura 3.32, por lo que dicho número genera su correspondiente frecuencia. Periodo call TONO decf aux3,f ;decrementar no. de veces ; de periodos btfss estado,Z ;checar si ya acabo en no. ;de periodos goto Periodo TONO bsf call bcf call return portb,0x07 RETARDO portb,0x07 RETARDO RETARDO movf ret,w ;número con el retardo movwf var1 ;del semiperiodo Bucle2 decf var1,f btfss estado,Z goto Bucle2 return ;estado en alto ;retardo del semiperiodo ;estado en bajo ;retardo del semiperiodo Figura 3.32 Rutina para el generador de señales. Tabla 3.2 Caracterización para el generador de frecuencia. Número Frecuencia Número Frecuencia 249 239 229 219 209 199 189 179 169 159 149 145 139 0,994 1,035 1,08 1,128 1,182 1,24 1,305 1,377 1,457 1,548 1,65 1,607 1,767 129 119 109 99 89 79 69 59 49 48 47 46 45 1,901 2,057 2,242 2,463 2,732 3,067 3,496 4,065 4,854 4,95 5,051 5,155 5,263 94 Con los datos de la tabla 3.2 se obtiene la siguiente gráfica: Figura 3.33 Caracterización del generador de señales de activación. Al igual que la otra función de ensamblador para generar las señales de activación (mencionado en la sección anterior), se observa en la figura 3.33 que no es una función lineal, por lo que se utilizó el mismo método para resolverlo. En MATLAB se obtiene la siguiente ecuación: Y = 0.29124078463x6 - 6.32150481492x5 + 56.25953631003x4 - 264.41332239284x3 +703.60080448892x2 - 1051.76677189924x + 809.77563804734 Al graficar los datos de la tabla 3.2 y la ecuación obtenida (figura 3.34), se puede apreciar el acercamiento del resultado de la ecuación con los datos originales de la tabla. 95 Figura 3.34 Comparación de la ecuación y los datos de la tabla 3.2. Donde los puntos nos indica la matriz de datos originales y la línea continua es lo que la ecuación genera, indicándonos que al generar las señales de activación tendrán un mínimo de error. A continuación se explicará el diseño de las rutinas que atenderan la recepción de datos hasta la generación de señales de activación. Hay que recordar que explicamos hasta la inicialización de microcontroladores y hay un hueco entre esta sección y la generación de señales de activación. 3.6.5 Recepción de datos y claves de conmutación (modo conexión pc) Una vez que llegaron los datos al PIC16C745 por el puerto USB, éste tiene que informar al PIC16F628 que tiene que encender el transmisor, esto es, para poder transmitir la frecuencia de activación. Esto se realiza transmitiendo por el puerto serie 96 síncrono una clave que el PIC16F628 lo interpretará como encendido de la etapa del transmisor (figura 3.35). Figura 3.35 Clave1 (arriba línea de dato, abajo línea de reloj). Después de transmitir esa clave, entra en una etapa de retardo (0.5 seg.), este retardo fue necesario debido a que la velocidad de los PICS es alta y al ejecutar la siguiente instrucción el transmisor no se encuentra encendido totalmente, esto se sabe a simple vista ya que la fuente de voltaje con la que se alimenta el módulo, tiene una aguja que indica la corriente o el consumo del módulo maestro, y esta aguja no llega a deflexionarse totalmente. Este retardo se calculó a prueba y error con la ayuda de un LED (figura 3.36) y viendo la deflexión de la aguja. Se fue aumentando el tiempo de este retardo hasta cuando se observara lo siguiente: Para cuando se encendía el LED, la aguja ya debería estar deflexionada totalmente, por lo que el encendido del LED indicaba el fin del retardo. Figura 3.36 Led indicador. 97 Después del retardo se genera la señal de activación (explicado en la sección 3.6.3), al terminar éste, se transmite nuevamente por el puerto serie síncrono otra clave (figura 3.37) para el PIC16F628, ya que con esto, se logra apagar la etapa del transmisor. Más tarde, entra a un ciclo dónde checa el estado de un PIN de control, en el cual el PIC16F628 le indica al PIC16C745 que está listo para enviarle los datos de humedad por medio del puerto serie síncrono. Figura 3.37 Clave2 (arriba línea de dato, abajo línea de reloj). Mientras en el PIC16F628, la clave1 es recibida por medio del puerto serie síncrono, cuando la recepción de la clave se completa, se produce una interrupción que lo saca del ciclo ocioso y entra en el RSI (rutina de servicio de interrupción), allí identifica que interrupción se efectuó, y en el caso de las claves salta a la interrupción serie (figura 3.38), después verifica el tipo de clave que recibió. Si es la clave1 el PIC16F628 enciende la etapa del transmisor poniendo en estado alto un PIN de control. recep_rx btfss retfie movf subwf btfss goto bsf retfie mm pir1,RCIF rcreg,w clave1,w estado,2 mm portb,0x06 movf subwf btfss Retfie bcf call bcf btfss goto bsf Retfie rcreg,w clave2,w estado,2 portb,0x06 delay rcsta,CREN portb,0x05 tt intcon,INTE Figura 3.38 Rutina de interrupción serie síncrona. 98 Si es la clave2 apaga la etapa del transmisor poniendo en estado bajo, el PIN de control antes mencionado, y después entra a un retardo (0.87 seg.). Este retardo fue necesario debido a que la velocidad del PIC es alta y el transmisor no se encuentra apagado totalmente cuando entra a la siguiente función, además tiene que esperar a que el módulo esclavo le envíe los datos de humedad. Este retardo se calculó a prueba y error con la ayuda de un LED (figura 3.39) y observando el osciloscopio. La punta del osciloscopio se conecta en el PIN dónde el PIC recibe la señal por parte de la etapa de adecuación, y se debe de observar que el LED debe de encender cuando en el osciloscopio se obtiene la señal de dato y se encuentre estable, por lo que el encendido del LED indica el fin del retardo. Figura 3.39 Led indicador para cálculo de retardo. 3.6.6 Recepción y apilamiento de datos en ram (modo conexión plc) Una vez lleguen los datos en el PIC16C745 por parte de la PC (sección 3.5.2), se verifica si es el primer paquete de 8 bytes enviados (figura 3.40), si es el caso, el primer byte indica el número de paquetes que se enviarán por el puerto, es por eso que se pasa a una función llamada “ndatos” para obtener ese byte y después se pasa el paquete a memoria RAM. Si no es el primer paquete, pasa directamente a almacenar los datos a la memoria RAM. Después de esos casos, verifica si ya se recibieron todos los paquetes, si no es el caso entra al ciclo en espera de datos, si es el caso, se transmiten todos los datos por el puerto serie síncrono hacia el PIC16F628. 99 bcf btfss call call decf btfss goto call goto STATUS,C aux6,0x00 ndatos buffer_ram aux7,f STATUS,2 EndLoopForData ram_serial EndLoopForData buffer_ram ram_serial clrf aux1 movlw 0x41 movlw 0x08 movwf FSR movwf aux movf INDF,w dat1 movwf aux movlw outbuffer decf FSR,f movwf FSR dat2 movf aux1,w movf INDF,w addwf FSR,f movwf TXREG movf INDF,w incf FSR,f ndatos movwf aux2 decf aux,f banksel outbuffer movlw 0x40 btfsc STATUS,2 movlw outbuffer movwf FSR return movwf FSR movf aux3,w Movlw .100 movf INDF,w addwf FSR,f movwf W_save movwf aux7 movf aux2,w decfsz W_save,f movwf aux5 movwf INDF goto $-1 bsf aux6,0x00 incf aux1,f goto dat2 return incf aux3,f return decf aux,f btfss STATUS,2 goto dat1 return Figura 3.40 Rutina para la recepción y transmisión de datos. El PIC16F628 recibe los datos por el puerto serie síncrono, y clasifica esta información obteniendo el número de transductores del sistema y el tiempo de barrido para el temporizador, los demás datos son apilados en memoria RAM para después habilitar la interrupción del TMR0 (figura 3.41). recep_rx btfss retfie movf movwf incf btfss goto movf movwf movwf decf decf ok datos incf fsr,f movlw 0x31 btfss pir1,RCIF movwf fsr rcreg,w goto $-1 movf INDF,w INDF movf rcreg,w movwf frec fsr,f movwf INDF movlw 0x05 pir1,RCIF decf var1,f subwf frec,f $-1 btfsc estado,Z incf fsr,f rcreg,w goto algo movf INDF,w INDF goto ok movwf seg var1 algo incf fsr,f var1,f call datos movf INDF,w var1,f bcf rcsta,CREN movwf min bcf intcon,TOIF incf fsr,f clrf tmr0 movf INDF,w bsf intcon,TOIE movwf hor bcf portb,0x03 return retfie Figura 3.41 Rutina para la recepción serie síncrona de datos y su clasificación. pir1,RCIF 100 Cada vez que se desborde este contador (TMR0), se incrementan variables que representa el tiempo de un segundo, al llegar a este tiempo, se incrementa el temporizador y se verifica si es igual al tiempo de barrido (el tiempo de barrido se encuentra dentro de los datos de información, que se recibieron por el puerto serie síncrono), si no son iguales, se regresa al ciclo ocioso. Si son iguales, se encuentra la frecuencia a generar dentro de los datos de información y se enciende el transmisor, para luego entrar a un retardo (0.097 seg) este retardo fue necesario para que el transmisor encendiera completamente. Después se genera la señal de activación (sección 3.6.4) y luego se envía a otro retardo (0.87 seg.). Este retardo se utiliza para la espera de datos que el módulo esclavo nos enviará vía RF. Servicio btfss goto btfss retfie bcf incf btfss retfie incf movf subwf btfss retfie clrf incf btfsc incf btfsc incf movf subwf btfss retfie intcon,TOIE recep_rx intcon,TOIF intcon,TOIF overflow1,f estado,Z overflow2,f var2,w overflow2,w estado,Z overflow2 aux1,f estado,Z aux2,f estado,Z aux3,f seg,w aux1,w estado,Z movf subwf btfss retfie movf subwf btfss retfie clrf movlw movwf movf movwf bsf cambio bsf call movlw movwf incf movf movwf min,w aux2,w estado,Z hor,w aux3,w estado,Z aux1 0x34 fsr frec,w cnt portb,0x04 portb,0x06 delay 0xFF aux3 fsr,f INDF,w ret nperiodos call decf btfss goto bcf call bcf rlf movwf incf call clrf decf btfss goto clrf clrf bcf clrf incf retfie TONO aux3,f estado,Z nperiodos portb,0x06 delay2 estado,C trans,w porta trans,f delay2 porta cnt,f estado,Z cambio aux2 aux3 portb,0x04 trans trans,f Figura 3.42 Rutina para el temporizador. Para calcular el número de incrementos que el contador TMR0 debe realizar en un segundo, se realizó a prueba y error con la ayuda de un LED que se encendía y apagaba, verificando visualmente que la duración del encendido y el apagado fueran de un segundo. 101 Con esto se logró que el temporizador se incrementará cada segundo, y en cada incremento se verificará con el tiempo de barrido que el usuario programó. Todo el funcionamiento del temporizador es realizado por la rutina que la figura 3. muestra. Después de este retardo se manda por medio de cuatro pines el número del transductor que se activo (figura 3.11), el PLC deberá interpretar esto como un control y que debe de medir la frecuencia. Hasta esta sección, se a diseñado los procesos de transmisión de datos desde la PC hasta generar el tono de activación en ambos modos de conexión, a continuación se presentará el diseño de los procesos realizados por el módulo esclavo (PIC16F873), y que son independiente del modo de conexión. 3.6.7 Detector de frecuencia válida Como su nombre lo indica, esta función se encarga de detectar una frecuencia válida. Es necesaria debido a que en el ambiente se encuentran señales portadoras que coinciden tener una señal moduladora a la frecuencia de activación (figura 3.43). Sin esto, haría que el módulo esclavo se active sin ser realmente activado por el módulo maestro, también es necesario debido, a que todos los módulos esclavos tanto como el maestro utilizarán una señal portadora de 81 Mhz, lo que significa, que a todos los módulos le estarán llegando las señales de activación, pero sólo uno se activará debido a que cada módulo esclavo está programado para activarse con una señal moduladora diferente. Figura 3.43 Ruido presente en estado de reposo (osciloscopio y acercamiento). 102 Si la señal de dato de humedad, de un módulo esclavo activado, llegará a generar una frecuencia exactamente igual a la señal de activación de algún otro módulo esclavo, para cuando éste último se active, el módulo maestro ya habrá capturado el dato y no creará conflicto en el sistema. Para realizar todas estas funciones se midió el tiempo del periodo de la señal, esto es posible detectando los filos de la frecuencia de la señal a medir, una vez medido el periodo, se determina si se encuentra dentro de un rango de error, si lo está, se incrementa un contador, si no, el contador toma el valor de cero. Con cada incremento del contador verifica si ya llegó a 5 comparaciones positivas, si es el caso, significa que la frecuencia de activación es válida. Cuando no se cumple ese número de veces, significa que el ruido coincidió con la frecuencia de activación, pero no se mantuvo un tiempo requerido para identificarla como señal válida. Los umbrales de frecuencia, significan el rango de frecuencias a la que el módulo esclavo se activará o también se le puede llamar rango de error, esto es necesario debido a que en el ambiente es muy difícil de predecir que la señal moduladora no sufrirá cambios de frecuencia en el trayecto o transmisión. Los umbrales de frecuencia se calculan de la siguiente manera: Por ejemplo: para validar la frecuencia de activación de 1 Khz se calcula los tiempos para las frecuencias superior e inferior con un rango de error de 10 Hz. arriba y debajo de la frecuencia que se pretende activar. 990 Hz. y 1010 Hz. dan 0.00101 seg. y 9.900099 seg. respectivamente. Ahora, es necesario saber hasta qué número tiene que contar el temporizador del PIC para detectar si la frecuencia medida esta en el rango de error. Este número depende de la frecuencia del cristal, y el PIC cuenta con uno de 8 Mhz. cada cambio en la cuenta del temporizador depende de 4 ciclos del cristal y la forma en que se encuentre configurado un prescalador y en algunos casos un postescalador. 103 Velocidad de cambio en el temporizador = Tiempo de cambio del temporizador = 1)Umbral Inferior = 8Mhz = 2Mhz. 4 1 = 500 Nanosegundos 2 Mhz. .00101 2020 = 2020.2 conteos è = 7.9235 conteos 5E - 7 255 (7.9235-7)x255 = 235.2 2)Umbral Superior = 9.900099 1980 = 1980.18 conteos è = 7.7654 conteos 5E - 7 255 (7.7654-7)x255 = 195.18 La medición de frecuencia da como resultado dos números, uno significa los sobreflujos del temporizador y el otro hasta donde alcanzó el temporizador a contar antes de generarse el fin del periodo, es obvio que se debe comparar si el sobreflujo medido es igual a 7 y el otro número, si está entre los números 195 y 235, las cuales definen el rango de error. 3.6.8 Generador de señal de dato El objetivo es convertir el voltaje del transductor a su correspondiente frecuencia que representará el dato de humedad, esto se realiza por medio del ADC interno del microcontrolador, el voltaje es convertido a un dato de 10 bits, y a su vez, esos 10 bits son convertidos a otro dato, que es necesario para generar la respectiva señal de dato o frecuencia. Primero se realizó una función en ensamblador (figura 3.44) para generar el ancho de banda en la que se transmitirá el dato de humedad. Hay que recordar que el sistema de RF trabaja de 1 a 5 Khz, de esta función obtuvimos el resultado que muestra la tabla 3.3. 104 nperiodos call decf btfss goto decf btfss goto TONO bsf call bcf call return RETARDO TONO vuelta2,f estado,Z nperiodos vuelta,f estado,Z Hola movf sobra,w movwf cont Bucle2 decf cont,f btfss estado,Z goto Bucle2 Return porta,0x01 RETARDO porta,0x01 RETARDO Figura 3.44 Rutina para el generador de datos o frecuencia. Tabla 3.3 Caracterización del generador de datos. Número Frecuencia (Khz) 249 246 205 184 165 145 1 1.089 1.204 1.319 1.457 1.607 Número Frecuencia (Khz) 123 105 85 64 44 1.845 2.164 2.732 3.594 4.854 El ADC interno del PIC tiene una resolución de 10 bits, lo que significa que tendremos: 210 = 1024 cambios 5 = 0.004882 volts por cada cambio. 1024 Para cero volts necesitamos generar una frecuencia de 1Khz y observamos que en la tabla 3.4 el número 249 logra generarlo, esto significa que debemos convertir el número cero que nos entregará el ADC al número 249 para generar esa frecuencia, pero también, para 5 volts el ADC nos entregará el número 1023, según la tabla 3.4 necesitamos convertir este número al número 44. Para el caso de cero volts se resuelve restando al número 249 el número que entrega el ADC, pero para el caso de 5 volts no funcionará, así que, se necesita 105 convertir primero el número 1023 a un número que si le restamos 249 nos pueda dar como resultado el 44 que deseamos. La operación que nos acerca a este número es dividir el número que nos entrega el ADC entre 5. ADC Cálculo 1 con 0 volts obtenemos el No. 0 => con 5 volts obtenemos el No. 1023 => 0 = 0 5 Cálculo 2 => 249 – 0 = 249 1023 = 204.6 => 249 – 204.6 = 44.4 5 Figura 3.45 Cálculo del número necesario para generar la frecuencia de dato. Aplicando estos cálculos se obtiene una pérdida de resolución, debido a que sólo se toma la parte entera del cálculo y esto ocasiona que genere la misma frecuencia cada 4 cambios de conversión del ADC, obteniendo como resultado lo siguiente: Tabla 3.4 Adecuación ADC. Volts 0 0.053757 1.060479 1.568727 2.037879 2.54124 3.064149 3.513753 4.002453 4.500927 4.999401 ADC 0 11 217 321 417 520 627 719 819 921 1023 ADC/5 0 2.2 43.4 64.2 83.4 104 125.4 143.8 163.8 184.2 102.3 249-(ADC/5) 249 246.8 205.6 184.8 165.6 145 123.6 105.2 85.2 64.8 204.6 Frecuencia (Khz) 1 1.089 1.204 1.319 1.457 1.607 1.845 2.164 2.732 3.594 4.854 Desde que alimenta al PIC16F873, se encuentra rechazando el ruido por medio de la proceso “detector de frecuencia valida”. En este proceso, detecta los flancos de subida, y si es el primero se inicia el contador con el TMR0 y regresa al ciclo ocioso, si es el segundo, se determina si la muestra está dentro del rango de error (figura 3.46), en caso de que no esté, se inicializa a cero el número de muestras y se 106 aplican las condiciones iniciales 1, esto es, colocar valores a las variables que permitan las subsecuentes muestras, de allí se regresa al ciclo ocioso. Puerto Ruido movf tmr0,w ;tmr0 a w clrf porta movwf cont ;w a cont Salir movlw 0x07 ;7 a w clrf w subwf overf,w ;f-w overf-7 clrf overf btfss estado,Z ;z=1? clrf sobra goto Noes clrf veces movlw 0xE4 ;228 a w movlw 0x01 subwf cont,w ;f-w cont-228 movwf cont btfsc estado,C ;c=0? cont<228 movlw 0xF9 goto Noes movwf cte movlw 0xBC ;188 a w movlw 0x14 subwf cont,w ;f-w cont-188 movwf vuelta btfss estado,C ;c=1? cont>188 bcf intcon,TOIF goto Noes bcf intcon,TOIE decf palta,f bcf intcon,INTF btfss estado,Z ;z=1? bsf intcon,INTE goto Ruido retfie Noes movlw 0x05 movwf palta Figura 3.46 Rutina para determinar el rango de error de la muestra de frecuencia. Si se encuentra dentro del rango de error, se incrementa el número de muestras y se verifica que ya se hayan realizado 4 de ellas, en caso negativo, se aplican las condiciones iniciales 1 antes mencionadas y regresa al ciclo ocioso, en caso positivo, se prepara el ADC (figura 3.47) e inicia la conversión (ver sección 3.6.8). La conversión consiste en obtener la muestra de humedad en forma de voltaje, se logra encendiendo la etapa “circuito del transductor” (ver figura 3.8 en la sección 3.2) dejando en estado alto un PIN de control. Después se deja un retardo para que la etapa antes mencionada se encienda totalmente. El valor de este retardo es desconocido, debido a que este circuito se encuenta en desarrollo todavía (tesis en desarrollo de Jesús Francisco Camou Orduño). Después el ADC obtiene la información de voltaje. 107 bsf bcf bcf call bsf call porta,0x05 ;enciendo oscilador intcon,INTE intcon,TOIE DELAY adcon0,ADON DELAY bsf adcon0,GODONE Per Chk movlw movwf 0xFF vuelta2 movlw 0x0A subwf btfss goto incf goto pbaja,f estado,C Alta veces,f Resta DIV Resta btfss pir1,ADIF goto Chk Alta bcf pir1,ADIF addwf pbaja,w bcf porta,0x05 addwf sobra,f bsf porta,0x02 movlw 0x01 call DELAY subwf palta,f movf adresh,w btfss estado,C movwf palta return bsf estado,RP0 movlw 0xFF movf adresl,w movwf pbaja bcf estado,RP0 goto DIV movwf pbaja call DIV CALC movf sobra,w bcf estado,C movwf pbaja rlf veces,f clrf palta movf veces,w call DIV subwf cte,w call CALC return movwf sobra Figura 3.47 Rutina para la adquisición de dato y proceso de cálculo. Una vez se tenga esta información, se apaga la etapa “circuito del transductor” y se enciende el transmisor, después de eso, la información es enviada a un proceso de cálculo (figura 3.36), para poder generar la señal de dato. Terminado el cálculo se genera dicha señal de dato (explicado en la sección 3.6.8), se aplican las condiciones iniciales 2 y regresa al ciclo ocioso. Las condiciones iniciales 2 son las condiciones y valores de las variables que permitirán las subsecuentes activaciones. Hasta esta sección se concluye con el diseño de los procesos realizados por el módulo esclavo (PIC16F873), también se finalizó el diseño de los procesos para el módulo maestro, en el caso donde el modo de conexión es con el PLC, debido a que faltaba diseñar los procesos del módulo esclavo, y a que el PLC se encargará de adquirir los datos de humedad generados en esta sección. En la sección siguiente mostraremos los procesos del módulo maestro faltantes, para finalizar con el proseso general de activación de transductores. 108 3.6.9 Medición de frecuencia El módulo esclavo devuelve una frecuencia que representa el dato de humedad. es necesario medir esta frecuencia y sea enviada al software de la PC, para ser interpretada como una cantidad de humedad. Cabe mencionar que esta rutina (figura 3.48) sólo se presenta en el modo de funcionamiento donde el módulo maestro estará conectado con la PC. y la realiza el PIC16F628. Servicio btfss goto decf btfss goto clrf bcf bcf bsf retfie Tmr0int btfss goto btfss retfie incf bcf retfie muestra movf movwf movlw subwf movwf incf movf movwf incf clrf clrf incf bcf bcf bcf decf btfss retfie movlw movwf intcon,INTF Tmr0int cont,f estado,Z muestra tmr0 intcon,INTF intcon,TOIF intcon,TOIE intcon,TOIE recep_rx intcon,TOIF overflow,f intcon,TOIF tmr0,w resta 0x0C resta,w INDF fsr,f overflow,w INDF fsr,f overflow cont cont,f intcon,TOIF intcon,TOIE intcon,INTF var1,f estado,Z 0x04 var1 ;<checa si la interrupcion es externa> ;<no es ext.> ;dec. contador ;esta la Z=1? ;<termino un periodo> ;borra el TMR0 ;bandera de int. ext. a 0 ;bandera de overf a 0 ;habilita int. de overf TMR0 ;esta hab. la int. del TMR0? ;no es int. TMR0 ;<checa si la interrupcion es de overf del TMR0> ;no es int. TMR0 ;incremento el contador de sobreflujos ;bandera de overf a 0 ;resguardo el valor del TMR0 ;preparo la resta de los ilapsos ;ocasionados por el número de códigos ;que se ejecutan, desde que se ocasiona ;la interrupción. <guardo sobra en RAM> ;apunto a la siguiente dirección RAM ;<guardo overflow en RAM> ;apunto a la siguiente dirección RAM ;<cond. para otra muestra> ;<cont=1 y overflow=0> ;bandera de overf a 0 ;deshabilita int. de overf TMR0 ;deshabilita int. de overf TMR0 ;bandera de int. ext. a 0 ;<¿ya son 4 muestras?> ;<condiciones para otras 4 muestras> ;<var1 = 4> Figura 3.48 Rutina para el medidor de frecuencia. 109 Esta medición se llevó acabo por medio de una función en ensamblador (figura 3.48), que mide el periodo de la señal, esto es posible detectando los flancos de subida de la frecuencia a medir, como la medición de frecuencia no es lineal (ver tabla 3.5), la relación se realiza con el voltaje. Tabla 3.5 Caracterización del medidor de frecuencia. Voltaje 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1 1.1 1.2 1.3 1.4 1.5 1.6 1.7 1.8 1.9 2 2.1 2.2 2.3 2.4 2.5 2.6 Frecuencia (Khz) 1.002 1.018 1.035 1.052 1.07 1.089 1.108 1.128 1.149 1.171 1.193 1.24 1.24 1.253 1.278 1.305 1.347 1.362 1.392 1.424 1.457 1.492 1.529 1.587 1.607 1.65 Número 1975 1943 1911 1879 1846 1815 1784 1754 1720 1689 1656 1593 1593 1577 1543 1514 1465 1449 1417 1384 1354 1320 1289 1243 1228 1194 Voltaje Frecuencia (Khz) 2.7 2.8 2.9 3 3.1 3.2 3.3 3.4 3.5 3.6 3.7 3.8 3.9 4 4.1 4.2 4.3 4.4 4.5 4.6 4.7 4.8 4.9 5 5.1 1.695 1.742 1.792 1.845 1.872 1.901 1.992 2.057 2.127 2.202 2.283 2.369 2.463 2.564 2.674 2.732 2.924 3.067 3.226 3.311 3.496 3.704 3.937 4.202 5 Número 1162 1130 1098 1066 1050 1034 986 954 923 891 858 828 794 764 731 716 669 639 603 589 554 524 493 461 425 Con la tabla 3.5 se obtiene la gráfica de la figura 3.49, la medición es aceptable debido a la resolución. En el rango donde no es lineal, el error es aceptable ya que se manejará porcentaje de humedad. Se optó por graficar contra la variable voltaje, ya que los datos de frecuencia no son lineales, y es necesario tener una linealidad para relacionarla con la cantidad de humedad, también es debido a que el transductor (todavía en proceso de diseño), fue caracterizado en porcentaje de humedad contra voltaje. 110 Figura 3.49 Resultado de la medición de frecuencia. El PIC16F628 se encuentra en un ciclo oscioso antes de entrar a la función medición de frecuencia, esto se logra habilitando las interrupciones externas, estas interrupciones detectan los flancos de subida de la señal de dato, para medir el tiempo entre flancos se utilizó otro tipo de interrupción esta es la interrupción del TMR0. El TMR0 es un registro de 8 bits que cuenta desde el primer flanco hasta el segundo, como la velocidad de conteo del TMR0 es alta, este registro se desborda varias veces por lo que es necesario contar las veces que se desborda. Cuando se detecta el primer flanco de la señal de dato se habilita la interrupción del TMR0 y se inicializa el conteo, antes que se presente el segundo flanco, el TMR0 se desbordará y entrará al RSI para identificar la interrupción e incrementar el número de desbordamientos (este número cambiará dependiendo de la frecuencia del dato), 111 cuando llega el segundo flanco, se revisa que ya se hallan realizado 4 muestras de frecuencias de dato, sino es el caso se dan las condiciones iniciales para que se realice otra muestra. Una vez terminadas las muestras, se pone en estado alto un PIN de control, para avisar al PIC16C745 que le serán enviados por el puerto serie síncrono los datos de humedad (figura 3.50). Después de enviar los datos por el puerto serie, se dejan las condiciones iniciales en las variables y entra al ciclo ocioso. transmitir bsf movlw movwf movlw movwf bsf bsf bcf bsf otra incf movf movwf bsf ansina portb,0x03 0x08 aux1 0x37 fsr estado,RP0 txsta,TXEN estado,RP0 porta,0x00 fsr,f INDF,w txreg estado,RP0 btfss goto bcf decf btfss goto txsta,TRMT ansina estado,RP0 aux1,f estado,Z otra bcf clrf clrf bsf bsf bcf bcf movlw movwf bcf retfie portb,0x03 portb porta rcsta,CREN estado,RP0 txsta,TXEN estado,RP0 0x30 fsr intcon,INTE salir Figura 3.50 Rutina de servicio de interrupción serie síncrona. El PIC16C745 quedó en un ciclo checando el estado lógico del pin de control, por el cual el PIC16F628 le indicaría el incio de transmisión serie síncrona de los datos del muetreo de frecuencia, pues bien, si el PIN esta en estado alto, el PIC16C745 entra a la rutina de recepción serie síncrono, adquiriendo los datos de humedad del PIC16F628. Una vez adquiridos los datos de humedad en el PIC16C745, se envían los datos por el puerto USB y regresa al ciclo de espera de datos por el mismo puerto. La figura 3.51 muestra la rutina donde el PIC16C745 envía las claves de conmutación, genera los tonos de activación, checa el estado del PIN de control, recibe y transmite los datos del muestreo de frecuencia. 112 Banksel movf movwf call call banksel movf movwf clave1 clave1,w TXREG delay2 tonos clave2 clave2,w TXREG ;selecciono el banco donde se encuentra la variable clave1 ;valor de la clave1 al acumulador ;envío la clave 1 para encender el transmisor ;tiempo necesario para que el transmisor encienda ;transmito el tono de activación del transductor (tabla 3.1) btfss goto movlw movwf movlw movwf bsf call PORTA,02 andale 0x50 FSR 0x08 aux PORTA,01h ini_rx ;por esta línea, el esclavo me avisa que ya muestreó ;4 tonos y está listo para enviarlos btfss goto movf movwf incf decf btfsc goto nop nop nop nop nop nop nop nop nop nop nop nop nop bsf goto PIR1,RCIF recep RCREG,w INDF FSR,f aux,f STATUS,2 acabar ;envío la clave 2 para apagar el transmisor andale ;8 datos serán enviadas a ram ;a partir de la dirección 50 banco 0 ;esta variable servirá como contador de las 4 lecturas ;modo RX=on TX=off del puerto serie síncrono recep ;hay 8 bits recibidos ;registro del byte recibido ;lo guarda en ram ;incremento puntero ;decremento el contador de las lecturas ;ya son 8 datos? ;si... son 8 lecturas, hay que salir ;retardo para que el pic16f628 pueda preparar el envío del ;siguiente byte 541.66 nanosegundos RCSTA,SREN recep ;mando otro tren de pulsos de reloj (modo maestro) ;hay que leer otra acabar bcf PORTA,01h call ini_tx ; modo RX=off TX=on del puerto serie síncrono Figura 3.51 Recepción de datos de humedad y transmisión por el puerto USB. Con esto se finaliza el diseño de los procesos para cada uno de los microcontroladores es sus 2 modos de conexión, y para hacer un resumen de esos procesos y mostrar los lugares donde se añadieron los retardos, se presentarán en las hojas de anexo 5. IV PRUEBAS Y RESULTADOS En esta sección, se mostrará el resultado final presentado por el programa residente en la PC, el módulo de despliegue que muestra el transductor activado en el modo interfaz con el PLC, además de ajustes y pruebas. 4.1 Pruebas y Ajustes Todas las pruebas se realizaron por medio de un divisor de voltaje, que simula la salida de voltaje del transductor de humedad, esto se realizó para poder llevar a cabo un mayor número de cambios posibles, ya que modificar la humedad a pasos específicos es difícil. A la salida de este divisor de voltaje se conectó un multímetro (FLUKE), para observar el voltaje aplicado al módulo esclavo (microcontrolador), los cambios de este divisor fueron de cada 100 milivolts empezando desde cero hasta 5 volts, el cual representa el 100% de humedad. Para poder comprobar diferentes frecuencias de activación en el módulo esclavo, se agregaron 2 jumpers y así poder cambiar la frecuencia de activación (figura 4.1), con esto se puede configurar 4 frecuencias de activación diferentes las cuales son 1000,1050,1100 y 1150 Hz. También se le agregó un push button para realizar activaciones sin que el módulo maestro intervenga y se pudieran hacer pruebas de transmisiones. El código adicional es el mostrado por la figura 4.2. Otra de las pruebas hechas fue ajustar la sincronización del retardo en la adquisición de dato de humedad (figura 4.3), donde el retardo se ajusta hasta que la señal de dato esté estabilizada, después se checa el nivel de la línea detector de portadora, si se encuentra en estado alto se realiza el muestreo. Al terminar éste se pone en alto el pin de control para dar aviso al PIC16C745 de una transmisión serie (prueba de caja blanca). 114 También en el modo interfaz con el PLC se realizaron pruebas, en las cuales se observó que se llevaran a cabo todas las activaciones de los transductores dados de alta en el sistema, y en los tiempos indicados. Esto se verificó por medio de un módulo de despliegue y viendo la señal de dato por medio del osciloscopio. Figura 4.1 Jumpers y push button para pruebas (1.- jumpers. 2.- Push button). clrf btfsc goto incf fa portc,0x02 mk fa,f movlw 0x31 ;49 a w movwf sb1 movlw 0x10 ;16 a w movwf sb2 mk goto ciclo btfsc portc,0x03 frec3 goto frec1 movlw 0x01 incf fa,f subwf fa,w incf fa,f btfss estado,0x02 frec1 goto frec4 movlw 0x03 movlw 0x07 ;7 a w subwf fa,w movwf of1 btfss estado,0x02 movlw 0x8A ;138 a w goto frec2 movwf sb1 movlw 0x06 ;6 a w movlw 0x65 ;101 a w movwf of1 movwf sb2 movlw 0xE0 ;224 a w goto ciclo movwf sb1 frec4 movlw 0xC2 ;194 a w movlw 0x07 ;7 a w movwf sb2 movwf of1 goto ciclo movlw 0xE4 ;228 a w frec2 movwf sb1 movlw 0x02 movlw 0xBC ;188 a w subwf fa,w movwf sb2 btfss estado,0x02 ciclo goto frec3 btfsc portc,0x04 movlw 0x07 ;7 a w goto ciclo movwf of1 goto Activar Figura 4.2 Rutina para configurar la frecuencia de activación del módulo esclavo. 115 Figura 4.3 Sincronización del retardo para la adquisición del dato de humedad. 4.2 Módulo de despliegue y su conexión En la entrada de la etapa de adecuación para el PLC (ver figura 4.4) se encuentran los 5 pines de datos conectados al cable de bus, donde 4 provienen del microcontrolador 16F628 y uno de la etapa de adecuación, todas las señales de datos varían de 0 a 5 volts. En la salida del módulo se encuentran las mismas señales de entrada, solo que invertidas y con tensiones de 0 a 24 volts que van hacia el conector db9, conector por el cual el PLC deberá tomar los datos. Figura 4.4 Etapa de adecuación para el PLC (1.- etapa de adecuación. 2.- cable de bus). 116 El módulo de adecuación para el PLC, consiste en transistores que son alimentados por el mismo PLC con 24 volts y su funcionamiento es entrar en estado de corte y saturación para variar los voltajes a la salida. El cable de bus es conectado a la entrada número 2 de la figura 4.5, para hacer contacto con los pines donde el microcontrolador proporcionará los datos. La entrada número 1 es para un módulo de despliegue (figura 4.6), el cual sirvió para verificar que efectivamente se estuviera mandando la información al conector db9, y de éste, hacia el PLC. Los 4 LEDs indican en número binario, el actual transductor activado, por lo que en las pruebas se verificaron que se activaran todas las que estuvieran dados de altas en el sistema y en el osciloscopio la frecuencia correspondiente. Figura 4.5 Receptores de cables (1.- módulo de despliegue. 2.- cable de bus). Figura 4.6 Módulo de despliegue para realizar pruebas. 117 La conexión final del módulo de despliegue y del cable de bus para realizar las prubas en el modo de conexión con el PLC lo muestra la figura 4.7. Figura 4.7 Conexión de cables para el interfaz con el PLC y módulo de despliegue. 4.3 Resultados En el modo interfaz con la PC, el resultado final es presentado en porcentaje de humedad, donde 5 Volts representan el 100% de humedad. Como ya habíamos mencionado, el resultado es casi lineal (ver tabla 3.5), así que se utilizó otra ecuación para llegar al resultado final por medio del programa MAT LAB y se obtiene lo siguiente. % de humedad = (0.00000002409442n2 - 0.00330379596851n + 6.51707742555624)*20% Donde n es el número que representa el semiperiodo de la señal de dato y se calcula a través de las variables OVERFLOWS y SOBRA que se obtienen de la medición de frecuencia. Cada volt representa el 20% de humedad. n = (overflows*255) + (sobra) Los valores de las variables OVERFLOWS y SOBRA, se obtienen de una de las 4 muestras realizadas por la función de medición de frecuencia (ver figura 4.1). 118 Tabla 4.1 Resultado final (voltaje de referencia del ADC a 5.2 volts). volts 0.1 0.2 0.4 0.5 0.6 0.7 0.8 0.9 1 1.1 1.2 1.4 1.5 1.6 1.7 1.8 1.9 2 2.1 2.2 2.4 2.5 2.6 2.7 2.8 2.9 3 3.1 3.2 3.4 3.5 3.6 3.7 3.8 3.9 4 4.1 4.2 4.4 4.5 4.6 4.7 4.8 4.9 5 frecuencia (Khz) 1.002 1.018 1.052 1.07 1.089 1.108 1.128 1.149 1.171 1.193 1.24 1.253 1.278 1.305 1.347 1.362 1.392 1.424 1.457 1.492 1.587 1.607 1.65 1.695 1.742 1.792 1.845 1.872 1.901 2.057 2.127 2.202 2.283 2.369 2.463 2.564 2.674 2.732 3.067 3.226 3.311 3.496 3.704 3.937 4.202 sobra 190 158 94 61 30 254 224 190 159 126 63 47 13 239 190 174 142 109 79 45 223 208 174 142 110 78 46 30 14 189 158 126 93 63 29 254 221 206 129 93 79 44 14 238 206 overflows 7 7 7 7 7 6 6 6 6 6 6 6 6 5 5 5 5 5 5 5 4 4 4 4 4 4 4 4 4 3 3 3 3 3 3 2 2 2 2 2 2 2 2 1 1 número 1975 1943 1879 1846 1815 1784 1754 1720 1689 1656 1593 1577 1543 1514 1465 1449 1417 1384 1354 1320 1243 1228 1194 1162 1130 1098 1066 1050 1034 954 923 891 858 828 794 764 731 716 639 603 589 554 524 493 461 porcentaje 1.7212737 3.77528588 7.88627096 10.0075402 12.0012037 13.9957934 15.9269233 18.1165858 20.1140139 22.2413259 26.3054726 27.3382459 29.5337084 31.4071892 34.5745676 35.6093147 37.6795492 39.8155121 41.7582074 43.9609773 48.9537219 49.9269995 52.1338982 54.2119971 56.2910829 58.3711556 60.4522152 61.4931151 62.5342618 67.7436958 69.7640096 71.8504664 74.0031586 75.9610622 78.1810683 80.1408224 82.2975538 83.2782332 88.3158012 90.6729881 91.5900092 93.8833884 95.8500818 97.8832428 99.9829611 119 La tabla 4.1 muestra el resultado de las pruebas realizadas y la relación de cada una de las variables medidas. Figura 4.8 Interpretación de la medición de frecuencia en porcentaje de humedad. V CONCLUSIONES Y RECOMENDACIONES Con los resultados mostrados se puede decir que se han cumplido con todos los objetivos y se concluye lo siguiente. Se ha diseñado un sistema de control para las etapas de radiofrecuencia, con el objetivo de transmitir activaciones y señales de datos de humedad, aplicado a un sistema de riego por goteo. Con este sistema no se requiere una transmisión contínua del porcentaje de humedad del área de cultivo, y por lo tanto, la duración de la batería de los módulos esclavos será más larga. Con la posibilidad de 2 modos de funcionamiento, se tiene la flexibilidad de aplicar este sistema para un simple control de riego o para otros controles más, como por ejemplo para un invernadero que controle sus correcciones de abono, fumigación, etc. por medio de la medición de otros parámetros como PH, calor, etc. o en una granja acuícola con parametros como oxígeno y nitrógeno. La interfáz del usuario para dar de alta, editar y manipular el sistema de monitoreo es amigable, la resolución de la medición de humedad mostrados en los resultados es aceptable, la designación de las frecuencias son flexibles ya que si se cambia el ancho de banda o la frecuencia de transmisión, los cambios en los programas serán mínimos. Por medio del control que ejerce el microcontrolador sobre las etapas, la interferencia entre ellas ya no afectan el dato de humedad o la frecuencia de activación como se presentaba antes de este trabajo de tesis. Este trabajo presenta una oportunidad para comprender la forma de trabajar del puerto USB, ya que se puede utilizar como una introducción a este puerto. 121 Aún faltan muchas mejoras de este sistema y se recomienda lo siguiente: En el modo PLC, se necesita guardar los datos de funcionamiento en la EEPROM del microcontrolador, ya que esos datos se encuentran en memoria RAM. En el software, no se tomó en cuenta en caso de que un transductor falle, entonces el software deberá reportarlo y continuar con el barrido de lectura, esto es, agregar código de detección de errores y su corrección. En la base de datos se puede hacer una estadística de las lecturas de humedad y mostrar gráficas. Los tiempos de retardos, se pueden reducir aún más, ya que los tiempos actuales que aparecen en el código fuente, son los necesarios para realizar las pruebas. En el tiempo de retardo para que se encienda el oscilador (módulo esclavo) y se estabilice, no es posible reducir su tiempo, debido a que el tiempo de encendido y la estabilización de su voltaje en la salida son lentos. 122 BIBLIOGRAFÍA [1].- Martín Cuenca, J.M. Angulo Usategui, I. Angulo Martinez. Microcontroladores PIC. Quinta edición. EDITORIAL PARAINFO THOMSON LEARNING. [2].- Jan Axelson. USB COMPLETE. Second and Third Editions. LAKE VIEW RESEARCH LLC. [3].- Steven McDowell, Martin D. Seyer. USB EXPLAINED. EDITORIAL PRENTICE HALL. [4].- www.usb.org. Universal serial bus Specification. Rev 1.1 Noviembre de 2005. 123 ANEXOS 124 ANEXO 1 Código completo PIC16C745 interfaz con la PC (archivo chicotex.asm) #include <p16c745.inc> #include "usb_defs.inc" aux8 aux9 errorlevel -302 __CONFIG _H4_OSC & _WDT_OFF & _PWRTE_OFF & _CP_OFF unbanked W_save bank0 udata Status_save PCLATH_save FSR_save outbuffer over over1 over2 over3 over4 over5 lower lower1 lower2 lower3 lower4 lower5 periodos periodos8 multiplo multiplo2 multiplo3 clave1 clave2 clave3 clave4 clave5 clave6 clave7 clave8 aux aux1 aux2 aux3 aux4 aux5 aux6 aux7 udata_shr res res res res res res res res res res res res res res res res res res res res res res res res res res res res res res res res res res res res res res 1 1 1 8 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 extern extern extern extern extern extern res res 1 1 InitUSB PutEP1 GetEP1 ServiceUSBInt CheckSleep RemoteWakeup 1 STARTUP code pagesel main goto main nop InterruptServiceVector movwf W_save movf STATUS,W clrf STATUS movwf Status_save movf PCLATH,w movwf PCLATH_save movf FSR,w movwf FSR_save Process_ISR btfsc INTCON,INTF nop btfsc INTCON,T0IF nop btfsc INTCON,RBIF nop BANKSEL PIR1 pagesel ServiceUSBInt btfsc PIR1,USBIF call ServiceUSBInt btfsc PIR1,ADIF nop btfsc PIR1,RCIF nop btfsc PIR1,TXIF nop btfsc PIR1,CCP1IF nop btfsc PIR1,TMR2IF nop btfsc PIR1,TMR1IF nop btfsc PIR2,CCP2IF nop EndISR clrf movf movwf movf movwf movf movwf swapf swapf retfie code STATUS FSR_save,w FSR PCLATH_save,w PCLATH Status_save,w STATUS W_save,f W_save,w main banksel TRISA clrf TRISC bsf TRISC,0x07 bsf TRISC,0x06 movlw 0x06 movwf ADCON1 clrf TRISA bsf TRISA,0x02 clrf TRISB banksel PORTA clrf PORTA clrf PORTB movlw .30 movwf W_save decfsz W_save,f goto $-1 BANKSEL OPTION_REG bcf OPTION_REG,NOT_RBPU pagesel InitUSB call InitUSB ConfiguredUSB call inicializar call ini_tx LoopForData pagesel GetEP1 banksel outbuffer bankisel outbuffer movlw outbuffer movwf FSR call GetEP1 pagesel tonos btfss STATUS,C goto LoopForData ;===================>PROCESOS call hand call datos ;******************************** pagesel PutEP1 bankisel outbuffer banksel outbuffer movlw outbuffer movwf FSR movlw 0x8 call PutEP1 EndLoopForData pagesel LoopForData goto LoopForData ;====================>FUNCIONES inicializar banksel SPBRG movlw 0x1A movwf SPBRG bcf PIE1,RCIE bcf PIE1,TXIE banksel PIR1 bcf PIR1,RCIF bcf PIR1,TXIF banksel periodos movlw 0x64 movwf periodos movlw 0xAA movwf clave1 movlw 0xBB movwf clave2 movlw 0xCC movwf clave3 return ini_tx banksel TXSTA movlw 0xB0 movwf TXSTA banksel RCSTA movlw 0x80 movwf RCSTA return ini_rx banksel TXSTA movlw 0x90 movwf TXSTA banksel RCSTA movlw 0xA0 movwf RCSTA return hand banksel clave1 movf clave1,w movwf TXREG call delay2 call tonos banksel clave2 movf clave2,w movwf TXREG Andale btfss goto movlw movwf movlw movwf bsf call PORTA,02 andale 0x50 FSR 0x08 aux PORTA,01h ini_rx btfss goto movf movwf incf decf btfsc goto nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop bsf goto PIR1,RCIF recep RCREG,w INDF FSR,f aux,f STATUS,2 acabar banksel outbuffer movlw outbuffer movwf FSR banksel aux1 movf aux1,w addwf FSR,f movf aux2,w movwf INDF incf aux1,f decf aux,f btfss STATUS,2 goto dat return recep tonos lo ok RCSTA,SREN recep acabar ok1 bcf PORTA,01h call ini_tx return ok2 datos movlw 0x08 movwf aux clrf aux1 ok3 dat movlw movwf movf addwf movf movwf 0x50 FSR aux1,w FSR,f INDF,w aux2 ok4 ok5 banksel outbuffer movf outbuffer,w movwf over movwf lower movf outbuffer+1,w movwf over1 movwf lower1 movf outbuffer+2,w movwf over2 movwf lower2 movf outbuffer+3,w movwf over3 movwf lower3 movf outbuffer+4,w movwf over4 movwf lower4 movf outbuffer+5,w movwf over5 movwf lower5 banksel PORTA bsf PORTA,00h decf over,f btfss STATUS,2 goto ok decf over1,f btfss STATUS,2 goto ok1 decf over2,f btfss STATUS,2 goto ok2 decf over3,f btfss STATUS,2 goto ok3 decf over4,f btfss STATUS,2 goto ok4 decf over5,f btfss STATUS,2 goto ok5 o o1 o2 o3 o4 o5 bcf decf btfss goto decf btfss goto decf btfss goto decf btfss goto decf btfss goto decf btfss goto decf btfss goto return PORTA,00h lower,f STATUS,2 o lower1,f STATUS,2 o1 lower2,f STATUS,2 o2 lower3,f STATUS,2 o3 lower4,f STATUS,2 o4 lower5,f STATUS,2 o5 periodos,f STATUS,2 lo delay2 si2 si1 si banksel multiplo movlw 0x0C movwf multiplo3 clrf multiplo2 clrf multiplo decf multiplo,f btfss STATUS,2 goto si decf multiplo2,f btfss STATUS,2 goto si1 decf multiplo3,f btfss STATUS,2 goto si2 return end PIC16C745 freeware (archivo descript.asm) #include <p16c745.inc> #include "usb_defs.inc" USBBANK global global global global global global global global global global global code Config_desc_index Report_desc_index Descriptions string_index DeviceDescriptor ReportDescriptor ReportDescriptorLen String0 String0_end StringDescriptions HID_Descriptor extern EP0_start extern temp extern temp2 Config_desc_index movwf temp movlw HIGH CDI_start movwf PCLATH movlw low CDI_start addwf temp,w btfsc STATUS,C incf PCLATH,f movwf PCL CDI_start retlw retlw low Config1 high Config1 Report_desc_index movwf temp movlw HIGH RDI_start movwf PCLATH movlw low RDI_start addwf temp,w btfsc STATUS,C incf PCLATH,f movwf PCL RDI_start retlw low ReportDescriptorLen retlw high ReportDescriptorLen Descriptions banksel EP0_start movf EP0_start+1,w movwf PCLATH movf EP0_start,w movwf PCL DeviceDescriptor StartDevDescr retlw 0x12 retlw 0x01 retlw 0x00 retlw 0x01 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x08 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x02 retlw 0x01 retlw 0x00 retlw NUM_CONFIGURATIONS Config1 retlw 0x09 retlw 0x02 retlw EndConfig1 - Config1 retlw 0x00 retlw 0x01 retlw 0x01 retlw 0x04 retlw 0x80 retlw 0x32 Interface1 retlw 0x09 retlw INTERFACE retlw 0x00 retlw 0x00 retlw 0x02 retlw 0x03 retlw 0x00 retlw 0x00 retlw 0x00 HID_Descriptor retlw (Endpoint1 - HID_Descriptor) retlw 0x21 retlw 0x00 retlw 0x01 retlw 0x00 retlw 0x01 retlw 0x22 retlw low (end_ReportDescriptor ReportDescriptor) retlw high (end_ReportDescriptor ReportDescriptor) Endpoint1 retlw 0x07 retlw ENDPOINT retlw 0x81 retlw 0x03 retlw 0x08 retlw 0x00 retlw 0x0A Endpoint2 retlw 0x07 retlw ENDPOINT retlw 0x01 retlw 0x03 retlw 0x08 retlw 0x00 retlw 0x0A EndConfig1 ReportDescriptorLen retlw low (end_ReportDescriptorReportDescriptor) ReportDescriptor dt 006h, 000h, 0ffh dt 009h, 001h dt 0a1h, 001h dt 019h, 001h dt 029h, 008h dt 015h, 000h dt 026h, 0ffh, 000h dt 075h, 008h dt 095h, 008h dt 081h, 002h dt 019h, 001h dt 029h, 008h dt 091h, 002h dt 0c0h end_ReportDescriptor StringDescriptions banksel EP0_start movf EP0_start+1,w movwf PCLATH movf EP0_start,w movwf PCL string_index movwf temp bcf STATUS,C rlf temp, f pagesel langid_index call langid_index movwf temp2 incf temp, f pagesel langid_index call langid_index movwf temp movf temp, w movwf PCLATH movf temp2,w addwf EP0_start+1,w btfsc STATUS,C incf PCLATH, f movwf PCL langid_index movlw high langids movwf PCLATH movlw low langids addwf temp, w btfsc STATUS,C incf PCLATH,f movwf PCL langids retlw low lang_1 retlw high lang_1 retlw low lang_2 retlw high lang_2 lang_1 retlw low String0 retlw high String0 retlw low String1_l1 retlw high String1_l1 retlw low String2_l1 retlw high String2_l1 retlw low String3_l1 retlw high String3_l1 retlw low String4_l1 retlw high String4_l1 retlw low String5_l1 retlw high String5_l1 lang_2 retlw low String0 retlw high String0 retlw low String1_l2 retlw high String1_l2 retlw low String2_l2 retlw high String2_l2 retlw low String3_l2 retlw high String3_l2 retlw low String4_l2 retlw high String4_l2 retlw low String5_l2 retlw high String5_l2 String0 retlw low (String1_l1 - String0) retlw 0x03 retlw 0x09 retlw 0x04 retlw 0x04 retlw 0x08 String0_end String1_l1 retlw retlw retlw retlw retlw retlw retlw retlw 0x00 retlw retlw retlw retlw retlw retlw retlw retlw retlw retlw retlw retlw String2_l1 retlw retlw retlw retlw retlw 'U' retlw retlw retlw retlw retlw retlw retlw retlw retlw retlw retlw retlw retlw retlw retlw retlw retlw 0x00 retlw retlw retlw retlw retlw retlw String2_l1-String1_l1 0x03 'C' 0x00 'H' 0x00 'I' 'C' 0x00 'O' 0x00 'T' 0x00 'E' 0x00 'X' 0x00 '.' 0x00 String3_l1-String2_l1 0x03 'J' 0x00 0x00 'A' 0x00 'N' 0x00 '' 0x00 'C' 0x00 'A' 0x00 'R' 0x00 'L' 0x00 'O' 'S' 0x00 '.' 0x00 '' 0x00 String3_l1 retlw retlw retlw retlw retlw retlw retlw retlw retlw retlw retlw retlw String4_l1 retlw retlw retlw retlw retlw retlw retlw retlw retlw retlw String5_l1 retlw retlw retlw retlw retlw retlw retlw retlw retlw retlw retlw retlw retlw retlw retlw retlw String1_l2 retlw retlw retlw retlw retlw retlw retlw retlw retlw retlw retlw retlw retlw String4_l1-String3_l1 0x03 'V' 0x00 '1' 0x00 '.' 0x00 '0' 0x00 '0' 0x00 String5_l1-String4_l1 0x03 'C' 0x00 'f' 0x00 'g' 0x00 '1' 0x00 String6_l1-String5_l1 0x03 'N' 0x00 'o' 0x00 't' 0x00 'h' 0x00 'i' 0x00 'n' 0x00 'g' 0x00 String2_l2-String1_l2 0x03 'M' 0x00 'i' 0x00 'c' 0x00 'r' 0x00 'o' 0x00 'c' retlw retlw retlw retlw retlw retlw retlw String2_l2 retlw retlw retlw retlw 0x00 retlw retlw retlw retlw retlw retlw retlw retlw retlw 'C' retlw retlw retlw retlw retlw retlw retlw 0x00 retlw retlw retlw retlw retlw retlw retlw retlw retlw retlw retlw retlw retlw retlw retlw retlw retlw retlw retlw retlw retlw retlw retlw retlw retlw retlw 0x00 'h' 0x00 'i' 0x00 'p' 0x00 String3_l2-String2_l2 0x03 'P' 'i' 0x00 'c' 0x00 '1' 0x00 '6' 0x00 0x00 '7' 0x00 '6' 0x00 '5' '' 0x00 'U' 0x00 'S' 0x00 'B' 0x00 '' 0x00 'L' 0x00 'C' 0x00 'D' 0x00 '' 0x00 'D' 0x00 'E' 0x00 'M' 0x00 'O' 0x00 String3_l2 retlw retlw retlw retlw retlw retlw retlw retlw retlw retlw retlw retlw String4_l2 retlw retlw retlw retlw retlw retlw retlw retlw String4_l2-String3_l2 0x03 'V' 0x00 '1' 0x00 '.' 0x00 '0' 0x00 '0' 0x00 String5_l2-String4_l2 0x03 'C' 0x00 'f' 0x00 'g' 0x00 retlw retlw String5_l2 retlw retlw retlw retlw retlw retlw retlw retlw retlw retlw retlw retlw retlw retlw retlw retlw String6_l2 end '1' 0x00 String6_l2-String5_l2 0x03 'N' 0x00 'o' 0x00 't' 0x00 'h' 0x00 'i' 0x00 'n' 0x00 'g' 0x00 PIC16C745 freeware (archivo hidclass.asm) #include <p16c745.inc> #include "usb_defs.inc" extern extern extern extern extern extern extern extern extern extern extern extern extern extern global ReportDescriptor ReportDescriptorLen HID_Descriptor Descriptions BufferData BufferDescriptor wrongstate USB_dev_req EP0_maxLength EP0_start EP0_end copy_descriptor_to_EP0 Send_0Len_pkt Report_desc_index ClassSpecificRequest USBBANK code ClassSpecificRequest Pagesel Dev2HostHIDRequest movf BufferData+bmRequestType,w xorlw 0x21 btfsc STATUS,Z goto Host2DevHIDRequest pagesel movf xorlw btfsc goto pagesel movf xorlw btfsc goto pagesel movf xorlw btfsc goto pagesel movf xorlw btfsc goto pagesel movf xorlw btfsc goto pagesel goto Host2DevReportRequest BufferData+bmRequestType,w 0x22 STATUS,Z Host2DevReportRequest Host2DevPhysicalRequest BufferData+bmRequestType,w 0x23 STATUS,Z Host2DevPhysicalRequest Dev2HostHIDRequest BufferData+bmRequestType,w 0xA1 STATUS,Z Dev2HostHIDRequest Dev2HostReportRequest BufferData+bmRequestType,w 0xA2 STATUS,Z Dev2HostReportRequest Dev2HostPhysicalRequest BufferData+bmRequestType,w 0xA3 STATUS,Z Dev2HostPhysicalRequest wrongstate wrongstate Host2DevHIDRequest movf BufferData+bRequest,w xorlw 0x01 pagesel GetHIDReport btfsc STATUS,Z goto GetHIDReport movf BufferData+bRequest,w xorlw 0x02 pagesel GetIdle btfsc STATUS,Z goto GetIdle movf BufferData+bRequest,w xorlw 0x03 pagesel GetPhysical btfsc STATUS,Z goto GetPhysical movf BufferData+bRequest,w xorlw 0x06 pagesel Get_Report_Descriptor btfsc STATUS,Z goto Get_Report_Descriptor movf BufferData+bRequest,w xorlw 0x09 pagesel SetHIDReport btfsc STATUS,Z goto SetHIDReport movf BufferData+bRequest,w xorlw 0x0A pagesel SetIdle btfsc STATUS,Z goto SetIdle movf BufferData+bRequest,w xorlw 0x0B pagesel SetProtocol btfsc STATUS,Z goto SetProtocol pagesel wrongstate goto wrongstate Get_Report_Descriptor global Get_Report_Descriptor banksel EP0_start movlw GET_DESCRIPTOR movwf USB_dev_req movlw 8 movwf EP0_maxLength movf BufferData+(wValue+1),w xorlw 0x01 pagesel TryOutputReport btfsc STATUS,Z goto TryOutputReport bcf STATUS,C rlf BufferData+wIndex,w pagesel Report_desc_index call Report_desc_index movwf EP0_start bcf STATUS,C rlf BufferData+wIndex,w addlw 1 call Report_desc_index movwf EP0_start+1 pagesel Descriptions call Descriptions movwf EP0_end incf EP0_start,f pagesel CheckReportLength goto CheckReportLength TryOutputReport movf BufferData+(wValue+1),w xorlw 0x02 pagesel TryFeatureReport btfsc STATUS,Z goto TryFeatureReport bcf STATUS,C rlf BufferData+wIndex,w pagesel Report_desc_index call Report_desc_index movwf EP0_start bcf STATUS,C rlf BufferData+wIndex,w addlw 1 call Report_desc_index movwf EP0_start+1 pagesel Descriptions call Descriptions movwf EP0_end incf EP0_start,f pagesel CheckReportLength goto CheckReportLength TryFeatureReport movf BufferData+(wValue+1),w xorlw 0x03 pagesel wrongstate btfsc STATUS,Z goto wrongstate return CheckReportLength movf BufferData+(wLength+1),w pagesel nolimit_rpt btfss STATUS,Z goto nolimit_rpt check_low_bytes movf BufferData+wLength,w subwf EP0_end,w movf BufferData+wLength,w btfsc STATUS,C movwf EP0_end nolimit_rpt incf EP0_end,f pagesel copy_descriptor_to_EP0 call copy_descriptor_to_EP0 return Get_HID_Descriptor global Get_HID_Descriptor movlw GET_DESCRIPTOR movwf USB_dev_req movlw 8 movwf EP0_maxLength movlw low HID_Descriptor movwf EP0_start movlw high HID_Descriptor movwf EP0_start + 1 pagesel Descriptions call Descriptions movwf EP0_end movf BufferData+(wLength+1),f pagesel nolimit_hid btfss STATUS,Z goto nolimit_hid subwf BufferData+wLength,w movf BufferData+wLength,w btfss STATUS,C movwf EP0_end nolimit_hid incf EP0_end,f pagesel copy_descriptor_to_EP0 call copy_descriptor_to_EP0 return Get_Physical_Descriptor return Check_Class_Specific_IN global Check_Class_Specific_IN pagesel copy_descriptor_to_EP0 movf USB_dev_req,w xorlw GET_DESCRIPTOR btfsc STATUS,Z call copy_descriptor_to_EP0 return Host2DevReportRequest Host2DevPhysicalRequest Dev2HostHIDRequest Dev2HostReportRequest Dev2HostPhysicalRequest GetHIDReport GetIdle GetPhysical SetProtocol SetIdle pagesel wrongstate goto wrongstate SetHIDReport movlw HID_SET_REPORT movwf USB_dev_req banksel BD0OST return end PIC16C745 freeware (archivo usb_ch9.asm) #include <p16c745.inc> #include "usb_defs.inc" errorlevel -302 unbanked udata_shr temp res 1 GPtemp res 1 global BufferDescriptor global BufferData global temp global temp2 global EP0_maxLength global EP0_start global EP0_end bank2 udata BufferDescriptor res BufferData res USBMaskedInterrupts res USB_Curr_Config res USB_status_device res USB_dev_req res 3 8 1 1 1 1 USB_address_pending USBMaskedErrors PIDs EP0_start EP0_end EP0_maxLength temp2 bufindex USB_Interface inner outer dest_ptr source_ptr hid_dest_ptr hid_source_ptr counter bytecounter RP_save IS_IDLE USB_USTAT res res res res res res res res res res res res res res res res res res res res 1 1 1 2 1 1 1 1 3 1 1 1 1 1 1 1 1 1 1 1 global USB_Curr_Config global USB_status_device global USB_dev_req global USB_Interface #ifdef COUNTERRORS USB_PID_ERR res 2 USB_CRC5_ERR res 2 USB_CRC16_ERR res 2 USB_DFN8_ERR res 2 USB_BTO_ERR res 2 USB_WRT_ERR res 2 USB_OWN_ERR res 2 USB_BTS_ERR res 2 #endif extern Config_desc_index extern Descriptions extern string_index extern String0 extern String0_end extern ClassSpecificRequest extern Check_Class_Specific_IN extern Get_Report_Descriptor extern Get_HID_Descriptor extern DeviceDescriptor extern StringDescriptions interface code GETEP1 GETEP2 PUTEP1 PUTEP2 StallUSBEP bsf STATUS,IRP andlw 0x03 addlw low UEP0 movwf FSR bsf INDF,EP_STALL return UnstallUSBEP bsf STATUS,IRP andlw 0x03 addlw low UEP0 movwf FSR bcf INDF,EP_STALL return CheckSleep global CheckSleep banksel IS_IDLE btfss IS_IDLE,0 return #ifdef SHOW_ENUM_STATUS banksel PORTB bsf PORTB,4 banksel UIR #endif #ifdef bsf STATUS,RP0 bcf UIR,ACTIVITY bsf UIE,ACTIVITY bsf UCTRL,SUSPND sleep nop bcf UCTRL,SUSPND bcf UIR,UIDLE bsf UIE,UIDLE bcf UIR,ACTIVITY bcf UIE,ACTIVITY SHOW_ENUM_STATUS banksel PORTB bcf PORTB,4 #endif return RemoteWakeup global RemoteWakeup banksel USB_status_device btfss USB_status_device, 1 return bsf STATUS, RP0 bcf UCTRL, SUSPND bsf UIE,UIDLE bcf UIR,UIDLE bcf UIE,ACTIVITY bcf UIR,ACTIVITY bsf UCTRL, 2 bcf STATUS, RP0 clrf inner movlw 0x80 movwf outer pagesel RemoteLoop RemoteLoop decfsz inner, f goto RemoteLoop decfsz outer, f goto RemoteLoop bsf STATUS, RP0 bcf UCTRL, 2 return SoftDetachUSB global SoftDetachUSB banksel UCTRL bcf UCTRL,DEV_ATT bcf STATUS, RP0 clrf outer clrf inner pagesel SoftDetachLoop SoftDetachLoop incfsz inner,f goto SoftDetachLoop incfsz outer,f goto SoftDetachLoop pagesel InitUSB call InitUSB return InitUSB global InitUSB banksel USWSTAT clrf USWSTAT movlw 0x01 movwf UIE clrf UIR movlw 0x08 movwf UCTRL bcf STATUS, RP0 clrf USB_Curr_Config movlw 1 movwf USB_status_device clrf USB_Interface clrf USB_Interface+1 clrf USB_Interface+2 movlw 0xFF movwf USB_dev_req #ifdef COUNTERRORS clrf USB_PID_ERR clrf USB_PID_ERR+1 clrf USB_CRC5_ERR clrf USB_CRC5_ERR+1 clrf USB_CRC16_ERR clrf USB_CRC16_ERR+1 clrf USB_DFN8_ERR clrf USB_DFN8_ERR+1 clrf USB_BTO_ERR clrf USB_BTO_ERR+1 clrf USB_WRT_ERR clrf USB_WRT_ERR+1 clrf USB_OWN_ERR clrf USB_OWN_ERR+1 clrf USB_BTS_ERR clrf USB_BTS_ERR+1 #endif banksel PIR1 bcf PIR1,USBIF bsf STATUS,RP0 bsf PIE1,USBIE bsf INTCON, 6 bsf INTCON, 7 #ifdef SHOW_ENUM_STATUS bcf STATUS,RP0 bsf PORTB,0 #endif return DeInitUSB global DeInitUSB banksel UCTRL bcf UCTRL,DEV_ATT bsf UCTRL,SUSPND clrf USWSTAT bcf STATUS,RP1 bcf PIE1,USBIE #ifdef SHOW_ENUM_STATUS bcf STATUS,RP0 movlw 0x01 movwf PORTB bsf STATUS,RP0 #endif return core code ServiceUSBInt global ServiceUSBInt banksel UIR movf UIR,w andwf UIE,w bcf STATUS, RP0 pagesel ExitServiceUSBInt btfsc STATUS,Z goto ExitServiceUSBInt movwf USBMaskedInterrupts pagesel TokenDone btfsc USBMaskedInterrupts,ACTIVITY call USBActivity pagesel USBReset btfsc USBMaskedInterrupts,USB_RST call USBReset pagesel USBStall btfsc USBMaskedInterrupts,TOK_DNE call TokenDone pagesel USBActivity btfsc USBMaskedInterrupts,STALL call USBStall pagesel USBError btfsc USBMaskedInterrupts,UERR call USBError pagesel USBSleep btfsc USBMaskedInterrupts,UIDLE call USBSleep pagesel ServiceUSBInt goto ServiceUSBInt ExitServiceUSBInt Banksel PIR1 bcf PIR1,USBIF return USBReset clrf USB_Curr_Config clrf IS_IDLE bsf STATUS, RP0 bcf UIR,TOK_DNE bcf UIR,TOK_DNE bcf UIR,TOK_DNE bcf UIR,TOK_DNE movlw 0x8 movwf BD0OBC Movlw USB_Buffer movwf BD0OAL movlw 0x88 movwf BD0OST movlw USB_Buffer+8 movwf BD0IAL movlw 0x08 movwf BD0IST clrf UADDR clrf UIR banksel PIR1 bcf PIR1,USBIF banksel UEP0 movlw ENDPT_CONTROL movwf UEP0 movlw 0x3B movwf UIE movlw 0xFF movwf UEIE movlw DEFAULT_STATE movwf USWSTAT bcf STATUS,RP0 movlw 0x01 movwf USB_status_device bcf STATUS,RP1 #ifdef SHOW_ENUM_STATUS bsf PORTB,1 #endif bsf STATUS,RP1 return USBSleep bsf STATUS, RP0 bcf UIE,UIDLE bcf UIR,UIDLE bcf UIR,ACTIVITY bsf UIE,ACTIVITY bsf UCTRL, SUSPND banksel PIR1 bcf PIR1,USBIF bsf STATUS, RP1 bsf IS_IDLE, 0 return USBStall bsf STATUS, RP0 bcf UIR, STALL banksel PIR1 bcf PIR1,USBIF bsf STATUS,RP1 return USBError bsf STATUS, RP0 bcf UIR,UERR movf UEIR,w andwf UEIE,w clrf UEIR banksel PIR1 bcf PIR1,USBIF bsf STATUS,RP1 movwf USBMaskedErrors #ifdef COUNTERRORS btfss USBMaskedErrors,PID_ERR goto CRC5Error INCREMENT16 USB_PID_ERR CRC5Error btfss USBMaskedErrors,CRC5 goto CRC16Error INCREMENT16 USB_CRC5_ERR CRC16Error btfss USBMaskedErrors,CRC16 goto DFN8Error INCREMENT16 USB_CRC16_ERR DFN8Error btfss USBMaskedErrors,DFN8 goto BTOError INCREMENT16 USB_DFN8_ERR BTOError btfss USBMaskedErrors,BTO_ERR goto WRTError INCREMENT16 USB_BTO_ERR WRTError btfss USBMaskedErrors,WRT_ERR goto OWNError INCREMENT16 USB_WRT_ERR OWNError btfss USBMaskedErrors,OWN_ERR goto BTSError INCREMENT16 USB_OWN_ERR BTSError btfss USBMaskedErrors,BTS_ERR goto EndError INCREMENT16 USB_BTS_ERR EndError #endif banksel USBMaskedInterrupts return USBActivity bsf STATUS, RP0 bcf UIE,ACTIVITY bcf UIR,ACTIVITY bcf UIR,UIDLE bsf UIE,UIDLE bcf UCTRL, SUSPND banksel PIR1 bcf PIR1,USBIF bsf STATUS,RP1 clrf IS_IDLE return TokenDone COPYBUFFERDESCRIPTOR banksel USTAT movf USTAT,w bcf UIR,TOK_DNE banksel PIR1 bcf PIR1,USBIF bsf STATUS,RP1 movwf USB_USTAT #ifdef SHOW_ENUM_STATUS bcf STATUS,RP1 andlw 0x18 pagesel tryEP1activity btfss STATUS,Z goto tryEP1activity movlw 0x20 pagesel maskport goto maskport tryEP1activity xorlw 0x08 btfss STATUS,Z movlw 0x80 btfsc STATUS,Z movlw 0x40 maskport xorwf PORTB,f bsf STATUS,RP1 #endif movf BufferDescriptor,w andlw 0x3c movwf PIDs xorlw TOKEN_IN pagesel TokenInPID btfsc STATUS,Z goto TokenInPID movf PIDs,w xorlw TOKEN_OUT pagesel TokenOutPID btfsc STATUS,Z goto TokenOutPID movf PIDs,w xorlw TOKEN_SETUP pagesel TokenSetupPID btfsc STATUS,Z goto TokenSetupPID return TokenOutPID movf USB_USTAT,w pagesel tryEP1 btfss STATUS,Z goto tryEP1 movf USB_dev_req,w xorlw HID_SET_REPORT pagesel ResetEP0OutBuffer btfss STATUS,Z goto ResetEP0OutBuffer HIDSetReport ResetEP0OutBuffer bsf STATUS,RP0 movlw 0x08 movwf BD0OBC movlw 0x88 movwf BD0OST pagesel Send_0Len_pkt bcf STATUS,RP0 goto Send_0Len_pkt return tryEP1 xorlw 0x08 pagesel tryEP2 btfss STATUS,Z goto tryEP2 return tryEP2 movf USB_USTAT,w xorlw 0x10 btfsc STATUS,Z return return TokenInPID EP0_in movf USB_USTAT,w andlw 0x18 pagesel tryEP1in btfss STATUS,Z goto tryEP1in movf USB_dev_req,w xorlw GET_DESCRIPTOR pagesel check_GSD btfss STATUS,Z goto check_GSD pagesel copy_descriptor_to_EP0 call copy_descriptor_to_EP0 goto exitEP0in check_GSD movf USB_dev_req,w xorlw GET_STRING_DESCRIPTOR pagesel check_SA btfss STATUS,Z goto check_SA pagesel copy_descriptor_to_EP0 call copy_descriptor_to_EP0 pagesel exitEP0in goto exitEP0in check_SA movf USB_dev_req,w xorlw SET_ADDRESS pagesel check_SF btfss STATUS,Z goto check_SF pagesel finish_set_address call finish_set_address pagesel exitEP0in goto exitEP0in check_SF movf USB_dev_req,w xorlw SET_FEATURE pagesel check_CF btfss STATUS,Z goto check_CF pagesel exitEP0in goto exitEP0in check_CF movf USB_dev_req,w xorlw CLEAR_FEATURE pagesel Class_Specific btfss STATUS,Z goto Class_Specific movf BufferData+4, w xorlw 1 pagesel clear_EP2 btfss STATUS,Z goto clear_EP2 bsf STATUS, RP0 bsf UEP1, EP_STALL bcf STATUS, RP0 pagesel exitEP0in goto exitEP0in clear_EP2 movf BufferData+wIndex, w xorlw 2 pagesel exitEP0in btfss STATUS,Z goto exitEP0in bsf STATUS, RP0 bsf UEP2, EP_STALL bcf STATUS, RP0 pagesel exitEP0in goto exitEP0in Class_Specific pagesel Check_Class_Specific_IN goto Check_Class_Specific_IN exitEP0in return tryEP1in xorlw 0x08 pagesel tryEP1in btfss STATUS,Z goto tryEP2in return tryEP2in return Send_0Len_pkt global Send_0Len_pkt banksel BD0IBC clrf BD0IBC movlw 0xc8 movwf BD0IST bcf STATUS,RP0 clrf USB_dev_req return TokenSetupPID bsf STATUS,IRP movf BufferDescriptor+ADDRESS,w movwf FSR movf INDF,w movwf BufferData incf FSR,f movf INDF,w movwf BufferData+1 incf FSR,f movf INDF,w movwf BufferData+2 incf FSR,f movf INDF,w movwf BufferData+3 incf FSR,f movf INDF,w movwf BufferData+4 incf FSR,f movf INDF,w movwf BufferData+5 incf FSR,f movf INDF,w movwf BufferData+6 incf FSR,f movf INDF,w movwf BufferData+7 bsf STATUS, RP0 movlw 0x08 movwf BD0OBC movwf BD0IST bcf STATUS, RP0 movf BufferData+bmRequestType, w xorlw HID_SET_REPORT movlw 0x88 btfsc STATUS, Z movlw 0xC8 bsf STATUS, RP0 movwf BD0OST bcf UCTRL,PKT_DIS bcf STATUS,RP0 clrf USB_dev_req movf BufferData+bmRequestType,w pagesel HostToDevice btfsc STATUS,Z goto HostToDevice movf BufferData+bmRequestType,w xorlw 0x01 pagesel HostToInterface btfsc STATUS,Z goto HostToInterface movf BufferData+bmRequestType,w xorlw 0x02 pagesel HostToEndpoint btfsc STATUS,Z goto HostToEndpoint movf BufferData+bmRequestType,w xorlw 0x80 pagesel DeviceToHost btfsc STATUS,Z goto DeviceToHost movf BufferData+bmRequestType,w xorlw 0x81 pagesel InterfaceToHost btfsc STATUS,Z goto InterfaceToHost movf BufferData+bmRequestType,w xorlw 0x82 pagesel EndpointToHost btfsc STATUS,Z goto EndpointToHost movf BufferData+bmRequestType,w andlw 0x60 xorlw 0x20 pagesel ClassSpecificRequest btfsc STATUS,Z goto ClassSpecificRequest CheckForVendorRequest movf BufferData+bmRequestType,w andlw 0x60 xorlw 0x40 pagesel wrongstate btfss STATUS,Z goto wrongstate pagesel CheckVendor goto CheckVendor return CheckForStandardRequest HostToDevice movf BufferData+bRequest,w xorlw CLEAR_FEATURE pagesel Clear_Device_Feature btfsc STATUS,Z goto Clear_Device_Feature movf BufferData+bRequest,w xorlw SET_ADDRESS pagesel Set_Address btfsc STATUS,Z goto Set_Address movf BufferData+bRequest,w xorlw SET_CONFIGURATION HostToInterface movf BufferData+bRequest,w xorlw CLEAR_FEATURE Pagesel Set_ Configuration btfsc STATUS,Z goto Set_Configuration movf BufferData+bRequest,w xorlw SET_FEATURE pagesel Set_Device_Feature btfsc STATUS,Z goto Set_Device_Feature pagesel wrongstate goto wrongstate pagesel Clear_Interface_Feature btfsc STATUS,Z goto Clear_Interface_Feature movf BufferData+bRequest,w xorlw SET_INTERFACE pagesel Set_Interface btfsc STATUS,Z goto Set_Interface movf BufferData+bRequest,w xorlw SET_FEATURE pagesel Set_Interface_Feature btfsc STATUS,Z goto Set_Interface_Feature pagesel wrongstate goto wrongstate HostToEndpoint movf BufferData+bRequest,w xorlw CLEAR_FEATURE pagesel Clear_Endpoint_Feature btfsc STATUS,Z goto Clear_Endpoint_Feature movf BufferData+bRequest,w xorlw SET_FEATURE pagesel Set_Endpoint_Feature btfsc STATUS,Z goto Set_Endpoint_Feature DeviceToHost movf BufferData+bRequest,w xorlw GET_CONFIGURATION pagesel Get_Configuration btfsc STATUS,Z goto Get_Configuration movf BufferData+bRequest,w xorlw GET_DESCRIPTOR pagesel Get_Descriptor btfsc STATUS,Z goto Get_Descriptor movf BufferData+bRequest,w xorlw GET_STATUS pagesel Get_Device_Status btfsc STATUS,Z goto Get_Device_Status InterfaceToHost movf BufferData+bRequest,w xorlw GET_INTERFACE pagesel Get_Interface btfsc STATUS,Z goto Get_Interface movf BufferData+bRequest,w xorlw GET_STATUS pagesel Get_Interface_Status btfsc STATUS,Z goto Get_Interface_Status movf BufferData+bRequest,w xorlw GET_DESCRIPTOR pagesel Get_Descriptor btfsc STATUS,Z goto Get_Descriptor EndpointToHost movf BufferData+bRequest,w xorlw GET_STATUS pagesel Get_Endpoint_Status btfsc STATUS,Z goto Get_Endpoint_Status pagesel wrongstate goto wrongstate return Get_Descriptor movf BufferData+(wValue+1),w xorlw 0x22 pagesel Get_Report_Descriptor btfsc STATUS,Z goto Get_Report_Descriptor movf BufferData+(wValue+1),w xorlw 0x21 pagesel Get_HID_Descriptor btfsc STATUS,Z goto Get_HID_Descriptor GetCh9Descriptor movlw high StartGDIndex movwf PCLATH bcf STATUS, C movf BufferData+(wValue+1),w andlw 0x03 addlw low StartGDIndex btfsc STATUS,C incf PCLATH,f movwf PCL StartGDIndex goto wrongstate goto Get_Device_Descriptor goto Get_Config_Descriptor goto Get_String_Descriptor Get_Device_Descriptor movlw GET_DESCRIPTOR movwf USB_dev_req movlw 8 movwf EP0_maxLength movlw low DeviceDescriptor movwf EP0_start movlw high DeviceDescriptor movwf EP0_start+1 pagesel Descriptions call Descriptions movwf EP0_end movf BufferData+(wLength+1),f pagesel DeviceEndPtr btfss STATUS,Z goto DeviceEndPtr subwf BufferData+wLength,w movf BufferData+wLength,w btfss STATUS,C movwf EP0_end DeviceEndPtr incf EP0_end,f pagesel copy_descriptor_to_EP0 call copy_descriptor_to_EP0 return Get_Config_Descriptor movlw GET_DESCRIPTOR movwf USB_dev_req bcf STATUS,C rlf BufferData+wValue,w pagesel Config_desc_index call Config_desc_index movwf EP0_start bcf STATUS,C rlf BufferData+wValue,w addlw 1 call Config_desc_index movwf EP0_start+1 movlw 2 addwf EP0_start,f btfsc STATUS,C incf EP0_start+1,f pagesel Descriptions call Descriptions movwf EP0_end movlw 2 subwf EP0_start,f btfss STATUS,C decf EP0_start+1,f movf BufferData+(wLength+1),f pagesel CmpLowerByte btfsc STATUS,Z goto CmpLowerByte pagesel ConfigEndPtr goto ConfigEndPtr CmpLowerByte movf EP0_end,w subwf BufferData+wLength,w pagesel ConfigEndPtr btfsc STATUS,C goto ConfigEndPtr LimitSize movf BufferData+wLength,w movwf EP0_end ConfigEndPtr movlw 8 movwf EP0_maxLength incf EP0_end,f pagesel copy_descriptor_to_EP0 call copy_descriptor_to_EP0 return Get_String_Descriptor movlw GET_STRING_DESCRIPTOR movwf USB_dev_req movf BufferData+wIndex,w pagesel not_string0 btfss STATUS,Z goto not_string0 movf BufferData+(wIndex+1),w btfss STATUS,Z goto not_string0 movlw low String0 movwf EP0_start movlw high String0 movwf EP0_start+1 pagesel found_string goto found_string not_string0 movlw high (String0+2) movwf EP0_start+1 movlw low (String0+2) movwf EP0_start clrf inner check_langid pagesel StringDescriptions call StringDescriptions incf EP0_start,f subwf BufferData+wIndex, w pagesel wrong_langid btfss STATUS, Z goto wrong_langid pagesel StringDescriptions call StringDescriptions subwf BufferData+(wIndex+1), w pagesel right_langid btfsc STATUS, Z goto right_langid wrong_langid incf EP0_start,f incf inner,f movlw low String0_end subwf EP0_start,w pagesel check_langid btfss STATUS,C goto check_langid clrf USB_dev_req pagesel wrongstate goto wrongstate right_langid movlw 6 subwf BufferData+wValue,w pagesel right_string btfss STATUS,C goto right_string clrf USB_dev_req pagesel wrongstate goto wrongstate right_string rlf BufferData+wValue,w movwf EP0_start+1 movf inner,w pagesel string_index call string_index movwf EP0_start incf EP0_start+1,f movf inner,w call string_index movwf EP0_start+1 found_string pagesel StringDescriptions call StringDescriptions movwf EP0_end subwf BufferData+wLength,w movf BufferData+wLength,w btfss STATUS,C movwf EP0_end movlw 8 movwf EP0_maxLength incf EP0_end,f pagesel copy_descriptor_to_EP0 call copy_descriptor_to_EP0 return wrongstate global wrongstate banksel UEP0 bsf UEP0,EP_STALL bcf STATUS,RP0 return Get_Device_Status bsf STATUS,RP0 movf BD0IAL,w movwf FSR bcf STATUS,RP0 bsf STATUS,IRP movf USB_status_device,w movwf INDF incf FSR,f clrf INDF bsf STATUS,RP0 movlw 0x02 movwf BD0IBC movlw 0xC8 movwf BD0IST return Get_Interface_Status bsf STATUS, RP0 movf USWSTAT,w xorlw ADDRESS_STATE pagesel Get_Interface_Status2 btfss STATUS, Z goto Get_Interface_Status2 bcf STATUS, RP0 movf BufferData+wIndex, w pagesel Get_Interface_Status2 btfss STATUS, Z goto Get_Interface_Status2 Get_Interface_Status2 bsf STATUS, RP0 movf USWSTAT,w xorlw CONFIG_STATE pagesel wrongstate btfss STATUS, Z goto wrongstate bcf STATUS, RP0 movf BufferData+wIndex,w sublw (NUM_INTERFACES-1) pagesel wrongstate btfss STATUS, C goto wrongstate Get_Interface_Status_end movf BufferData+wIndex,w addlw low USB_Interface movwf FSR bsf STATUS,IRP movf INDF,w movwf temp bsf STATUS,RP0 movf BD0IAL,w movwf FSR movf temp,w movwf INDF movlw 0x02 movwf BD0IBC movlw 0xc8 movwf BD0IST return Get_Endpoint_Status movlw 0x0f andwf BufferData+wIndex,w xorlw 0x01 pagesel get_EP1_status btfsc STATUS,Z goto get_EP1_status movlw 0x0f andwf BufferData+wIndex,w xorlw 0x02 pagesel wrongstate btfss STATUS,Z goto wrongstate get_EP2_status bcf STATUS,C bsf STATUS,RP0 btfsc UEP2,EP_STALL bsf STATUS,C pagesel build_status_buffer goto build_status_buffer get_EP1_status bcf STATUS,C bsf STATUS,RP0 btfsc UEP1,EP_STALL bsf STATUS,C build_status_buffer movf BD0IAL,w movwf FSR clrf INDF rlf INDF,f incf FSR,f clrf INDF movlw 0x02 movwf BD0IBC movlw 0xC8 movwf BD0IST return Set_Address movf BufferData+wValue,w movwf USB_address_pending pagesel wrongstate btfsc USB_address_pending, 7 goto wrongstate pagesel Send_0Len_pkt call Send_0Len_pkt movlw SET_ADDRESS movwf USB_dev_req return finish_set_address clrf USB_dev_req clrf USB_Curr_Config movf USB_address_pending,w bsf STATUS, RP0 movwf UADDR pagesel endfinishsetaddr btfsc STATUS,Z goto endfinishsetaddr movlw ADDRESS_STATE movwf USWSTAT #ifdef SHOW_ENUM_STATUS banksel PORTB bsf PORTB,2 banksel USWSTAT #endif endfinishsetaddr return Clear_Device_Feature movf BufferData+wValue,w xorlw 0x01 pagesel wrongstate btfss STATUS,Z goto wrongstate right_state_clear_feature bcf USB_status_device,1 pagesel Send_0Len_pkt call Send_0Len_pkt return Clear_Endpoint_Feature movf BufferData+wValue, w pagesel wrongstate btfss STATUS, Z goto wrongstate movf BufferData+(wValue+1), w btfss STATUS, Z goto wrongstate bsf STATUS, RP0 movlw 0x03 andwf USWSTAT, w xorlw ADDRESS_STATE pagesel clear_endpoint_feature2 btfss STATUS, Z goto clear_endpoint_feature2 bcf STATUS, RP0 movlw 0x0F andwf BufferData+wIndex, w btfss STATUS, Z goto clear_endpoint_feature2 bsf STATUS, RP0 bcf UEP0, 0 pagesel Send_0Len_pkt call Send_0Len_pkt return clear_endpoint_feature2 bsf STATUS, RP0 movlw 0x03 andwf USWSTAT, w xorlw CONFIG_STATE pagesel wrongstate btfss STATUS, Z goto wrongstate bcf STATUS, RP0 movlw 0x0F andwf BufferData+wIndex, w sublw 2 pagesel wrongstate btfss STATUS, C goto wrongstate bsf STATUS, IRP movlw 0x0F andwf BufferData+wIndex,w bsf STATUS, RP0 addlw UEP0&0xFF movwf FSR bcf INDF, 0 pagesel Send_0Len_pkt call Send_0Len_pkt return Clear_Interface_Feature pagesel wrongstate goto wrongstate Set_Device_Feature movf BufferData+wValue,w xorlw 0x01 pagesel wrongstate btfss STATUS,Z goto wrongstate bsf USB_status_device,1 pagesel Send_0Len_pkt call Send_0Len_pkt return Set_Endpoint_Feature movf BufferData+wValue, w pagesel wrongstate btfss STATUS, Z goto wrongstate movf BufferData+(wValue+1), w btfss STATUS, Z goto wrongstate bsf STATUS, RP0 movlw 0x03 andwf USWSTAT, w xorlw ADDRESS_STATE pagesel set_endpoint_feature2 btfss STATUS, Z goto set_endpoint_feature2 bcf STATUS, RP0 movlw 0x0F andwf BufferData+wIndex, w btfss STATUS, Z goto set_endpoint_feature2 bsf STATUS, RP0 bsf UEP0, 0 pagesel Send_0Len_pkt call Send_0Len_pkt return set_endpoint_feature2 bsf STATUS, RP0 movlw 0x03 andwf USWSTAT, w xorlw CONFIG_STATE pagesel wrongstate btfss STATUS, Z goto wrongstate bcf STATUS, RP0 movlw 0x0F andwf BufferData+wIndex, w sublw 2 pagesel wrongstate btfss STATUS, C goto wrongstate bsf STATUS, IRP movlw 0x0F andwf BufferData+wIndex,w bsf STATUS, RP0 addlw UEP0&0xFF movwf FSR bsf INDF, 0 pagesel Send_0Len_pkt call Send_0Len_pkt return Set_Interface_Feature pagesel wrongstate goto wrongstate Get_Configuration bsf STATUS, RP0 movf low BD0IAL,w movwf FSR bcf STATUS, RP0 bsf STATUS,IRP movf USB_Curr_Config,w movwf INDF bsf STATUS, RP0 movlw 0x01 movwf BD0IBC movlw 0xc8 movwf BD0IST return Set_Configuration movf BufferData+wValue,w sublw NUM_CONFIGURATIONS pagesel wrongstate btfss STATUS,C goto wrongstate movf BufferData+wValue,w movwf USB_Curr_Config pagesel AckSetConfigCmd btfsc STATUS,Z goto AckSetConfigCmd bsf STATUS, RP0 movlw CONFIG_STATE movwf USWSTAT #ifdef SHOW_ENUM_STATUS banksel PORTB bsf PORTB,3 #endif AckSetConfigCmd pagesel Send_0Len_pkt call Send_0Len_pkt banksel BD1OAL movlw USB_Buffer+0x10 movwf BD1OAL movlw 8 movwf BD1OBC movlw 0x88 movwf BD1OST movlw 8 movwf BD1IBC movlw USB_Buffer+0x18 movwf BD1IAL movlw 0x48 movwf BD1IST movlw USB_Buffer+0x20 movwf BD2OAL movlw 8 movwf BD2OBC movlw 0x88 movwf BD2OST movlw 8 movwf BD2IBC movlw USB_Buffer+0x20 movwf BD2IAL movlw 0x48 movwf BD2IST movlw ENDPT_NON_CONTROL movwf UEP1 movlw ENDPT_NON_CONTROL movwf UEP2 return Get_Interface bsf STATUS, RP0 movf USWSTAT,w xorlw CONFIG_STATE pagesel wrongstate btfss STATUS, Z goto wrongstate bcf STATUS, RP0 movf BufferData+wIndex,w sublw (NUM_INTERFACES-1) pagesel wrongstate btfss STATUS, C goto wrongstate movf BufferData+wIndex,w addlw low USB_Interface movwf FSR bsf STATUS,IRP movf INDF,w movwf temp bsf STATUS,RP0 movf BD0IAL,w movwf FSR movf temp,w movwf INDF movlw 0x01 movwf BD0IBC movlw 0xc8 movwf BD0IST return Set_Interface bsf STATUS, RP0 movf USWSTAT,w bcf STATUS,RP0 andlw 0x03 xorlw CONFIG_STATE pagesel wrongstate btfss STATUS,Z goto wrongstate movf BufferData+wIndex,w addlw USB_Interface movwf FSR bsf STATUS,IRP movf BufferData+wValue,w movwf INDF pagesel Send_0Len_pkt call Send_0Len_pkt return copy_descriptor_to_EP0 global copy_descriptor_to_EP0 banksel BD0IAL bankisel BD0IAL movf BD0IAL,w movwf FSR banksel bufindex clrf bufindex gdd_loop movf bufindex,w subwf EP0_maxLength,w pagesel end_gdd_loop btfsc STATUS,Z goto end_gdd_loop pagesel gdd_copy_loop decfsz EP0_end, f goto gdd_copy_loop pagesel end_gdd_loop_short_packet goto end_gdd_loop_short_packet gdd_copy_loop pagesel Descriptions call Descriptions movwf INDF incf bufindex,f incf FSR,f pagesel gdd_loop incfsz EP0_start,f goto gdd_loop incf EP0_start+1,f goto gdd_loop end_gdd_loop_short_packet clrf USB_dev_req end_gdd_loop movf bufindex,w bsf STATUS,RP0 movwf BD0IBC movlw (0x01<<DATA01) xorwf BD0IST,w andlw (0x01<<DATA01) iorlw 0x88 movwf BD0IST pagesel copy_descriptor_to_EP0 return SetConfiguration global SetConfiguration return CheckVendor global CheckVendor return end PIC16C745 freeware (archivo usb_defs.inc) #define NUM_CONFIGURATIONS 1 #define NUM_INTERFACES 1 #define SHOW_ENUM_STATUS #define POWERED_STATE 0x00 #define DEFAULT_STATE 0x01 #define ADDRESS_STATE 0x02 #define CONFIG_STATE 0x03 #define EP_IDLE_STATE 0x00 #define EP_SETUP_STATE 0x01 #define EP_DISABLED_STATE 0xff #define ENDPT_DISABLED 0x00 #define ENDPT_IN_ONLY 0x02 #define ENDPT_OUT_ONLY 0x04 #define ENDPT_CONTROL 0x06 #define ENDPT_NON_CONTROL 0x0E #define INT_STAT_MASK_RESET 0x01 #define INT_STAT_MASK_ERROR 0x02 #define INT_STAT_MASK_TOKEN_DONE 0x04 #define INT_STAT_MASK_SLEEP 0x08 #define INT_STAT_MASK_STALL 0x10 #define TOKEN_OUT (0x01<<2) #define TOKEN_ACK (0x02<<2) #define TOKEN_IN (0x09<<2) #define TOKEN_SETUP (0x0D<<2) #define USB_Buffer 0xB8 #define BYTECOUNT 0x01 #define ADDRESS 0x02 #define DEVICE 1 #define CONFIGURATION 2 #define STRING 3 #define INTERFACE 4 #define ENDPOINT 5 #define bmRequestType 0x00 #define bRequest 0x01 #define wValue 0x02 #define wValueHigh 0x03 #define wIndex 0x04 #define wIndexHigh 0x05 #define wLength 0x06 #define wLengthHigh 0x07 #define CLEAR_FEATURE 0x01 #define GET_CONFIGURATION 0x08 #define GET_DESCRIPTOR 0x06 #define GET_STRING_DESCRIPTOR 0x66 #define GET_INTERFACE 0x0A #define GET_STATUS 0x00 #define SET_ADDRESS 0x05 #define SET_CONFIGURATION 0x09 #define SET_FEATURE 0x03 #define SET_INTERFACE 0x0B #define HID_SET_REPORT 0x21 #define VEND_SET_MEMORY 0x80 #define SVCUSBINT 0x01 << 2 #define SVCTOKENDONE 0x02 << 2 #define SVCRESET 0x03 << 2 #define SVCSLEEP 0x04 << 2 #define SVCSTALL 0x05 << 2 #define SVCERROR 0x06 << 2 #define SVCACTIVITY 0x07 << 2 #define TOKENOUT 0x08 << 2 #define TOKENIN 0x09 << 2 #define TOKENSETUP 0x0A << 2 #define CLEARFEATURE 0x0B << 2 #define GETCONFIG 0x0C << 2 #define GETDESCRIPTOR 0x0D << 2 #define GETINTERFACE 0x0E << 2 #define GETSTATUS 0x0F << 2 #define SETADDRESS 0x10 << 2 #define SETCONFIG 0x11 << 2 #define SETFEATURE 0x12 << 2 #define SETINTERFACE 0x13 << 2 #define FINISHSETADDRESS 0x14 << 2 #define COPYDESC2EP0 0x15 << 2 #define COPYSTRINGDESC2EP0 0x16 << 2 #define ZEROLENPACKET 0x17 << 2 COPYBUFFERDESCRIPTOR macro bankisel BD0OST banksel BD0OST movf USTAT,w addlw 0xA0 movwf FSR bcf STATUS, RP0 movf INDF,w movwf BufferDescriptor incf FSR,f movf INDF,w movwf BufferDescriptor+1 incf FSR,f movf INDF,w movwf BufferDescriptor+2 endm INCREMENT16macro index local endinc16 incfsz index,f goto endinc16 incf index+1,f endinc16 endm REQUESTERROR macro bsf STATUS,RP0 movf USTAT,w addlw 0xA0 movwf FSR bsf INDF,EP_STALL bcf STATUS,RP0 endm ConfiguredUSB macro local enumloop banksel USWSTAT pagesel enumloop enumloop clrwdt movlw 0x03 andwf USWSTAT,w xorlw CONFIG_STATE btfss STATUS,Z goto enumloop endm GETEP1 macro GetEP1 global GetEP1 local getEPloop local exitgetloop local nobuffer movf STATUS,w banksel RP_save movwf RP_save movf FSR,w movwf dest_ptr banksel BD1OST pagesel nobuffer btfsc BD1OST,UOWN goto nobuffer movf BD1OBC,w banksel counter movwf counter movwf bytecounter pagesel exitgetloop btfsc STATUS,Z goto exitgetloop banksel BD1OAL movf BD1OAL,w banksel source_ptr movwf source_ptr getEPloop bsf STATUS,IRP movf source_ptr,w movwf FSR movf INDF,w movwf GPtemp movf dest_ptr,w movwf FSR btfss RP_save,IRP bcf STATUS,IRP movf GPtemp,w movwf INDF incf dest_ptr,f incf source_ptr,f pagesel getEPloop decfsz counter,f goto getEPloop exitgetloop bsf STATUS,RP0 movf BD1OST,w andlw 0x40 xorlw 0x40 iorlw 0x88 movwf BD1OST movlw 0x08 movwf BD1OBC bcf STATUS,RP0 movf bytecounter,w movwf GPtemp movf RP_save,w movwf STATUS movf GPtemp,w bsf STATUS,C return nobuffer banksel RP_save movf RP_save,w movwf STATUS bcf STATUS,C return endm GETEP2 macro GetEP2 global GetEP2 local getEPloop2 local exitgetloop2 local nobuffer2 movf STATUS,w banksel RP_save movwf RP_save movf FSR,w movwf dest_ptr banksel BD2OST pagesel nobuffer2 btfsc BD2OST,UOWN goto nobuffer2 movf BD2OBC,w banksel counter movwf counter movwf bytecounter pagesel exitgetloop2 btfsc STATUS,Z goto exitgetloop2 banksel BD2OAL movf BD2OAL,w banksel source_ptr movwf source_ptr getEPloop2 bsf STATUS,IRP movf source_ptr,w movwf FSR movf INDF,w movwf GPtemp movf dest_ptr,w movwf FSR btfss RP_save,IRP bcf STATUS,IRP movf GPtemp,w movwf INDF incf dest_ptr,f incf source_ptr,f pagesel getEPloop2 decfsz counter,f goto getEPloop2 exitgetloop2 bsf STATUS,RP0 movf BD2OST,w andlw 0x40 xorlw 0x40 iorlw 0x88 movwf BD2OST movlw 0x08 movwf BD2OBC bcf STATUS,RP0 movf bytecounter,w movwf GPtemp movf RP_save,w movwf STATUS movf GPtemp,w bsf STATUS,C return nobuffer2 banksel RP_save movf RP_save,w movwf STATUS bcf STATUS,C return endm PUTEP1 macro PutEP1 global PutEP1 local putEPloop local exitputloop local nobufferputep movwf GPtemp movf STATUS,w banksel RP_save movwf RP_save movf GPtemp,w andlw 0x0F movwf counter movf FSR,w movwf source_ptr movf counter,w banksel BD1IST pagesel nobufferputep1 btfsc BD1IST,UOWN goto nobufferputep1 movwf BD1IBC pagesel exitputloop btfsc STATUS,Z goto exitputloop movf BD1IAL,w bcf STATUS,RP0 movwf dest_ptr putEPloop bsf STATUS,IRP btfss RP_save,IRP bcf STATUS,IRP movf source_ptr,w movwf FSR movf INDF,w movwf GPtemp bsf STATUS,IRP movf dest_ptr,w movwf FSR movf GPtemp,w movwf INDF incf dest_ptr,f incf source_ptr,f pagesel putEPloop decfsz counter,f goto putEPloop exitputloop bsf STATUS,RP0 movf BD1IST,w andlw 0x40 xorlw 0x40 iorlw 0x88 movwf BD1IST banksel RP_save movf RP_save,w movwf STATUS bsf STATUS,C return nobufferputep1 bcf STATUS,C return endm PUTEP2 macro PutEP2 global PutEP2 local putEPloop2 local exitputloop2 local nobufferputep2 movwf GPtemp movf STATUS,w banksel RP_save movwf RP_save movf GPtemp,w andlw 0x0F movwf counter movf FSR,w movwf source_ptr movf counter,w banksel BD2IST pagesel nobufferputep2 btfsc BD2IST,UOWN goto nobufferputep2 movwf BD2IBC pagesel exitputloop2 btfsc STATUS,Z goto exitputloop2 movf BD2IAL,w bcf STATUS,RP0 movwf dest_ptr putEPloop2 bsf STATUS,IRP btfss RP_save,IRP bcf STATUS,IRP movf source_ptr,w movwf FSR movf INDF,w movwf GPtemp bsf STATUS,IRP movf dest_ptr,w movwf FSR movf GPtemp,w movwf INDF incf dest_ptr,f incf source_ptr,f pagesel putEPloop2 decfsz counter,f goto exitputloop2 bsf movf andlw xorlw iorlw movwf putEPloop2 banksel RP_save movf RP_save,w movwf STATUS bsf STATUS,C return nobufferputep2 bcf STATUS,C return endm STATUS,RP0 BD2IST,w 0x40 0x40 0x88 BD2IST Código completo PIC16F628 interfaz con la PC (archivo esclavo2.asm) LIST p=16F628 RADIX HEX #include "P16f628.inc" __config _HS_OSC & _MCLRE_OFF & _LVP_OFF & _WDT_OFF & _PWRTE_ON & _CP_OFF & _BODEN_OFF ;================>registros ;banco 0 estado equ 0x03 tmr0 equ 0x01 portb equ 0x06 porta equ 0x05 pir1 equ 0x0C rcsta equ 0x18 txreg equ 0x19 rcreg equ 0x1A intcon equ 0x0B cmcon equ 0x1F fsr equ 0x04 ;banco 1 trisb equ 0x06 trisa equ 0x05 pcon equ 0x0E opcion equ 0x01 pie1 equ 0x0C txsta equ 0x18 spbrg equ 0x19 ;bits RP0 equ 0x05 INTF equ 0x01 INTE equ 0x04 TOIE equ 0x05 TOIF equ 0x02 OSCF equ 0x03 CREN equ 0x04 TXEN equ 0x05 RCIF equ 0x05 TXIF equ 0x04 TRMT equ 0x01 Z equ C equ SPEN equ ;variables f equ w equ overflow equ cont equ multiplo equ multiplo2 equ multiplo3 equ aux1 equ aux2 equ aux3 equ aux4 equ aux5 equ var1 equ clave1 equ clave2 equ clave3 equ var2 equ resta equ 0x02 0x00 0x07 0x20 0x21 0x22 0x23 0x24 0x25 0x26 0x27 0x28 0x29 0x2A 0x2B 0x2C 0x2D 0x2E 0x2F 0x41 0x42 org goto org goto 0x00 Inicio 0x04 Servicio call call goto inicial serial ciclo Inicio ciclo Servicio btfss goto decf btfss goto clrf intcon,INTF Tmr0int cont,f estado,Z muestra tmr0 bcf intcon,INTF bcf intcon,TOIF bsf intcon,TOIE retfie Tmr0int btfss intcon,TOIE goto recep_rx btfss intcon,TOIF retfie incf overflow,f bcf intcon,TOIF retfie recep_rx btfss pir1,RCIF retfie movf rcreg,w subwf clave1,w btfss estado,2 goto mm bsf portb,0x06 retfie mm movf rcreg,w subwf clave2,w btfss estado,2 retfie bcf portb,0x06 call delay bcf rcsta,CREN tt btfss portb,0x05 goto tt bsf portb,0x04 bsf intcon,INTE retfie muestra movf tmr0,w movwf resta movlw 0x0C subwf resta,w movwf INDF incf fsr,f movf movwf incf clrf clrf incf bcf bcf bcf decf btfss retfie movlw movwf bcf transmitir bsf movlw movwf movlw movwf bsf bsf bcf bsf otra incf movf movwf bsf ansina btfss goto bcf decf btfss goto overflow,w INDF fsr,f overflow cont cont,f intcon,TOIF intcon,TOIE intcon,INTF var1,f estado,Z 0x08 var1 portb,0x04 portb,0x03 0x08 aux1 0x37 fsr estado,RP0 txsta,TXEN estado,RP0 porta,0x00 fsr,f INDF,w txreg estado,RP0 txsta,TRMT ansina estado,RP0 aux1,f estado,Z otra salir bcf portb,0x03 clrf portb clrf porta bsf rcsta,CREN bsf estado,RP0 bcf txsta,TXEN bcf estado,RP0 movlw 0x30 movwf fsr bcf intcon,INTE retfie ;===========>FUNCIONES serial bsf estado,RP0 movlw b'00010000' movwf txsta bcf estado,RP0 movlw b'10010000' movwf rcsta return inicial bsf estado,RP0 movlw b'00100111' movwf trisb clrf trisa bsf trisa,0x05 movlw b'11001000' movwf opcion movlw b'11000000' movwf intcon bsf pie1,RCIE bcf pie1,TXIE bcf estado,RP0 bcf pir1,RCIF bcf pir1,TXIF movlw 0xAA movwf clave1 movlw 0xBB movwf clave2 movlw 0xCC movwf clave3 clrf porta movlw 0x07 movwf cmcon clrf w movlw 0x01 movwf f movwf cont movlw 0x30 movwf fsr movlw 0x04 movwf var1 clrf overflow clrf portb bcf portb,0x03 return delay banksel multiplo movlw 0x1B movwf multiplo3 si2 clrf multiplo2 si1 clrf multiplo si decf multiplo,f btfss STATUS,2 goto si decf multiplo2,f btfss STATUS,2 goto si1 decf multiplo3,f btfss STATUS,2 goto si2 return end Código completo PIC16C745 interfaz con el PLC (archivo chicotex.asm) #include <p16c745.inc> #include "usb_defs.inc" errorlevel -302 __CONFIG _H4_OSC & _WDT_OFF & _PWRTE_OFF & _CP_OFF unbanked W_save bank0 Status_save PCLATH_save FSR_save udata_shr res 1 udata res 1 res 1 res 1 outbuffer periodos multiplo multiplo2 multiplo3 clave1 clave2 clave3 aux aux1 aux2 aux3 res res res res res res res res res res res res 8 1 1 1 1 1 1 1 1 1 1 1 aux4 aux5 aux6 aux7 extern extern extern extern extern extern res res res res 1 1 1 1 InitUSB PutEP1 GetEP1 ServiceUSBInt CheckSleep RemoteWakeup STARTUP code pagesel main goto main nop InterruptServiceVector movwf W_save movf STATUS,W clrf STATUS movwf Status_save movf PCLATH,w movwf PCLATH_save movf FSR,w movwf FSR_save Process_ISR btfsc INTCON,INTF nop btfsc INTCON,T0IF nop btfsc INTCON,RBIF nop BANKSEL PIR1 pagesel ServiceUSBInt btfsc PIR1,USBIF call ServiceUSBInt btfsc PIR1,ADIF nop btfsc PIR1,RCIF nop btfsc PIR1,TXIF nop btfsc PIR1,CCP1IF nop btfsc PIR1,TMR2IF nop btfsc PIR1,TMR1IF nop btfsc PIR2,CCP2IF nop EndISR clrf STATUS movf FSR_save,w movwf FSR movf PCLATH_save,w movwf PCLATH movf movwf swapf swapf retfie code Status_save,w STATUS W_save,f W_save,w main banksel TRISA clrf TRISC bsf TRISC,0x07 bsf TRISC,0x06 movlw 0x06 movwf ADCON1 clrf TRISA bsf TRISA,0x02 clrf TRISB banksel PORTA clrf PORTA clrf PORTB movlw .30 movwf W_save decfsz W_save,f goto $-1 BANKSEL OPTION_REG bcf OPTION_REG,NOT_RBPU pagesel InitUSB call InitUSB ConfiguredUSB call inicializar call ini_tx ;=====================>PROCESOS LoopForData pagesel GetEP1 banksel outbuffer bankisel outbuffer movlw outbuffer movwf FSR movlw 0x8 call GetEP1 pagesel ndatos btfss STATUS,C goto LoopForData bcf STATUS,C btfss aux6,0x00 call ndatos call buffer_ram decf aux7,f btfss STATUS,2 goto EndLoopForData call ram_serial goto EndLoopForData EndLoopForData pagesel LoopForData goto LoopForData ;====================>FUNCIONES inicializar banksel SPBRG bcf PIE1,RCIE bcf PIE1,TXIE banksel PIR1 bcf PIR1,RCIF bcf PIR1,TXIF banksel aux3 clrf aux3 clrf aux6 return ini_tx banksel TXSTA movlw 0xB0 movwf TXSTA banksel RCSTA movlw 0x80 movwf RCSTA return ini_rx banksel TXSTA movlw 0x90 movwf TXSTA banksel RCSTA movlw 0xA0 movwf RCSTA return ndatos banksel outbuffer movlw outbuffer movwf FSR movf INDF,w movwf aux7 movwf aux5 bsf aux6,0x00 return incremento movlw 0x08 movwf aux movlw outbuffer movwf FSR otr incf INDF,f incf FSR,f decf aux,f btfsc STATUS,2 return goto otr return buffer_ram clrf aux1 movlw 0x08 movwf aux dat1 movlw outbuffer movwf FSR movf aux1,w addwf FSR,f movf INDF,w movwf aux2 movlw 0x40 movwf FSR movf aux3,w addwf FSR,f movf aux2,w movwf INDF incf aux1,f incf aux3,f decf aux,f btfss STATUS,2 goto dat1 return ram_serial movlw 0x41 movwf FSR movf INDF,w movwf aux decf FSR,f dat2 movf INDF,w movwf TXREG incf FSR,f decf aux,f btfsc STATUS,2 return movlw .100 movwf W_save decfsz W_save,fgoto $-1 goto dat2 return end Código completo PIC16F628 interfaz con el PLC (archivo esclavo2.asm) LIST p=16F628 RADIX HEX #include "P16f628.inc" __config _HS_OSC & _MCLRE_OFF & _LVP_OFF & _WDT_OFF & _PWRTE_ON & _CP_OFF & _BODEN_OFF ;================>registros estado equ 0x03 tmr0 equ 0x01 portb equ 0x06 porta equ 0x05 pir1 equ 0x0C tmr2 equ 0x11 t2con equ 0x12 ccpr1l equ 0x15 ccp1con equ 0x17 rcsta equ 0x18 txreg equ 0x19 rcreg equ 0x1A intcon equ 0x0B cmcon equ 0x1F fsr equ 0x04 trisb equ 0x06 trisa equ 0x05 pcon equ 0x0E opcion equ 0x01 pie1 equ 0x0C pr2 equ 0x12 txsta equ 0x18 spbrg equ 0x19 RP0 equ 0x05 INTF equ 0x01 INTE equ 0x04 TOIE equ 0x05 TOIF equ 0x02 CREN equ 0x04 TXEN equ 0x05 RCIF equ 0x05 TXIF equ 0x04 TRMT equ 0x01 Z equ 0x02 C equ 0x00 SPEN equ 0x07 f equ 0x20 w equ 0x21 var1 equ 0x22 var2 equ 0x23 multiplo equ 0x24 multiplo2 equ 0x25 multiplo3 equ 0x26 aux1 equ 0x27 aux2 aux3 seg min hor overflow1 overflow2 ret trans aux4 frec cnt equ equ equ equ equ equ equ equ equ equ equ equ 0x28 0x29 0x2A 0x2B 0x2C 0x2D 0x2E 0x2F 0x7B 0x7C 0x7D 0x7E org goto org goto 0x00 Inicio 0x04 Servicio call call goto inicial serial ciclo Inicio ciclo Servicio btfss goto btfss retfie bcf incf btfss retfie incf movf subwf btfss retfie clrf incf btfsc incf btfsc incf movf subwf btfss retfie movf subwf btfss retfie intcon,TOIE recep_rx intcon,TOIF intcon,TOIF overflow1,f estado,Z overflow2,f var2,w overflow2,w estado,Z overflow2 aux1,f estado,Z aux2,f estado,Z aux3,f seg,w aux1,w estado,Z min,w aux2,w estado,Z movf subwf btfss retfie clrf movlw movwf movf movwf bsf hor,w aux3,w estado,Z bsf call movlw movwf incf movf movwf portb,0x06 delay 0xFF aux3 fsr,f INDF,w ret call decf btfss goto bcf call bcf rlf movwf incf call clrf decf btfss goto clrf clrf bcf clrf incf retfie recep_rx btfss retfie movf movwf incf btfss goto movf movwf movwf decf decf ok incf TONO aux3,f estado,Z Period portb,0x06 delay2 estado,C trans,w porta trans,f delay2 porta cnt,f estado,Z cambio aux2 aux3 portb,0x04 trans trans,f aux1 0x34 fsr frec,w cnt portb,0x04 cambio Period pir1,RCIF rcreg,w INDF fsr,f pir1,RCIF $-1 rcreg,w INDF var1 var1,f var1,f fsr,f btfss goto movf movwf decf btfsc goto goto pir1,RCIF $-1 rcreg,w INDF var1,f estado,Z algo ok algo call datos bcf rcsta,CREN bcf intcon,TOIF clrf tmr0 bsf intcon,TOIE bcf portb,0x03 retfie ;====================>FUNCIONES serial bsf estado,RP0 movlw b'00010000' movwf txsta bcf estado,RP0 movlw b'10010000' movwf rcsta return inicial bsf estado,RP0 movlw b'00000110' movwf trisb clrf trisa movlw b'11001000' movwf opcion movlw b'11000000' movwf intcon bsf pie1,RCIE bcf pie1,TXIE bcf estado,RP0 bcf pir1,RCIF bcf pir1,TXIF clrf porta movlw 0x07 movwf cmcon clrf w movlw 0x01 movwf f movlw 0x30 movwf fsr movlw 0x1F movwf var2 clrf overflow1 clrf overflow2 clrf aux1 clrf aux2 clrf aux3 clrf portb bsf portb,0x03 clrf trans incf trans,f return datos movlw movwf movf movwf movlw subwf incf movf movwf incf movf movwf incf movf movwf return TONO bsf call bcf call return RETARDO movf movwf Bucle2 decf btfss goto return 0x31 fsr INDF,w frec 0x05 frec,f fsr,f INDF,w seg fsr,f INDF,w min fsr,f INDF,w hor portb,0x07 RETARDO portb,0x07 RETARDO ret,w var1 var1,f estado,Z Bucle2 delay si2 si1 si banksel multiplo movlw 0x03 movwf multiplo3 clrf multiplo2 clrf multiplo decf multiplo,f btfss STATUS,2 goto si decf multiplo2,f btfss STATUS,2 goto si1 decf multiplo3,f btfss STATUS,2 goto si2 return delay2 zi2 zi1 zi goto decf goto banksel multiplo movlw 0x1B movwf multiplo3 clrf multiplo2 clrf multiplo decf multiplo,f btfss STATUS,2 zi decf multiplo2,f btfss STATUS,2 goto zi1 multiplo3,f btfss STATUS,2 zi2 return end Código completo PIC16F873 (archivo 16f873.asm) #include <p16f873.inc> RADIX HEX errorlevel -302 __CONFIG _HS_OSC & _WDT_OFF & _PWRTE_OFF & _CP_OFF tmr0 estado FSR porta portb portc intcon pir1 rcsta txreg rcreg adresh equ equ equ equ equ equ equ equ equ equ equ equ 0x01 0x03 0x04 0x05 0x06 0x07 0x0B 0x0C 0x18 0x19 0x1A 0x1E adcon0 equ opcion equ trisa equ trisb equ trisc equ pie1 equ txsta equ spbrg equ adresl equ adcon1 equ RP0 equ Z equ C equ INTF equ TOIF equ INTE equ TOIE equ ADIF equ RCIF equ ADON equ GODONE equ overf equ cont equ palta equ pbaja equ f equ w equ sobra equ veces equ vuelta equ cte equ vuelta2 equ resta equ fa equ of1 equ sb1 equ sb2 equ 0x1F 0x01 0x05 0x06 0x07 0x0C 0x18 0x19 0x1E 0x1F 0x05 0x02 0x00 0x01 0x02 0x04 0x05 0x06 0x05 0x00 0x02 0x20 0x21 0x22 0x23 0x24 0x25 0x26 0x27 0x28 0x29 0x2A 0x2B 0x2C 0x2D 0x2E 0x30 org 0x00 goto Inicio org 0x04 goto Servicio Inicio bsf estado,RP0 movlw b'11001111' movwf opcion movlw b'10001110' movwf adcon1 clrf pie1 clrf trisb bsf trisb,0x00 clrf trisa bsf trisa,0x00 movlw b'00011100' movwf trisc bcf estado,RP0 movlw 0x01 movwf f movwf cont clrf movlw movwf clrf clrf clrf clrf clrf clrf clrf movlw movwf movlw movwf movlw movwf clrf btfsc goto incf mk btfsc goto incf incf frec1 movlw subwf btfss goto movlw movwf movlw movwf movlw movwf goto frec2 movlw subwf btfss goto movlw movwf movlw movwf movlw movwf goto frec3 movlw subwf btfss goto movlw 0x07 w b'11010000' intcon adcon0 porta portb portc overf sobra veces 0xF9 cte 0x14 vuelta 0x05 palta fa portc,0x02 mk fa,f portc,0x03 frec1 fa,f fa,f 0x03 fa,w estado,0x02 frec2 0x06 of1 0xE0 sb1 0xC2 sb2 ciclo 0x02 fa,w estado,0x02 frec3 0x07 of1 0x31 sb1 0x10 sb2 ciclo 0x01 fa,w estado,0x02 frec4 movwf movlw movwf movlw movwf goto of1 0x8A sb1 0x65 sb2 ciclo frec4 movlw movwf movlw movwf movlw movwf ciclo btfsc goto goto Servicio btfss goto decf btfss goto clrf bcf goto 0x07 of1 0xE4 sb1 0xBC sb2 portc,0x04 ciclo Activar intcon,INTF Tmr0int cont,f estado,Z Puerto tmr0 intcon,INTF Atajo Tmr0int btfss retfie incf intcon,TOIF bcf bsf retfie intcon,TOIF intcon,TOIE overf,f Atajo Puerto movf tmr0,w interrupción movwf cont movf of1,w subwf overf,w btfss estado,Z goto Noes movf sb1,w subwf cont,w btfsc estado,C goto Noes movf sb2,w subwf cont,w btfss estado,C goto Noes decf palta,f btfss estado,Z goto Ruido Activar bsf porta,0x05 bcf intcon,INTE bcf call call call call call call call call call bsf call Per bsf Chk btfss goto bcf bcf bsf call call movf movwf bsf movf bcf movwf call movf movwf clrf call call movwf movlw movwf Period call decf btfss goto decf btfss goto call movlw movwf Noes movlw movwf Ruido clrf Salir clrf clrf clrf clrf movlw movwf movlw movwf intcon,TOIE DELAY DELAY DELAY DELAY DELAY DELAY DELAY DELAY DELAY adcon0,ADON DELAY adcon0,GODONE pir1,ADIF Chk pir1,ADIF porta,0x05 porta,0x02 DELAY DELAY adresh,w palta estado,RP0 adresl,w estado,RP0 pbaja DIV sobra,w pbaja palta DIV CALC sobra 0xFF vuelta2 TONO vuelta2,f estado,Z Period vuelta,f estado,Z Period DELAY 0x02 vuelta 0x05 palta porta w overf sobra veces 0x01 cont 0xF9 cte movlw movwf bcf bcf bcf bsf retfie DELAY movlw movwf movlw bucle3 movwf bucle2 movwf bucle1 decf btfss goto decf btfss goto decf btfss goto return 0x14 vuelta intcon,TOIF intcon,TOIE intcon,INTF intcon,INTE 0x02 palta 0xFF overf cont cont,f estado,Z bucle1 overf,f estado,Z bucle2 palta,f estado,Z bucle3 DIV movlw 0x0A Resta subwf pbaja,f btfss estado,C goto Alta incf veces,f goto Resta Alta addwf addwf movlw subwf btfss return movlw movwf goto pbaja,w sobra,f 0x01 palta,f estado,C CALC bcf rlf movf subwf return estado,C veces,f veces,w cte,w TONO bsf call bcf call return porta,0x01 RETARDO porta,0x01 RETARDO RETARDO movf movwf decf btfss goto return Bucle2 0xFF pbaja DIV sobra,w cont cont,f estado,Z Bucle2 end Código Visual Basic interfaz con la PC (archivo chicotex.vbp) Dim buffer() As Byte Dim buffer2() As Byte Dim llego, manual, auto As Boolean Dim askaban As Integer Private Sub banterior3_Click() If interfaz.rslectura.EOF Then Exit Sub End If interfaz.rslectura.MovePrevious Call humedad If interfaz.rslectura.BOF Then interfaz.rslectura.MoveFirst Call humedad End If End Sub Private Sub bcancel2_Click() txthor.Locked = True txtmin.Locked = True interfaz.rstablatiempo.CancelUpdate End Sub Private Sub beditar2_Click() txthor.Locked = False txtmin.Locked = False txtfrecuencia.SetFocus End Sub Private Sub beliminar2_Click() interfaz.rstablatiempo.Delete If interfaz.rstablatiempo.EOF Then Exit Sub End If interfaz.rstablatiempo.MoveNext If interfaz.rstablatiempo.EOF Then interfaz.rstablatiempo.MoveLast End If End Sub Private Sub beditar_Click() txtfrecuencia.Locked = False txtfrecuencia.SetFocus End Sub Private Sub bnuevo2_Click() interfaz.rstablatiempo.AddNew txthor.Text = "" txtmin.Text = "" txthor.Locked = False txtmin.Locked = False txthor.SetFocus End Sub Private Sub bguardar_Click() interfaz.rstablatrans.Update End Sub Private Sub bprimero_Click() Private Sub beliminar_Click() If interfaz.rstablatrans.EOF Then Exit Sub End If interfaz.rstablatrans.Delete If interfaz.rstablatrans.EOF Then Exit Sub End If interfaz.rstablatrans.MoveFirst End Sub Private Sub banterior_Click() interfaz.rstablatrans.MoveNext If interfaz.rstablatrans.EOF Then interfaz.rstablatrans.MoveLast End If If interfaz.rstablatrans.EOF Then Exit Sub End If interfaz.rstablatrans.MovePrevious End Sub Private Sub bguardar2_Click() interfaz.rstablatiempo.Update End Sub If interfaz.rstablatrans.BOF Then interfaz.rstablatrans.MoveFirst End If End Sub Private Sub biniciar_Click() llego = False auto = True tim3.Enabled = True biniciar.Enabled = False End Sub Private Sub bnuevo_Click() interfaz.rstablatrans.AddNew txtfrecuencia.Text = "" txtfrecuencia.Locked = False txtfrecuencia.SetFocus End Sub Private Sub bcancel_Click() txtfrecuencia.Locked = True interfaz.rstablatrans.CancelUpdate End Sub Private Sub bprimero3_Click() If interfaz.rslectura.EOF Then Exit Sub End If interfaz.rslectura.MoveFirst Call humedad End Sub Private Sub bsiguiente_Click() If interfaz.rstablatrans.EOF Then Exit Sub End If interfaz.rstablatrans.MoveNext If interfaz.rstablatrans.EOF Then interfaz.rstablatrans.MoveLast End If If interfaz.rstablatiempo.EOF Then Exit Sub End If End Sub interfaz.rstablatiempo.MoveNext Private Sub bsiguiente3_Click() If interfaz.rslectura.EOF Then Exit Sub End If If interfaz.rstablatiempo.EOF Then interfaz.rstablatiempo.MoveLast End If End Sub interfaz.rslectura.MoveNext Call humedad Private Sub bultimo2_Click() If interfaz.rslectura.EOF Then interfaz.rslectura.MoveLast Call humedad End If If interfaz.rstablatiempo.EOF Then Exit Sub End If interfaz.rstablatiempo.MoveLast End Sub End Sub Private Sub bultimo_Click() Private Sub benviar_Click() ReDim buffer(8) ReDim buffer2(8) If interfaz.rstablatrans.EOF Then Exit Sub End If buffer2() = HIDComm1.ReadFrom(8) interfaz.rstablatrans.MoveLast End Sub On Error Resume Next Call blimpiar_Click Call bcalc_Click benviar.Enabled = False Private Sub bprimero2_Click() If interfaz.rstablatiempo.EOF Then Exit Sub End If interfaz.rstablatiempo.MoveFirst End Sub buffer(0) = t.Text buffer(1) = t1.Text buffer(2) = t2.Text buffer(3) = t3.Text buffer(4) = t4.Text buffer(5) = t5.Text HIDComm1.WriteTo buffer(), 8 Private Sub banterior2_Click() If interfaz.rstablatiempo.EOF Then Exit Sub End If interfaz.rstablatiempo.MovePrevious If interfaz.rstablatiempo.BOF Then interfaz.rstablatiempo.MoveFirst End If End Sub Private Sub bsiguiente2_Click() tim2.Enabled = True manual = True End Sub Private Sub blimpiar_Click() t.Text = "" t1.Text = "" t2.Text = "" t3.Text = "" t4.Text = "" t5.Text = "" t6.Text = "" t7.Text = "" End Sub Private Sub bultimo3_Click() If interfaz.rslectura.EOF Then Exit Sub End If interfaz.rslectura.MoveLast Call humedad End Sub Private Sub Form_Load() askaban = 0 llego = False manual = False auto = False Call bprimero3_Click HIDComm1.Connect End Sub Private Sub Form_Terminate() HIDComm1.Uninit End Sub Private Sub HIDComm1_ConnectSuccess(ByVal Status As Long) benviar.Enabled = True f1.Caption = "USB-PIC Conectado" t4.Text = buffer2(4) t5.Text = buffer2(5) t6.Text = buffer2(6) t7.Text = buffer2(7) interfaz.rslectura.AddNew txtid.Text = "" txtsobra.Text = "" txtoverflow.Text = "" txttiempo.Text = "" txtfecha.Text = "" If buffer2(5) <> 0 Then txtsobra.Text = t4.Text txtoverflow.Text = t5.Text Else txtsobra.Text = t6.Text txtoverflow.Text = t7.Text End If If Right(Time, 4) = "p.m." Then If Left(Time, 2) <> 12 Then ra = Left(Time, 2) + 12 End If ra = Left(Time, 2) Else ra = Left(Time, 2) End If txttiempo.Text = Trim(Str(ra)) & Mid(Time, 3, 3) txtfecha.Text = Date End Sub interfaz.rslectura.Update Private Sub HIDComm1_Disconnected(ByVal Status As Long) tim2.Enabled = False benviar.Enabled = False f1.Caption = "USB-PIC DESCONECTADO" End Sub Private Sub tim2_Timer() ReDim buffer2(8) Dim ra As Integer buffer2() = HIDComm1.ReadFrom(8) If manual = True Then manual = False End If llego = True askaban = 0 benviar.Enabled = True Else askaban = askaban + 1 End If If (buffer2(5) <> 0) Or (buffer2(7) <> 0) Then t.Text = buffer2(0) t1.Text = buffer2(1) t2.Text = buffer2(2) t3.Text = buffer2(3) If askaban >= 6 Then MsgBox "error" tim2.Enabled = False If manual = True Then manual = False End If llego = True benviar.Enabled = True askaban = 0 End If End Sub Private Sub bcalc_Click() Dim s As Double Dim r As Double Dim veces As Integer Dim sobra As Integer s = (Val(tnum.Text) / 1000) r = (1.01983321076 * s * s * s * s * s * s) (21.76684340806 * s * s * s * s * s) + (189.46208279318 * s * s * s * s) (867.57740836853 * s * s * s) + (2246.43786488113 * s * s) (3275.43053009874 * s) + 2474.90135900252 veces = r \ 255 sobra = (r Mod 255) t.Text = "1" t1.Text = "1" t2.Text = "1" t3.Text = "1" t4.Text = "1" t5.Text = "1" If veces > 1 Then t3.Text = Trim(Str(sobra)) t4.Text = "255" t5.Text = "255" End If If veces = 1 Then t4.Text = Trim(Str(sobra)) t5.Text = "255" End If If veces < 1 Then t5.Text = Trim(Str(sobra)) End If Private Sub humedad() Dim ll As Double ll = (Val(Trim(txtoverflow.Text)) * 255) + Val(Trim(txtsobra.Text)) ll = ((((0.00000002409442 * ll * ll) (0.00330379596851 * ll)) + 6.51707742555624) * 20) If (ll <= 101) And (ll > 0) Then panel.FloodPercent = ll eti.Caption = "Humedad" Else eti.Caption = "Valor Fuera de Rango" panel.FloodPercent = 0 End If End Sub Private Sub tim3_Timer() Dim j As Integer Dim lk As Integer Call bprimero_Click Call bprimero2_Click If Right(Time, 4) = "p.m." Then lk = Left(Time, 2) + 12 Else lk = Left(Time, 2) End If otracomp: If Trim(txthor.Text) = Trim(Str(lk)) And Trim(txtmin.Text) = Trim(Str(Mid(Time, 4, 2))) Then otrotrans: tnum.Text = txtfrecuencia.Text Call bcalc_Click Call benviar_Click j=0 Do While llego = False j=j+1 If j = 1000 Then DoEvents j=0 End If Loop interfaz.rstablatrans.MoveNext End Sub If interfaz.rstablatrans.EOF Then interfaz.rstablatrans.MoveFirst GoTo condini: End If GoTo otrotrans: interfaz.rstablatiempo.MoveFirst GoTo condini: End If End If Else interfaz.rstablatiempo.MoveNext GoTo otracomp: condini: If interfaz.rstablatiempo.EOF Then End Sub Código Visual Basic interfaz con el PLC (archivo chicotex.vbp) Dim buffer() As Byte Dim trans() As Byte Dim orale() As Byte Dim todo() As Byte Dim registro As Integer Dim n As Double Dim edo As Boolean Private Sub bbase_Click() If edo = False Then frame.Visible = True list.Visible = False bbase.Caption = "cambiar a lista" edo = True Else frame.Visible = False list.Visible = True bbase.Caption = "Cambiar a DB" edo = False End If End Sub Private Sub benviar_Click() ReDim buffer(50) ReDim trans(8) ReDim orale(8) Dim i, n, l, o, p As Integer Dim lop As Long n = (Val(Trim(thoras.Text)) * 3600) n = n + (Val(Trim(tminutos.Text)) * 60) n = n + (Val(Trim(tsegundos.Text))) i = n \ 255 If i > 255 Then buffer(4) = n \ 3600 n = n Mod 3600 End If buffer(3) = n \ 255 i = n Mod 255 buffer(2) = i i=6 interfaz.rscntb.MoveFirst buffer(5) = Val(Trim(txtnumero.Text)) otra: interfaz.rscntb.MoveNext If interfaz.rscntb.EOF Then interfaz.rscntb.MoveFirst GoTo salir Else buffer(i) = Val(Trim(txtnumero.Text)) i=i+1 End If On Error Resume Next GoTo otra salir: p = list.ListCount + 5 n=0 buffer(0) = p \ 8 For i = 0 To (p - 1) trans(n) = buffer(i) n=n+1 If n > 7 Then If (p Mod 8) > 0 Then buffer(0) = buffer(0) + 1 End If buffer(1) = p HIDComm1.WriteTo trans(), 8 For l = 0 To 60000 o=0 o=0+1 Next n=0 End If Next If (p Mod 8) <> 0 Then For l = 0 To 60000 o=0 o=0+1 Next HIDComm1.WriteTo trans(), 8 End If End Sub Private Sub bguardar_Click() n = (list.ListCount * 50) + 1000 n = n / 1000 n = (0.29124078463 * n * n * n * n * n * n) (6.32150481492 * n * n * n * n * n) + (56.25953631003 * n * n * n * n) (264.41332239284 * n * n * n) + (703.60080448892 * n * n) (1051.76677189924 * n) + 809.77563804734 n = Round(n, 0) txtnumero.Text = Str(n) interfaz.rscntb.Update txttransductor.Locked = True txtnumero.Locked = True list.AddItem Trim(txttransductor.Text) bguardar.Enabled = False bcancel.Enabled = False End Sub Private Sub beditar_Click() txttransductor.Locked = False txtnumero.Locked = False bguardar.Enabled = True bcancel.Enabled = True End Sub Private Sub bcancel_Click() txttransductor.Locked = True txtnumero.Locked = True interfaz.rscntb.CancelUpdate bguardar.Enabled = False bcancel.Enabled = False End Sub Private Sub bnuevo_Click() interfaz.rscntb.AddNew txttransductor.Locked = False txtnumero.Locked = False txtid.Text = "" txttransductor.Text = "" txtnumero.Text = "" txttransductor.SetFocus bguardar.Enabled = True bcancel.Enabled = True End Sub Private Sub beliminar_Click() Dim n, i As Integer interfaz.rscntb.Delete interfaz.rscntb.MoveNext If interfaz.rscntb.EOF Then interfaz.rscntb.MoveLast End If list.RemoveItem registro Call bprimero_Click interfaz.rscntb.MoveNext If interfaz.rscntb.EOF Then Call bprimero_Click Else registro = registro + 1 End If otra: n = (registro * 50) + 1000 n = n / 1000 n = (2.479848712157 * n * n * n * n) (36.548586166465 * n * n * n) + (200.849383811325 * n * n) (508.543487349061 * n) + 586.17748967466 txtnumero.Text = Str(n) interfaz.rscntb.Update interfaz.rscntb.MoveNext If interfaz.rscntb.EOF Then Call bprimero_Click Exit Sub Else registro = registro + 1 GoTo otra End If End Sub Private Sub bprimero_Click() registro = 0 interfaz.rscntb.MoveFirst End Sub Private Sub banterior_Click() registro = (registro - 1) interfaz.rscntb.MovePrevious If interfaz.rscntb.BOF Then interfaz.rscntb.MoveFirst registro = 0 MsgBox "Estamos en el primer registro" End If End Sub Private Sub bsiguiente_Click() registro = registro + 1 interfaz.rscntb.MoveNext If interfaz.rscntb.EOF Then interfaz.rscntb.MoveLast registro = (list.ListCount - 1) MsgBox "Estamos en el último registro" End If Private Sub Form_Terminate() HIDComm1.Uninit End Sub Private Sub HIDComm1_ConnectSuccess(ByVal Status As Long) benviar.Enabled = True f1.Caption = "USB-PIC Conectado" End Sub Private Sub HIDComm1_Disconnected(ByVal Status As Long) benviar.Enabled = False f1.Caption = "USB-PIC DESCONECTADO" End Sub Private Sub tim2_Timer() ReDim todo(50) Dim l, o As Integer Dim hojas As Long End Sub Private Sub bultimo_Click() registro = (list.ListCount - 1) interfaz.rscntb.MoveLast End Sub Private Sub Form_Load() HIDComm1.Connect interfaz.rscntb.MoveFirst list.AddItem Trim(txttransductor.Text) otra: interfaz.rscntb.MoveNext If interfaz.rscntb.EOF Then interfaz.rscntb.MoveFirst Exit Sub Else list.AddItem Trim(txttransductor.Text) End If GoTo otra interfaz.rscntb.MoveFirst registro = 0 edo = False End Sub todo = HIDComm1.ReadFrom(hojas) MsgBox "hojas= " & hojas If hojas >= buffer(1) Then MsgBox "datos= " & buffer(1) For l = 0 To 8 MsgBox "todo(" & l & ")= " & todo(l) Next tim2.Enabled = False benviar.Enabled = True End If End Sub Private Sub tim1_Timer() If HIDComm1.Connected = False Then HIDComm1.Connect End If End Sub Public Function dec_bin(ByRef d As Integer) As String Dim cad As String Dim cad1 As String Dim i As Integer Do While d >= 1 If Trim(Str(d Mod 2)) = "1" Then cad = cad & "1" Else cad = cad & "0" End If d = Round((d / 2) - 0.4) Loop f=f+1 i=i-1 Loop bin_dec = n End Function Public Function elevar(ByRef factor As Integer) As Integer Dim r As Integer Dim l As Integer l = factor i = Len(cad) Do While i > 0 cad1 = cad1 & Mid(cad, i, 1) i=i-1 Loop dec_bin = cad1 End Function Public Function bin_dec(ByRef c As String) As Integer Dim i As Integer Dim f As Integer Dim n As Integer f=0 n=0 i = Len(c) Do While i > 0 If Mid(c, i, 1) = "1" Then n = n + elevar(f) End If If l = 0 Then elevar = 1 Exit Function End If If l = 1 Then elevar = 2 Exit Function End If r=2*2 l=l-2 Do While l > 0 r=r*2 l=l-1 Loop elevar = r End Function 167 ANEXO 2 Cuadros de diálogos en el proceso de enumeración (win98) Cuadros de diálogos en el proceso de enumeración (win2000) Cuadros de diálogos en el proceso de enumeración (winXP) 172 ANEXO 3 Para configurar el módulo maestro con interfaz hacia la PC, se colocan 2 jumpers en las posiciones que indica la siguiente figura. Para configurar el módulo maestro con interfaz hacia la PLC, se quitan los 2 jumpers mencionados en la figura anterior y sólo se coloca el que indica la siguiente figura. 173 ANEXO 4 Módulo maestro Módulo esclavo 174 ANEXO 5 Inicio 1 Inicialización de puertos Retardo en la espera del RESET USB Inicializar los registros de USB Espera de la configuración USB Espera de la señal de control RSI Recepción serie de datos de humedad y asignadas a memoria RAM Datos en memoria RAM a Buffer de transmisión USB Inicializar variables Configurar comunicación serie Transmisión de datos por el puerto USB Esperar datos de activación por el puerto USB Transmitir por el puerto serie CLAVE1 para encender el TX analógico Retardo para el encendido total del TX analógico Generar la señal de activación 1 Transmitir por el puerto serie CLAVE2 para apagar el TX analógico Figura 3.51 PIC16C745 modo de conexión PC. Interrupción Serie Inicio Identificar clave Inicialización de puertos y variables Configurar puerto serie Clave1 Encender TX analógico Clave2 Apagar TX analógico Ciclo oscioso 1 Retardo 1 RSI Deshabilito recepción serie y Habilito interrupción externa Identificar interrupción y saltar según sea el caso 1 Interrupción Externa Interrupción TMR0 Identificar periodo Incrementar contador de desbordamientos Inicio Periodo Fin Periodo 1 Borrar TMR0 Habilito interrupción TMR0 1 Muestra a RAM número de muestras insusficientes Determinar número de muestras Habilito transmisión serie y transmito las muestras de frecuencia Condiciones Iniciales 2 Condiciones Iniciales 1 1 Figura 3.52 PIC16F628 modo de conexión PC. 1 Inicio Inicialización de puertos Retardo en la espera del reset USB RSI Inicializar los registros de USB Espera de la configuración USB Inicializar variables 1 Configurar comunicación serie Esperar datos de configuración para el sistema de monitoreo, enviados por el puerto USB en paquetes Identificar primer paquete Primer paquete Obtener el número de paquetes a leer en el puerto USB Pasar datos del buffer USB a memoria RAM Identificar fin de transmisión de paquetes 1 Transmito memoria RAM de datos al puerto serie Fin de transmisión de paquetes Figura 3.53 PIC16C745 modo de conexión PLC. Interrupción serie Inicio Inicialización de puertos y variables Recepción serie de datos Se obtiene el número de transductores Y el tiempo para cada barrido Configuración del puerto serie 1 Ciclo oscioso Se habilita la interrupción TMR0 RSI 1 Identificar interrupción Interrupción TMR0 Incrementar el temporizador 1 Condiciones iniciales no igual Identificar temporizador = tiempo de barrido Fin de barrido Igual Identificar fin de barrido Obtener frecuencia a generar Número del transductor activado al PLC Encender TX analógico Retardo en espera del dato de humdad Apagar TX analógico Retardo para que se encienda el TX totalmente Generar la frecuencia de activación Figura 3.54 PIC16F628 modo de conexión PLC. Interrupción TMR0 Inicio Incrementar contador de desbordamientos Inicialización de puertos y variables 1 1 Ciclo oscioso RSI Interrupción Externa Identificar periodo Inicio de Periodo Borrar TMR0 Fin de Periodo Fuera del rango Identificar rango Inicializar muestras Habilito interrupción TMR0 Dentro del rango Identificar número 1 Condiciones Iniciales 1 de muestras 1 Activación válida Preparar ADC e iniciar conversión Muestras insufucientes Calcular datos para generar frecuencia Generar frecuencia de dato de humedad Condiciones Iniciales 2 Figura 3.51 PIC16F873.