133
Implementación del protocolo de comunicaciones X-MODEM sobre un microcontrolador. AUTOR: César Pérez Iglesias DIRECTOR: Esteban del Castillo Pérez FECHA: Enero / 2004

Implementación del protocolo de comunicaciones X-MODEM …deeea.urv.cat/public/PROPOSTES/pub/pdf/518pub.pdf · 2009. 9. 22. · establecimiento de las comunicaciones y el intercambio

  • Upload
    others

  • View
    1

  • Download
    0

Embed Size (px)

Citation preview

Implementación del protocolo de comunicaciones

X-MODEM sobre un microcontrolador.

AUTOR: César Pérez Iglesias

DIRECTOR: Esteban del Castillo Pérez

FECHA: Enero / 2004

GRACIAS a:

MERITXELL, por haberme prestado el módem que me faltaba.

DAVID, por todos los consejos y la ayuda a la hora de elaborar la placa de circuito impreso.

JORDI, por prestarme su programador.

LAIA, por ese empujón final que necesitaba para la memoria.

A todas aquellas personas que con su ayuda o su aliento han contribuido al desarrollo de este proyecto.

ÍNDICE 1. Introducción...............................................................................................................3

1.1 Objetivos............................................................................................................3 1.2 Justificación de utilidad ......................................................................................3 1.3 ¿Por qué un soporte embedido? ..........................................................................4 1.4 Generalidades.....................................................................................................5

2. Protocolo XModem........................................................................................................7 2.1 Introducción.............................................................................................................7 2.2 Protocolo a nivel de paquete.....................................................................................7 2.3 Terminología............................................................................................................8 2.4 Inicialización............................................................................................................9 2.5 Transmisión XModem............................................................................................10 2.6 Recepción XModem...............................................................................................12 2.7 Errores ...................................................................................................................14

2.7.1 Errores por exceso de tiempo (TIMEOUTS)....................................................14 2.7.2 Errores de secuencia ........................................................................................15 2.7.3 Errores de integridad del campo de datos.........................................................15

2.7.3.1 Bit de paridad .......................................................................................15 2.7.3.2 Redundancia de bloques: Suma de comprobación .................................17 2.7.3.3 Comprobación de redundancias cíclicas ................................................17

2.7.4 Falsa finalización de la comunicación.......................................................24 2.8 Observaciones ..................................................................................................25 2.9 Ejemplo del flujo de datos ................................................................................26

3. El Módem....................................................................................................................28 3.1 Introducción...........................................................................................................28 3.2 El módem y su funcionamiento ..............................................................................28 3.3 Velocidades de transmisión....................................................................................29 3.4 Conexión RS-232 entre terminal y módem.............................................................30 3.5 Control de flujo ......................................................................................................30 3.6 Manejo del módem.................................................................................................30

3.6.1 Modos de funcionamiento ...............................................................................30 3.6.2 Comandos de control del módem.....................................................................31 3.6.3 Códigos de resultados y respuestas de monitorizado de progreso de la llamada.................................................................................................................................34 3.6.4 Programación de los registros S.......................................................................35

4. Especificaciones Software............................................................................................37 4.1 Objetivos................................................................................................................37 4.2 Principio de funcionamiento...................................................................................37 4.3 Estructura del código..............................................................................................38 4.4 Rutina de Servicio a la Interrupción: GET_D. ........................................................39

4.4.1 Control de errores de secuencia. ......................................................................41 4.5 Rutina de Servicio a la Interrupción: PUT_D..........................................................44 4.6 Implementación del Código de Redundancia Cíclica: DO_CRC. ............................46 4.7 Tiempos de ejecución de RSI’s y entre interrupciones. .....................................48 4.8 Rutinas para el módem.....................................................................................50

4.8.1 Establecimiento de conexión: función CONN. ..........................................50 4.8.2 Desconexión.............................................................................................53

4.9 Suma inicial de comprobación..........................................................................53

4.10 Control de las comunicaciones .........................................................................56 4.10.1 Función de alto nivel para emisión: LLENADO........................................57 4.10.2 Funciones de control de buffer: INTO(T/R) y OUTFROM(T/R)...............58 4.10.3 Lectura del buffer de transmisión y envío: SND_BYTE............................61 4.10.4 Recepciones. .................................................................................................61 4.10.5 Escritura en el buffer de 128 posiciones: ARAM. .....................................62 4.10.6 Escritura en la memoria FLASH: SALVAR..............................................64

4.11 Temporizaciones. .............................................................................................65 4.11.1 Control del temporizador. ..............................................................................66 4.11.2 Habilitaciones: ENAOUTR y ENAOUTT .....................................................67 4.11.3 Deshabilitaciones: DISOUTR y DISOUTT....................................................69 4.11.4 Desarrollo de los servicios a excesos de tiempos............................................69

5. Hardware .....................................................................................................................72 5.1 Objetivos................................................................................................................72 5.2 Sistema de alimentación.........................................................................................72 5.3 Microcontrolador y circuitos necesarios su funcionamiento....................................74

5.3.1 PIC 16F876 .....................................................................................................74 5.3.2 Circuito oscilador ............................................................................................75 5.3.3 Circuito de reset ..............................................................................................75 5.3.4 Circuitos de señalización de averías y maniobra ..............................................77

5.4 Etapa de acceso al medio físico y conector. ............................................................78

jmare
A.I Solución circuital adoptada .....................................................................................80
jmare
jmare
A. II Código ..................................................................................................................86

1. Introducción

1. Introducción

1.1 Objetivos Este proyecto consiste en la implementación de un sistema de comunicaciones basado en el protocolo XModem. Serán comunicaciones por un canal serie siguiendo la norma RS-232. El proyecto se centra básicamente en la creación del software necesario para el intercambio de información. Precisamente, la utilidad de un protocolo es la de establecer unas normas mediante las cuales esto último sea posible. Entenderemos por racional un intercambio de información que prevea posibles errores de emisión/recepción y sus posibles soluciones. El código será implementado para el PIC 16F876 y compatibles, cuyo fabricante es Microchip. El lenguaje utilizado para desarrollar el software será el ensamblador propio del circuito integrado. Además de este software, se desarrollará adicionalmente una pequeña rutina o rutinas de control de módem. De esta manera se podrá establecer un entorno más real para la aplicación y probar con elementos reales de comunicación la implementación del protocolo. De la misma manera, será necesario un pequeño diseño hardware que esté compuesto por el microcontrolador y todos los elementos necesarios para la gestión de líneas de transmisión. Esta será específica en mayor o menor medida para la demostración que se realice del proyecto y estará relacionada con la finalidad última del mismo sin ser necesariamente parte fundamental.

1.2 Justificación de utilidad Si se hace un balance de lo ocurrido en el pasado siglo, observamos que la característica principal de nuestro tiempo es el cambio; ya que a diferencia de otras épocas, en donde se han presentado eventos semejantes en cuanto a importancia y características, actualmente éstos producen cambios de gran impacto en la humanidad. Existen grandes problemas generados por la globalización del espacio económico mundial. Este ha sido uno de los cambios, sin duda, más relevantes del tiempo actual. Esta globalización eleva el nivel de competitividad entre las empresas del primer mundo, que dado el marco económico, se ven obligadas a “defender” su parcela mercantil de otras empresas del mismo sector pero que, como novedad, no son necesariamente limítrofes. Como contrapartida y al mismo tiempo, se ven posibilitadas para ampliar su cuota de mercado más allá de sus fronteras. Por otra parte, la competitividad se basa en dos pilares básicos: productividad y control de calidad. Estas premisas nos pueden indicar la tendencia generalizada de cualquier empresa que se encuentre inmersa en el problema (y por otro lado ventaja) de la globalización. En cuanto a productividad, sería muy razonable (desde el punto de vista de los fines) que una empresa optara por el abaratamiento de costes de producción. Es decir, ahorro en mano de obra (automatización) y ahorro en materias primas. En cuanto a control de calidad, la empresa buscará que cada uno de sus productos salga de fábrica con una fiabilidad prefijada mínima. Una de las maneras de conseguir esto viene a ser el aumento del grado de automatización de la producción, porque las máquinas no se suelen equivocar y son altamente precisas. Un operario puede tener errores y provocar imperfecciones. Recapitulando nos daremos cuenta de que las dos estrategias clave ejecutadas por las empresas para afrontar la globalización las llevan al incremento de la automatización y la desaparición de la mano de obra. Por tanto, para que una empresa pueda subsistir en una

jmare

2. Protocolo XModem

economía como la actual deberá basar su política en la automatización y en los recortes de personal. Llegados a esta conclusión, advertiremos otro problema, y es que por muy automatizada que sea una planta de producción o explotación de análogas características, siempre va a necesitar de la supervisión humana para su funcionamiento. Conociendo todos estos datos buscaremos la manera de minimizar la cantidad de mano de obra que pueda supervisar el máximo de sistemas automáticos, que viene a ser lo más lógico. Dada esta disyuntiva, cobra fuerza el campo de las telecomunicaciones. Este campo abre un enorme abanico de posibilidades a la hora del control a distancia, la adquisición de información (también a larga distancia o que esté muy dispersa) y en definitiva permite poner al alcance de una sola persona, todo un mundo de posibilidades de control. El proyecto en el que se basa esta memoria intenta, de alguna manera, servir a los propósitos anteriormente mencionados. En resumidas cuentas, estos son los de facilitar a una persona el manejo de datos y ordenes a distancia. Entendidos estos razonamientos, y vista esta necesidad se da una solución aplicada al establecimiento de las comunicaciones y el intercambio de información entre dispositivos.

Figura 1. Objetivos generales de la empresa actual

1.3 ¿Por qué un soporte embedido? Las razones que apoyan el uso de microcontroladores en el desarrollo de un proyecto de este tipo son diversas. Empezando por el bajo coste de estos pequeños computadores y de

GLOBALIZACIÓN

PRODUCTIVIDAD CONTROL DE CALIDAD

COMPETITIVIDAD

MINIMIZACIÓN DE COSTES FIABILIDAD

AHORRO EN: - MANO DE OBRA (AUTOMATIZACIÓN) - MATERIAS PRIMAS

AUTOMATIZACIÓN

CONTROL HUMANO MÍNIMO NECESARIO Y SUFICIENTE

jmare

1. Introducción

la consecuente bajada del precio del producto acabado. Además, son de fácil utilización, no requiriendo grandes conocimientos de sistemas digitales. En el caso concreto de Microchip se puede añadir un aliciente más, que son las herramientas de trabajo dispuestas para el diseño de programas y prototipado de proyectos. Además de eso, el mismo fabricante dispone de hojas de características y manuales muy completos, que no suponen coste alguno para el usuario. La fiabilidad de estos dispositivos (uC’s en general) es además alta. Otra razón a tener en cuenta, es la gran utilización que se hace de ellos en el sector de las telecomunicaciones. La mayor parte de los uC’s del mercado tienen como destino final una aplicación de telecomunicaciones. Más incluso que los utilizados en automoción, informática o electrónica de consumo (electrodomésticos en general). Como razón última expondremos que, salvando ciertas distancias, la única limitación de los microcontroladores actuales está en la imaginación del diseñador, ya que presentan una cantidad de posibilidades y combinaciones desorbitadas.

1.4 Generalidades

Figura 2. Generalidades sobre el manejo de la información

Dada la naturaleza del proyecto, utilizaremos conceptos específicos que pueden llevar a confusión. Entre ellos está el de protocolo y estándar, que suelen ser confundidos entre ellos. En el esquema anterior se muestra de manera básica, la forma en que se estructura el proyecto. Los espacios sombreados son los dedicados a la parte software que se implementará, mientras que el resto corresponden a parte hardware. De esta manera, observaremos que los datos forman archivos lógicos, los cuales son organizados en paquetes, que finalmente conformarán la información enviada. Podría pensarse que los paquetes simplemente son secciones del archivo, de tal manera que se envían los mismos datos contenidos en él durante diferentes ciclos. Esto no es del todo cierto. Si que es verdad que se envían “pedazos” de archivo, pero también otras

DATO

ARCHIVO

ESTRUCTURA DE ENVÍO / PAQUETE

PROTOCOLO

SOPORTE EMBEDIDO

NORMA / ESTÁNDAR

jmare

2. Protocolo XModem

informaciones mediante las cuales el receptor puede controlar mejor los datos entrantes y diferenciar los erróneos de los correctos. Una vez formados los paquetes (que también deben estar montados conforme a los requisitos del protocolo), existen multitud de maneras de enviarlos. Por tanto, cada protocolo debe especificar otros aspectos:

- En que orden enviar los paquetes - Estrategias y herramientas de búsqueda de errores - Forma de solventar los errores, sean del tipo que sean - Como comenzar y acabar la comunicación - Cuando enviar cada paquete

Todo este soporte lógico tendrá como base física un microcontrolador; o lo que es lo mismo: un sistema embedido. Mediante este sistema, obtendremos los datos, los procesaremos y los enviaremos. Todo este hardware, deberá estar supeditado a un estándar unificado para todos los usuarios de este tipo de comunicaciones serie. De esta manera, cualquier usuario de comunicaciones serie (que sigan el estándar RS-232) podrá hacer uso de ese sistema sin ningún tipo de adaptación y sin riesgo de causar daños a otros dispositivos. Los estándares especifican aspectos como:

- Distancia máxima entre interlocutores - Cantidad, función y tipo de señales - Niveles lógicos utilizados - Velocidades de transmisión - Cuestiones de fiabilidad y robustez

2. Protocolo XModem

2. Protocolo XModem

2.1 Introducción El XModem es un protocolo de recuperación de errores para transmisión de ficheros entre dos dispositivos. Las comunicaciones entre estos últimos serán de tipo serie, asíncronas, de 8 bits de datos en cada envío, sin bit de paridad y un bit de stop. Este protocolo es del tipo ARQ (Automatic Repeat Request) o “solicitud de repetición automática”. Lo que quiere decir esto, es que se retransmite un paquete en cuanto el receptor encuentra un error o si hay ausencia de señal de reconocimiento (handshake).

Figura 3. ARQ de envío y espera.

2.2 Protocolo a nivel de paquete Existen multitud de variantes del mismo protocolo XModem. Desde el XModem 1k hasta el CRC y pasando por el WXModem, existen igualmente diversas variantes del mismo paquete. En nuestro caso, tendremos un paquete de 5 campos, el tamaño de los cuales no es el mismo: SOH: “start of header”. Este byte anuncia la llegada del paquete. El carácter al que corresponde en el código ASCII es el h’01’. Por tanto, cada vez que se reciba un 1 mientras se espera un paquete en el receptor, este será interpretado como un comienzo de paquete. Esto implica que el próximo carácter recibido se tomará como número de secuencia de paquete y así sucesivamente.

RECEPTOR

1 2 3 3 4 4

EMISOR

1 2 3 3 4 4

ACK

ACK

NAK

ACK

NAK

RETRANSMITIR

RETRANSMITIR

ERROR

ERROR

2. Protocolo XModem

SOH Número de

secuencia de paquete

Complemento a 1 del número de

secuencia DATA Control de

errores

Figura 4. Formato del paquete

Número de secuencia de paquete: Número del paquete en cuestión. Este campo ocupa un byte. Por tanto, como mucho podrá haber 255. El primer paquete llevará el número 1, por lo que este es el valor inicial. Complemento a 1 del número de secuencia: Complemento a 1 del número anterior. Tiene también un tamaño de 1 byte. DATA: La longitud será de 128 bytes para nuestro protocolo. En algunas variantes como el XModem 1k, este campo tiene una longitud diferente (de 1k como su nombre indica). No hay más restricciones que el tamaño propio de campo para la información que se guarda. Se pueden guardar datos binarios o de texto. Control de errores1: Este campo podrá tener 1 ó 2 bytes de tamaño. Originalmente, el XModem CRC dispone de un tamaño de 2 bytes para su control de errores (que será mediante CRC) mientras que el XModem original dispone de un control de errores por suma aritmética sin acarreos de un tamaño equivalente a 1 byte.

2.3 Terminología Definiremos, llegados a este punto, dos conceptos básicos: transmisor y receptor. El transmisor será el dispositivo o software que envía paquetes de datos y recibe bytes de reconocimiento (a groso modo). El receptor es el dispositivo recíproco, que recibe paquetes de datos y envía caracteres de reconocimiento. Los caracteres ASCII más utilizados, tanto por el receptor como por el emisor, son los siguientes:

DENOMINACIÓN VALOR DEC.

VALOR HEX. SIGNIFICADO OBSERVACIONES

SOH 01 001 Start Of Header

Carácter enviado al inicio de cada paquete por el emisor para marcar la llegada del mismo.

EOT 04 004 End Of Transmision

Enviado por el emisor en el momento en que debería enviar un nuevo paquete para indicar que se han enviado y reconocido ya todos los paquetes y que se debe acabar la comunicación.

ACK 06 006 Acknowledge Enviado por el receptor. De

1 Por lo que respecta a nuestro código, podrá trabajar con las dos variables del protocolo.

2. Protocolo XModem

esta manera, valida el paquete al emisor y la comunicación seguirá su curso.

NAK 21 015 Negative Acknowledge

Enviado por el receptor, indica al emisor que el paquete no se da por válido por alguna razón. En consecuencia, el emisor deberá reenviar el mismo.

CAN 24 018 Cancel

Enviado por el receptor, implica la finalización incondicional de la transmisión por problema irrecuperable.

Tabla 1. Caracteres ASCII más utilizados

2.4 Inicialización Antes de que se ponga en marcha de forma práctica la comunicación, es necesario que el emisor tenga la información que ha de enviar o pueda obtenerla de alguna manera (punteros a direcciones de memoria por ejemplo). De la misma manera, se le debe delimitar al receptor un espacio para que pueda guardar la información que recibe. Se dice que el protocolo XModem está dirigido por el receptor: es decir, que este es el encargado de estimular y mantener el flujo de datos. De esta manera, el receptor será el que envíe el byte de sincronismo al emisor. Este byte corresponderá al carácter NAK o “C” del código ASCII. En caso de estar aplicando el protocolo XModem CRC utilizaremos el carácter “C” y en caso de ser el XModem original será el otro. Una vez el emisor haya recibido el “handshake”, empieza el envío de paquetes. Según la velocidad de proceso del dispositivo, este deberá maquetar los paquetes antes de comenzar el envío o podrá ir montándolos sobre la marcha. Una vez recibidos y validados todos los paquetes (por parte del receptor), el emisor enviará el carácter EOT, de tal manera que anunciará el fin del envío. En algunas ocasiones puede darse el caso en que el receptor envíe el carácter de sincronismo y el emisor no responda de ninguna manera. Esto puede ser debido a que el canal de comunicación se ha deteriorado, a que el emisor no está preparado o a la falta de sincronismo entre emisor y receptor. Por ello, el receptor seguirá intentando establecer la comunicación mediante el envío sucesivo de caracteres de sincronismo durante un tiempo determinado. Este tiempo (o TIMEOUT) y el número de intentos de sincronismo, también vienen prefijados por el protocolo. En caso de sobrepasarse este tiempo, se desiste de la comunicación y se toman acciones al respecto. El mismo mecanismo de seguridad se encuentra implementado en el emisor. De esta manera, si no recibe carácter de sincronismo en un tiempo máximo prefijado, no considerará la posibilidad de establecimiento de comunicación y cursará acciones en consecuencia.

2. Protocolo XModem

2.5 Transmisión XModem El transmisor se encarga de dividir2 la información en bloques de 128 bytes, calcular los bytes de flanqueo e ir enviando el paquete byte a byte. Dividiremos estas tareas en tres fases:

- Fase de comienzo. En este punto, el emisor espera a que el receptor le envíe el carácter de sincronismo (NAK / ”C”). El inicio de la comunicación está marcado por este acontecimiento. En cualquier caso, el emisor no esperará de manera indefinida, sino que considerará una espera que no supere un tiempo o TIMEOUT determinado por el mismo protocolo. En caso de producirse el exceso de tiempo se valorará la acción a tomar. Por lo general, se permitirán varios errores por TIMEOUT antes de considerar el estado de error como definitivo (que impide la comunicación de manera indefinida). Una de las acciones a llevar a cabo puede ser la de informar al usuario del error.

- Fase intermedia. Una vez recibido el carácter de sincronismo, el emisor empieza a

enviar paquetes (previo maquetado de todos ellos si es necesario). Después de que el primer envío se complete, el emisor espera el envío de un byte del receptor. En este byte, el dispositivo remoto le indicará al emisor si valida o no el contenido del paquete. En caso de no validarlo enviará un NAK y en caso contrario un ACK. Si un paquete no es validado, el emisor intentará un reenvío del mismo. Si por el contrario lo es, y el emisor recibe un ACK, el paquete se habrá transmitido con éxito y se producirá el envío del siguiente paquete. De recibir un CAN, el emisor interpretará la necesidad por parte del receptor de terminar de manera anormal la comunicación (por un fallo irrecuperable o similar). En caso contrario, la comunicación acabará cuando se hayan enviado la totalidad de los paquetes. Es importante remarcar el hecho de que, la cantidad de información que puede enviar un paquete es como mucho de 128 bytes. Esto, que a priori no parece tener gran importancia, compromete la integridad del fichero o conjunto de datos a enviar. La razón es muy simple: un fichero rara vez presentará una cantidad de información de tamaño múltiple de 128. Es decir, en la mayor parte de los casos no podremos dividir la totalidad de nuestro fichero en un número exacto de paquetes. Lo cual quiere decir que el último paquete no se completará. El protocolo prevé esto y obliga a rellenar con caracteres “0” el resto del campo de datos que queda vacío. En definitiva esto conllevará que el fichero recibido sea más grande que el emitido, conteniendo una cantidad indefinida de “0” al final del mismo. En algunos casos esto puede dar problemas como la inutilización del archivo (en caso de que sea un archivo binario ejecutable por ejemplo). Más adelante veremos posibles soluciones a este problema.

- Fase final. Si la fase intermedia termina con normalidad, el emisor transmitirá un

EOT para informar al receptor que no tiene más paquetes que transmitir. El receptor deberá reconocer este EOT con un ACK. Esto es susceptible también de mejora, como veremos en el apartado de observaciones. De terminar la comunicación con un CAN, el emisor no enviará el EOT.

2 Si el paquete se maqueta sobre la marcha, no será necesaria la división. En tal caso se irá enviando la información en bloques de 128 bytes utilizando, por ejemplo, un puntero a dirección de memoria.

2. Protocolo XModem

¿Se recibe un ACK?

Envio de EOT

No

No

No

Carácter no reconocido

Fin

No

Abandono

¿Se recibe un CAN?

No

No

¿Se recibe un NAK?

¿Se recibe un ACK?

A la espera del reconocimiento del

receptor

¿Error por TIMEOUT?

¿Límite de errores por TIMEOUT?

¿Límite de errores por TIMEOUT?

No

¿Quedan paquetes por

enviar?

Tomar el paquete

Envio de paquete

¿Se recibe el carácter

de sincronismo?

No

No

A la espera del carácter de sincronismo.

Inicio

Figura 5. Procedimiento a seguir por un transmisor XModem.

2. Protocolo XModem

2.6 Recepción XModem El receptor es el encargado de aceptar todos los paquetes. Ha de comprobar si ha recibido el paquete correcto y sin ningún error en su contenido. Además, el receptor dirigirá y estimulará la comunicación mediante los caracteres de reconocimiento.

- Fase de comienzo. En esta fase, el receptor se limita a enviar el carácter de sincronismo. Como ya se ha especificado antes, este carácter podrá ser un NAK o un “C” del código ASCII según la versión del protocolo que se esté empleando. En caso de no recibir el envío de ningún paquete como respuesta al byte de sincronismo, el receptor cuantificará un error, una vez haya pasado el tiempo pertinente. Además de eso volverá a enviar el byte de sincronismo. Si se acumulasen demasiados errores, el receptor abandonaría sus intenciones de establecer el sincronismo.

- Fase intermedia. En este punto, el receptor entra en un bucle de espera en el que se detectan los paquetes y se envía el handshake necesario en cada caso. La llegada de un SOH anuncia la entrada de un paquete, que se evalúa del modo siguiente:

o Un EOT solitario recibido en el lugar de un SOH da a entender que no hay más paquetes y hace salir al receptor de esta fase intermedia.

o Mediante los campos 2º y 3º se hace la comprobación del número de secuencia del paquete. En este punto, se pueden dar varios casos: § Número de paquete y su complemento correctos y en secuencia:

todo está correcto y se espera la recepción completa del paquete. § Hay un error en la integridad del número de paquete o de su

complemento: se han dañado los datos relativos a los campos 2º y/o 3º. El receptor debe enviar un NAK.

§ Hay un error de secuencia y el paquete esperado corresponde al anteriormente recibido: Esta información es redundante y se enviará un ACK para que el emisor continúe con el siguiente paquete.

§ Hay un error de secuencia y el paquete recibido es el siguiente en orden (o sucesivos) al que debería haber llegado: hay parte de la información que el receptor no podrá recuperar, dado que no ha recibido o no se ha percatado de la recepción de un paquete. En consecuencia, debe enviar una CAN, cancelando la comunicación actual de manera incondicional.

o Por último y si todas las comprobaciones anteriores han resultado satisfactorias, se verifica la integridad del campo de datos. Para ello se comparará el campo del control de errores con el valor calculado por el receptor. En caso de darse la coincidencia, se enviará un ACK y en caso contrario un NAK (esto ya en la tercera fase) . Como ya se ha especificado, el valor a comparar podrá tener una extensión de 1 o de 2 bytes. Esto vendrá en función de si se trata del XModem o de su versión para el CRC (que incorpora 2 bytes para el control de errores).

- Fase final. Llegados a este punto deberán hacerse (o estar ya hechas en parte y ser finalizadas) todas las operaciones necesarias del manejo y almacenado de información. Una vez estas operaciones se han realizado se recibirá el EOT del emisor y se responderá al mismo con un ACK3.

3 Veremos con posterioridad, que se pueden implementar fácilmente mejoras en esta fase. Estas mejoras a las que se alude mejorarían en gran medida la robustez del sistema.

2. Protocolo XModem

Envío de ACK

Envío de NAK

Se ignora el byte

¿Paquete anteriormente recibido?

¿Fatal?

Fin

Paquete válido

No

Byte desconocidoNo

No

¿Error de secuencia?

¿Error integridad

de campos?

¿Es parte de un

paquete?

¿CAN?

No

Abandonar

No

Envío de NAK

Envío de ACK

No

Primer carácter recibido

No

¿EOT?

No

¿Se recibe un byte?

¿Exceso de tiempo entre

bytes?

No

Enviar carácter de sincronismo ("C"/NAK).

¿TIMEOUT por no recepción de

paquete?

Inicio

¿Límite de errores por TIMEOUT?

No

Figura 6. Procedimiento a seguir por un receptor XModem.

2. Protocolo XModem

2.7 Errores En este apartado se pormenorizará en los diversos tipos de errores que se pueden dar durante el transcurso de las comunicaciones y se comentarán las acciones a llevar a cabo. 2.7.1 Errores por exceso de tiempo (TIMEOUTS) Los errores por exceso de tiempo forman parte integrante de cualquier protocolo. Su propósito es evitar que el programa entre en un bucle de espera indefinido (se “cuelgue”) por un acontecimiento indefinido. El software implementa contadores con los que puede controlar el número de errores de este tipo que se producen y así seguir unas ciertas normas especificadas en el protocolo. Los errores por exceso de tiempo pueden producirse por una mala sincronización de emisor y receptor, por “pérdida” de un byte durante su envío, por carencias en el canal de comunicación,...etc. Dentro de este protocolo se especifican diversos errores por exceso de tiempo: ERRORES DE TRANSMISIÓN

TIEMPO (SEG.)

ITERACIONES (MÁX) CAUSA CONSECUENCIA

10 10 Ausencia de carácter de sincronismo.

Abandono del estado de espera del carácter de sincronismo si el problema es de carácter permanente.

10 10 Ausencia de handshake. Reenvío del mismo paquete y, de persistir el error, abandono de la transferencia.

ERRORES DE RECEPCIÓN

TIEMPO (SEG.)

ITERACIONES (MÁX) CAUSA CONSECUENCIA

3 3

En XModem CRC, ausencia de entrada de paquete tras envío de carácter de sincronismo “C”.

Reenvío del carácter de sincronismo a cada iteración y llegado el límite de iteraciones abandono del intento de establecer el sincronismo.

10 10

En XModem, ausencia de entrada de paquete tras envío de carácter de sincronismo NAK.

Reenvío del carácter de sincronismo a cada iteración y llegado el límite de iteraciones abandono del intento de establecer el sincronismo.

10 10 Ausencia de toda recepción.

Envío de un NAK y espera de información entrante. Al cumplirse el número de iteraciones, el receptor desistirá en sus intentos de estimular la comunicación.

Tabla 2. Errores por exceso de tiempo

2. Protocolo XModem

Como se puede ver en la tabla, cada vez que se produce un error nos encontramos con una iteración. En un momento dado, un fallo espúreo nos producirá un error y con ello una iteración del mismo. En ese caso, nuestra comunicación no será interrumpida, como es nuestro deseo. 2.7.2 Errores de secuencia Un error de secuencia se produce cuando el valor recibido para el campo 2º y/o el campo 3º del paquete no concuerda con el calculado por el receptor. El cálculo del receptor se realiza mediante una variable software de contado, que se incrementa cuando un paquete es recibido y valorado como íntegro (es decir, de información correcta). Para comprobar si el valor del contador coincide con el valor recibido como número de paquete se realiza la operación XOR entre ambos. Una vez hecho esto se comprueba que el resultado ha sido 0. En el caso de encontrarnos con un uC (como es nuestro caso), esto se realiza mediante la lectura del flag Z (flag cero). Las posibles discrepancias de valores son varias y sus acciones derivadas de estas situaciones también. Si los campos 2º y 3º son complementarios se puede considerar que el paquete no tiene errores de numeración. De darse este caso y no coincidir la numeración con la esperada tendríamos dos posibles errores de secuencia. Nos podríamos encontrar con un paquete superior al esperado, con lo que deberíamos abandonar la comunicación por error fatal mediante el envío de un CAN. Por el contrario, también podríamos tener un paquete con un número inferior al calculado. Esto no supone un error crítico. Se validará el paquete al emisor de manera que envíe cuanto antes el paquete con valor inmediatamente superior. 2.7.3 Errores de integridad del campo de datos La parte esencial de nuestro paquete es, por lógica, el campo de datos. Estos 128 bytes de información deben ser transmitidos y recibidos de manera segura y fiable. De todas maneras, son susceptibles (como cualquier otro byte) de ser alterados debido a factores derivados de su manejo. Los errores pueden producirse por dos tipos de fallos diferentes en su naturaleza: sucesos estáticos, cuyo comportamiento y existencia son conocidos de antemano, y sucesos transitorios, que aparecen de forma aleatoria. Como ejemplo de los primeros se pueden citar, la distorsión de señal y la pérdida por atenuación. Dentro de la segunda clase se encuentran fenómenos como los relámpagos o las variaciones periódicas de las manchas solares. Estos serían únicamente algunos ejemplos típicos, dado que podríamos encontrarnos con diversidad de elementos que nos darían problemas del mismo tipo. Con el fin de resolver en la mayor medida posible estos problemas se utilizan métodos como el bit de paridad, el Checksum o el CRC. Todas estas estrategias se basan en lo que se llama redundancia para minimizar al máximo los errores dentro del campo de datos. Cada uno de estos métodos tiene sus particularidades ventajas e inconvenientes, que entraremos a discutir seguidamente: 2.7.3.1 BIT DE PARIDAD Este método se basa en forzar la regla de que todos los caracteres tengan un número par (o impar) de bits a 1. De esta manera, si se trabaja con paridad impar durante la transmisión, 0100001 se transforma, por ejemplo en 01000011 porque se necesita este 1 para generar un número impar de unos en el byte. Por el contrario, si implementásemos un bit de paridad par obtendríamos el byte 01000010. El emisor se encarga de calcular el bit de paridad y añadirlo al carácter a enviar. Se puede observar fácilmente que el bit de paridad par es producto de la operación XOR de todos los bits del carácter.

2. Protocolo XModem

El receptor calcula el bit a partir del carácter que le llega y lo compara con el bit de paridad recibido. Si no coincidieran sería síntoma de que la información puede4 ser incorrecta. De manera recíproca se asume que, el hecho de que el bit de paridad calculado y el recibido coincidan es buen síntoma pero no da la total seguridad de que la información sea correcta. La razón de todo esto es muy simple: la estrategia del bit de paridad solo es capaz de detectar errores en un número impar de bits. Estos son unos ejemplos de todo ello: TRANSMITIDO RECIBIDO RESULTADOS (PARIDAD PAR)

001000001 001000001 Número par de unos: paridad correcta. 001000001 001000011 Error en 1 bit. Número impar de unos: error detectado 001000001 000000011 Error en 2 bits. Número par de unos: error no detectado. 001000001 001011101 Error en 3 bits. Número impar de unos: error detectado en

Tabla 3. Ejemplo de detección de errores

Por otro lado, y en comparación con las siguientes estrategias, esta implica mucho más tiempo de envío que las otras. En cada envío se debe transmitir 1 bit extra, que sería el valor de paridad. Esto implica una sobretasa muy alta, o lo que es lo mismo, se debe enviar demasiada información para la comprobación de errores que no formará parte del archivo enviado. La comparativa es la siguiente:

NÚMERO DE ENVÍOS BITS POR ENVÍO (CON 8 BITS DE

DATOS)

TOTAL DE TIEMPO

UTILIZADO (A 9600 BPS)

BIT DE PARIDAD

SOH + PAQ. + PAQ. NEGADO + 128 DATOS = 131

START + STOP + PARIDAD + 8 DE DATOS =11

131 * 11 * 1·10-4

=144,1 ms

CHECKSUM

SOH + PAQ. + PAQ. NEGADO + 128 DATOS + CHECKSUM = 132

START + STOP + + 8 DE DATOS =10

132 * 10 * 1·10-4

=132 ms

CRC

SOH + PAQ. + PAQ. NEGADO + 128 DATOS + 2 DE CRC = 133

START + STOP + 8 DE DATOS =10

133 * 10 * 1·10-4

= 133ms

Tabla 4. Comparativa de tiempos de envío de 1 paquete

A priori, una diferencia de 11 ms no parece mucha pero hay casos como en el que nos encontramos, en los que es un tiempo de espera inadmisible. La razón de que sea inadmisible en nuestro caso es que nuestro dispositivo embedido trabaja a velocidades de 1 us, con lo que puede aprovechar ampliamente estos milisegundos.

4 Se dice “puede ser incorrecta” y no “es la incorrecta” porque el envío del bit de paridad se hace de igual manera que el resto de bits del carácter. De aquí se extrae que puede ser afectado por multitud de elementos que lo hagan cambiar de estado. En tal caso, la información podría ser correcta y el bit de paridad erróneo.

2. Protocolo XModem

Por otro lado encontraremos métodos de Redundancia de Bloques, como son los de CRC y Checksum que presentan diversas ventajas. También se podría utilizar un método híbrido, que .implica una seguridad muy alta, dado que se emplean bits de paridad y la redundancia de bloques. Como contrapartida se penaliza gravemente el tiempo, además de otras desventajas. Todo esto viene en función del compromiso que se quiera adoptar. 2.7.3.2 REDUNDANCIA DE BLOQUES: SUMA DE COMPROBACIÓN La suma de comprobación o Checksum, es un sistema de recuperación de errores mediante redundancia de bloques. En este caso, a partir de los caracteres enviados se calcula un BCC (block-check character) que se envía de la misma manera que el resto de bytes. El receptor, que también calculará individualmente su BCC, lo cotejará con el recibido con el fin de comprobar que el bloque de información es correcto. Seguidamente mostraremos un ejemplo:

TRANSMITIDO RECIBIDO

MENSAJE ERROR DE DOS BITS EN UNA FILA

ERROR DE DOS BITS EN DOS FILAS

ERROR DE UN BIT EN DOS COLUMNAS

C 1000011 1000011 1000011 1000010 f 1100110 1100110 1100110 1100111 y 1111001 1100001 1100001 1111001 U 1010101 1010101 1001101 1010101 BCC 101110111 101110111 101110111 101110111 BCC calculado por el receptor

101011111 (detectado)

101010111 (detectado)

101110111 (no detectado)

Tabla 5. Suma de comprobación (checksum)

En este ejemplo hemos resaltado en negrita los bits dañados. Como se puede ver, la suma de comprobación detecta errores de 2 bits en una o dos filas (en el mismo carácter), pero falla en las detecciones de un número par de bits erróneos en una columna (bits de posiciones equivalentes en diversos caracteres). Es importante destacar que esta técnica no permite detectar errores de secuencia: es decir, se produce una suma idéntica si el mensaje se envía en un orden o en otro. Esta es la propiedad conmutativa que tiene cualquier suma aritmética. Para nuestra aplicación, enviaríamos un solo byte de Checksum en el campo correspondiente a comprobación de errores. Esto se producirá en el caso que nuestro dispositivo trabaje en modo Checksum. Como es lógico, la suma de los 128 bytes son daría un resultado con tamaño muy superior al byte. Esta discrepancia se subsana haciendo la suma aritmética sin acarreos. De esta manera, podemos ir sumando los bytes enviados sin tener en cuenta el flag de carry, dado que nuestro sistema trabaja con bytes. 2.7.3.3 COMPROBACIÓN DE REDUNDANCIAS CÍCLICAS

a) Introducción

Por último veremos este método que es mucho más potente que la suma de comprobación y con una sobretasa ligeramente superior. Para empezar veremos los datos técnicos de efectividad del sistema. Estos datos se han calculado para un valor de comprobación de 16 bits.

2. Protocolo XModem

Errores en un solo bit: 100% Errores en dos bits: 100% Errores en un número impar de bits: 100% Errores menores de 16 bits: 100% Errores de 17 bits exactamente: 99,9969% Todos los demás errores: 99,9984% En comparación con el resto de métodos, este es mucho más efectivo. El hardware de los ordenadores manipula normalmente bytes, por lo que el tamaño de la CRC suele asignarse a valores de 16 bits, si bien es verdad que todo depende de la aplicación y lo crítica que sea la comprobación para el funcionamiento del código. La CRC puede comprenderse fácilmente entendiéndola como una estrategia derivada de la suma de comprobación. Esta vez, está basada en la división y no en la adición. Para ejemplificar el funcionamiento, utilizaremos los datos anteriores:

C 11000011 f 01100110 y 11111001 U 01010101

Consideraremos todos estos datos como un número binario de mayor tamaño, en vez de la consideración previa en forma de matriz. Es decir:

11000011011001101111100101010101, que es equivalente al decimal 3 278 305 621.

Dividiremos este número por otro (el divisor) seleccionado entre los demás números vulgares por propiedades que lo hacen ser útil en este campo y que hacen que se puedan conseguir las efectividades buscadas. Suponiendo que el divisor sea el número 525 obtendremos:

624439

5253278305621

= (1)

El resto de este cálculo será 356. El problema surgido ahora, es que el cociente de 23 bits que nos ha resultado es perfectamente válido, pero de un tamaño considerable. Esto dificulta su envío. No podemos asegurar un número de bits máximo para el cociente, pero si que podemos asegurar un número de bits máximo para el resto. Esto se explica por el hecho de que el resto siempre será un número de valor inferior al cociente. De esta manera, un divisor de 17 bits garantiza que el resto no tendrá más de 16 bits. Así, utilizando como divisor 65540 obtendremos:

5001965540

3278305621= (2)

El resto en este caso tiene un valor de 60361 = EBC9 = 1110101111001001

b) Polinomios En la práctica, se describe la CRC en forma de polinomios. En esta terminología, el mensaje queda expresado como un largo polinomio cuyos bits constituyen los coeficientes de los diferentes términos. El exponente de cada término se deduce de la posición que cada

2. Protocolo XModem

uno de los bits tiene en los mensajes. Por ejemplo, el número 23 decimal, equivalente al 17 hexadecimal o el binario 10111 corresponde al polinomio:

1 * X4 + 0 * X3 + 1 * X2 + 1 * X1 + 1 * X0 (3) O el equivalente:

X4 + X2 +X+1 (4) La comodidad de la representación es, evidentemente, una de las razones por las que se ha adoptado la terminología polinómica.

c) Aritmética de polinomios Las divisiones en lógica binaria usual son demasiado complicadas de implementar en un sistema lógico como pueda ser un PC o sistema embedido. Los sistemas CRC se diseñaron para su implementación en dispositivos hardware de comunicaciones y posteriormente en controladores de disco. El hecho de que se seleccionara la aritmética de polinomios o en Módulo 2 responde al hecho de que un cálculo en esta aritmética puede ser implementado de manera simple. Solamente con la ayuda de algunos registros de desplazamiento y puertas lógicas es posible. Por el contrario, en caso de utilizar aritmética binario se necesitaría una lógica adicional para gestionar los acarreos. Por supuesto, esta simplicidad implica también un aumento de la velocidad del proceso. Por ejemplo, en suma binaria tendríamos el siguiente ejemplo:

101010100101010101010101

(5)

Este cálculo resulta laborioso porque obligamos a la máquina a efectuar acarreos en cada una de las columnas. Por el contrario, en adiciones módulo 2 no surgen tales acarreos:

000000000101010101010101

(6)

Esta operación es mucho más simple. El resultado obtenido puede resultar familiar, dado que la suma en aritmética Módulo 2 (o aritmética sin acarreos) es idéntica a una operación XOR. Bajo estas reglas, la suma y la resta son idénticas. Todas estas nuevas reglas, nos llevan a tener que hacer nuevas definiciones. Por ejemplo, la definición de mayor y menor cambia. Esta idea es directa sabiendo que suma y resta dan el mismo resultado:

1010 = 1010 + 0011 1010 = 1010 – 0011

(7) (8)

2. Protocolo XModem

Por tanto, la nueva definición será la siguiente: un número X es mayor o igual que un número Y si la posición del bit más alto a 1 de X es la misma o mayor que la posición del bit más alto a 1 de Y. De la misma manera cambia la definición de número divisible o múltiplo. Diremos que un número A es múltiplo de un número B cuando sea posible obtener el número A a partir de varias operaciones XOR entre 0 y el número B aplicándole a este último diversos desplazamientos. Esto es:

d) Ejemplo básico Para calcular el CRC podemos seguir el siguiente procedimiento. Dispondremos de dos datos:

- El mensaje original - Un polinomio

Por ejemplo, para el polinomio 10011, la posición del bit más alto es 4. Lógicamente, la potencia más alta que encontramos en el polinomio equivalente X4+X+1 es 4. Nos referiremos a este dato como “W”, dado que esta también es la anchura del polinomio. Para que los efectos que cada uno de los bits ejercen sobre el resto se produzcan, debemos aumentar el dividendo un número W de ceros. Para ello añadiremos a la derecha del mensaje concatenado tantos ceros como ancho tenga el polinomio divisor: Mensaje original: 1101011011 Mensaje aumentado: 11010110110000 Polinomio: 10011 Llegados a este punto solo tendremos que efectuar la división en aritmética polinómica entre el mensaje aumentado y el polinomio. Nuestro resto será el valor CRC.

A = 0111010110 B = 11

0000000000 0000000110 0000110000 0001100000 0110000000 0111010110

(9) ⊕

2. Protocolo XModem

10011 11010110110000 10011 10011 10011 00001 00000 00010 00000 00101 00000 01011 00000 10110 10011 01010 00000 10100 10011 01110 00000 1110

000001100001010

Por tanto, el resultado o cociente será 000 0011 0000 1010 y el resto 1110 . El valor de la CRC es el mismo que el del resto: 1110. Una vez recibido el mensaje, el receptor puede realizar de dos maneras la comprobación:

1. Separar el mensaje y el valor de comprobación recibido. Calcular el valor de CRC del mensaje (después de añadirle W ceros) y comparar los dos sabiendo que han de ser iguales para que se considere que no hay información dañada.

2. Calcular del CRC considerando el valor de comprobación como parte integrante del mensaje. El resultado de este cálculo ha de dar 0 para que se considere la información como buena.

En el segundo caso, cabe la remota posibilidad de que se vea dañado el valor de la comprobación y algunos de los valores del mensaje, con lo que podríamos tener un resultado favorable con información incorrecta. Por esto consideraremos mínimamente más seguro el primer procedimiento. En este caso, comprobaremos separadamente todos los valores. Resumiendo, los pasos a seguir serán:

1. Definir la anchura W y a partir de esta buscar el polinomio idóneo. 2. Añadir “W” ceros al número binario conseguido al concatenar todos los bytes

componentes del mensaje. 3. Dividir el dato (mensaje aumentado) entre el polinomio mediante las reglas de

aritmética polinómica. El resto será el valor CRC. Definiremos, por tanto, CRC como el resto obtenido de una división en módulo 2 de un mensaje al cual se han añadido tantos bits 0 como número de bits contiene el propio registro de resto.

e) Elección de polinomio divisor

2. Protocolo XModem

Si exceptuamos el hecho de que todos los polinomios divisores deben comenzar y finalizar con un término 1, cualquier discusión alternativa escapa a los límites y objetivos de este proyecto. Un estudio cuidadoso de este aspecto precisaría de amplios conocimientos matemáticos. Los polinomios más utilizados son los siguientes: TAMAÑO 16 POLINOMIO 1021 (1 0001 0000 0010 0001) VALOR INICIAL FFFF

Tabla 6. CRC-16/CITT

TAMAÑO 16 POLINOMIO 8408 (1 1000 0100 0000 1000) VALOR INICIAL 0000

Tabla 7. XModem TAMAÑO 16 POLINOMIO 8005 (1 1000 0000 0000 0101) VALOR INICIAL 0000

Tabla 8. ARC TAMAÑO 32 POLINOMIO 04C11DB7 VALOR INICIAL FFFFFFFF

Tabla 9. CRC-32

En nuestro caso utilizaremos una variante del CRC-16/CITT, dado que es el más adiente para nuestra demostración. El software terminal que maneja las comunicaciones del ordenador es compatible con este tipo de CRC. Como es lógico, si cambiásemos el valor inicial para utilizar el CRC-16/CITT original el valor final fruto de todos los cálculos sería diferente. En cualquier caso, el manejo del valor inicial hace que el código sea más o menos susceptible a unos determinados tipos de errores. TAMAÑO 16 POLINOMIO 1021 (1 0001 0000 0010 0001) VALOR INICIAL 0000

Tabla 10. Polinomio utilizado

f) Implementación del algoritmo Como es lógico existen multitud de formas de implementar el código. De todas maneras destacaremos las 2 formas más generales. En este punto se acaban los conocimientos teóricos para dar paso a la información relativa a como implementar en la práctica un algoritmo que calcule la CRC de un número. Las opciones son las siguientes:

2. Protocolo XModem

1. Implementación directa:

Para implementar el CRC de manera directa no utilizaremos ningún truco que nos permita ahorrar tiempo de proceso o aumentar la velocidad cálculo. Debemos implementar la división tal y como la hemos especificado. Hay dos motivos por los cuales no debemos simplificar este trabajo utilizando el comando “dividir” que aparece en algunos lenguajes. El primero es porque nuestra división no sigue lógica aritmética binaria usual, sino la módulo 2. La otra razón es que nuestro mensaje (dividendo) ocupa 128 · 8 bytes y los registros que utilizamos normalmente no tienen (en el mejor de los casos) una amplitud mayor a 32 bits, con lo que el manejo de este número sería imposible. Para la implementación se utilizará un registro de desplazamiento. Se considerará el conjunto de bytes del mensaje como una cadena de 128 · 8 bits que empieza con el primer byte recibido y acaba con el último. La cadena iría circulando a través del registro de desplazamiento. Al mismo tiempo se irán calculando las divisiones pertinentes hasta completar el cálculo (incluidos los W ceros añadidos). Un ejemplo de pseudocódigo es el siguiente: - Aumento del registro con W bits de valor 0 al final del mensaje - Mientras (haya bits del mensaje ampliado por procesar) - Desplaza hacia la izquierda un bit el registro leyendo el nuevo bit del

mensaje aumentado e introduciéndolo en la posición 0 del registro. - Si (un bit de valor 1 es extraído de la parte alta del registro) - Registro = Registro XOR Polinomio.

- En este punto el registro contiene el resto

2. Implementación con tabla: El código anterior es la forma más simple de implementar la CRC, pero es ineficiente. El bucle se ejecutaría una vez por cada bit del mensaje y eso requiere mucho tiempo de ejecución. Para hacer el proceso más rápido deberemos utilizar un algoritmo que permita trabajar con unidades más grandes. La mejor opción la constituyen los bytes, por encima de los 4 bits (nibbles) y los 8 bits (words) como es lógico, porque a más longitud más velocidad. Si desglosásemos el programa anterior nos daríamos cuenta de que se basa en una serie de desplazamientos hacia la izquierda y una sería de operaciones XOR. Fácilmente podríamos deducir las siguientes premisas:

o El byte alto del registro no importa. Una vez aplicados 8 desplazamientos, desaparecerá. Por tanto, no importa el desplazamiento del byte del polinomio divisor ni el número de operaciones XOR hechas.

2. Protocolo XModem

o El resto de bits serán desplazados hacia la izquierda y el byte siguiente ocupará la parte alta del registro.

o Mientras todo esto se lleva a cabo, el registro se verá sujeto a una serie de operaciones XOR.

También podemos considerar el efecto que genera efectuar varias operaciones XOR de un mismo registro al que se le aplican diferentes desplazamientos. Este efecto es el mismo que se obtiene aplicando una única operación XOR con un valor equivalente Una posible solución de pseudocódigo sería la siguiente: - Mientras (el mensaje aumentado no se haya acabado) - Examinar el byte más alto del registro. - Calcular el byte de control basándose en el byte más alto. - Sumar todos los polinomios (con los diferentes desplazamientos posibles) con el registro de acuerdo con el byte de control. - Desplazar el registro un byte hacia la izquierda, introduciendo en la parte baja del mismo otro byte más procedente de la concatenación del mensaje. - XOR de los polinomios sumados con el registro. Pero la verdadera ventaja de esta forma de implementación reside en el hecho de que se pueden almacenar las sumas de polinomios en una tabla. Por tanto, un programa realmente eficiente seguiría los siguientes pasos:

1. Desplazamiento del registro hacia la izquierda 8 posiciones (1 byte), leyendo como byte entrante al registro el siguiente en posición dentro del mensaje.

2. Usar este byte alto como índice para una tabla de 256 posiciones con valores precalculados.

3. XOR del valor de la tabla con el registro. 4. Se repetirán estos pasos desde el 1 si la cadena de caracteres no se ha acabado aún.

2.7.4 Falsa finalización de la comunicación La comunicación puede ser finalizada de manera errónea por dos caracteres diferentes: el CAN y el EOT. Cuando un receptor entiende que le ha llegado un EOT (que no ha sido transmitido por el emisor, sino que es fruto de un error aleatorio de las comunicaciones) en el lugar de un SOH, asume que ha recibido toda la comunicación completamente. Esto, como es lógico puede generar un error irrecuperable. Una posible mejora para este aspecto sería la de facultar al algoritmo para que cada vez que recibiera un EOT respondiera con un NAK. De esta manera, si el EOT es un dato correctamente enviado por el emisor, este reenviará el EOT y obtendremos una confirmación de que la intención del emisor es la de finalizar la comunicación. La recepción aleatoria de dos EOT’s de manera continuada es altamente improbable. En caso de que el emisor no tuviera la intención de enviar el EOT en un principio, se daría cuenta mediante el NAK de que su transmisión no se recibe correctamente.

2. Protocolo XModem

Este tipo de algoritmo se podría considerar una mejora del protocolo, dado que en la práctica, el protocolo XModem original no contempla esta medida y no da solución al problema. Por otro lado, el CAN no necesita un carácter de handshake por parte del emisor para que se produzcan sus efectos. En este caso, el receptor enviaría en CAN si se encontrase en la necesidad y automáticamente la comunicación se interrumpiría incondicionalmente. De la misma manera, errores aleatorios pueden ocasionar problemas en comunicaciones que se interrumpirían antes de tiempo y sin causa justificada. La posible solución a esto sería imponer la recepción de dos caracteres CAN para que la comunicación se diera por interrumpida. La recepción sería continua de tal manera que tras recibir el segundo CAN se validase la interrupción.

2.8 Observaciones

- En algunas clases de software para PC que soportan XModem, los envíos y recepciones de información deben hacerse carácter a carácter. Lo que quiere decir esto es que en cada envío completo de 8 bits, con sus bits correspondientes de flanqueo, el bit más alto (bit 7) tiene siempre valor 0. En caso de hacer un envío concatenado de todos los caracteres empleando los 8 bits útiles al programa terminal, el archivo que puede entender dicho software no es el mismo que se ha intentado enviar. Esto, como es lógico alentece en gran medida la transmisión. Este es el caso que nos hemos encontrado al utilizar el programa “HyperTerminal” (de Hilgraeve Monroe) para implementar una pequeña demostración del protocolo. En su versión para Windows, nos dimos cuenta de que debíamos trabajar los envíos desde la plataforma embedida carácter a carácter. En cualquier caso, somos conscientes de que es posible concatenar la información de envío o manejarla de 8 bits en 8 bits.

- Una de las particularidades del protocolo XModem es el hecho de que llena con

caracteres “0” el último paquete a enviar en caso de que no haya información justa y suficiente para el llenado del mismo. Esto, como es lógico, provoca que el archivo recibido sea diferente al que posee el transmisor y de tamaño superior. No hay manera de diferenciar entre un carácter “0” de relleno y uno que forma parte del archivo original. Podemos proponer una solución para este problema: en vez de complementar los paquetes con caracteres “0” podríamos hacerlo con el carácter número 26 (decimal) . Este es un carácter no imprimible del código ASCII llamado “sustituto”. El hecho de que sea no imprimible y además no tenga nada que ver con el retorno de carro ni el salto de línea (entre otros), nos permite diferenciarlo del contenido del archivo. No formará parte integrante del mismo porque no expresa ninguna propiedad del texto en cuanto a espaciado o posicionamiento y no es parte integrante del mismo, ya que no es ningún carácter del alfabeto ni ningún número.

- El protocolo original establece que los paquetes son enviados “a ciegas”, es decir,

sin reconocimientos entre caracteres y que tras ser transmitido el paquete el receptor envía el handshake validándolo o dándolo por malo. Esta forma de procesar la información es muy válida cuando el error se encuentra en el campo de datos, dado que el byte/s de comprobación de errores será recibido en último lugar y por tanto, no será posible averiguar antes si el paquete es válido o no. Pero

2. Protocolo XModem

- existen otros muchos casos en los que es sabido con antelación que el paquete no se acepta, como pueden ser los fallos de secuencia o de error en el campo de número de paquete. En estos casos se debería esperar a recibir todo el paquete y luego a que el emisor recibiera el handshake enviado para volver a un punto en el cual se esté realizando trabajo que no sea en balde. El receptor podría, por otro lado, enviar el carácter de handshake tan pronto como supiese cual debe enviar. En un caso de error en el campo de número de paquete, esto se produciría nada más el tercer campo. Esta mejora se ha implementado en el código desarrollado.

- El protocolo XModem está pensado para un sistema semi-duplex. Por esta razón

algunas de las aplicaciones (si no todas) que lo soporten será bajo este tipo de comunicaciones. En nuestro caso hemos implementado un sistema full-duplex, con lo que puede presentar grandes ventajas en aplicaciones en las que (por ejemplo) la velocidad sea una variable crítica.

2.9 Ejemplo del flujo de datos Seguidamente mostraremos un ejemplo de flujo de datos basado en el protocolo XModem original.

ENVÍOS EMISOR

MEDIO DE TRANSMISIÓN

ENVÍOS RECEPTOR

(Tras 10 segundos sin ninguna recepción...)

NAK

SOH 01 FE DATA Check

ACK

SOH 02 FD DATA Check

(se detecta un error en

campo de datos mediante checksum)

NAK

SOH 02 FD DATA Check

ACK

SOH 03 FC DATA Check

2. Protocolo XModem

(el handshake se corrompe)

ACK

(TIMEOUT de 10 segundos)

SOH 03 FC DATA Check

ACK

EOT

ACK

Figura 7. Ejemplo de flujo de datos

3. El Módem

3. El Módem

3.1 Introducción La información que se genera en un sistema digital, como pueda ser un PC, es un conjunto de dos valores discretos: el 1 y el 0. Debido a las limitaciones físicas de las líneas de transmisión no es posible enviar información de este tipo a través de un circuito telefónico. Para poder enviar dicha información a través de las líneas telefónicas (y en general cualquier línea de transmisión), es necesario un proceso de transformación de la información discreta. Durante la transformación, la información se adecua para ser transportada por el canal de comunicación. Este proceso se conoce como modulación-demodulación y se realiza en el módem. Las señales (bits) son generadas por un dispositivo de procesamiento de datos digitales para ser transportadas por un camino originalmente analógico. Estas técnicas permiten transmitir señales sin que se pierda su integridad. Vista la necesidad de este dispositivo, estudiaremos unas breves nociones para su manejo. De esta manera, podremos trabajar en un entorno más real para nuestro diseño. De la misma manera, implementaremos parte de código de control de este periférico. Nos valdremos también de esos aparatos para realizar una pequeña demostración del proyecto.

3.2 El módem y su funcionamiento Es un dispositivo que permite conectar dos ordenadores (o dos sistemas terminales similares) remotos utilizando la línea telefónica de forma que puedan intercambiar información entre si. Convierte las señales digitales provenientes del sistema terminal en señales analógicas que pueden transmitirse a través de la línea. El método en si de conversión de señales digitales en analógicas recibe el nombre de modulación. Existen diversos tipos de modulación como son la modulación de amplitud, fase o frecuencia; pero en definitiva todas tienen la finalidad de evitar al máximo que la información se degrade al pasar a través de la línea. El sistema de intercambio de información entre el módem y su sistema terminal puede realizarse de muchas maneras. En el caso que nos atañe, se realiza mediante comunicaciones serie. Estas comunicaciones se rigen por el estándar RS-232, que viene explicado de manera extendida en el apartado de especificaciones hardware de esta misma memoria. El módem es uno de los métodos más extendidos para la interconexión de ordenadores por su sencillez y bajo coste. Además, la gran cobertura de la red telefónica convencional posibilita la casi inmediata conexión de dos ordenadores que puedan estar separados millones de kilómetros. Los pasos que sigue el módem para comunicarse con otros módems es el siguiente:

1. El software de comunicaciones en el sistema terminal aserta la señal DTR. Esta señal indica al módem que el sistema terminal está preparado para enviar información. El módem aserta la señal DSR que indica al dispositivo terminal que el módem está preparado para recibir instrucciones o datos. La presencia de estas dos señales marca el inicio de la comunicación.

3. El Módem

2. El software de comunicaciones empieza a enviar los comandos al módem. El software y el módem comunican usando el conjunto de comandos AT, que fue desarrollado de forma original para los módems HAYES. Después de recibir cada comando, el módem devolverá al sistema terminal información referente a dicho comando (esto será por defecto). Esta opción, como tantas otras, es configurable a través de los mismo comandos.

3. Cuando el sistema terminal está listo para la comunicación con el otro extremo de la línea envía un comando que indica al módem que debe realizar la conexión. En este comando, el terminal indicará al módem con que dispositivo debe realizar la conexión (mediante un número) y de que manera debe realizarla (tonos, pulsos, etc...)

4. Si todo va bien, el módem receptor contestará la llamada y la conexión se producirá. Cuando esto ocurra, nuestro módem enviará un tono para identificarse como módem y no como llamada de voz normal. El receptor enviará un tono de respuesta en un tono más agudo. Es posible escuchar todos estos sonidos a través del speaker del módem.

5. En un proceso denominado establecimiento de comunicaciones, los módems negocian con el fin de establecer los protocolos que usarán para comunicarse.

6. Asertando la señal CD, el módem indicará al sistema terminal que está recibiendo una señal portadora. Esto viene a ser un tono constante que puede modularse para transmitir datos.

7. Cuando el programa terminal desee enviar datos asertará la señal RTS. Esta señal informa al módem de estas intenciones. De la misma manera, el módem asertará la señal CTS cuando esté disponible, es decir, cuando no esté ocupado recibiendo o enviando.

8. El módem modulará los datos digitales que la computadora desee enviar y los transmitirá a través de la línea telefónica. El módem remoto recibirá la señal analógica, la demodulará y la enviará a su sistema terminal adyacente. Ambos módems pueden enviar información al mismo tiempo a través de la línea.

9. El software de comunicaciones del programa terminal enviará una señal al módem cuando deba para romper la conexión (siempre y cuando no se haya roto antes por motivos no esperados). El módem desconectará la llamada y luego desasertará la señal CD para indicar todo ello al sistema terminal.

3.3 Velocidades de transmisión A veces, las velocidades de transmisión de los módems se especifican en baudios. Este tipo de unidades se refieren a la cantidad de veces que cambia la frecuencia, voltaje o fase de la señal del módem en un tiempo de un segundo. Anteriormente, el número de cambios que se producían en la línea eran equivalentes al número de bits que se enviaban. En la actualidad sabemos que esto no es así. Existen sistemas mediante los cuales se pueden comprimir y empaquetar los datos con el fin de que el módem pueda enviar más información por cada cambio de la línea. Por esta razón, estos dos parámetros no coinciden. Definiremos seguidamente las dos unidades: Baudios: Número de veces que se produce un cambio en el voltaje, frecuencia, fase...etc de la señal que pasa a través de la línea de transmisión por segundo. Los módems se valen de una serie de tonos para enviar datos a través de la línea telefónica. Los módems modernos pueden enviar hasta 4 o más bits por baudio producido.

3. El Módem

Bits por segundo (BPS): Es el número efectivo de bits/seg que se transmiten en una línea. Como hemos visto, un módem de 600 baudios puede transmitir a 1200, 2400 o incluso a 9600 BPS.

3.4 Conexión RS-232 entre terminal y módem Los módems se conectan con el sistema terminal a través de un puerto de comunicaciones del segundo, como por ejemplo el puerto serie o el USB. Como ya se ha dicho, en nuestro caso se comunicarán a través del puerto serie, y este sigue la norma RS-232. Los dos puertos se unen utilizando un cable que sigue la misma norma RS-232. Hay varios circuitos independientes en el interfaz . Dos de ellos son el utilizado para transmitir datos, o TD, y el propio para recibir datos o RD. Estos dos forman una conexión de datos entre el sistema terminal y el módem. Por otro lado, hay varios circuitos adicionales que permiten realizar diferentes funciones. Todos estos circuitos serán comentados en el apartado de especificaciones hardware con más profundidad.

3.5 Control de flujo El control de flujo es un mecanismo por el cual el módem y el sistema terminal gestionan los intercambios de información. Estos mecanismos permiten detener el flujo de datos cuando uno de los elementos no puede procesar más información y reanudarlo en cuanto vuelva a estar disponible. Los métodos más comunes de control de flujo son:

• Control de flujo hardware: RTS y CTS permiten al terminal y al módem detener el flujo de datos que se establece entre ellos de forma temporal. Este sistema es el más seguro y el que soporta operaciones a velocidades más altas.

• Control de flujo software: Aquí se utilizan para el control dos caracteres especiales: XON y XOFF ( en vez de las líneas hardware RTS y CTS) que controlan el flujo. Cuando el terminal quiere que el módem pare un envío de datos envía XOFF y cuando desea reanudarlo envía XON. De la misma manera, el módem controla los datos que le llegan del sistema terminal. Dado que todo envío requiere un tiempo, que depende de la velocidad de proceso y de la de transmisión, este sistema no es adecuado para altas velocidades.

3.6 Manejo del módem 3.6.1 Modos de funcionamiento Un módem tiene dos estados o modos de funcionamiento: el de comandos y el de línea. Cuando el módem está en estado de comandos responde a todos los comandos que recibe del sistema terminal. En este modo es posible realizar la configuración del módem y operaciones de marcado y conexión. Antes de poder enviar un comando al módem, este debe estar en estado de comandos. Cuando el módem se conecta con otro pasa al modo de línea. En este modo cualquier información que reciba del terminal será enviada al módem distante. En este modo el módem no procesa la información y simplemente la transmite a través de la línea de comunicaciones. Para salir del modo en línea y pasar de nuevo al modo de comandos es

3. El Módem

necesario introducir el carácter de escape 3 veces seguidas, tras esperar un tiempo de guarda manteniendo inactividad. Por defecto el carácter de escape es el “+”. 3.6.2 Comandos de control del módem El lenguaje de comandos para módem más extendido es el HAYES, que fue inicialmente incorporado a los módems de este fabricante. Existen dos tipos principales de comandos: - Comandos que ejecutan acciones inmediatas (ATD marcación, ATA contestación o

ATH Desconexión) - Comandos que cambian algún parámetro del módem (por ejemplo ATS=90)

Originalmente, comandos HAYES empezaban con la secuencia AT para seguir con cualquier otra letra del alfabeto. La excepción es el comando A/ que provoca la repetición del último comando ejecutado. El código AT consigue la atención del módem y determina la velocidad y formato de datos. A medida que los módems fueron ganando en complicación, surgió la necesidad de incluir más comandos. En consecuencia se incorporaron los comandos extendidos, que son de la forma AT&X (por ejemplo), donde “&” sirve para marcar la X como un comando extendido. En resumidas cuentas, un comando HAYES es una cadena ASCII que se envía al módem para que este realice alguna acción o configure alguno de sus parámetros. Este comienza con los caracteres “AT”, seguido de nombres de comando y sus respectivos parámetros. Todo ello irá seguido en último lugar por un retorno de carro. El comando no debe sobrepasar los 256 caracteres: AT <comando1> <parámetro 1> <comando 2> <parámetro 2> ···· <comando n> <parámetro n> <CR> Algunos módems actuales incluyen muchas funciones adicionales como el marcado automático, métodos de compresión y corrección de datos, distintos protocolos de intercambio de datos con el DTE,...etc. Por ello, los módem son configurables a través de los comandos software aunque salen de fábrica con una configuración por defecto. A continuación se muestran algunos comandos típicos que suelen estar incluidos en la mayoría de los módems.

• ATA (Answer). Indica al módem que debe descolgar y responder a una llamada entrante. Después de esto se producirán negociaciones con el módem remoto. Cuando el módem devuelve un código de resultado RING (o aserta por hardware la señal RING) se le puede mandar la línea de comando ATA<CR>. El módem enviará una señal portadora de respuesta al módem remoto. Tras esto, espera que el módem remoto responda con la inyección en la línea de otra señal portadora. Cuando el módem local reciba esta señal iniciará negociaciones con tal de establecer la conexión. Los módems devolverán a sus respectivos sistemas terminales el código de resultado del tipo: CONNECT, en donde seguido de la palabra CONNECT se especificarían datos de la comunicación ya establecida. En caso de no ser recibida ninguna portadora en el tiempo especificado en el registro S7, el módem colgaría y devolvería el código de resultado NO CARRIER; para después entrar en el modo de comandos.

3. El Módem

• ATD (Dial). Este comando provoca que el módem desarrolle funciones de automarcado. El comando puede ser enviado al módem de manera solitaria o acompañado de un número de teléfono. En caso de no llevar número de teléfono, el módem descolgará e intentará conectar directamente. Sea cual sea la forma de envío, se finalizará la línea de código mediante un retorno de carro. El comando no es válido cuando el módem está on-line o en cualquiera de los modos de comunicaciones controlados por los comandos extendidos &Q2 o &Q3. Los paréntesis y guiones serán ignorados en una cadena de marcado por el sistema de automarcado, pero serán contados como caracteres en el buffer de comandos, que tiene una extensión de 255 posiciones de carácter. Existen diferentes modificadores de este comando:

0-9 A B C D # * -- Dígitos / Caracteres para el marcado. Son utilizados para especificar que número de módem hay que marcar. Los caracteres A B C D # * indican diversos tipos de tonos, que pueden ser utilizados solo cuando se selecciona una marcación por tono.

P-- Método de marcado por pulsos. Este modificador se puede emplear conjuntamente con el comando ATD, es decir , ATDP. También se puede emplear de manera individual para configurar el modo de marcado de futuras llamadas. Una vez un método es seleccionado, este es usado hasta que otro es elegido o el módem se resetea. T -- Método de marcado por tonos. Presenta las mismas características que el anterior, pero esta vez, es para marcado por tonos. , -- Retardo en el proceso del siguiente carácter. Tras procesar este comando, el módem entiende que ha de esperar un tiempo preseleccionado antes de procesar el siguiente carácter. Este tiempo preseleccionado se especifica en el registro S8. ; -- Retorno al modo de comandos después del marcado. Usado solo en el final de la línea de comando y seguido de un retorno de carro, obliga al módem a volver al modo de comandos inmediatamente después del marcado, sin romper la conexión.

• ATZ. Realiza un reset por software. El módem aborta la ejecución de cualquier

comando que pueda estar situado en la misma línea. Existen, dos variables de este comando: ATZ1 y ATZ0. Cada una restablece unos parámetros de fábrica diferentes. El comando escrito tal cual (ATZ) es equivalente al comando ATZ0. Esto es válido para cualquier otro comando. Por lo que el 0 no se suele utilizar nunca.

• ATE. Controla el eco que genera el módem hacia el DTE de los caracteres recibidos en el modo de comandos. El comando ATE0 (o ATE) deshabilita el eco y el comando ATE1 lo habilita.

• ATH. Este comando proporciona control sobre el relé de línea. Este es el comando de colgado y descolgado. Enviando el comando ATH al módem, este iniciará el proceso de colgado. Esto solo puede producirse en estado on-line. Enviando el comando ATH1 el módem procesará el descolgado sin ejecutar procesos de negociación como los del comando ATA.

3. El Módem

• ATQ. Este comando gestiona el uso de códigos de resultado. Se pueden deshabilitar los códigos que se envían por defecto al DTE correspondiente mediante el comando ATQ1. Para habilitarlos, se utiliza el comando ATQ / ATQ0. Un tercer comando ATQ3 deshabilita el código de resultado RING. Además, este último comando deshabilita en modo respuesta (ATA) los códigos de resultado CONNECT y NO CARRIER.

• ATV. Determina si los códigos de resultados (incluyendo los mensajes del proceso de llamada y de negociación) son emitidos como números o como palabras. ATV configura modo numérico y ATV1 modo verbal.

• ATX. Este comando habilita opciones de detección de tono utilizadas en el proceso de marcado. Al cambiar estas opciones (habilitando o deshabilitando) se altera el envío de códigos de resultado. Por esta razón, este comando puede ser utilizado para alterar el rango de respuestas del módem. De todas maneras, su función principal es la de controlar las capacidades de respuesta de llamadas que posee el módem. Existen 5 posibles variables de este comando:

o ATX0. La detección del estado de ocupado y del tono de marcado se deshabilitan. Solo los códigos de resultados que van del 0 al 4 están activos. Solo el código de resultado CONNECT está permitido, pero sin que indique la velocidad de la línea.

o ATX1. La detección del estado de ocupado y del tono de marcado se deshabilitan. Solo los códigos de resultados que van del 0 al 5 están activos y también la velocidad de la línea conjuntamente con el código CONNECT.

o ATX2. La detección del estado de ocupado se deshabilita. La detección del tono de marcado se habilita. Los códigos de resultado del 1 al 6 están activos y la velocidad de la línea se especifica junto al código CONNECT.

o ATX3. La detección del estado de ocupado se habilita. La detección del tono de marcado se deshabilita. Los códigos de resultado del 1 al 7 están activos y la velocidad de la línea se especifica junto al código CONNECT.

o ATX4. La detección del estado de ocupado y del tono de marcado se habilitan. Solo los códigos de resultados que van del 0 al 7 están activos y la velocidad de la línea conjuntamente con el código CONNECT también.

Existen multitud de comandos, además de los ya especificados y que no llegaremos a aplicar. De todas formas, distinguiremos algunos a título informativo:

• ATI. Revisa la ROM del módem mediante un checksum. • ATL. Programa el volumen del altavoz. • ATM. Programa la conexión/desconexión del altavoz. • ATO. Vuelve al estado on-line desde el estado de comandos. • ATS. Visualiza/cambia contenidos de los registros S. • ATW. Envía códigos del progreso de la negociación. • AT&C. Programa la detección de portadora. • AT&D. Programa el control de la DTR. • AT&K. Programa el control de flujo. • AT&W. Almacena el perfil de configuración del usuario. • AT&Y. Especifica que perfil de configuración del usuario de los almacenados se

va a utilizar.

3. El Módem

3.6.3 Códigos de resultados y respuestas de monitorizado de progreso de la llamada. Definiremos los mensajes más importantes de estos tipos. Para ello indicaremos su forma verbal (o por palabra) y número, además de una breve descripción de su significado. : 0 – OK Este código de resultado indica que un comando o una cadena de comando fue ejecutada. Es importante remarcar que si más de un comando es incluido en una línea de comando y se recibe un código de error, esto querrá decir que uno o más de los comandos no fueron procesados. Si uno o más comandos fueron ejecutados correctamente pero hubo alguno que no, no se recibirá un código de OK sino únicamente uno de error. 1 – CONNECT Este código de resultado indica que una conexión ha sido realizada entre un DTE y un módem. SI X4 fue previamente seleccionado, este código indicará que la conexión se ha realizado a una velocidad entre 0 y 300 bps. Si X0 fué seleccionado, la conexión pudo ser realizada a velocidades 0-300, 1200, 1200/75, 75/1200, 2400, 4800, 9600, 19200 o 38400 bps. Si el módem no está operando en modo de control de errores, esta es la misma velocidad de la línea. 2 – RING Este código indica que el módem ha detectado una llamada entrante. No se pueden distinguir las llamadas de voz, de las provenientes de un módem, un fax u otro tipo de dispositivo. 3 – NO CARRIER Este código de resultado indica que no se detectó ninguna señal portadora, o que la señal se perdió. Esta es la respuesta que el módem da cuando no se realiza la conexión. El hecho de que se pierda la portadora puede ser debida, por ejemplo, a que dificultades en la línea rompan la conexión. 4 – ERROR Este código de resultados puede indicar que se ha enviado al módem un comando incorrecto o que hay un error en la línea de comando. Este comando también puede ser devuelto a modo de respuesta desde el módem hacia el DTE en caso de que se detecte un error en el checksum de la ROM interna. 5 - CONNECT 1200 Indica que la conexión ha sido establecida a 1200 o 1200/75, 75/1200 bps entre el módem y el DTE. Si el módem no está operando en modo de control de errores, esta será la misma velocidad que la de la línea. Es deshabilitado por el comando X0. 7 - BUSY Este código de resultado indica que el módem ha detectado una señal indicadora de ocupado al intentar establecer la conexión con el número requerido. La detección de la señal de ocupado y este código de resultado se habilita mediante el comando X3 y X4. 10 – CONNECT 2400

3. El Módem

Indica que la conexión ha sido establecida a 2400 bps entre el DTE y el módem. Si el módem no está operando en modo de control de errores, esta será la misma velocidad que la de la línea. Es deshabilitado por el comando X0. 11 – CONNECT 4800 12 – CONNECT 9600 13 – CONNECT 19200 Este código de resultado indica que la conexión se ha establecido a 4800, 9600 o 19200 bps entre el módem y el DTE. Estos códigos de resultado son deshabilitados mediante el comando X0. 22 – CONNECT 1200/75 Este código de resultado indica que una conexión ha sido establecida a 1200 bps cuando se transmite y 75 bps cuando se reciben datos entre el módem y el DTE. 23 – CONNECT 75/1200 Este código de resultado indica que una conexión ha sido establecida a 75 bps cuando se transmite y 1200 bps cuando se reciben datos entre el módem y el DTE. 28 – CONNECT 38400 Este código de resultado indica una conexión establecida a 38400 bps entre el módem y el DTE. Este código puede ser deshabilitado mediante X0. 3.6.4 Programación de los registros S Los registros internos del módem le indican como debe operar todo el tiempo. Los registros S son usados para configurar parámetros que describen el funcionamiento. Es posible leer el contenido de los registros S empleando el comando ATSn?, donde el lugar de la n debería ser ocupado por un número de registro. Por ejemplo, si deseásemos leer el contenido del registro S15 enviaríamos al módem el comando ATS15?. Durante la fabricación se le asignan a estos registros valores para un funcionamiento confiable del módem en condiciones normales. Sin embargo es posible cambiar estos valores a través del comando ATSn=, para casos especiales como por ejemplo; líneas telefónicas que tardan demasiado en entregar el tono de marcado. A continuación mostraremos los más comunes:

• S0: especifica el número de timbres antes de contestar, en caso de que el módem esté situado en modo autorespuesta. En caso de ser introducido un 0, se deshabilita la autorespuesta.

• S1: Cuando el módem está en modo de comandos y configurado para autorespuesta, este automáticamente cuenta el número de timbres recibidos, incrementando y guardando este dato en S1. El valor vuelve a 0 cuando no aparece ningún timbre en 8 segundos o al establecerse una comunicación.

• S2: Este registro guarda el valor del carácter de escape. El carácter por defecto es el número 43 (+).

• S3: Define el carácter para el retorno de carro, que por defecto es el número 13 (CR).

3. El Módem

• S4: Guarda el carácter de salto de línea. Por defecto, este carácter es el número 10. • S5: Guarda el carácter de retroceso. El valor de fábrica es el número 8. Este

carácter mueve el cursor hacia la izquierda, borrando el carácter previo. • S6: Este registro determina el tiempo que el módem espera tras descolgar para

marcar. Este retardo da tiempo a la central de teléfonos a detectar la condición de descolgado de la línea y emitir el tono de marcado. Este valor puede oscilar entre 4 y 7 segundos. Esta característica permite al usuario incrementar el tiempo de retardo si tiene dificultades obteniendo el tono de marcado en 4 segundos.

• S7: Marca el tiempo en que el módem responderá a una señal portadora tras el marcado. En caso de no detectar una portadora en este tiempo, el módem colgará y devolverá un código de resultado NO CARRIER.

• S8: Duración de una pausa de marcado. Las pausas de marcado se generan en un comando ATD mediante una coma (,).

• S9: Indica el tiempo (en segundos) que ha de permanecer activa la señal portadora para ser reconocida y que se considere una operativa de detección de portadora. El valor de fábrica es de 6 (0,6 segundos), mientras que el rango va de 1 (0,1 segundos) hasta 255 (25,5 segundos).

• S10: Tiempo entre la pérdida de una señal portadora y la desconexión local del módem. Este retardo permite que desaparezca momentáneamente la portadora sin ocasionar el colgado por parte del módem. El valor de este registro se mide en décimas de segundo y su rango va de 1 a 255.

• S11: Determina la duración y el espaciado entre tonos cuando se utiliza la marcación en tonos de frecuencia múltiple. Este valor no afecta a la velocidad del pulso de marcado.

• S12: Este registro sirve para especificar el tiempo de guarda necesario antes del envío de una secuencia de escape. El tiempo de guarda también sirve para indicar la velocidad a la que se deben entrar los caracteres de escape, dado que el intervalo entre caracteres debe ser inferior al tiempo de guarda. Si el tiempo especificado es 0, el tiempo no será un factor.

4. Especificaciones Software

4. Especificaciones Software.

4.1 Objetivos Deseamos diseñar un programa de intercambio de información. Dicho intercambio se hará bajo las directrices de un protocolo XModem híbrido (entre el CRC y el original). El sistema podrá enviar y recibir información al mismo tiempo, por lo que nos encontraremos con una aplicación full-duplex. Este programa se implementará en un lenguaje ensamblador compatible con la familia de controladores 16F87X (en concreto para el 16F876) de Microchip © . Este PIC dispone de una USART. Con estos recursos, el manejo de la información será mucho más fácil. La base de dicho manejo consistirá en el envío a un registro propio de la USART y la lectura de otro registro similar para las recepciones. El código deberá funcionar mediante un sistema de interrupciones. Al utilizar las interrupciones ya podemos estar hablando de un proyecto que pueda formar parte de otro más grande para su posterior aplicación. En definitiva, nuestro diseño está pensado para formar parte de un sistema remoto y autónomo. Dicho sistema se valdrá del código implementado para poder comunicarse.

Figura 8. Esquema básico de funcionamiento

4.2 Principio de funcionamiento El funcionamiento de nuestro código deberá demostrar que el sistema implementado es capaz de interpretar las recepciones y componer envíos basados en el protocolo. Como es lógico, las emisiones que realice deben ser entendidas por un terminal cualquiera de uso estándar. En función de estas premisas, se desarrolla el código para que realice las siguientes comunicaciones:

Figura 9. Funcionamiento práctico del sistema.

SOFTWARE

USART (Hardware)

USUARIO

TERMINAL

XModem

1. ENVÍO DE ARCHIVO DE SALUDO.

2. RECEPCIÓN DE ARCHIVO ALEATORIO DE CARACTERES .

3. REENVÍO DEL MISMO ARCHIVO ANTERIOR.

DISPOSITIVO

REMOTO TERMINAL

(USUARIO)

4. Especificaciones Software

Según la ilustración, el sistema remoto diseñado ha de efectuar dos operaciones de envío y una de recepción. Nuestro dispositivo leerá de memoria los caracteres que componen el archivo de saludo y los enviará con la forma correspondiente (siguiendo el XModem) a través de la USART. La memoria a la que nos referimos es la del programa del uC. Se ha elegido esta memoria de entre las otras dos por cuestiones de espacio, ya que es la única en la que se le puede dar cabida a un tamaño de archivo coherente con el de paquete del propio protocolo. Enviando un archivo aleatorio que se ha recibido con anterioridad queda claro que el sistema entiende cualquier archivo de caracteres, dado que sino no sería capaz de reenviarlo con la misma información. Es preciso un almacenamiento del archivo recibido de manera progresiva porque el software terminal que está manejado por el usuario no es capaz de enviar y responder al mismo tiempo. Como es lógico almacenaremos esta información en la misma memoria FLASH de programa. Es necesario remarcar, que los ciclos de borrado y escritura de la propia memoria son limitados (aproximadamente unos 1000), por lo que no será válido su uso para aplicaciones en las que sea necesario el almacenamiento de manera masiva. En nuestro caso, buscamos demostrar el funcionamiento de nuestro dispositivo, los objetivos del cual no se centran en la forma de almacenamiento sino en la de comunicación.

4.3 Estructura del código. La estructura del programa está basada en dos niveles básicos de ejecución. El nivel principal y el propio de las interrupciones. Dado que la naturaleza del proyecto se basa en la implementación de un sistema de comunicaciones, en el nivel principal se ha dispuesto un bucle. Este será substituido en la práctica por el código principal de cualquier aplicación. Después de realizar un Checksum de todo el código para detectar errores hardware y de las inicializaciones de variables y periféricos, se ejecutará la función de establecimiento de conexión (compuesta para el módem). Más tarde se pasará un estado estacionario. Este estado se implementa mediante el denominado bucle. Esta sería la aplicación principal:

Figura 10. Esquema de la estructura general de la aplicación

- Suma de comprobación del código

palabra a palabra. - Inicialización de puertos. - Inicialización de variables generales. - Inicialización y habilitación de

interrupciones. - Inicialización del Timer 0.

- Establecimiento de conexión mediante el

módem.

- <<BUCLE DE ESPERA INFINITO>>

PRINCIPAL (MAIN) 1º Temporizador. 2º Envío. 3º Recepción.

INTERRUPCIÓN

4. Especificaciones Software

Como se puede observar, las interrupciones serán por 3 motivos: por desbordamiento del timer (TMR0), porque el registro de envío de la USART se ha quedado vacío o porque se ha recibido un carácter en la misma USART. También se podrán dar interrupciones de otro tipo, como por ejemplo, por cambio de estado de una señal RS-232 determinada, pero estas serán muy minoritarias. En principio todas tienen el mismo nivel de prioridad, y no existe el fenómeno llamado anidamiento en este caso. De todas maneras, dada su disposición a lo largo del código, de requerirse el servicio de dos interrupciones al mismo tiempo, se serviría la que se presentase con anterioridad en el código, es decir, por orden de ejecución. Después de este servicio, se volvería a saltar a la única rutina de atención a la interrupción existente. Esta es la encargada de derivar la ejecución del código hacia las RSI’s restantes. Esto supone una prioridad implícita. Todo es de esta manera porqué el vector que contiene un puntero para rutinas de servicio a interrupción es único y por tanto solo puede apuntar a una rutina. Esta es la clave del funcionamiento. El timer se utiliza para establecer un patrón de tiempo necesario para los errores por exceso del mismo. Aparecerá una interrupción de manera periódica y contando estas interrupciones será posible dilucidar (considerando una pequeña tolerancia) si ha transcurrido un tiempo determinado. En cuanto a la interrupción generada por el registro de envío de la USART, esta aparecerá cada vez que sea posible guardar información en dicho registro. De esta manera podremos mantener continuamente alimentado el envío de bytes, sin perder tiempo de manejo de información entre envíos. Las funciones propias de esto último serán desarrolladas por la rutina de servicio PUT_D. La última fuente de interrupción es la referente al registro de recepción de la USART. Cada vez que se reciba un byte de información (ya sea con o sin errores), esta interrupción se asertará. Asimismo se servirá, siguiendo los procedimientos pertinentes mediante la rutina GET_D. Por lo que respecta al código principal, se han estructurado las inicializaciones de manera que el código se presente más intuitivo.

4.4 Rutina de Servicio a la Interrupción: GET_D. Ilustraremos de la manera más pragmática posible el funcionamiento elemental de esta rutina. Como su nombre indica es la encargada de la recepción de información, tanto si nuestro dispositivo trabaja en funciones de emisor de paquetes como si trabaja recibiéndolos. Esta distinción es necesaria, dado que nos encontramos ante un sistema full-duplex y, por lo tanto, nuestra USART podrá recibir tanto caracteres de reconocimiento de un receptor remoto, como paquetes de un emisor remoto. Esta rutina de servicio a la interrupción (única para todas las recepciones) se ejecutará cada vez que el sistema reciba cualquier byte de información. Como se puede ver, el trabajo fundamental de la RSI es el de derivar a subrutinas según corresponda. Por ejemplo, en caso de haber recibido un ACK se ejecutará la rutina correspondiente y en caso de ser parte integrante de un paquete, el byte recibido se seguirá valorando para comprobar el campo al que corresponde. Previamente a la derivación, se comprueba que no haya habido errores propios de la USART en cuanto a transmisión. De ser así se toman las medidas pertinentes. El funcionamiento específico de la rutina se describe en el esquema siguiente. Los nombres utilizados son los correspondientes a cada parte de la rutina en si. Cualquier byte recibido, salvo que genere un error, debe corresponder con una de las opciones especificadas en el esquema. En caso de ser un carácter desconocido nos encontraremos con una posible corrupción del dato durante su manejo o comunicación y

4. Especificaciones Software

esto supone un error. Asimismo, esta recepción se ignorará y se tomarán las medidas preventivas consecuentes.

Figura 11. Estructura general de la RSI.

El orden en el que se evalúan los caracteres no es aleatorio, sino que tiene un sentido de aprovechamiento de tiempo de ejecución. Para empezar, se evalúa la posibilidad de que la información recibida forme parte de un paquete. Esto será así a partir del carácter SOH y sucesivos. Utilizaremos una variable booleana para la evaluación. Se le dará valor 1 a la variable cuando se reciba un carácter de saludo, es decir, un SOH. Esta opción es la primera que se evalúa porque, de evaluar antes el resto de handshakes, existirían algunos casos en los que podríamos encontrarnos con caracteres del campo de datos del paquete que coincidieran con el valor de alguno de estos handshakes. Esto ocasionaría problemas, sobretodo cuando trabajásemos con envíos de 8 bits útiles y no carácter a carácter. Además, desde el punto de vista del aprovechamiento es directo ver que las recepciones ocasionadas por un paquete serán muy superiores a las ocasionadas por handshakes, dado que ya solo el campo de datos tienen una extensión de 128 posiciones o recepciones. Seguidamente evaluamos la recepción de los caracteres NAK y CAN. Estos pueden ser recibidos en cualquier momento, salvo en medio de un paquete, como antes hemos dicho. Seguidamente, evaluamos el carácter ACK. Este puede llegar en cualquier momento excepto cuando nuestro dispositivo espera la llegada del carácter de sincronismo. El carácter “C” podrá llegar una sola vez, como carácter de sincronismo en caso de que estemos manejando un control de errores CRC. La función asociada a esta recepción es la misma que la del NAK. El carácter SOH podrá llegar cuando hayamos enviado nuestro

X X X X X X X X

Byte recibido

? 0 0 0 0 0 0 0 1

SOH

0 0 0 1 0 1 0 1 NAK

GET_D

PAQUETE (DATOS)

0 0 0 1 1 0 0 0 CAN

0 0 0 0 0 1 1 0 ACK

0 0 0 0 0 1 0 0 EOT

0 1 0 0 0 0 1 1 “C”

4. Especificaciones Software

handshake de reconocimiento al dispositivo remoto. La llegada se limitará a una vez por cada paquete a modo de cabecera. La señal EOT llegará justo en el momento de la finalización de la transmisión y una única vez. Por esta razón está evaluada al final.

Figura 12. Funcionamiento práctico de la RSI de recepción. Por lo que respecta al caso particular de la recepción de un paquete, una vez evaluada y aceptada la posibilidad de que la recepción sea de este tipo, aparece la necesidad de poder averiguar la ubicación correcta del byte en un campo determinado. De esta manera, en las subrutinas NEG_NUM y NUM_P se desarrolla todo el control de errores de secuencia. En DTOS se envía los bytes recibidos a un buffer en RAM y se calcula de manera paulatina el byte o bytes de control de errores. Al acabarse el contenido del paquete y según nos encontremos en el modo CRC o Checksum, ejecutaremos una o dos subrutinas (COMP2 puede o no ejecutarse). Esto es debido a que el CRC tiene una extensión de 2 bytes. 4.4.1 Control de errores de secuencia. La subrutina a la cual se derivan todas las recepciones de bytes pertenecientes a un paquete es la ES_PAQ. En esta subrutina se desarrollan procesos referentes a los paquetes como pueden ser el almacenamiento de los datos, el control de errores del campo de datos y el de secuencia. En cuanto a estos últimos, existen dos rutinas concretas que llevan a cabo todas las labores. Estas rutinas son NUM_P Y NEG_NUM. De manera esquemática explicaremos su funcionamiento, ya que presenta cierta complejidad. Pero para comenzar indicaremos cuales son las variables y sus características.

INICIO (R

¿ERRORES DE RECEPCIÓN? CAMPO Nº 2 NÚMERO DE

PAQUETE CAMPO Nº 3 NÚMERO DE

PAQUETE NEGADO CAMPOS Nº 4-131 DATO

CAMPO Nº 132 CHECKSUM / CRC-1

CAMPO Nº 133 CRC-2

¿PARTE DE UN PAQUETE?

¿CAN?

¿NAK?

¿ACK?

¿”C”?

¿SOH?

¿EOT?

¿CARÁCTER DESCONOCIDO?

OPERATIVA CORRESPONDIENTE AL

CARÁCTER RECIBIDO.

4. Especificaciones Software

GPR’S DESCRIPCIÓN

PAQ_REC Valor precalculado del paquete que se debe recibir.

AUXRC

Registro auxiliar que contiene el byte recibido. Que en este caso puede ser el número de paquete o el número de paquete complementado.

PAQUETE Registro que guarda el valor del número de paquete recibido.

PAQ_PRE_ERROR

Bit del registro RX_STATUS cuya utilidad estriba en señalizar si el paquete que nos mandan tiene un número superior al esperado.

PAQ_PRE_ERROR2

Bit del registro RX_STATUS cuya utilidad estriba en señalizar si el paquete que nos mandan tiene un número inferior al esperado.

Tabla 11. Tabla de los registros utilizados y su descripción.

La subrutina NUM_P gestiona la recepción del número de paquete. Para que todo sea satisfactorio, el dato recibido y guardado en PAQUETE debe ser idéntico al calculado por software y almacenado en PAQ_REC. En ese caso, se pasará a ejecutar la rutina NEG_NUM en la próxima recepción y si también el dato recibido es el esperado, se seguirá con el proceso de recepción de paquete. En caso contrario, tendríamos un número de paquete que no se corresponde con nuestras expectativas. Entonces, podríamos contemplar las posibilidades que nos muestra el esquema. Si el número de paquete recibido es superior al precalculado (PAQ_REC), podemos encontrarnos con que el valor recibido no es el correcto o con que sí que lo es pero de un paquete no esperado y superior. Si estamos recibiendo un paquete fuera de sincronismo y de número superior al esperado nos encontramos con un error irrecuperable que se reconoce con un CAN. En caso de que esté dañado el envío del número de paquete, al saltar a la rutina NEG_NUM, nos daremos cuenta de que el valor recibido y calculado complementando PAQUETE (valor de número de paquete recibido inicialmente) no coinciden. El reconocimiento correspondiente sería un NAK, dado que sabemos que recibimos un campo de manera errónea. En caso de que el valor recibido para el paquete sea inferior al esperado, también podemos encontrarnos con un número de paquete corrupto. Las consecuencias de esto serían idénticas a las anteriores y los síntomas también. Por otro lado, también podemos estar recibiendo un paquete que ya tenemos. En tal caso debemos remitir un ACK y esperar al nuevo envío de paquetes. En definitiva, el control de errores de secuencia se distribuye en dos bloques. Como muestra la figura 13, estos son el correspondiente a la función NUM_P (superior) y el correspondiente a la función NEG_NUM (inferior). En el ejemplo (figura 14), los números A, B y C se han cotejado con el byte recibido en la posición del campo 3. Para esto se hace el complementario, dado que el byte que se recibe a en ese campo es el complemento a 1 del número de paquete. El resultado ha sido satisfactorio por lo que se asume que estos datos son realmente los que ha enviado el emisor y no fruto de errores de transmisión. En caso de no conseguir coincidencia

4. Especificaciones Software

satisfactoria mediante la complementación nos encontraríamos con un error en el campo de número de paquete o complemento del paquete y se requeriría el envío de un NAK.

Figura 13. Esquema práctico de las rutinas NEG_NUM y NUM_P.

Figura 14. Ejemplo de control de errores de secuencia.

PAQ_REC ≠ PAQUETE

PAQ_REC >PAQUETE PAQ_REC < PAQUETE

PAQ_PRE_ERROR=1 PAQ_PRE_ERROR2=1

COMPLEMENTO DE PAQ_REC =

AUXRC

COMPLEMENTO DE PAQ_REC =

AUXRC

COMPLEMENTO DE PAQ_REC

≠ AUXRC

CAN ACK NAK

0 0 0 0 0 1 0 0 NÚMERO DE PAQUETE RECIBIDO

A

0 0 0 0 0 0 1 0 NÚMERO DE PAQUETE RECIBIDO

B

0 0 0 0 0 0 1 1 NÚMERO DE PAQUETE CALCULADO DE

MANERA LOCAL

0 0 0 0 0 0 1 1 NÚMERO DE PAQUETE RECIBIDO

C

NÚMERO DE PAQUETE (4) RECIBIDO MAYOR QUE EL CALCULADO (3). FALTA DE SINCRONISMO IRRECUPERABLE. SE PRECISA DEL ENVÍO DE UN CAN AL EMISOR.

NÚMERO DE PAQUETE RECIBIDO(2) MENOR QUE EL CALCULADO(3). FALTA DE SINCRONISMO RECUPERABLE. SE PRECISA DEL ENVÍO DE UN ACK AL EMISOR.

NÚMERO DE PAQUETE RECIBIDO IGUAL AL CALCULADO. SIGUE EL PROCESO DE RECEPCIÓN.

4. Especificaciones Software

4.5 Rutina de Servicio a la Interrupción: PUT_D. En esta rutina se atienden las interrupciones generadas por el buffer del transmisor de la USART. Este buffer sirve para hacer una precarga del dato antes de que este se guarde en el buffer de envío y mediante desplazamientos se produzca la comunicación serie por el pin TX. Cada vez que el buffer se queda vacío hace una petición de interrupción, que si está habilitada provoca un salto del PC hacia la rutina de atención a la interrupción. Posteriormente el código hace la derivación a la subrutina particular correspondiente. Esta subrutina es la PUT_D. El envío del carácter se hace al principio de la subrutina por razones de tiempo. Para provocarlo hace falta escribir en el registro TXREG, que es el buffer de envío de la USART. Al enviarse en ese momento no se pierde tiempo de proceso. De esta manera, al principio se manda el byte de información y el resto de subrutina se ejecuta en tiempo de envío. Se solapa el proceso de selección del byte a enviar con el envío del byte anterior. En resumen: no introducimos retardos en los envíos, salvo por el tiempo de atención de la interrupción.

Código 1. Función PUT_D. En cada ejecución de la rutina se lee el registro auxiliar y se manda a la USART para después llenar este registro con el siguiente valor a enviar. En caso de que desde la rutina GET_D se haya impuesto el envío de paquete, se llenará el GPR auxiliar de envío (AUXTX) con el valor perteneciente a uno de los campos. En caso de que sea necesario el envío de un handshake, este se obtendrá del registro HANDSHAKE y se guardará en el mismo AUXTX. La prioridad está clara, el envío de paquetes tiene prioridad sobre el de handshakes. Si tuviesen prioridad los handshakes, se podría dar el caso del envío de un reconocimiento de este tipo entremedio de un paquete. Esto sería funesto para la integridad del paquete y la sincronización de los dos dispositivos. Por lo tanto, los envíos de paquetes se harán de manera lineal y no se interrumpirán para el envío de valores de

PUT_D BANKSEL AUXTX MOVF AUXTX,W BANKSEL TXREG ;Escritura en el registro de transmisión MOVWF TXREG ;de la USART BTFSC TX_STATUS,SND_NOTHAND GOTO ENVIAN ;Va a la subrutina de envío de paquetes. BTFSC TX_STATUS,HAND_BY_RECEP GOTO S_HAND ;Va a la subrutina de envío de HANDSHAKES. CALL OFF_RSI ;Deshabilita el servicio de ; interrupciones de envío. GOTO FIN ;Finaliza el servicio de interrupciones.

4. Especificaciones Software

reconocimiento. En cuanto a los handshakes, están compuestos únicamente por un único envío, por lo que no tiene sentido hablar de interrupciones.

Figura 15. Esquema funcional que debe seguir la aplicación.

Como se puede ver en el código 1. Existen tres rutinas adicionales que se utilizan para diversas funciones y que se han formateado en negrita. La rutina ENVIAN tiene la finalidad de obtener el valor que se debe enviar en caso de requerirse un envío de paquetes. La S_HAND simplemente lee del registro HANDSHAKE y coloca el dato en el registro auxiliar de envío AUXTX. Por último, la rutina OFF_RSI es de uso general y lo que hace es deshabilitar la atención de interrupciones de envío de USART. Dentro de las posibilidades del envío de paquetes, casi toda la información de los campos se obtiene a partir de un direccionamiento indirecto de la RAM. De esta manera, se direccionan los GPR’s PAQ, NOT_PAQ, CHECK_TXH y CHECK_TXL (en caso de encontrarnos con un control de errores por CRC). Para el campo de datos, se obtiene la información de la memoria FLASH. Para ello se emplea la función LECTURA.

FIN DE SERVICIO

PASO 3 FIN DE SERVICIO

X X X X X X X X GUARDAR EN REGISTRO AUXILIAR

DE ENVÍO

OBTENCIÓN DEL BYTE PERTINENTE.

X X X X X X X X Registro de envío (USART)

X X X X X X X X REGISTRO AUXILIAR DE ENVÍO

¿Envío de paquetes?

¿Envío de

handshake?

ESCRITURA “AUTOMÁTICA” EN EL REGISTRO DE DESPLAZAMIENTO DE LA USART.

1

2

NO

FIN DE SERVICIO

X X X X X X X X REGISTRO AUXILIAR DE ENVÍO

LECTURA DE REGISTRO DE HANDSHAKES

3

NO

4. Especificaciones Software

4.6 Implementación del Código de Redundancia Cíclica: DO_CRC. Barajadas ya las diversas opciones posibles, buscaremos el tipo de rutina que se ajuste mejor a nuestras posibilidades. La función deberá generar un CRC sobre la marcha, esto es, durante la emisión o recepción del campo de datos del paquete. De esta manera, al final del envío/recepción de todos los datos el cálculo llega a su final y se obtiene el valor de CRC del paquete. El valor inicial a partir del cual se agrega el primer valor y sucesivos es 0. Se ha utilizado este tipo de rutina, sabiendo de antemano que no es la más optimizada, por sus ventajas particulares para nuestro caso. Por ejemplo, las rutina de CRC mediante tabla precalculada requiere de un espacio amplio de almacenamiento: exactamente 256 espacios de 16 bits. Esto supone a la postre gran cantidad de espacio cubierto con unidades de información difícilmente manejables por nuestro dispositivo (PIC). La manejabilidad es precaria porque el único soporte donde esta tabla podría tener suficiente espacio para ser implementada es en la memoria FLASH. En nuestro tipo de uC esta está administrada en palabras de 14 bits, lo que complica el código. Por tanto, la mejora en el tiempo de ejecución conseguida se pierde con toda seguridad por carencia en la manejabilidad, que ralentizará el procesado. Por si eso no fuera poco, con este tipo de implementación no ralentizamos las recepciones, dado que el tiempo utilizado por la rutina entra por completo dentro del tiempo de recepción de un byte de información. Por todo esto, el tiempo “extra” que presumiblemente emplea la rutina no supone un gasto crítico. El diagrama conceptual de la rutina que buscamos será el siguiente:

Figura 16. Diagrama conceptual de la función de cálculo del CRC.

Esta función calcula el valor CRC resultado a partir de dos valores: un CRC o valor inicial y un valor adicional para agregar al cálculo. El valor inicial se introduce en los registros CRCH y CRCL, teniendo un tamaño de 16 bits. El valor a agregar al cálculo se le pasa a la función a través del registro acumulador W, que tiene una longitud de 8 bits. El funcionamiento general de la rutina es el siguiente:

VALOR RESULTADO

VALOR INICIAL

BYTE A AGREGAR AL CRC

CÁLCULOS

4. Especificaciones Software

Figura 17. Esquema de funcionamiento específico de la función DO_CRC.

REGISTRO DESCRIPCIÓN W Dato nuevo a agregar al cálculo

CRCH/CRCL Valor del CRC en 16 bits en cada momento de la operación ITERA Contador de 8 iteraciones.

C Bit de Carry del PIC POLYH/POLYL Polinomio divisor característico 11021h.

Tabla 12. Registros utilizados y sus descripciones.

El funcionamiento de esta rutina es simple: Se hace la operación XOR del valor que se desea agregar con el valor en ese momento de la parte alta del CRC (CRCH). Una vez hecho esto, se implementa un registro de desplazamiento con el valor entero (16 bits) del CRC extrayendo el bit de valor más alto al bit de Carry. Si este bit es un 1 se hará la operación XOR de todo el polinomio característico con el valor total del CRC. En caso de que sea 0 no se realizará operación alguna. El bucle constituido se repetirá 8 veces. Una vez haya ocurrido esto el valor contenido en los registros CRCH y CRCL será equivalente al CRC total de los datos calculados hasta el momento.

W XOR CRCH

ITERA = 8

CRCH CRCL C

¿ C = 0 ? ¿ C = 1 ?

ITERA = ITERA –1 ¿ ITERA = 0 ?

CRCH XOR POLYH CRCL XOR POLYL

NO

FIN DE BUCLE SÍ

4. Especificaciones Software

Este tipo de implementación es equivalente al cálculo directo de CRC comentado en esta memoria, con la salvedad de que haciéndolo de esta manera no es necesario el incremento de 0’s que se hacía en el otro.

Código 2. Rutina de cálculo secuencial de CRC.

4.7 Tiempos de ejecución de RSI’s y entre interrupciones.

NOMBRE DE RUTINA DESCRIPCIÓN TIEMPO (US) TOUTT TIMEOUT de transmisión <60 TOUTR TIMEOUT de recepción <75 PUT_D RSI de emisión <180 GET_D RSI de recepción <175

Tabla 13. Costes temporales de servicio de interrupciones.

Como todo sistema implementado mediante la utilización de interrupciones, este requiere de un estudio pormenorizado de los tiempos de ejecución de dichas subrutinas y de otros aspectos como el tiempo entre interrupciones. Ningún tiempo de ejecución de una RSI ha de ser superior al tiempo máximo entre interrupciones. Esta necesidad está basada en el hecho de que si no pudiésemos ir procesando el servicio de interrupciones según van llegando podríamos “perder” parte de ellas. Por ejemplo, el timer provoca interrupciones de manera periódica. Para servirla, se rellena el timer otra vez con el valor de cuenta pertinente y se resetea el flag correspondiente con el fin de que la misma interrupción no se sirva dos veces. Si antes de resetear el flag recibiésemos otra interrupción, el flag se asertaría (no cambiando de estado ya que inicialmente estaba a 1) por la llegada de la interrupción y sería reseteado por nosotros una vez servida la primera. Como fruto de esto,

DO_CRC BANKSEL CRCH XORWF CRCH,F ;W XOR CRCH = CRCH MOVLW .8 MOVWF ITERA ;Inicializamos el contador a 8 iteraciones. SHIFT CLRC ;(Se limpia el bit de carry para desplazar.) RLF CRCL,F ;Implementación del registro de

RLF CRCH,F ;desplazamiento de dos bytes. BTFSS STATUS,C GOTO LOOP MOVLW POLYH ;Si el carry es 1 se hace la XOR con el XORWF CRCH,F ;registro que contiene el polinomio. MOVLW POLYL XORWF CRCL,F LOOP DECFSZ ITERA,F ;Se realiza el bucle un número “ITERA” GOTO SHIFT ; de veces y después se sale. RETURN

4. Especificaciones Software

perderíamos una cuenta de los contadores de la rutina de gestión de TIMEOUTS que se alimenta del timer. Esto supone un desfase negativo del temporizado en tantos ms como se hayan programado entre interrupciones. Las interrupciones que para nosotros son críticas son las de recepción en la USART y del timer 0. La interrupción generada por el transmisor no es crítica porque hasta que no se sirva no será posible la aparición de otra. Esto es así porqué esta interrupción se aserta cuando se vacía el buffer de envío. La pérdida está completamente clara si recibiésemos una segunda interrupción de recepción antes de procesar la primera; perderíamos un byte de información. De todas maneras, la USART posee un buffer de 2 posiciones con forma de pila. Para que ocurriese esto deberíamos llenar las dos posiciones del buffer y además recibir otro byte. Dado que imponemos una velocidad de 9600 bps, nos encontramos con las siguientes consideraciones:

usbps

17,1049600

1≈

Este es el tiempo en enviar cada bit, y dado que enviamos 8 bits útiles, además de uno de start y uno de stop tardaremos en enviar un byte entero un tiempo igual a:

msbits 04,110·17,104 = Entonces, si queremos asegurarnos de que no perderemos ninguna interrupción, forzaremos un tiempo de atención a la rutina que sea inferior al indicado arriba. La interrupción más crítica de las dos es la de recepción, considerando que presenta una limitación más importante temporalmente hablando. Si no se pierden interrupciones de recepción tampoco se perderán de timer.

PETICIÓN DE INT. GENERAL.

PETICIÓN INT. DE TOUT .

EJECUCIÓN DE RSI TOUTT.

EJECUCIÓN DE RSI TOUTR.

PETICIÓN INT. DE PUT_D.

PETICIÓN INT. DE GET_D.

EJECUCIÓN DE RSI PUT_D.

EJECUCIÓN DE RSI GET_D.

Figura 18. Ejemplo de reconocimiento y servicio de interrupciones

La interrupción de recepción es la que tiene menos prioridad. Esto viene a ser solo por disposición de las líneas de evaluación dentro de la RSI del PIC. La RSI es única y a partir de ella se hacen derivaciones a las diferentes rutinas de servicio a los diferentes tipos de

4. Especificaciones Software

interrupciones. Como la prioridad es la más baja, nos encontramos con que cualquier RSI debe tener un tiempo máximo de ejecución inferior a 1,04ms. Para evaluar el coste temporal máximo de cada rutina hemos dispuesto una tabla: Como se puede observar en la tabla 13, el tiempo mayor es el correspondiente a la rutina de emisión, que será siempre inferior a 180us. Además de esto, la suma de los tiempos tampoco excede de 1,04ms. Este es el peor caso. Este tiempo es muy inferior al tiempo límite barrera de 1,04ms. Por eso concluimos que tenemos holgura suficiente para el proceso de las interrupciones.

4.8 Rutinas para el módem Se han desarrollado dos funciones para el control de un módem serie. Estas funciones tendrán como objetivo la configuración del módem para que establezca una conexión o se desconecte, según las necesidades. Esta configuración se realizará mediante los comandos HAYES, propios de los módems de la misma marca. Estos comandos se han extendido hasta ser muy utilizados y la gran mayoría de módems son compatibles con ellos. A partir de una conexión, esta se deberá mantener durante el tiempo que dure el intercambio de información. Esto se monitorizará mediante varias líneas RS-232. Estas rutinas sirven para poder comprobar el funcionamiento del sistema en un medio real de comunicación utilizado a diario. Para la configuración se envían los comandos al módem. El envío se hace carácter a carácter mediante el puerto serie. El módem, en caso de recibir correctamente cada comando, actuará al respecto. 4.8.1 Establecimiento de conexión: función CONN. Mediante esta función se configurará el módem para que realice una conexión a través de la línea telefónica. Como paso previo, asertaremos DTR y RTS, esperando que el módem aserte DSR. Estas son señales RS-232 que nos servirán para comunicarnos con el módem. Se reseteará el dispositivo. Con esto conseguiremos situarlo en estado inicial. Podremos preveer las reacciones del módem, ya que serán las del estado por defecto. Seguidamente configuraremos los reconocimientos del módem, entre otras cosas, para que sean favorables a nuestras necesidades. Por último enviaremos al módem un comando de llamada, seguido del número al que se debe conectar. Los comandos se enviarán carácter a carácter a través del puerto serie. En algunos casos se obtendrá lo que se llama el eco por parte del módem. Como se puede deducir el mismo nombre, el eco es el envío por parte del módem del mismo carácter recibido con la finalidad de comprobar errores de comunicación. Si no se recibe este eco al enviar el comando de reseteo es porqué la configuración anterior al envío del comando así lo forzaba. Una vez reseteado el módem, el eco se activa por defecto. Tras cada comando enviado, se debe enviar también un carácter de retorno de carro. De esta manera el módem advierte el fin de la cadena de comandos.

COMANDO ENVIADO DESCRIPCIÓN ATZ Reseteo del módem.

ATEQVS12=10

ATEQVS0=3S12=10

Se activa el eco. Se habilitan los códigos de resultados en modo numérico. Se establece un tiempo de guarda antes del envío de la secuencia de escape de 200 ms. La versión superior es la que se envía en caso de no desear modo de autorespuesta y

4. Especificaciones Software

la de abajo en caso de si desearlo. El comando extra establece 3 tonos antes de que el módem responde de forma automática.

ATDT656555444 Comando de marcado por tonos para establecer la conexión con el número incluido en el mismo comando.

Tabla 14. Comandos enviados al módem en una conexión.

Entender las respuestas del módem con respecto a los comandos es sumamente importante. Mediante estas respuestas comprobaremos que el comando se ha ejecutado con éxito o, si no lo ha hecho podremos averiguar por que razón ha pasado esto. En la tabla 15 mostraremos las respuestas correctas que ha de recibir el sistema procedentes del módem. En caso de que todo vaya tal y como se espera, el módem establecerá conexión y pasará a un modo de línea. En este modo, todos los envíos realizados al módem se transmitirán directamente a través de la línea. En este punto la función finaliza su trabajo y el manejo del módem pasa a un segundo plano. El intercambio de información mediante el protocolo XModem toma todo el protagonismo. COMANDO ENVIADO RESPUESTA OBSERVACIONES

ATZ(CR)(CR)(LF)OK(CR)(LF)

ATZ

(CR)(CR)(LF)OK(CR)(LF)

El byte CR se introduce entre paréntesis para diferenciarlo de la C y la R por separado y se corresponde con el retorno de carro (carácter 13 en decimal del código ASCII). Lo mismo ocurre con el carácter LF,. Que corresponde con el salto de línea en código ASCII ( carácter 10 decimal). Existen dos posibles respuestas correctas. Una para el caso en que está configurado el eco y la otra para el caso contrario. De esta manera, en el primero el módem retorna el comando introducido, incluyendo el retorno de carro.

ATEQVS12=10 ATEQVS12=10(CR)0(CR)

ATEQVS0=3S12=10 ATEQVS0=3S12=10(CR)0(CR)

Dada la configuración para modo numérico de respuesta, obtenemos un 0 equivalente a un OK del modo verbal. También desaparecen los saltos de línea.

ATDT656555444 12(CR)

Este tipo de respuesta es para una comunicación a 9600 bps, aunque cualquier otra respuesta con el 1 delante serviría para advertir un establecimiento de

4. Especificaciones Software

comunicación a una velocidad determinada.

Tabla 15. Respuestas que se obtienen del módem si no se producen errores.

Figura 19. Funcionamiento de la función CONN. Si se produjese algún error de manera persistente que evitase la comunicación entre el módem y el microprocesador de manera correcta, nos encontraríamos con un error de tipo hardware. Esto puede producirse, por ejemplo si el módem no está preparado o si existe algún defecto en el cable RS-232. En este caso, el sistema advertiría al usuario de la imposibilidad de comunicar con el módem por un error de este tipo.

ENVÍO DE “A”

ESPERA DE 100 MS (APROX.)

SE ENVÍA “TZ(CR)”

ESPERA CUMPLIDA TOTALMENTE CARÁCTER “REFLEJADO” DESDE EL MÓDEM.

SE ENVÍA “TZ(CR)” RECIBIENDO LOS ECOS

SE RECIBEN RESPUESTAS SE RECIBEN RESPUESTAS

ENVÍO DE STRING DE CONFIGURACIÓN

OBTENCIÓN DE RESPUESTA

ENVÍO DE COMANDO DE MARCADO

OBTENCIÓN DE RESPUESTA

FIN ¿ERROR?

4. Especificaciones Software

La rutina que se ha desarrollado es de carácter secuencial y se vale del método de encuesta. No se han utilizado interrupciones en esta parte del código por dos razones fundamentales:

• Limitaciones del uC. El PIC solo dispone de un espacio de direcciones para RSI’s por lo que cada vez que se produzca una interrupción de cualquier tipo, el contador de programa se situará en una única posición. En esta posición tenemos situada la rutina de gestión de interrupciones propia del mismo protocolo XModem. En caso de querer utilizar interrupciones, deberíamos sobrecargar esta rutina con algunas líneas que al menos nos permitieran diferenciar entre una recepción durante el proceso de conexionado y otra de diferente tipo. Esto alentecería el desarrollo del protocolo ya que esta parte del código se ejecuta un gran número de veces; eso sin contar con que lo haría realmente más complejo.

• El tiempo no es una variable crítica en este punto. Efectivamente, no estamos enviando información ni compartiendo recursos de temporizado. El tiempo, por tanto, no es necesario que sea optimizado al 100%. De hecho, desde que se envía un carácter al módem hasta que se recibe éste no tendría necesidad de hacer ningún trabajo alternativo, sino solamente esperar.

En la figura 19 se ha señalado con línea discontinua la posibilidad de que las respuestas y ecos no sean satisfactorias, produciendo un error. 4.8.2 Desconexión Las señales RTS, DTR y DSR deben mantenerse asertadas. Se pondrá (de no estarlo antes) a 0 la primera, que está controlada por nuestro PIC (haciendo las veces de terminal). Las dos últimas deberían estar siempre a 0, dado que son señales clave y de cambiar este estado supondría la finalización de la comunicación. Por tanto, si llegados a este punto, las señales no estuvieran asertadas, la comunicación habría acabado de manera no prevista. Si todo transcurre tal y como está previsto, se esperará un tiempo de guarda (sin envío alguno hacia el módem) de aproximadamente 300 ms. Tal y como hemos configurado el módem sería suficiente con un tiempo de espera de 200ms, pero por seguridad, guardaremos el valor especificado de 300. Tras esto, enviaremos al módem el carácter de escape 3 veces. Este carácter se especifica arbitrariamente a través del registro S2, interno al módem, y por defecto será el “+” (43 decimal del código ASCII). Entre envío y envío de este carácter no se debe superar el tiempo de guarda. Además no es necesario enviar retorno de carro. Tras este envío, si el módem lo recibe correctamente pasará a modo comandos. Indicará esto mediante el envío de un reconocimiento afirmativo del tipo “OK”, que en nuestro caso será la cadena de caracteres (OD)0(OD), porque hemos configurado el módem en modo numérico de reconocimientos. Recibido este reconocimiento, se le enviará al módem la instrucción de colgado ATH, seguida de un retorno de carro. El periférico reconocerá, de ir todo como se espera, el comando con un “0”. Llegados a este punto la señal “Carrier Detect” se desasertará y la comunicación quedará interrumpida. El módem se mantendrá entonces en modo comandos.

4.9 Suma inicial de comprobación Con el tiempo, la parte hardware del sistema puede ir deteriorándose. En concreto la memoria FLASH de programa podría verse corrompida o perder información. Esto

4. Especificaciones Software

provocaría errores impredecibles en la ejecución del código por lo que este problema debe ser tomado en consideración. En caso de producirse un daño de este tipo sería razonable cambiar el microcontrolador por otro idéntico con el mismo programa. Con esto se solucionaría por completo el problema. El problema en cuestión, dado que la solución está clara es el de poder averiguar si el dispositivo presenta errores de este tipo. Para conseguir esto de una manera razonable se implementa una función de suma de comprobación (o checksum). Situada al inicio del código, leerá una a una todas las instrucciones almacenadas en la memoria FLASH y efectuará una suma sin acarreos de su valor hexadecimal. Al final de los cálculos, el valor de la suma debe coincidir con otro que el código pueda obtener, por ejemplo, de la memoria EEPROM. En caso de que se produzca la discrepancia de valores la función debería anunciar esto al usuario. No es posible almacenar el valor de comprobación precalculado en la misma memoria FLASH, porqué entonces variaríamos al mismo tiempo el propio cálculo de la función. CHEQUEA BANKSEL CHVALUEH CLRF CHVALUEH CLRF CHVALUEL BANKSEL EEADRH CLRF EEADRH CLRF EEADR OTRO2 CALL LECTURA BANKSEL EEDATA MOVF EEDATA,W BANKSEL CHVALUEL ADDWF CHVALUEL BNC NOCARRY INCF CHVALUEH,F NOCARRY BANKSEL EEDATH MOVF EEDATH,W BANKSEL CHVALUEH ADDWF CHVALUEH,F BANKSEL EEADR MOVF EEADR,W XORLW @ENDDOWN BTFSS STATUS,Z GOTO OTRO2

;Inicializaciones de variables. ;Función que lee una palabra en ;FLASH. ;Suma de la parte baja de la palabra ;con el valor anterior del registro ;implementado en 2 bytes. ;Suma de la parte alta.

4. Especificaciones Software

BANKSEL EEADRH MOVF EEADRH,W XORLW @ENDUP BTFSS STATUS,Z GOTO OTRO2 BANKSEL PTRO_EEP MOVLW H'EF' MOVWF PTRO_EEP CALL EEPROM BANKSEL CHVALUEH XORWF CHVALUEH,W BTFSS STATUS,Z GOTO GRAVE CALL EEPROM BANKSEL CHVALUEL XORWF CHVALUEL,W BTFSS STATUS,Z GOTO GRAVE CALL LA0INT CALL LA1INT RETURN GRAVE NOP GOTO GRAVE

;Se comprueba que no hayamos llegado ;al final del espacio ocupado por el ;programa. En caso afirmativo, ;comprobaremos el resultado con el ;valor precalculado y guardado en ;EEPROM. ;Función que leerá de memoria EEPROM ;la parte baja y alta del valor ;precalculado. ;Se apagan los dos LED’s

Código 3. Rutina que genera el checksum. Dado que el tamaño del checksum es de 16 bits, utilizaremos el bit de carry para sumar en caso de ser necesario el acarreo al byte alto del checksum. Posteriormente sumaremos el propio byte alto del checksum con los 6 bits altos restantes que en total forman las palabras de 14 bits para programa. Al llegar a la dirección donde finaliza el código, la rutina sale del bucle de suma y compara un valor extraído de la EEPROM con el calculado. Los dos valores tendrán que coincidir. En caso de haber discrepancia se encenderá el led correspondiente a la detección de un error hardware y el programa entrará en un bucle infinito, por lo que se requerirá del reseteo del dispositivo.

4. Especificaciones Software

Figura 20. Funcionamiento del checksum inicial.

4.10 Control de las comunicaciones Todo este completo sistema de comunicaciones deberá ser utilizado al servicio de otro proyecto. Por ello, se requiere una manera simple de que el diseñador pueda utilizar dicho código basándose en sus necesidades. En un determinado momento se deseará enviar información y/o recibirla. Con el fin de versatilizar el código y contemplar todas estas necesidades se implementan toda una serie de rutinas. De esta manera será mucho más fácil para el usuario enviar información, dado que podrá hacerlo simplemente ejecutando

LECTURA DE WORD (14 BITS) DE MEMORIA FLASH.

SIGUIENTE DIRECCIÓN.

SUMA DEL VALOR NUMÉRICO

INICIALIZACIONES DE CONTADORES...

¿HA LLEGADO EL FINAL

DEL CÓDIGO?

COMPROBAR IGUALDAD ENTRE VALOR ALMACENADO Y

CALCULADO.

¿DISCREPANCIA?

AVISO DE ERROR Sí

No FIN

NO

4. Especificaciones Software

correctamente una determinada función. Por otro lado, las recepciones también deben ser agilizadas mediante una idea similar. 4.10.1 Función de alto nivel para emisión: LLENADO

Código 4. Función LLENADO Se ha creado una función de alto nivel que haga de punto de contacto con el mismo diseñador y mediante la cual él pueda utilizar el código con comodidad. Como parámetros, se le pasará a la rutina un valor de puntero a dirección de memoria de programa, la cantidad de datos del último paquete (que no tiene porqué ser de 128, ya que los huecos se llenarán con caracteres “1A”) y el número de paquetes enteros que se enviarán. Esta función recibe el nombre de LLENADO. Se utilizará en el nivel principal de ejecución (MAIN) y es la encargada del llenado de un buffer de envío con una capacidad de 16 bytes. Este buffer será de tipo cola (FIFO). Mientras esta función llena el buffer, otra lo vaciará desde la RSI de envío de datos. Como es lógico, las mismas funciones se asegurarán de no sobreescribir información no enviada y de no leer información del buffer cuando este esté vacío. Para acabar, la función de lectura del buffer (que también controla las variables de contado) se ocupará de llenar con el carácter substituto (1A) del código ASCII el resto de bytes que se deben enviar hasta completar el último paquete con 128 bytes. Como se puede ver en esta rutina, el dato recibido por acumulador se guarda en la variable VALOR. Se leen (LECTURA) datos de la memoria de programa y se escriben en la cola (INTOT) de transmisión hasta que el buffer está lleno. Una vez el buffer se ha vaciado por lo menos en una posición se continua el llenado. Esto se repite tantas veces como el número introducido en la variable VALOR.

LLENADO

BANKSEL VALOR ;VALOR indica el número de llenados que se MOVWF VALOR ; han de efectuar.

INCF VALOR,F LLENAMAS DECFSZ VALOR,F GOTO LLENA RETURN LLENA CALL LECTURA ;Lectura de memoria de programa.

CALL INTOT ;Introduce el dato en el buffer de ; transmisión.

VERFULL BTFSS BUFFERS,FULLT ;Bucle de espera si el buffer está GOTO LLENAMAS ;lleno. GOTO VERFULL

4. Especificaciones Software

Figura 21. Forma en que se llena el buffer de envío. 4.10.2 Funciones de control de buffer: INTO(T/R) y OUTFROM(T/R) Como se puede ver en la figura anterior, la función LLENADO se sirve de otra para introducir los datos en el buffer. Esta función se denomina INTOT.

PUNTERO DE LECTURA

PUNTERO DE ESCRITURA

INTOT (2)

PUNTERO DE LECTURA

PUNTERO DE ESCRITURA

ESTADO INICIAL (1)

DISEÑADOR

FUNCIÓN LLENADO

PUNTERO A MEMORIA

TAMAÑO PAQUETE FINAL

NUM. DE PAQUETES FUNCIÓN INTOT

BUFFER DE ENVÍO

4. Especificaciones Software

Figura 22. Maniobra de lectura y escritura en el buffer.

Código 5. Función INTOT (Transmisión).

PUNTERO DE LECTURA

PUNTERO DE ESCRITURA

OUTFROMT (3)

INTOT BTFSS BUFFERS,FULLT ;Si el buffer esta lleno pone a GOTO OKF ;el bit RETORNO y sale de la BSF BUFFERS,RETORNO ;función. RETURN OKF BTFSC BUFFERS,EMPTYT ;Si el buffer está vacío y se BCF BUFFERS,EMPTYT ;introduce un byte, el bit ; indicador debe resetearse. BSF STATUS,IRP BANKSEL BTH MOVF BTH,W MOVWF FSR ;Acceso indirecto a las diferentes ;posiciones de memoria. BANKSEL EEDATA MOVF EEDATA,W MOVWF INDF BANKSEL BTH INCF BTH,F ;Control de dirección inferior y MOVF BTH,W ;superior para implementar un buffer XORWF BTMAX,W ;circular. BTFSS STATUS,Z GOTO NOMIN MOVF BTMIN,W MOVWF BTH NOMIN MOVF BTH,W ;En caso de coincidir puntero superior XORWF BTL,W ;e inferior, hemos llenado el buffer. BTFSC STATUS,Z BSF BUFFERS,FULLT BCF BUFFERS,RETORNO RETURN

4. Especificaciones Software

Dicha función y otra recíproca (OUTFROM) se utilizan tanto para el buffer de emisión como para el de recepción. Claro está que son 4 rutinas que funcionalmente hacen lo mismo (2 a 2) pero que tienen bits de control diferentes y direcciones de buffer diferentes. Por esta razón, la última letra indicará si se trata de emisión o recepción. En caso de encontrarnos con la función INTOT sabremos que introduce valores en la cola de transmisión. Si de lo contrario, utilizamos la función OUTFROMR estaremos extrayendo datos del buffer de recepción.

Código 6. Función OUTFROMT (Transmisión).

Estas dos funciones deben ser capaces de implementar un buffer rotativo de 16 registros (cola). La función INTO es, como hemos dicho ya, la que escribe en el buffer un byte de información. Esta función es la encargada de informar sobre el estado del buffer. En caso de estar lleno la dirección del puntero de escritura y el de lectura coincidirán al ser incrementado el primero. En tal caso, la función pondrá a 1 un determinado bit que controla e informa de este hecho. De manera recíproca, OUTFROM leerá del buffer un dato y puede ser que al incrementar el puntero de lectura los dos coincidan. Entonces

OUTFROMT BTFSS BUFFERS,EMPTYT ;En caso de querer extraer un GOTO OKE ;dato de un buffer vacío se BSF BUFFERS,RETORNO ;pone a 1 el bit RETORNO. RETURN OKE BTFSC BUFFERS,FULLT ;Al extraer un byte de un BCF BUFFERS,FULLT ;buffer lleno, esto dejará de ;estarlo. BSF STATUS,IRP BANKSEL BTL MOVF BTL,W MOVWF FSR MOVF INDF,W BANKSEL SND MOVWF SND CLRF INDF ;Mismo acceso a las posiciones de ;memoria que en el código 5. BANKSEL BTL INCF BTL,F MOVF BTL,W XORWF BTMAX,W BTFSS STATUS,Z GOTO NOMIN2 MOVF BTMIN,W MOVWF BTL NOMIN2 MOVF BTL,W ;De coincidir los dos punteros XORWF BTH,W ;habremos vaciado el buffer. BTFSC STATUS,Z BSF BUFFERS,EMPTYT BCF BUFFERS,RETORNO RETURN

4. Especificaciones Software

deberá informar del estado de buffer vacío. En caso de estar un buffer lleno, la función INTO correspondiente no realizará ninguna acción sobre él y devolverá mediante otro bit un estado de error. Recíprocamente, al leer de un buffer vacío se devuelve un error y la cola correspondiente se deja tal y como está. Las rutinas correspondientes para recepción serán las mismas, cambiando únicamente bits de información, direcciones y registros. Funcionalmente y en cuanto a trabajo desarrollado son idénticas.

4.10.3 Lectura del buffer de transmisión y envío: SND_BYTE. Una vez se ha llenado el buffer o mientras se llena puede aparecer una interrupción de envió de datos. El registro de alimentación de la USART se ha quedado vacío y es posible escribir en él para el próximo envío. En tal caso, a nivel de ejecución de la RSI de envío (PUT_D) se ejecutará la función SND_BYTE. El trabajo de esta función consiste en obtener un byte (mediante OUTFROMT) si es posible y pasarlo a la RSI mediante el acumulador. En caso de no poder conseguir un dato se dará la información por acabada y se introducirán caracteres 1A hasta finalizar los 128 bytes. Esta rutina maneja la variable del contado de datos (un contador decremental de 128 unidades) y las referentes al cambio de campo del paquete.

Código 7. Rutina SND_BYTE 4.10.4 Recepciones. En cuanto a las recepciones de datos y la ruta que sigue la información antes de ser almacenada de forma definitiva tenemos algunas similitudes con respecto a la emisión. Utilizaremos de la misma manera el sistema de escritura y lectura en un buffer diferente al de transmisión pero de idénticas características. En consecuencia, utilizaremos funciones de manejo idénticas pero con denominación acabada en R y no en T, es decir: INTOR y OUTFROMR. Por cuestiones de limitación de recursos en PIC, el almacenamiento final se realizará en espacios de la memoria de programa, como ya se ha comentado en varias ocasiones. Se ha habilitado además, un buffer del tamaño de un bloque de datos (128 bytes). Esto mejora en gran medida la eficiencia, ya que cada vez que queremos escribir en FLASH debemos parar la comunicación. Es necesario que durante la escritura prescindamos del

SND_BYTE CALL OUTFROMT ;Se extrae del buffer un dato. BTFSS BUFFERS,RETORNO

GOTO OKRET MOVLW H'1A' ;En caso de encontrar el buffer vacío

BANKSEL SND ;se manda el carácter “1A” hasta com- MOVWF SND ;pletar el resto del paquete. BSF AUXILIAR,FINENVIOS OKRET BANKSEL DATOS ;Faltará un envío menos del campo de DECFSZ DATOS,F ;datos. RETURN INCF TX_STATUS,F RETURN

4. Especificaciones Software

uso de interrupciones y además, el tiempo empleado para una sola operación es más alto que el de la cadencia de recepciones. Si parásemos las comunicaciones cada 16 recepciones tendríamos un código con una eficiencia muy baja, ya que tardaríamos mucho tiempo en enviar la misma información. En conclusión, la RSI de recepción recogerá el byte del registro de recepción pertinente y lo depositará en el buffer de recepción. A nivel de ejecución principal (MAIN), otra rutina denominada ARAM será la encargada de extraer la información del buffer de 16 y depositarla en el de 128 bytes. Una vez el buffer esté lleno se detendrán las comunicaciones para dar paso al guardado en memoria FLASH. Una vez se haya almacenado pertinentemente cada uno de los datos se restablecerá el flujo de comunicaciones.

Figura 23. Manejo de la información recibida. 4.10.5 Escritura en el buffer de 128 posiciones: ARAM. La función ARAM implementa un buffer de 128 posiciones de byte en la memoria RAM. Este será llenado y vaciado sistemáticamente y por completo, dado que el tamaño de paquete es fijo.

XXXXXXXX

GPR DE RECEPCIÓN BUFFER DE

RECEPCIÓN DE 16 BYTES

BUFFER DE 128 BYTES MEMORIA FLASH PALABRAS DE 14 BITS.

4. Especificaciones Software

Figura 24. Zona de implementación del buffer en el PIC.

Código 8. Función ARAM.

ARAM CALL OUTFROMR ;Obtención de byte de buffer de Rx

;de 16 bytes. BCF STATUS,IRP

BANKSEL PTRO_BUF_RC MOVF PTRO_BUF_RC,W MOVWF FSR MOVF AUXRC,W MOVWF INDF BANKSEL PTRO_BUF_RC INCF PTRO_BUF_RC,F MOVLW H'70' XORWF PTRO_BUF_RC,W BTFSC STATUS,Z ;Una vez se llega a la posición 70

GOTO ENDB0A ;se debe redireccionar el puntero al ;siguiente banco.

MOVLW H'D0' XORWF PTRO_BUF_RC,W BTFSC STATUS,Z ;En cuanto se llega al final del GOTO ENDBUFA ;se redirecciona el puntero hacia RETURN ;el inicio. ENDB0A MOVLW H'A0' MOVWF PTRO_BUF_RC RETURN ENDBUFA MOVLW H'20' MOVWF PTRO_BUF_RC RETURN

20h

70h

A0h D0h

XXXXXXXX

BANCO 0 BANCO 1 BANCO 2 BANCO 3

BYTE RECIBIDO

4. Especificaciones Software

VARIABLE DESCRIPCIÓN

AUXRC Registro auxiliar donde se guarda el valor del byte recibido y leído del registro de la USART.

PTRO_BUF_RC Puntero a memoria RAM.

Tabla 16. Registros significativos. Esta función maneja un puntero haciéndolo recorrer un total de 128 registros en total. Se obtiene el valor del byte recibido del registro auxiliar y se escribe en la posición que toca. Inmediatamente se incrementa el puntero para que apunte a la siguiente posición de memoria. 4.10.6 Escritura en la memoria FLASH: SALVAR. Como ya se ha especificado, para guardar en la memoria FLASH es necesario deshabilitar interrupciones y interrumpir el flujo de comunicación. La escritura en memoria FLASH puede tardar típicamente 4ms y las recepciones deberían llevarse a cabo cada 1ms aproximadamente. Si no interrumpiésemos el flujo perderíamos gran cantidad de la información. Por otro lado, la grabación no puede realizarse por bloques sino que se ha de hacer por palabras. La necesidad de interrupción de flujo por tanto es evidente. La función DIS_RTS pondrá a 1 la señal RTS, desasertándola, con lo que el dispositivo con el que estamos comunicando entenderá una orden de parada de flujo de datos. La función STANDBY guardará el valor del timer en un registro auxiliar dado que, por hardware, este timer no se para nunca y hemos de considerar que al parar el flujo de datos, se han de congelar los errores por exceso de tiempo. DRAM es la función recíproca de ARAM, ya que lee del buffer de 128 bytes progresivamente y guarda el valor en el registro STORE. SAVEINF escribirá en FLASH el dato que previamente se ha leído de STORE y se ha almacenado en los registros EEDATA y EEDATAH. Las escrituras se sucederán hasta que se haya recorrido todo el buffer de 128 posiciones. La función ENA_RTS habilita el flujo de datos, reseteando la señal RTS. COMEON restablecerá el timer al valor anterior al paro del flujo para que el control de exceso de tiempos vuelva a las condiciones anteriores.

SALVAR CALL DIS_RTS ;Se desaserta la señal RTS. CALL STANDBY ;Se congelan los valores de timer. BANKSEL SAVED_IN_FLASH INCF SAVED_IN_FLASH,F ;Se incrementa el contador de ;datos salvados en FLASH. BCF STATUS,IRP CALL DRAM ;Se lee del buffer de 128 bytes. BUCLE BANKSEL STORE

MOVF STORE,W BANKSEL EEDATA MOVWF EEDATA

4. Especificaciones Software

CLRF EEDATH CALL SAVEINF ;Se salva en FLASH. BANKSEL EEADR

INCFSZ EEADR,F ;Se incrementa dirección de FLASH. GOTO NO_HI INCF EEADRH,F NO_HI CALL DRAM ;Se vuelve a leer del buffer, haciendo MOVLW H'21' ;esto hasta que se acabe el buffer. BANKSEL PTRO_BUF_RC XORWF PTRO_BUF_RC,W BTFSS STATUS,Z GOTO BUCLE BANKSEL AD_REC MOVF AD_REC,W

MOVWF PTRO_BUF_RC ;Reinicialización del puntero. CALL ENA_RTS ;Se aserta la RTS. BTFSC COM_STATUS,INPROG GOTO SEGUIR BCF INTCON,T0IE BCF INTCON,PEIE RETURN SEGUIR CALL COMEON ;Se restituye el valor del timer. RETURN

Código 9. Función SALVAR

4.11 Temporizaciones. Durante el desarrollo del protocolo en el que trabajamos, pueden surgir discrepancias o algún tipo de error espúreo que deje el código en un estado imprevisto. Esto puede llevar al estancamiento de la comunicación, o como se suele decir vulgarmente, a que el sistema se “cuelgue”. Por ejemplo, si no se recibe ningún dato (sea información o handshake) el sistema se dispondría en espera del mismo durante un tiempo indefinido. Este fallo, sin ir más lejos, puede ocurrir cuando un byte se pierde en el transcurso de la transmisión. El emisor envía un paquete y espera el reconocimiento. El reconocimiento es enviado por el receptor pero se pierde. Entonces el emisor esperaría indefinidamente el reconocimiento y el receptor el siguiente paquete. Esto está previsto por el protocolo que especifica lo que se llaman TIMEOUTS o excesos de tiempo. Un error por exceso de tiempo, implica que emisor o receptor no hayan intercambiado información en un determinado tiempo suficientemente amplio como para asegurar que se haya producido una situación de excepción. Por ello deberemos medir tiempos de alguna manera. El PIC dispone de un timer (de más de uno en realidad) interno que nos servirá para poder conocer tiempos entre sucesos y poder valorar acontecimientos de este tipo. Una vez configurado el periférico nos indicará mediante interrupciones, o mediante un flag

4. Especificaciones Software

específico, si ha transcurrido un determinado tiempo. Posee un registro que va incrementando progresivamente hasta que este se desborda y genera una interrupción. Dicha interrupción será atendida por una RSI que cuente la cantidad de unidades de tiempo que va marcando el timer. De esta manera se lleva el control del tiempo transcurrido hasta un cierto valor.

Figura 25. Funcionamiento del sistema de temporizado. 4.11.1 Control del temporizador. El control del periférico se puede realizar de muchas maneras. Existen varias configuraciones posibles que ofrecen diversas posibilidades al usuario.

Código 10. Rutina de inicialización del timer.

HABILITACIÓN

HABILITACIÓN

RESET

RESET

CONTADOR SOFTWARE

TIMER (PERIFÉRICO)

DESBORDAMIENTO = INTERRUPCIÓN

CUENTA TOTALIZADA = ERROR

INI_T BANKSEL OPTION_REG MOVLW H'07' ;Configuración del timer. MOVWF OPTION_REG BANKSEL TICST MOVLW .200 ;Variable de control de periodos que MOVWF TICST ; servirá para contar a partir de una base

;de tiempos. (TICST= transmisión, TICSR= ;recepción)

MOVLW .60 MOVWF TICSR MOVLW .10 ;Cuenta los errores que se producen, bien MOVWF ERRTX ;sea en transmisión (ERRTX) o en recepción ;(EERRX). MOVLW .3 MOVWF ERRRX RETURN

4. Especificaciones Software

En nuestro caso distinguiremos 3 rutinas. Como punto de inicio, emplearemos una rutina de configuración: INI_T. En este nos limitaremos a configurar el timer mediante su registro de configuración correspondiente. Destacaremos la configuración del prescaler a un rango de 1:256. Esto quiere decir que si bien el timer se alimenta con una frecuencia igual a Fosc/4 ( Frecuencia del cristal externo / 4 ), cada 256 pulsos de esta frecuencia se incrementará una cuenta el registro TMR0. Implementaremos dos rutinas más: una de “puesta en marcha” (ON_T) y otra de “desactivación” llamada OFF_T. Se escriben entre comillas estas palabras porque, como ya hemos dicho, el periférico temporiza de manera continuada. Su funcionamiento estriba en el incrementando un registro particular TMR0. La utilidad de estas dos últimas rutinas es la de habilitar y deshabilitar la petición de interrupción del timer. En el caso de ON_T resetearemos el flag de interrupciones propio del timer, en previsión de que estuviera activo. Además, introduciremos el valor correspondiente en el registro TMR0 para que el timer pida interrupción pasado el tiempo deseado (que será de 50ms en este caso). Finalmente habilitaremos la petición de interrupciones. Si no habilitásemos, el timer se desbordaría pero no pediría interrupción, con lo que no ejecutaríamos código alguno. La rutina OFF_T es todavía más simple. Su única función es la de deshabilitar las peticiones de interrupción y resetear el flag correspondiente.

Código 11. Habilitación de petición de interrupciones del timer.

Código 12. Deshabilitación de petición de interrupciones del timer. 4.11.2 Habilitaciones: ENAOUTR y ENAOUTT La labor desarrollada por estas dos funciones consiste en “encender” el timer (habilitar el servicio a la interrupción correspondiente), si no está activado ya. Para ello, ejecutan la función ON_T en caso de que no se haya ejecutado de manera previa. Es decir, si ejecutásemos ENAOUTR y más tarde ENAOUTT, la segunda función no haría una llamada a la subrutina ON_T. La primera rutina en ejecutarse sería la que llamase a la función. Estas dos rutinas vienen a habilitar el control de excesos de tiempo de transmisión

ON_T BANKSEL TMR0 CLRF TMR0 ;Se limpia el registro del timer

BCF INTCON,T0IF ;Se resetea el flag propio. MOVLW H'3D' ;Escribiendo este valor el timer

MOVWF TMR0 ;desbordará cada 50ms aproxima- BSF INTCON,T0IE ;mente. RETURN

OFF_T BCF INTCON,T0IF ;Se resetea el flag de desbordamiento. BCF INTCON,T0IE ;Se deshabilitan las interrupciones ; del timer. RETURN

4. Especificaciones Software

y de recepción, con lo que el timer ha de estar activo cuando uno de los dos controles esté habilitado. El valor de un bit (uno para emisión y otro para recepción) indicará si está habilitado el control de errores por exceso de tiempo (de una y de otra vertiente). Como se puede ver, estos bits pertenecerán al registro COM_STATUS y serán denominados: ENA_TEMI y ENA_TREC.

Figura 26. Lógica de rutinas de habilitación. Además de la función de manejo del timer, estas dos rutinas inicializan variables de contado. Remarcando el caso del receptor, se puede decir que existen dos posibles inicializaciones de variables, dado que la recepción se inicia en modo CRC y de no ser fructuosa se continúa en modo Checksum. La función RESOUTR reinicializa las variables del contado de recepción, es una variable de ENAOUTR que se utiliza durante el transcurso de las recepciones.

Código 13. ENAOUTR. La rutina ENAOUTT es análoga.

ENAOUTR BSF COM_STATUS,ENA_TREC BTFSS COM_STATUS,ENA_TEMI ;En caso de que el timer no esté CALL ON_T ;trabajando ya para el control de

;de errores de transmisión, debe ;”encenderse”.

BANKSEL TICSR BTFSC AUXILIAR,FIRST_CHAR GOTO NO_F MOVLW .60 ;Inicialmente, los valores para los tics y los MOVWF TICSR ;contados de errores en recepción serán 60 y 3. ;Cuando ya se ha recibido el primer carácter MOVLW .3 ;serán 200 y 10 como se puede ver. Esto es MOVWF ERRRX ;porque primero se envía el carácter “C” cada ;3 segundos y después el NAK cada 10. Así se RETURN ;ajusta el contado de la base de tiempos. NO_F MOVLW .200 ;Los valores 3 y 10 corresponden al número de MOVWF TICSR ;caracteres “C” y NAK que se enviarán como ;máximo. MOVLW .10 MOVWF ERRRX RETURN

4. Especificaciones Software

4.11.3 Deshabilitaciones: DISOUTR y DISOUTT. Estas dos rutinas tienen la función de desactivar el servicio de las peticiones de interrupción provenientes del mismo. El funcionamiento de las dos es análogo. En recepción (DISOUTR), la rutina ejecutará OFF_T en caso de que no se esté utilizando el timer para controlar los excesos de tiempo de emisiones. Esto funciona también de manera recíproca. Como es lógico en cada función se resetean los valores de los bits de información correspondientes, ubicados en el registro COM_STATUS.

Código 14. Deshabilitación de transmisión. La rutina de recepción es análoga.

Figura 27. Lógica de rutinas de deshabilitación. 4.11.4 Desarrollo de los servicios a excesos de tiempos. Se utiliza únicamente un timer TMR0 para el control de los excesos y dos contadores, uno para cada tipo de error (emisión/recepción) de manera independiente. La razón de esto viene a ser que el timer es un periférico hardware que al utilizarlo dejará de estar disponible para la utilización en el proyecto generalizado que utilice nuestro código. Sin embargo, los contadores software únicamente utilizan algunos recursos de propósito general. Como solo se utiliza un timer, solo tendremos un tipo de interrupción generada por el mismo al desbordarse. Hará falta distinguir entre los dos tipos de errores por exceso de tiempo, entre si un tipo está habilitado o no y, en algunos casos, también diferenciar si se ha servido o no. Las funciones anteriormente descritas de activación y desactivación del servicio de estos errores son las que, como su nombre indica, los habilitan y deshabilitan. Todo esto visto desde un punto de vista software. Como se puede ver en la Figura 28, existen dos posibilidades en el servicio de los excesos de tiempo. En la primera tendremos habilitados uno o los dos errores, mientras que en la segunda solo tendremos habilitados los errores de transmisión. La prioridad que otorgamos al ejecutarse primero una rutina y luego la otra es del todo arbitraria. Para no dar por servida la interrupción, basta con no resetear el flag correspondiente. De esta manera, al salir de la RSI general, se habilitarán de manera automática las interrupciones y volverá a asertarse la correspondiente al timer, que volverá a ser servida de inmediato.

DISOUTT CALL LA1OFF ;Se resetea LED.

BCF COM_STATUS,ENA_TEMI ;Bit booleano de información ;para otros puntos de código. BTFSS COM_STATUS,ENA_TREC ;Si se desea deshabilitar el CALL OFF_T ;control de errores de TX

;y los de RX están ya ;habilitados, no se utilizará

;para nada el timer. Se des- RETURN ;habilitan las interrupciones

4. Especificaciones Software

Figura 28. Servicio de los excesos de tiempo.

Código 15. Manejo de los dos tipos de errores.

NOMBRE DESCRIPCIÓN

PASSED Bit de carácter booleano. Manejado por la rutina TOUTR indica si se ha ejecutado esta rutina en el transcurso del servicio de una interrupción. En caso de haberse ejecutado y

INTERRUPCIÓN DEL TIMER 0!!

HABILITADO ERROR POR EXCESOS EN RECEPCIÓN.

EJECUCIÓN DE RUTINA DE RECEPCIONES.

NO HABILITADO ERROR POR EXCESOS EN TRANSMISIÓN.

FINALIZAR EL SERVICIO DE LA INTERRUPCIÓN.

HABILITADO ERROR POR EXCESOS EN TRANSMISIÓN.

NO FINALIZAR EL SERVICIO DE LA INTERRUPCIÓN. SE VOLVERÁ A EJECUTAR LA RSI.

EJECUCIÓN DE RUTINA DE TRANSMISIONES.

2º FINALIZAR EL SERVICIO DE LA INTERRUPCIÓN.

TOUT BANKSEL TMR0 MOVLW H'3D' ;Restablecimiento del valor del MOVWF TMR0 ;timer de antes de desbordarse. BTFSC COM_STATUS,PASSED GOTO RECOK BTFSC COM_STATUS,ENA_TREC ;En caso de habilitadas las GOTO TOUTR ;recepciones se ejecuta la ;rutina correspondiente. RECOK BTFSC COM_STATUS,ENA_TEMI ;Lo mismo para los excesos de GOTO TOUTT ;tiempo de las emisiones. GOTO FIN

4. Especificaciones Software

estar habilitada la rutina de transmisión se pasará directamente a ejecutar dicha rutina.

TOUT Rutina general a la que se salta tras una interrupción de timer. Todo esto siempre y cuando las interrupciones de timer estén habilitadas.

TOUTR

Rutina específica que gestiona los errores por exceso de tiempo en la recepción. Esta rutina maneja un contador software de tal manera que pueda calcular tiempos. Una vez pasados estos tiempos y registrados, realiza las acciones descritas en la teoría.

TOUTT

Rutina que gestiona los errores por exceso de tiempo en la transmisión. De funcionamiento análogo a la anterior. Cuenta tiempos diferentes como es lógico y realiza acciones específicas de los errores que maneja.

Tabla 17. Variables y rutinas relevantes para el desarrollo de los excesos de tiempo.

Cabe destacar que la función TOUTR es la que se encarga de enviar los bytes iniciales de sincronismo para que dé comienzo la transmisión. En nuestro código en particular, se realizarán 3 envíos consecutivos del carácter “C”, con un desfase entre ellos de 3 segundos. Si entre estos caracteres se recibiera un paquete entrante, se dejarían de enviar. En caso de enviarse los 3 y pasar los 3 segundos finales, el sistema entendería que debe cambiar a modo checksum. Probablemente el sistema remoto con el que se quiere comunicar entiende solo un protocolo checksum y no CRC. En este punto se inician los envíos de caracteres NAK separados por un desfase de 10 segundos. En caso de realizar 10 envíos y no recibir paquetes entrantes, se asumiría un problema irrecuperable con las comunicaciones y el sistema encendería un LED para comunicarle el estado al usuario. De esta manera, nuestro sistema es capaz de comunicarse con dispositivos que utilices cualquiera las dos versiones del protocolo XModem.

5. Hardware

5.1 Objetivos Para poder ofrecer un mínimo de confianza sobre un diseño como el que nos ocupa, es necesario comprobar su funcionamiento. Para ello se puede realizar un proyecto piloto o prototipo que sirva para probar directamente la funcionalidad. Nuestro prototipo consistirá en un pequeño diseño hardware centrado en el PIC que nos ocupa. Por tanto, el mismo microcontrolador nos marcará en gran medida la necesidad de componentes adicionales. El circuito que se diseñe deberá permitir la comunicación bidireccional entre el PIC y otro dispositivo mediante el canal serie. Se buscará seguir el estándar RS-232 en esta comunicación por lo que deberemos utilizar un conector normalizado y una etapa de adaptación de niveles de tensión. Todo ello deberá estar alimentado con un sistema que sea coherente con el consumo del PIC y el resto de componentes, que previsiblemente no será muy alto. Finalmente, dispondremos un mínimo entorno de comunicación con el usuario de tal manera que se pueden advertir situaciones de excepción y errores por parte del mismo. De la misma manera ha de servir para mostrar la correcta evolución de la comunicación.

Figura 29. Funcionamiento general.

5.2 Sistema de alimentación

COMPONENTE VALOR/ESPECIFICACIÓN D5 1N4004 C14 47 uF (electrolítico) C15 100 nF C16 100 nF D6 LED de 3mm de color verde

J1 Regleta de dos contactos para soldado sobre placa

SW3 Interruptor de carácter general

L7805 (U5)

Regulador de tensión. El encapsulado puede ser TO-220 u otro, no siendo necesario un encapsulado para gran

disipación de potencia.

uC

ETAPA

DE

ACCESO AL

MEDIO FÍSICO

(MAC)

CONECTOR

CIRCUITERÍA NECESARIA PARA EL FUNCIONAMIENTO

DEL UC.

SISTEMA

DE MANIOBRA Y DE

INTERCAMBIO DE INFORMACIÓN

CON EL USUARIO.

5. Hardware

R6 1 K Ω

Tabla 18. Componentes del sistema de alimentación referenciados al esquema general. El diseño gira en torno al regulador 7805; que dispone de limitación interna de corriente y protección contra sobrecalentamiento. Dicho regulador ofrece un rango de voltaje de salida de 4,75V a 5,25V.

Figura 30. Pines del regulador 7805 dispuestos en el encapsulado TO-220 Por lo que respecta al resto del circuito, el diodo D5, previene de inversiones de polaridad, que puedan ocasionar cualquier desperfecto circuital. Los condensadores C15 y C16 implementan polos dominantes necesarios para estabilizar el regular, dado que en base es un circuito realimentado. El C14 implementa un filtro paso bajo para la entrada del regulador. El LED (verde de 3mm) formaría parte del “Sistema de intercambio de información con el usuario”, indicando que la placa está alimentada. La resistencia R situada en serie limita la intensidad que circula a través del LED a unos 3,3 mA. Es necesario calcular la disipación térmica del regulador, de tal manera que podamos asegurar que no será más elevada que el valor máximo especificado por el fabricante. Si esto pasara, el regulador se destruiría. Inicialmente tomaremos los consumos de cada uno de los elementos disipativos del circuito. En el caso de que no podamos saber el consumo instantáneo contemplaremos el peor caso: el consumo máximo.

COMPONENTE CONSUMO (MA)

CONSUMOS DEL SISTEMA DE ALIMENTACIÓN

LED de 3 mm verde 3,3

CONSUMOS DEL PIC Y SI CIRCUITERÍA ADICIONAL Alimentación del PIC (Vdd) 250 (máx.)

Interruptor puerto RA4 25 (máx.)

CONSUMOS ETAPA ST232 Alimentación de los integrados 15 (máx.) * 2 integrados = 30

TOTAL 308,3

Tabla 19. Consumos.

La potencia disipada por el regulador será:

5. Hardware

donde V es la tensión caída entre los terminales de entrada y de salida e I la intensidad de salida, que es la misma que la que consume el circuito. Observando las hojas de características del fabricante podemos obtener la resistencia térmica entre la unión-encapsulado y la unión-aire. Mediante la ecuación de disipación térmica tenemos que: Donde T es la temperatura máxima a la que trabajará nuestro dispositivo en el peor de los casos. Esta temperatura no supera los +125ºC marcados por el fabricante como temperatura máxima de funcionamiento por lo que no será necesaria ningún tipo de ayuda externa para la disipación de calor. En cualquier caso montaremos el regulador atornillándolo sobre una superficie de cobre aislada del resto del circuito. Esta superficie no será atacada a la hora de fabricar el circuito y formará parte de la misma placa de baquelita.

5.3 Microcontrolador y circuitos necesarios su funcionamiento. 5.3.1 PIC 16F876 Utilizaremos parte de los puertos A, B y C del PIC. El criterio de uso será simplemente el de utilizar lo más óptimamente posible el micro, sin malgastar periféricos o implementar utilidades superfluas. El proyecto en si debe formar parte de otro más generalizado y completo. Si empleásemos muchos recursos en la parte de comunicaciones (o sea en el proyecto que nos ocupa), el proyecto general en el que se utilizaría el nuestro debería ser muy limitado. Utilizando pocos, podremos utilizar nuestro sistema de comunicaciones en un número más amplio de proyectos. Por otro lado, la utilización de estos pines responde al desarrollo de una aplicación concreta para la demostración del funcionamiento del código y que puede o no tener que ver con el proyecto generalizado del que hablamos. En otros casos, algunos de los pines utilizados podrían ser diferentes. En caso de que queramos ampliar el presente proyecto o aplicarlo a un diseño determinado deberemos tener en cuenta los recursos utilizados y por esa razón se justifican en este apartado. De esta manera queda clara la optimización del uso del PIC. Utilizaremos 3 pins del puerto A, con lo que limitaremos el número de canales del conversor A/D disponibles y desposeeremos al PIC de entrada para “clock” externo del TMR0 (T0CKL). También utilizaremos 5 pines del PORTB dado que disponen de sistemas de interrupción al cambio de bit y de interrupción externa. Esto nos será muy útil en la implementación del código. Como contrapartida, nuestro PIC dispondrá de menos pines de este tipo para utilizarlos en otras aplicaciones. Para acabar utilizaremos 2 pines del PORTC. Estos corresponderán a las señales de transmisión (TX) y recepción (RX) de la USART interna del PIC, con lo que su utilización es ineludible.

WIVP 31,110·3.308)·75,49(· 3 =−== − (10)

( )

CTT

WC

WCWCT

RPT

º7,1137,9122

º65º5·31,1º22

·

==−

+=−

=∆

∑∑

(11)

5. Hardware

Además de todo esto se utilizan:

• Parte de la memoria FLASH: donde se aloja el programa y otras informaciones. • Parte de la memoria EEPROM: donde se guarda información referente a las rutinas

de conexión/desconexión y a la de checksum inicial. • Diversos registros de la memoria RAM: donde se implementa un buffer de

recepción de 128 bytes y todos las variables necesarias para el desarrollo del programa.

• El timer 0: que se emplea para implementar las diversas actuaciones por errores de exceso de tiempo, entre otras cosas.

5.3.2 Circuito oscilador

Figura 31. Esquema de conexionado del circuito oscilador.

Los componentes utilizados son los siguientes:

COMPONENTE VALOR C8/C9 15pF

X1 4MHz

Tabla 20. Componentes del circuito oscilador. Sabiendo el valor del cristal de cuarzo requerido, se ha extraído el valor de los condensadores necesarios de tablas de las hojas de características del propio microcontrolador (pag. 122 del datasheet) . El microcontrolador puede trabajar a una frecuencia máxima de 20MHz. Es desaconsejable utilizar un cristal de esa frecuencia. Una de las razones es que hacer trabajar a esa frecuencia al micro lo haría mucho más sensible al ruido. Por otro lado, a 20MHz se limita el rango de voltaje de entrada entre 4,5-5,5V; mientras que para 4MHz sería de 4,0-5,5V. Finalmente y como razón fundamental, remarcaremos que no es necesaria ni mucho menos una frecuencia similar. Con un valor de 4MHz como el utilizado tendremos margen temporal suficiente para el manejo de la información manteniendo una disciplina de envío constante mediante el trabajo de USART a 9600 bps. 5.3.3 Circuito de reset El PIC experimenta un reset de encendido (Power-On) cuando se detecta un flanco de subida en el rango de 1,2 a 1,7 V en el pin MCLR. A priori no es necesario utilizar

5. Hardware

pequeños circuitos RC para controlar este reset por parte del usuario (maniobras de reset). Basta con un pulsador y un divisor de tensión para este fin. Alimentando el conjunto, el usuario podrá resetear el dispositivo cuando tenga necesidad. Se observa, por otro lado, una limitación máxima de tiempo de subida (flanco ascendente) de la señal de 0,05V/ms. Esta limitación deberá ser cumplida para el correcto generado del reset. Para asegurar esto, nos serviremos de un condensador conectado en paralelo con el pin MCLR. De esta manera, fijaremos el incremento del voltaje sin importar el tipo de alimentación que se le aplique al equipo. En definitiva, si que utilizaremos un circuito RC. En el circuito que se muestra en la figura, hemos utilizado los componentes anteriormente nombrados. Analizándolo superficialmente posiblemente llegaríamos a la conclusión de que la resistencia de 100 Ω es superflua, dado que necesitamos provocar un flanco de subida dentro de un determinado rango de voltaje. Esto no es del todo cierto, dado que esta resistencia no se usa con la finalidad expuesta sino que tiene otra utilidad. Cuando se produce un pico de tensión de valor inferior a Vss en el pin MCLR, esto induce una corriente mayor de 80mA en el pin. Esto puede provocar el borrado del “latch” (latch-up). Por eso, el fabricante recomienda la utilización de una resistencia de 50-100 Ω en serie con el nodo común (para la aplicación del nivel bajo). Esto es más recomendable, por lo tanto, que aplicar directamente la tensión Vss. Deberemos calcular el valor del condensador que asegure una pendiente de subida de tensión en el pin no superior a la indicada. La ecuación que describe la tensión en el pin a partir del momento en el que se suelta el pulsador es la siguiente: Si consideramos que la tensión llega a su nivel estacionario (5V) en un tiempo denominado

τ4 y que CR ·1=τ tendremos las siguientes gráficas:

Figura 31. Gráfica del incremento de tensión máximo y del fijado por el condensador.

5·95,4 ·1 +−=−

CRt

MCLR eV (12)

5. Hardware

Si contemplamos una pendiente de msv /05,0 tendremos la gráfica de la derecha. Con una simple regla de tres podremos averiguar cuanto tiempo tardaría en alcanzar el valor estacionario de 5v. La gráfica de la izquierda corresponde a la tensión que varía en bornes del condensador. Según el valor del condensador que conectemos podremos forzar el tiempo en que tardará en llegar al estado estacionario la tensión. Si deseamos una pendiente máxima como la indicada, la gráfica de la izquierda deberá quedar por debajo de la de la derecha. Calcularemos seguidamente cual ha de ser el valor del condensador para que se cumpla la condición anterior:

En conclusión: conectando un condensador de una capacidad igual o mayor a la indicada obtendremos subida de tensión que será inferior a la de la gráfica de la derecha. Esto nos viene obligado por el fabricante. Finalmente elegiremos un valor comercial de 4,7uF para el condensador.

COMPONENTE VALOR

SW2 Pulsador de uso general R4 10K Ω R7 100 Ω C20 4,7 uF

Tabla 21. Componentes del circuito de reset. Siempre referenciados al esquema general.

5.3.4 Circuitos de señalización de averías y maniobra Utilizaremos dos circuitos de señalización de averías formados por un LED y una resistencia cada uno. Estos estarán conectados entre el pin RA0/RA1 (respectivamente) y masa, de tal manera que el encendido será controlado directamente por software. Además, se utilizará un determinado código de frecuencias de encendido y apagado con el fin de diferenciar los errores posibles en cada caso, bien sean software o hardware. De esta manera se establece un interfaz de intercambio de información con el usuario.

COMPONENTE VALOR R1/R2 1K Ω D1/D2 LED’s rojos de 3mm SW1 Conmutador

Tabla 22. Componentes del circuito interfaz.

El LED1 permitirá que el usuario se dé cuenta de que el sistema incurre en un fallo de hardware, como pueda ser un error del checksum de FLASH. En el caso de lucir el LED2 nos encontraríamos con un fallo de software, que bien puede venir dado por un fallo irrecuperable por secuencia incorrecta de paquete. Como en el caso anterior, las resistencias en serie nos limitan la intensidad que pasa a través de los LED’s a un valor de 3,3mA. De esta manera prevenimos el deterioro de los LED’s y disminuimos el consumo.

FCC

msCR

µ

τ

5,210·100·40000

100··4·43

1

≥≥

≥=− (13)

5. Hardware

Además, mediante el conmutador SW1 podremos configurar el funcionamiento del programa distinguiendo entre dos estados, el de establecimiento de comunicación y el de espera de llamada. Con lo cual estamos ante el tercer circuito de esta índole (la de interfaz con usuario). Por otro lado, dispondremos de dos LED’s más que nos indiquen que la comunicación está produciéndose. Estos diodos irán conectados directamente a las señales Rx/Tx en la parte correspondiente a los niveles RS-232. De esta manera podremos observar un rápido parpadeo durante la transferencia de información. Buscaremos una resistencia que colocada en serie con dichos diodos luminosos y considerando el voltaje de niveles RS-232 deje pasar una intensidad a través de ellos similar a la de los anteriores casos, es decir 3,3mA. Considerando un voltaje típico (por hoja de características) de 7,8V y una caída de tensión en el diodo de 3mm de 1,7V obtendremos un valor para la resistencia de 1848,48Ω . El valor comercial más aproximado a esta cifra es de 1800 Ω y esta será la resistencia utilizada. Con esta resistencia fijaremos la intensidad que pasa a través de los diodos a 3,4mA aproximadamente. Esta variación de intensidad será inapreciable en cuando a luminiscencia se refiere, con respecto a los otros LED’s.

COMPONENTE VALOR

R3/R5 1K8 Ω D3/D4 Amarillos de 3mm

Tabla 23. Componentes para el circuito de los LED’s que indican transcurso de comunicación.

5.4 Etapa de acceso al medio físico y conector. Esta etapa se basa en el integrado ST232. Este integrado lo componen dos drivers y dos receptores que adaptan determinados niveles de tensión al estándar RS232. El voltaje de salida de los transmisores (o drivers) será de ± 7,8V tipicamente. El rango de voltaje de entrada permisible en los receptores será de ± 30V. Su alimentación puede oscilar entre 4,5 y 5,5V y la corriente que se le debe suministrar no será superior a 10mA.

COMPONENTE VALOR C5/C6/C10/C11/C7/C12/C13/C17/C18 1Uf (electrolítico)

1MAX232/2MAX232 ST232 (o compatible) P1 Conector DSUB de 9 pines

Tabla 24. Componentes de la etapa de acceso al medio y conector.

La velocidad típica de funcionamiento es de 220Kbps. Nosotros utilizaremos hasta 9K6 bps por lo que también este parámetro nos es del todo suficiente. El chip ST232 así también como otros compatibles, como el MAX232, pueden necesitar de la aplicación de algunas capacidades para el correcto funcionamiento de los mismos. En nuestro caso necesitaremos 5 capacidades para cada chip. Una de estas capacidades se situará en paralelo con la alimentación. Esta capacidad tiene la finalidad de implementar un filtro paso bajo para la tensión de alimentación. Por este motivo, aunque utilicemos 2 chips ST232, solo utilizaremos una capacidad de este tipo que filtrará la alimentación de ambos. Por lo que respecta al conexionado, nos encontramos ante un conector DSUB de 9 pines, que sigue la norma RS-232.

Anexo I: Solución circuital adoptada

La solución total adoptada es la que se muestra a continuación. En estas figuras aparecen el esquema total del circuito, la lista de componentes y la distribución de los mismos, así también como la disposición de las pistas. CANTIDAD REFERENCIA VALOR

9 C5,C6,C7,C10,C11,C12,C13,C17,C18 1u 2 C8,C9 15p 1 C14 47u 2 C16,C15 100n 1 C20 4,7u 5 D1,D2,D3,D4,D6 LED (3 mm) 1 J1 Regleta de dos contactos. 1 P1 Conector DSUB (9 pines) 3 R1,R2,R6 1K 2 R3,R5 1K8 1 R4 100 1 R7 10K 2 SW3,SW1 Conmutador de 3 contactos 1 SW2 Pulsador de 2 contactos 1 U2 PIC16F876 2 U3,U4 ST232 (o compatibles) 1 U5 Regulador 7805 1 X1 Cuarzo de 4MHz 1 D5 1N4004

Tabla 26. Lista total de componentes.

VCC

R5

1k8

P1

CONNECTOR DB9

594837261

SW3

12 3

J1

CON2

12

SW1

12

3

VCC

R4

10k

U4

MAX232

138

1110

134526

129

147

1615

R1INR2IN

T1INT2IN

C+C1-C2+C2-V+V-

R1OUTR2OUT

T1OUTT2OUT

VC

CG

ND

C1447u

R1

1k

R3

1k8

D4

LED

C204,7u

U5L7805/TO220

1

2

3VIN

GN

D

VOUT

C15100n

D6

LED

X14MHz

R7

100

VCC

C13

1u

C815p

1N4004

DIODE

SW2

12

D3

LEDC71u

C51u

C17

1u

D1

LED

U2

PIC16F876

1

234567

8

9

10

1112131415161718

1920

2122232425262728

MCLR

RA0RA1RA2RA3

RA4/TOCKIRA5/SS

Vss

OSC1/CLKIN

OSC2/CLKOUT

RC0/T1OSO/T1CKIRC1/T1OSI/CCP2

RC2/CCP1RC3/SCK/SCLRC4/SDI/SDA

RC5/SDORC6/TX/CKRC7/RX/DTV

ssV

DD

RB0/INTRB1RB2RB3RB4RB5RB6RB7

C16100n

U3

MAX232

138

1110

134526

129

147

1615

R1INR2IN

T1INT2IN

C+C1-C2+C2-V+V-

R1OUTR2OUT

T1OUTT2OUT

VC

CG

ND

C121u

C10

1u

R2

1k

C915p

VCC

C18

1u

D2

LED

VCC

VCC

C11

1u

VCC

R6

1k

VCC

VCC

C6

1u

jmare
Figura 32. Esquema Total del circuito
jmare
Figura 33. Esquema total de la placa
jmare
Figura 34. Distribución de los componentes
jmare
jmare
Figura 35. Disposición de las pistas

Anexo II: Código

#include <p16f877.inc>

__CONFIG _CP_OFF & _WDT_OFF & _BODEN_OFF & _PWRTE_OFF & _XT_OSC & _WRT_ENABLE_ON & _LVP_OFF &_DEBUG_OFF & _CPD_OFF

COMP_RX MACRO VALOR, SALIDAMOVLW VALORXORWF RX_STATUS,WBTFSC STATUS,ZGOTO SALIDAENDM

COAUXRC MACRO VALOR2, SALIDAMOVLW VALOR2XORWF AUXRC,WBTFSC STATUS,ZGOTO SALIDAENDM

RESPU MACRO COLORMOVLW COLOR

BTFSC TX_STATUS,SND_NOTHANDGOTO $+6BANKSEL AUXTXMOVWF AUXTXCALL ON_RSIGOTO FIN

BSF TX_STATUS,HAND_BY_RECEPBANKSEL HANDSHAKEMOVWF HANDSHAKE

GOTO FINENDM

;BITS DEL PORTA/B PARA RS-232

CD EQU .0 ;Carrier DetectDSR EQU .1 ;Data Set ReadyRTS EQU .2 ;Request To SendCTS EQU .3 ;Clear To SendDTR EQU .4 ;Data Terminal Ready

;BITS DEL GPR "AUXILIAR"

FIRST_CHAR EQU .2 ;Indicador de recepción del primer carácter.L1INT EQU .6 ;Indicador de LED encendido de manera intermitente.FINENVIOS EQU .7 ;Indicador de que se han enviado todos los bytes.

;BITS DEL GPR "COM_STATUS"

CRC_NOTCHECK EQU .0 ; Configuración de las comprobaciones 1->CRC / 0 ->CHECKSUMWAIT_FOR_NAK EQU .1 ; Estado de espera del bit de sincronismo para enviar / bit ya recibidoSTOP EQU .3 ; Flujo detenido por el dispositivo con el que se comunica ENA_TREC EQU .4 ; Habilitación de timers de TIMEOUT's de receptor ENA_TEMI EQU .5 ; Habilitación de timers de TIMEOUT's de

emisor PASSED EQU .6 ; Bit de control de ejecución de RSI's de TIMEOUT'sINPROG EQU .7 ; Bit que indica comunicación en progreso.

;BITS DEL GPR "TX_STATUS"

SND_NOTHAND EQU .3 ; Estado de envio de un paquete / de un HANDSHAKEHAND_BY_RECEP EQU .4 ; Marca la necesidad de envio de un HANDSHAKEen cuanto sea posibleEOT_SNDED EQU .5 ; "EOT" enviado /no enviado

;BITS DEL GPR "RX_STATUS"

PAQ_NOTOTHER EQU .3 ; Estado de recepción de un paquete/recepciónde cualquier byte...CAN,ACK,NAK,ETC...EOT_RCED EQU .4 ; EOT recibidoPAQ_PRE_ERROR EQU .5 ; Control de errores de secuencia de paquetesPAQ_PRE_ERROR2 EQU .6 ; Control de errores de secuencia de paquetes

;BITS DEL GPR "BUFFERS"

FULLT EQU .7 ;Buffer de transmisión llenoEMPTYT EQU .6 ;Buffer de transmisión vacío.RETORNO EQU .5 ;Retorno en caso de no poder guardar o leer

;por encontrarnos con un buffer lleno o vacío.RETORNOR EQU .4 ;Retorno para las recepciones.EMPTYR EQU .3 ;Buffer de recepción vacío.FULLR EQU .2 ;Buffer de recepción lleno.

;REGISTROS UTILIZADOS POR LA APLICACIÓN DE COMUNICACIONES (BANCO 3)

HANDSHAKE EQU H'190' ; Registro de guardado de un byte de handshake cualquiera

PAQ EQU H'192' ; Valor del paqueteNOT_PAQ EQU H'193' ; Complemento a 1 de PAQCHECK_TXH EQU H'194' ; Byte de comprobación CHECKSUM O alto del valor del comprobación CRC (TX)CHECK_TXL EQU H'195' ; Byte bajo de la comprobación mediante CRC

CONT_PAQ EQU H'196' ; Contador decremental de paquetes enviadosPTRO_ENV EQU H'197' ; Puntero que recorre los diferentes campos precalculados del paquete de envioPTRO_BUF_RC EQU H'198' ; Puntero del buffer de recepción en RAMAD_ENV EQU H'199' ; @ inicial del conjunto de registros que contienen campos de paquetes de envioAD_REC EQU H'19A' ; @ inicial de buffer de RxPAQ_REC EQU H'19B' ; Contador incremental de paquetes recibidos

ERRORES EQU H'19E' ; Contador de Framming Errors y bytes recibidos y "no contemplados"DAT_REC EQU H'19F' ; Contador decremental de .128 (datos a recibir en total)PAQUETE EQU H'1A0' ; Registro para el control de error de secuencia de paqueteCONTADOR EQU H'1A1' ; ¡¡¡¡¡esto irá fuera en breves!!!!!CHECK_RXH EQU H'1A2' ; Byte de comprobación CHECKSUM O alto del valor del comprobación CRC (RX)DATOS EQU H'1A3' ; Contador decremental de datos enviados (hasta un total de 128)CHECK_RXL EQU H'1A4' ; Byte bajo de la comprobación mediante CRCAUXTX EQU H'1A5' ; Registro auxiliar de trabajo del byte recibido

;RUTINAS DE MANEJO DE ERRORES POR TIMEOUT

ERRTX EQU H'1A7' ; Contador decremental de errores de TxTICST EQU H'1A8' ; Contador de pulsos en una determinada base de tiempo para la RSI de TxERRRX EQU H'1A9' ; Contador decremental de errores de RxTICSR EQU H'1AA' ; Contador de pulsos en una determinada base de tiempo para la RSI de Rx

SAVED_IN_FLASH EQU H'1AB' ;Contador de paquetes guardados en memoria FLASH

INFO_CAMPO EQU H'1AF' ; Registro auxiliar para comparaciones en rutina de Tx

TMR0_TMP EQU H'1B2' ; Valor de timer guardado cuando se para la comunicación.

DATA_AD_L_TX EQU H'1B3' ; Byte bajo del puntero de direcciones de FLASH (lectura).DATA_AD_H_TX EQU H'1B4' ; Byte alto del puntero de direcciones de FLASH (lectura).

SND EQU H'1B5' ; Registro auxiliar que guarda byte de datos que se enviará

; CALCULO DEL CRC

ITERA EQU H'1B6' ; Variable local de contadoCRCH EQU H'1B7' ; Variable local de cálculo de CRC (byte alto)CRCL EQU H'1B8' ; Variable local de cálculo de CRC (byte bajo)

STORE EQU H'1B9' ; Pasa un byte de info leido del buffer de 128 bytes.PTRO_RECH EQU H'1BA' ; Puntero de memoria FLASH para la recepción y escritura (H).PTRO_RECL EQU H'1BB' ; Puntero de memoria FLASH para la recepción y escritura (L).

; RUTINA DE MÓDEM

ITERACIONES EQU H'1B9' ; Contador para bases de tiempo.CONTA EQU H'1BA' ; Contador de uso general.PTRO_EEP EQU H'1BB' ; Puntero a memoria EEPROMAD_EEP EQU H'1BC' ; Registro donde se guarda la dirección inicial a memoria EEPROM.

; MANEJO DE BUFFER DE ENTRADA Y SALIDA

VALOR EQU H'1BD' ; Contador de número de veces que se escribe en el buffer.

BTH EQU H'1BE' ; Puntero del buffer de trans., parte más alta.BTL EQU H'1BF' ; Puntero del buffer, parte más baja.BTMAX EQU H'1C0' ; Dirección extrema del buffer de Txen el espacio RAM.BTMIN EQU H'1C1' ; Dirección mínima a la que llega el buffer de Tx en

; el espacio RAM.

BRH EQU H'1C2' ; Puntero del buffer de recep., parte más alta.

BRL EQU H'1C3' ; Puntero del buffer de recep., parte más baja.BRMAX EQU H'1C4' ; Dirección extrema del buffer Rx en el espacio RAM.BRMIN EQU H'1C5' ; Dirección mínima a la que llega el buffer de Rx en

; el espacio RAM.

;A partir de la dirección h'1D0' está el buffer de transmisión de 16 posiciones.

;A partir de la dirección h'110' esté el buffer de recepción de 16 posiciones.

; CHECKLIST INICIAL

CHVALUEL EQU H'1C6' ; Registro acumulativo donde se guarda el valor bajo.CHVALUEH EQU H'1C7' ; Registro acumulativo donde se guarda el valor alto.

;******* CONSTANTES *******

@ENDUP EQU H'06' ; Dirección donde acaba el código, parte alta.@ENDDOWN EQU H'81' ; Dirección donde acaba el código, parte baja.

CR EQU H'0D' ; Retorno de carro.LF EQU H'0A' ; Salto de linea.

POLYH EQU H'10' ; Parte alta del polinomio para CRC.POLYL EQU H'21' ; Parte baja del polinomio para CRC.

SPBRG_VAL EQU .25 ; Valor de Baud Rate Generator

; Handshakes

NAK EQU H'15' ; Not AcknowledgeCAN EQU H'18' ; CancelarACK EQU H'6' ; AcknowledgeSOH EQU H'1' ; Start of HeaderEOT EQU H'4' ; End of Transmision

LONG_DATA EQU .128 ; Cantidad de datos por paquete

;Registros accesibles desde cualquier banco.

RX_STATUS EQU H'71' ; Bits de estado de las recepciones.TX_STATUS EQU H'72' ; Bits de estado de las emisiones.COM_STATUS EQU H'73' ; Bits de estado general de las comunicacionesAUXILIAR EQU H'74' ; Registro auxiliar de bits de estado.AUXRC EQU H'75' ; Auxiliar donde se guarda el byte recibidoSTATUS_TEMP EQU H'76' ; Registros de uso temporal para guardar el contexto durante la ejecuciónW_TEMP EQU H'77' ; de una RSI. Se guardará el registro de STATUS y de W.BUFFERS EQU H'78' ; Registro de control de los buffers.

org 0x2100de "ATZ\rATEQVX3S12=10S2=43\rATDT977205620\r12\r"

org 0x2190de "ATZ\rATEQVS0=2S12=10\r12\r"

org 0x2150

de "+++\r0\rATH\r"

org 0x2170de H'0D',H'0A',H'4F',H'4B',H'0D',H'0A'

org 0x21F0de H'72',H'67'

org 0x1000dw A'E',A's',A't',A'e',A'

',A's',A'i',A's',A't',A'e',A'm',A'a',A' ',A'b',A'a',dw A's',A'a',A'd',A'o',A' ',A'e',A'n',A' ',A'e',A'l',A'

',A'P',A'I',A'C',A' ',dw A'1',A'6',A'F',A'8',A'7',A'6',A' ',A'e',A's',A'

',A'c',A'a',A'p',A'a',A'z',dw A' ',A'd',A'e',A'

',A'c',A'o',A'm',A'p',A'o',A'n',A'e',A'r',A' ',A'p',A'a',dw A'q',A'u',A'e',A't',A'e',A's',A' ',A'c',A'o',A'n',A'

',A'f',A'o',A'r',A'm',dw A'a',A't',A'o',A' ',A'X',A'M',A'O',A'D',A'E',A'M',A'

',A'y',A' ',A'e',A'n',dw A'v',A'i',A'a',A'r',A'l',A'o',A's',A' ',A'a',A'

',A't',A'r',A'a',A'v',A'é',dw A's',A' ',A'd',A'e',A' ',A'u',A'n',A'

',A'p',A'u',A'e',A'r',A't',A'o',A' ',dw A's',A'e',A'r',A'i',A'e',A' ',A'd',A'e',A'

',A'u',A's',A'o',A' ',A'g',A'e',dw A'n',A'e',A'r',A'a',A'l',A'.'

ORG 0x000CLRF PCLATHGOTO MAIN

ORG 0x004GOTO INT

MAINBCF INTCON,GIE ;Deshabilitamos interrupciones.

CALL INIPRT ;Inicialización de los puertos utilizados.

CALL LA1ONCALL LA0ON

CALL CHEQUEA

CALL CONN ;Se llama o se espera una llamada.

CALL INIVAR ;Inicialización de variables y USART.

CALL INIINTE ;Inicialización y configuración de interrupciones.

CALL INI_T ;Inicialización de timer.

CALL ON_RSI

CALL ENAOUTT ;Habilita TIMEOUT de envio porque hay tiempo máximo sin recibir

;el primer caracter de sincronismo del receptor.

CALL ACT_AD ;Inicializa punteros.

MOVLW .13 ;Se especifica el número de bytes con los quese debe llenar RELLEN ;el buffer.

CALL LLENADO

DECFSZ CONT_PAQ,FGOTO MULTIGOTO BUC

MULTIMOVLW .128GOTO RELLEN

BUC

BSF AUXILIAR,FINENVIOS ;Después de esto se acaban los envios.

BTFSS TX_STATUS,EOT_SNDED GOTO $-1

CALL ACT_ADR ;Carga de las direcciones de recepción.

MOVLW A'C'

BTFSC TX_STATUS,SND_NOTHANDGOTO $+6BANKSEL AUXTXMOVWF AUXTXCALL ON_RSIGOTO OUT

BSF TX_STATUS,HAND_BY_RECEPBANKSEL HANDSHAKEMOVWF HANDSHAKE

OUT

CALL ENAOUTR ;Habilitación TIMEOUTS recepción

BUC2BTFSS RX_STATUS,EOT_RCED ;Bucle es espera hasta que se recibe

el EOT.GOTO BUC2

BCF TX_STATUS,EOT_SNDEDBSF COM_STATUS,CRC_NOTCHECKBCF COM_STATUS,WAIT_FOR_NAK

CALL ENAOUTT

BANKSEL SAVED_IN_FLASHMOVF SAVED_IN_FLASH,WMOVWF CONT_PAQ

CLRF AUXILIAR ;Reinicializaciones de variables.CLRF TX_STATUSCLRF RX_STATUS

BANKSEL CRCH

CLRF CRCHCLRF CRCL

CLRF CHECK_RXHCLRF CHECK_RXL

CLRF CHECK_TXHCLRF CHECK_TXL

MOVLW H'20'MOVWF AD_RECMOVWF PTRO_BUF_RC

MOVLW .1MOVWF PAQ_REC

MOVLW LONG_DATAMOVWF DAT_REC

CLRF ERRORES

MOVLW .1MOVWF PAQCOMF PAQ,WMOVWF NOT_PAQ

CALL ACT_ADR ;Enviamos lo que hemos recibido, por tanto cargaremos este puntero.

MOVF CONT_PAQ,W ;Si se han recibido 0 paquetes se va directamente al final.

BTFSC STATUS,ZGOTO BUC3

MOVLW .128 ;Se llena el buffer con los datos a enviar.RELLEN2

CALL LLENADO

DECFSZ CONT_PAQ,FGOTO MULT2GOTO BUC3

MULT2

MOVLW .128GOTO RELLEN2

BUC3 BSF AUXILIAR,FINENVIOS

BTFSS TX_STATUS,EOT_SNDEDGOTO BUC3

MOVLW .80BANKSEL ITERACIONES ;Tiempo prudencial de espera para evitar

interferencias conMOVWF ITERACIONES ;protocolo XModem

PRUDENCALL ON_T2

BTFSS INTCON,T0IFGOTO $-1

BANKSEL ITERACIONESDECFSZ ITERACIONES,FGOTO PRUDEN

CALL DESCONN ;Colgado

BUC4 NOPGOTO BUC4 ;Final de prueba. Bucle indefinido.

SALVAR ;Salva en memoria FLASH los datos contenidos en un buffer de RAM. ;El tamaño es de 128 bytes.

CALL DIS_RTS ;Utiliza el control de flujo para parar los envios y recepciones

;mientras se vacía el buffer en la flash.

CALL STANDBY ;Guarda el valor del TMR0 dado que al parar el flujo se deben parar

;los TIMEOUTS.

BANKSEL SAVED_IN_FLASHINCF SAVED_IN_FLASH,F ;Contador de paquetes guardados.

BCF STATUS,IRP ;Configuración para el direccionamiento indirecto.

CALL DRAM ;Lee del buffer de 128 bytes y lo guarda en el registro STORE.

BUCLE

BANKSEL STORE ;Guarda el byte en el registro de datos para su escritura

MOVF STORE,W ;en FLASH.BANKSEL EEDATAMOVWF EEDATACLRF EEDATH

CALL SAVEINF ;Escribe un word de 14 bits en FLASH con las configuraciones previas.

BANKSEL EEADR ;Incremento de la dirección especificada.INCFSZ EEADR,FGOTO NO_HIINCF EEADRH,F

NO_HI

CALL DRAM ;Va guardando los datos del buffer general derecepción al registro

;STORE.MOVLW H'21'BANKSEL PTRO_BUF_RC

XORWF PTRO_BUF_RC,WBTFSS STATUS,Z GOTO BUCLE

BANKSEL AD_RECMOVF AD_REC,W ;Inicialización del puntero del

buffer

BANKSEL PTRO_BUF_RCMOVWF PTRO_BUF_RC

CALL ENA_RTS ;Mediante el control de flujo se ponen otra vez en marcha las comunicaciones.

;El buffer al completo se ha vaciado en FLASH.

BTFSC COM_STATUS,INPROGGOTO SEGUIR

CALL LA0ON ;La comunicación se ha interrumpido. Comunicamos a usuario y

;paramos indefinidamente el programa.NOPGOTO $-1

SEGUIRCALL COMEON ;Se llena el timer con el valor guardado

anteriormente, si es ;necesario.

RETURN

DIS_RTS ;Rutina que desaserta la señal RTS deshabilitando el flujo de datos.

BANKSEL PORTBBSF PORTB,RTS

BCF INTCON, RBIF

RETURN

ENA_RTS ;Esta rutina aserta la señal RTS si la comunicación se encuentra en curso, con lo que se

;reanuda el flujo de datos si se cumple dicha condición y el modem está listo para recibir.

BANKSEL PORTBBCF PORTB,RTS

BTFSC PORTB,CTS ;Se comprueba que el modem esté listo para recibir.

GOTO $-1

BSF COM_STATUS,INPROG

BTFSC PORTB,CD ;Se comprueba que la comunicación siga en curso.

BCF COM_STATUS,INPROG

BCF INTCON,RBIFRETURN

INTMOVWF W_TEMP ;Se guarda el contexto.SWAPF STATUS,WMOVWF STATUS_TEMP

BTFSS INTCON, T0IF ;Se valora si se trata de una interrupción del TMR0

GOTO NOR_T0BTFSC INTCON, T0IEGOTO TOUT

NOR_T0BTFSS INTCON,RBIF ;Se valora si es una interrupción por cambio

de estado de un bitGOTO NOR_RBS ;del PORTB.BTFSC INTCON,RBIEGOTO RBCHNGE

NOR_RBSBTFSS INTCON,INTF ;Se valora si es una interrupción por el pin

0 de PORTB. (CD)GOTO NOR_ICDBTFSC INTCON,RBIEGOTO RBCHNGE

NOR_ICD

BANKSEL PIR1 ;Se valora si es una interrupción del transmisor de la USART.

BTFSC PIR1, TXIFBSF STATUS,RP0BTFSC PIE1,TXIEGOTO PUT_D

BANKSEL PIR1 ;Se valora si es una interrupción del receptor de la USART.

BTFSC PIR1, RCIFBSF STATUS,RP0BTFSC PIE1,RCIEGOTO GET_D

FIN

SWAPF STATUS_TEMP,W ;Se carga de nuevo el contexto de los registros STATUS (de estado)

MOVWF STATUS ;y el acumulador W.

SWAPF W_TEMP,F ;La carga debe hacerse de esta manera para noalterar el registro de

SWAPF W_TEMP,W ;estado.

RETFIE

TOUT

BANKSEL TMR0MOVLW H'3D' ;La carga de este valor hará que el timer

cuente 30 ms antes de MOVWF TMR0 ;desbordarse.

BTFSC COM_STATUS,PASSEDGOTO RECOK

BTFSC COM_STATUS,ENA_TREC ;En caso de tener habilitadas recepciones se deriva a la

GOTO TOUTR ;rutina correspondiente.

RECOK

BTFSC COM_STATUS,ENA_TEMI ;En caso de tener habilitadas emisiones se deriva a la

GOTO TOUTT ;rutina correspondiente.

GOTO FIN

RBCHNGE ;Rutina que gestiona el control de las señales RS-232: CD y CTS.

BCF INTCON,RBIF

BANKSEL PORTBBTFSS PORTB,CTSGOTO CTS_OK

BANKSEL PIE1BTFSS PIE1,TXIEGOTO NO_DES

CALL OFF_RSI

NO_DES

BSF COM_STATUS,STOP ;Flag que nos indica si hemos modificado el control de flujo

;por indicaciones del modem.GOTO SEE_CD

CTS_OKBTFSS COM_STATUS,STOPGOTO SEE_CD

BCF COM_STATUS,STOP

MOVLW EOTBANKSEL AUXTX ;Las interrupciones solo se deberan

rehabilitar si no ha acabadoXORWF AUXTX,W ;la comunicación. Si ya se había enviado el

EOT la comunicaciónBTFSC STATUS,Z ;ha llegado a su fin.GOTO SEE_CD

CALL ON_RSI

SEE_CDBANKSEL PORTBBTFSS PORTB,CDGOTO CD_OK

CALL LA0ON ;La comunicación se ha interrumpido. Comunicamos a usuario y

;paramos indefinidamente el programa.NOPGOTO $-1

CD_OK

GOTO FIN

GET_D ;Esta función gestiona la recepción y posterior procesado de los bytes recibidos en la

;USART.

BANKSEL RCSTABTFSS RCSTA,OERR ;Se valora si hay error de "Overrun".GOTO NO_OE

BCF RCSTA,CREN ;En caso de incurrir en un error de "Overrun"se ha de limpiar de

BSF RCSTA,CREN ;de esta manera.

GOTO SI_ERR

NO_OE

BTFSS RCSTA,FERR ;Se valora si hay error de "Framing".GOTO NO_FE

SI_ERRBANKSEL ERRORESINCF ERRORES,F

MOVLW .10 ;Se permitirán 10 iteraciones sin que se considere un error irrecu-

XORWF ERRORES,W ;perable.BTFSC STATUS,ZGOTO ERRORS1 ;Incurrimos en un error Software.

BTFSC RX_STATUS,PAQ_NOTOTHER ;Si hemos perdido un byte del campo de datos de un paquete

GOTO P_NAK ;podemos pedir la repetición del mismo.

;En caso de que esto no sea así, deberiamos esperar el TIMEOUT

;del emisor.

NO_FE

BANKSEL RCREGMOVF RCREG,W

MOVWF AUXRC

BTFSC RX_STATUS,PAQ_NOTOTHER ;Se valora si estamos inmersos en la recepción de un

GOTO ES_PAQ ;paquete.

COAUXRC CAN,ES_CAN ;Valoramos la llegada de un CAN.

COAUXRC NAK,ES_NAK ;Valoramos la llegada de un NAK.

BTFSS COM_STATUS,WAIT_FOR_NAK ;Se sabe que el caracter ACK podrá llegar en

GOTO SYNC_OK ;cualquier momento siempre y cuando se haya

;recibido el caracter de sincronismo.

COAUXRC ACK,ES_ACK ;Valoramos la llegada de un ACK.

SYNC_OK

BTFSC COM_STATUS,CRC_NOTCHECK ;En caso de estar en modo CRCde corrección de

COAUXRC A'C',ES_NAK ;errores, deberemos

sincronizar con un caracter ;'C'.

COAUXRC SOH,ES_SOH ;Valoramos la llegada de un SOH.

COAUXRC EOT,ES_EOT ;Valoramos la llegada de un EOT.

ERBANKSEL ERRORES ;En caso de no ser ningún caracter de los

considerados podremos estarINCF ERRORES,F ;incurriendo en un error de sincronismo o de

otro tipo.

MOVLW .10 ;Se permitirán 10 iteraciones sin que se considere un error irrecu-

XORWF ERRORES,W ;perable.BTFSS STATUS,ZGOTO FIN

GOTO ERRORS1 ;Incurrimos en un error Software.

GOTO FIN

;<<<<<<<******PROCESADO DE LOS CARACTERES RECIBIDOS******>>>>>>>

ES_EOTCALL DISOUTR ;Se deshabilitan TIMEOUTS de recepción.

BSF RX_STATUS,EOT_RCED

GOTO P_ACK

ES_CANCALL DISOUTT ;Se deshabilitan TIMEOUTS de transmisión.CALL DISOUTR ;Se deshabilitan TIMEOUTS de recepción.

GOTO FIN

ES_ACKCALL DISOUTT ;Se deshabilitan TIMEOUTS de transmisión.

BTFSC TX_STATUS,EOT_SNDED ;Valoramos si es una confirmación de EOT recibido por el

GOTO FIN ;emisor.

CALL ACT_PTS ;Si se ha aceptado un paquete se actualiza el puntero para

;que apunte a un paquete nuevo.

BTFSS BUFFERS,EMPTYTGOTO NOT_EOT

BTFSS AUXILIAR,FINENVIOSGOTO NOT_EOT

BCF AUXILIAR,FINENVIOS

GOTO P_EOT

NOT_EOTINCF PAQ,F ;Se actualizan los valores locales de

comparación para los camposCOMF PAQ,W ;"num. de paquete" y "complemento a 1 del

num. de paquete".MOVWF NOT_PAQ

GOTO COMUN

ES_NAK ;Procesado de la recepción de un NAK

CALL DISOUTT

BTFSC COM_STATUS,WAIT_FOR_NAKGOTO NO_W

BSF COM_STATUS,WAIT_FOR_NAKGOTO SI_W

NO_WBTFSC TX_STATUS,EOT_SNDED ;Si lo que no se ha recibido

correctamente es un EOTGOTO P_EOT ;se debe enviar este mismo handshake

de nuevo.

CALL ACT_AD ;Carga en los punteros la dirección correspondiente al byte siguiente

;al último aceptado por el receptor.

COMUNBANKSEL CHECK_TXH ;Para controlar los errores

se utiliza este GPRCLRF CHECK_TXH ;en caso de estar en modo

checksum y los dosBTFSC COM_STATUS,CRC_NOTCHECK ; GPR's (CHECK_TXL y

CHECK_TXH) en caso de estarCLRF CHECK_TXL ;en modo CRC. Se deben

resetear en cada paquete ya;que son acumulativos.

SI_WBANKSEL TXSTABSF TXSTA,TXEN ;Habilitación de la USART para el envio.

BSF TX_STATUS,SND_NOTHAND

MOVLW SOH ;En caso de ser un NAK/C de sincronismo se pone en marcha el

BANKSEL AUXTX ;sistema de envios empezando por el caracter SOH.

MOVWF AUXTX

CALL ON_RSI ;Se desinhiben interrupciones de emisor.

GOTO FIN

ES_SOH ;Se ha recibido un caracter de saludo SOH.

CALL RESOUTR ;Se resetea el contador de TIMEOUTS entre

caracteres recibidos.

BSF RX_STATUS,PAQ_NOTOTHER ;Al recibir el caracter de saludo, seindica en este bit

;el estado de recepción de paquete.

BSF AUXILIAR,FIRST_CHAR ;Se actualiza la información del flag, indicando que se ha

;recibido un primer caracter.

BANKSEL CHECK_RXH ;Se resetean los registros de cálculode CRC/CHECKSUM

CLRF CHECK_RXH ;segun sea necesario.BTFSC COM_STATUS,CRC_NOTCHECKCLRF CHECK_RXL

BANKSEL DAT_REC ;Reseteo de la variable que controla la sucesión de caracteres que

MOVLW LONG_DATA ;componen un paquete (en este caso 128).MOVWF DAT_REC

GOTO FIN

ES_PAQ ;Hemos recibido un byte correspondiente a algún campo de un paquete.

CALL RESOUTR ;Se resetea el TIMEOUT de recepción

COMP_RX B'00001000',NUM_P ;MACRO que direcciona a la posición de código correspondiente

;según el tipo de byte recibido.COMP_RX B'00001001',NEG_NUM

COMP_RX B'00001010',DTOS

COMP_RX B'00001011',COMP

COMP_RX B'00001100',COMP2

GOTO FIN ;Linea introducida por seguridad.

;--->Rutinas de tratado de información correspondientes a cada campo del paquete.

NUM_P ;Se ha recibido el byte que contiene el número de paquete.

BANKSEL PAQ_RECMOVF AUXRC,WMOVWF PAQUETE ;Se guarda el dato en previsión de que

podamos tener un error.MOVF PAQ_REC,WSUBWF AUXRC,WBTFSC STATUS,ZGOTO SI

BTFSS STATUS,CBSF RX_STATUS,PAQ_PRE_ERROR2;Se utilizan estos 2 de pre-error

bits para valorar ;las diferentes posibilidades en

cuanto a errores ;que se pueden dar.

BTFSC STATUS,CBSF RX_STATUS,PAQ_PRE_ERROR

GOTO FIN

SI INCF RX_STATUS,FGOTO FIN

NEG_NUM

BANKSEL PAQUETEBTFSC RX_STATUS,PAQ_PRE_ERRORGOTO P_ERROR

BTFSC RX_STATUS,PAQ_PRE_ERROR2GOTO P_ERR2

COMF PAQ_REC,WXORWF AUXRC,WBTFSC STATUS,ZGOTO SIGOTO P_NAK

P_ERRORBCF RX_STATUS,PAQ_PRE_ERROR ;Si el número de paquete se recibe

coherentemente (el com-COMF PAQUETE,W ;plemente a 1 coincide) y es superior

al esperado tenemos un XORWF AUXRC,W ;fallo de secuencia que se resuelve

con el envio de un CAN.BTFSC STATUS,ZGOTO P_CANGOTO P_NAK

P_ERR2BCF RX_STATUS,PAQ_PRE_ERROR2COMF PAQUETE,W ;Si el número de paquete recibido es

coherente con el comp. aXORWF AUXRC,W ;1 en un pre-error nos encontraremos

con un paquete ya recibidoBTFSC STATUS,Z ;con anterioridad y deberemos enviar

un ACK para recibir siguientesGOTO P_ACK ;volúmenes. Es caso de no encontrar

coherencia incurrimos en un errorGOTO P_NAK ;de num. de paquete o de comp. de

paquete.

DTOS ;Procesa la llegada de bytes de datos, calculando el CRC/Checksum progresivamente y

;almacenándolos en el registro general de 128 bytes situado en la RAM.

CALL INTORCALL ARAM

BTFSS COM_STATUS,CRC_NOTCHECKGOTO DO_CHEC

CALL DO_CRCR

GOTO OKCRC

DO_CHECMOVF AUXRC,WBANKSEL CHECK_RXHADDWF CHECK_RXH,F ;Cálculo del checksum. Realizado utilizando

solo el registro ;especificado.

OKCRC

DECFSZ DAT_REC,F ;Se va decrementando el contador de datos recibidos.

GOTO FININCF RX_STATUS,FGOTO FIN

COMPBTFSC COM_STATUS,CRC_NOTCHECKGOTO COM_CRC

CALL DISOUTR ;Se deshabilita TIMEOUT receptor porque el emisor espera que

;nuestro dispositivo le valide o no el últimopaquete.

BANKSEL CHECK_RXHMOVF CHECK_RXH,W ;Comparamos el valor obtenido para el control

de errores con elXORWF AUXRC,W ;calculado de manera local.BTFSS STATUS,ZGOTO P_NAKGOTO TODOOK

COM_CRCBANKSEL CHECK_RXHMOVF CHECK_RXH,WXORWF AUXRC,WBTFSS STATUS,ZGOTO P_NAK ;Si no coincide el primer byte tendremos que

enviar un NAK para que ;sea repetido el envio del mismo paquete.

INCF RX_STATUS,F ;En CRC, dado que tenemos dos bytes de comprobación, esperaremos al segundo

GOTO FIN ;antes de validar o no el paquete recibido.

COMP2CALL DISOUTR ;Se deshabilita TIMEOUT receptor porque el

emisor espera que ;nuestro dispositivo le valide o no el último

paquete.BANKSEL CHECK_RXLMOVF CHECK_RXL,W ;Se comprueba el segundo byte. La

coincidencia con el calculado deXORWF AUXRC,W ;manera local nos da una alata probabilidad

de buena recepción.

BTFSS STATUS,Z ;De no encontrar la igualdad se envia un NAK esperando que se repita

GOTO P_NAK ;el paquete.

TODOOKBANKSEL PAQ_REC ;Si se encuentra igualdad se incrementa el

contador de paquetes INCF PAQ_REC,F ;recibidos.

CALL SALVAR ;Se salva el contenido total del paquete en la memoria FLASH.

GOTO P_ACK ;Se envia un ACK validando el paquete.

P_CAN CLRF RX_STATUSCALL LA1ONRESPU CAN ;MACRO que envia al registro pertinente el

byte de handshake ;para su posterior envio mediante la rutina

PUT_D.P_ACK MOVLW B'10010000'

ANDWF RX_STATUS,F

RESPU ACK

P_NAK CLRF RX_STATUSRESPU NAK

P_EOT BSF TX_STATUS,EOT_SNDEDRESPU EOT

P_C RESPU A'C'

DO_CRCRBANKSEL CHECK_RXHMOVF CHECK_RXH,WMOVWF CRCH

MOVF CHECK_RXL,WMOVWF CRCL

MOVF AUXRC,WCALL DO_CRC

BANKSEL CRCHMOVF CRCH,WMOVWF CHECK_RXH

MOVF CRCL,WMOVWF CHECK_RXL

RETURN

DO_CRC ;Función que calcula el CRC mediante el suministro de dos números. Uno será el valor

;acumulado del cálculo de anteriores bytes de datos y el otro será unnuevo byte

;para procesar. El segundo se suministrará mediante el registro W y el primero a través

;de los registros CRCH/CRCL.

BANKSEL CRCHXORWF CRCH,F

CLRWXORWF CRCL,F

MOVLW .8MOVWF ITERA

SHIFT CLRCRLF CRCL,FRLF CRCH,F

BTFSS STATUS,CGOTO LOOP

MOVLW POLYHXORWF CRCH,FMOVLW POLYLXORWF CRCL,F

LOOP DECFSZ ITERA,FGOTO SHIFT

RETURN

;*********--------**************----------*******

PUT_D ;Maneja los envios de paquetes y HANDSHAKES necesarios para la parte receptora, de tal manera

;que no ocasionen conflictos ni se pierda la información.

BANKSEL AUXTX ;Se envia el byte guardado en este registro nada más empezar la

MOVF AUXTX,W ;rutina.

BANKSEL TXREGMOVWF TXREG

BTFSC TX_STATUS,SND_NOTHAND ;En caso de que el emisor se encuentre en estado de envio de

GOTO ENVIAN ;paquete, nos vamos a la posición de rutina correspondiente.

BTFSC TX_STATUS,HAND_BY_RECEPGOTO S_HAND ;En caso de no estar en modo envio de

paquete y tener la CALL OFF_RSI ;necesidad de cumplir los requisitos

de envio de HANDSHAKE GOTO FIN ;a "petición" de la rutina de

recepción iremos a otra parte ;diferente del código.

S_HAND ;Envia un handshake necesario para que como receptor, nuestro dispositivo valide o no

;paquetes al emisor remoto.

BCF TX_STATUS,HAND_BY_RECEP

BANKSEL HANDSHAKEMOVF HANDSHAKE,WGOTO ENVIO

ENVIANBANKSEL INFO_CAMPOMOVLW B'00001111'ANDWF TX_STATUS,W MOVWF INFO_CAMPO ;Registro auxiliar de información sobre campo

del paquete que se debe;tratar.

MOVLW B'00001010' ;Combinación correspondiente al campo de datos del paquete.

XORWF INFO_CAMPO,WBTFSC STATUS,ZGOTO S_DATA

BTFSS COM_STATUS,CRC_NOTCHECKGOTO LISTOCH

MOVLW B'00001100' ;Combinación correspondiente al campo 2 de CRC (solo para CRC) .

XORWF INFO_CAMPO,W

BTFSC STATUS,ZGOTO CORRECGOTO NOESCH

LISTOCH MOVLW B'00001011' ;Campo 1 de CRC y campo de Checksum para los paquetes con corrección

XORWF INFO_CAMPO,W ;de errores con el mismo nombre.BTFSC STATUS,ZGOTO CORREC

NOESCH CALL SIGUEGOTO FIN

CORREC ;Procesado del último campo del paquete: CRC2/Checksum y reinicializaciones.

CALL SIGUE

BCF TX_STATUS,SND_NOTHAND ;Se establece el modo de manejo de handshakes.

BANKSEL AD_ENVMOVF AD_ENV,W ;Se reinicia puntero a registros situados en

RAM con algunosMOVWF PTRO_ENV ;de los campos del paquete.

MOVLW B'11110000'ANDWF TX_STATUS,F ;Se reinicia el registro de estado.

GOTO FIN

S_DATA

CALL SND_BYTE

BTFSC COM_STATUS,CRC_NOTCHECKGOTO DO_CRCT

BANKSEL CHECK_TXHADDWF CHECK_TXH,F

ENVIOBANKSEL AUXTX ;Se carga en el resgistro auxiliar para enviarlo en

la próxima ejecución MOVWF AUXTX ;de la rutina.

GOTO FIN

SIGUEBANKSEL PTRO_ENVMOVF PTRO_ENV,WMOVWF FSR

BSF STATUS,IRP ;Configuración para la parte alta, dado que nos situamos en el

;banco 3. Accesos indirectos.

MOVF INDF,WINCF TX_STATUS,F

INCF PTRO_ENV,F

MOVWF AUXTX

RETURN

DO_CRCTBANKSEL CHECK_TXHMOVF CHECK_TXH,WMOVWF CRCH

MOVF CHECK_TXL,WMOVWF CRCL

MOVF SND,W

CALL DO_CRC

BANKSEL CRCHMOVF CRCH,WMOVWF CHECK_TXH

MOVF CRCL,WMOVWF CHECK_TXL

BANKSEL SNDMOVF SND,W

GOTO ENVIO

;*********--------**************----------*******

LECTURA ;Lee de la memoria de programa. La posición deberá ser especificada mediante los GPR's

;EEADR/EEADRH y el dato obtenido se situará en los GPR's EEDATH/EEDATA.

BANKSEL EECON1BSF EECON1,EEPGD

BSF EECON1,RD

NOP ;Quitar estos NOPS genera problemas imprevistos en las siguientes instrucciones

NOP ;como por ejemplo que las dos instrucciones siguientes no lasejecute.

BANKSEL EEADRINCFSZ EEADR,FRETURNINCF EEADRH,FRETURN

ACT_AD ;Función que coloca las direcciones correspondientes en los registrosEEADR Y EEADRH

;para la posterior lectura del campo de datos de un paquete.

BANKSEL DATA_AD_H_TX ;Se cargan los punteros en el registro de direcciones

MOVF DATA_AD_H_TX,W ;correspondiente.

BANKSEL EEADRHMOVWF EEADRH

BANKSEL DATA_AD_L_TXMOVF DATA_AD_L_TX,W

BANKSEL EEADRMOVWF EEADR

BANKSEL DATOSMOVLW LONG_DATAMOVWF DATOSRETURN

ACT_PTS ;Guarda la dirección instantanea de los registros EEADR/EEADRH en losGPR's habilitados

;como punteros.

BANKSEL DATOS ;En caso de vernos en la necesidad de guardarlas direcciones

MOVF DATOS,W ;en punteros cuando estamos posicionados en medio de un paquete,

BZ NOINC ; no guardaremos la dirección instantanea sinó la calculada para

;el inicio del siguiente paquete.

BANKSEL EEADRADDWF EEADR,F

BNC NOINC

INCF EEADRH,F

NOINC

BANKSEL EEADRMOVF EEADR,W

BANKSEL DATA_AD_L_TXMOVWF DATA_AD_L_TX

BANKSEL EEADRHMOVF EEADRH,W

BANKSEL DATA_AD_H_TXMOVWF DATA_AD_H_TX

BANKSEL DATOSMOVLW LONG_DATAMOVWF DATOSRETURN

LA1INT ;Cambia de estado del bit 1 del PORTA al estado complementario.

BANKSEL PORTAMOVLW B'00000010'XORWF PORTA,F

RETURN

LA1ON ;Pone a 1 el bit 1 del PORTA. ERRORES SOFTWARE

BANKSEL PORTABSF PORTA,1

RETURN

LA1OFF ;Pone a 0 el bit 1 del PORTA. ERRORES SOFTWARE

BANKSEL PORTABCF PORTA,1

RETURN

LA0INT ;Cambia de estado del bit 0 del PORTA al estado complementario.

BANKSEL PORTAMOVLW B'00000001'XORWF PORTA,F

RETURN

LA0ON ;Pone a 1 el bit 0 del PORTA. ERRORES HARDWARE

BANKSEL PORTABSF PORTA,0RETURN

INI_PA ;Inicializa PORTA.

BANKSEL PORTACLRF PORTA

BANKSEL ADCON1MOVLW H'6'MOVWF ADCON1

BANKSEL TRISA ;Todos los pines del PORTA son SALIDAS.CLRF TRISA

RETURN

SAVEINF ;Función que guarda la información situada en los GPR's EEDATA y EEDATH en la dirección

;de memoria FLASH que se especifica en los GPR's EEADR y EEADRH.

BANKSEL EECON1BSF EECON1, EEPGD ;Configuración para memoria FLASH.BSF EECON1, WREN ;Habilitación de escritura.

MOVLW H'55' MOVWF EECON2 ;Procedimiento de seguridad para

evitar escrituras inde-MOVLW H'AA' ;seadas.MOVWF EECON2

BSF EECON1, WR ;Bit de control que inicia un ciclo de control.

NOP NOP

BCF EECON1, WREN ;Deshabilitación de las escrituras.

RETURN

INIUST ;Inicialización de la USART.

MOVLW SPBRG_VAL

BANKSEL SPBRG ;Se introduce el valor correspondiente en el registrode Baud Rate Generator.

MOVWF SPBRG

MOVLW B'00000110'BANKSEL TXSTA ;Configuraciones de transmisiónMOVWF TXSTA

MOVLW B'10000000'BANKSEL RCSTA ;Configuraciones de recepción.MOVWF RCSTA

RETURN

INIINTE ;Inicializaciones de las interrupciones.

CALL OFF_RSI

BANKSEL PIE1CLRF PIE1BSF PIE1,RCIE

MOVLW B'11000000'

BANKSEL INTCON ;Habilitación general de interrupciones y periféricos.

MOVWF INTCON

CALL INT_PB

RETURN

INIVAR ;Inicialización general de variables.

CLRF AUXILIARCLRF TX_STATUSCLRF RX_STATUSCLRF COM_STATUSBSF COM_STATUS,CRC_NOTCHECK ;Inicialmente control de

errores mediante CRC.

BANKSEL CRCH

CLRF CRCHCLRF CRCL

CLRF CHECK_RXHCLRF CHECK_RXL

CLRF CHECK_TXHCLRF CHECK_TXL

MOVLW H'20'MOVWF AD_RECMOVWF PTRO_BUF_RC

MOVLW .1MOVWF PAQ_REC

MOVLW LONG_DATAMOVWF DAT_REC

CLRF ERRORES

CLRF SAVED_IN_FLASH

MOVLW .1MOVWF PAQCOMF PAQ,WMOVWF NOT_PAQ

MOVLW .2MOVWF CONT_PAQ

MOVLW H'92'MOVWF AD_ENVMOVWF PTRO_ENV

MOVLW H'00'MOVWF DATA_AD_L_TX

MOVLW H'10'MOVWF DATA_AD_H_TX

MOVLW H'11'MOVWF PTRO_RECH

MOVLW H'00'MOVWF PTRO_RECL

MOVLW H'D0'MOVWF BTHMOVWF BTLMOVWF BTMIN

ADDLW .16MOVWF BTMAX

MOVLW H'10'MOVWF BRHMOVWF BRLMOVWF BRMIN

ADDLW .16MOVWF BRMAX

CLRF BUFFERS

CALL INIUST ;Inicialización de la USART.

BANKSEL RCSTABSF RCSTA,CREN ;Habilitación de la USART para recepción

continuada

RETURN

INIPRT ;Inicialización de los puertos utilizados.

CALL INI_PACALL INI_PB

RETURN

INI_PB ;Inicialización del PORTB

BANKSEL PORTBCLRF PORTB

BANKSEL TRISBMOVLW B'11011101'MOVWF TRISB

RETURNINT_PB ;Inicilización de interrupciones por cambio en PORTB.

BCF INTCON, RBIFBSF INTCON,INTEBSF INTCON,RBIE

BANKSEL OPTION_REG

BSF OPTION_REG,INTEDG

RETURN

ARAM ;Escribe un byte determinado en un buffer de 128 bytes creado en RAM.

CALL OUTFROMR

BCF STATUS,IRP ;Configuramos el STATUS para direccionamientoindirecto de los

;bancos inferiores.

BANKSEL PTRO_BUF_RCMOVF PTRO_BUF_RC,WMOVWF FSR

MOVF AUXRC,WMOVWF INDF

BANKSEL PTRO_BUF_RCINCF PTRO_BUF_RC,F

MOVLW H'70'XORWF PTRO_BUF_RC,WBTFSC STATUS,Z GOTO ENDB0A

MOVLW H'D0'XORWF PTRO_BUF_RC,WBTFSC STATUS,Z GOTO ENDBUFARETURN

ENDB0AMOVLW H'A0'MOVWF PTRO_BUF_RCRETURN

ENDBUFAMOVLW H'20'MOVWF PTRO_BUF_RCRETURN

TOUTR ;Rutina de tratamiento del error por TIMEOUT de recepción.

BTFSC COM_STATUS,ENA_TEMI ;Si no hay que atender rutinas de TIMEOUT por emisión bajamos

GOTO PASBCF INTCON,T0IF ;el flag.GOTO NOPAS

PASBSF COM_STATUS,PASSED ;Se espefica RSI de emisión

ejecutada.

NOPASBANKSEL TICSRDECFSZ TICSR,F ;Decrementa el contador de "pulsos"

de recepción.GOTO NO_RNGR

BANKSEL ERRRXDECFSZ ERRRX,F ;Decrementa el contador de

iteraciones. Un error puedeGOTO ACTUA ;producirse hasta 10 veces en algún

caso antes de que se;convierta en un fallo irrecuperable.

BTFSC COM_STATUS,CRC_NOTCHECKGOTO CHANGE

CALL LA1ON ;Cúmulo de errores. Encendido permanente.

ALL NOPGOTO ALL

CHANGEBCF COM_STATUS,CRC_NOTCHECKBANKSEL ERRRXMOVLW .10MOVWF ERRRXGOTO NOFIRST

ACTUA BSF AUXILIAR,L1INTCALL LA1INT ;Error Software, encendido de LED.

BTFSC AUXILIAR,FIRST_CHARGOTO NOFIRST

BTFSC COM_STATUS,CRC_NOTCHECKGOTO SICRC

NOFIRSTBANKSEL TICSRMOVLW .200MOVWF TICSRGOTO P_NAK

SICRCBANKSEL TICSRMOVLW .60MOVWF TICSRGOTO P_C

NO_RNGR BTFSC AUXILIAR,L1INT

CALL LA1INT

GOTO FIN

TOUTT ;Rutina de tratamiento del error por TIMEOUT de emisión.

BCF INTCON,T0IF ;Se baja el flag, ya que no se ejecutarán más rutinas en esta

;interrupción.

BTFSC COM_STATUS,ENA_TREC ;Desaserta el flag en caso necesario.BCF COM_STATUS,PASSED

BANKSEL TICSTDECFSZ TICST,FGOTO NO_RNGT

MOVLW .200MOVWF TICST

BANKSEL ERRTXDECFSZ ERRTX,FGOTO INTERM

CALL LA1ON ;Cúmulo de errores. Encendido permanente.

ALL2 NOPGOTO ALL2

INTERMBSF AUXILIAR,L1INTCALL LA1INT ;Error Software. Destellos del LED.

BTFSC COM_STATUS,WAIT_FOR_NAK GOTO NO_WGOTO FIN

NO_RNGTBTFSC AUXILIAR,L1INTCALL LA1INT

GOTO FIN

DISOUTR ;Se deshabilita control de errores por tiempo de recepción.

CALL LA1OFF

BCF COM_STATUS,ENA_TREC

BTFSS COM_STATUS,ENA_TEMICALL OFF_TRETURN

DISOUTT ;Se deshabilita control de errores por tiempo de transmisión.

CALL LA1OFF

BCF COM_STATUS,ENA_TEMI

BTFSS COM_STATUS,ENA_TRECCALL OFF_T

RETURN

STANDBY ;Se guarda el tiempo marcado por el TMR0 en una variable.

BTFSS COM_STATUS,ENA_TRECGOTO OTROGOTO SI_T

OTRO BTFSS COM_STATUS,ENA_TEMIGOTO NO_T

SI_TBANKSEL TMR0MOVF TMR0,W

BANKSEL TMR0_TMPMOVWF TMR0_TMP

NO_TRETURN

COMEON ;Función recíproca a STANDBY.

BTFSS COM_STATUS,ENA_TRECGOTO NO_T2GOTO SI_T2

BTFSS COM_STATUS,ENA_TEMIGOTO NO_T2

SI_T2BANKSEL TMR0_TMPMOVF TMR0_TMP,WBANKSEL TMR0MOVWF TMR0BCF INTCON,T0IF

NO_T2

RETURN

ENAOUTR ;Habilitación de control de errores por recepción.

BSF COM_STATUS,ENA_TREC

BTFSS COM_STATUS,ENA_TEMICALL ON_T

BANKSEL TICSR

BTFSC AUXILIAR,FIRST_CHARGOTO NO_F

MOVLW .60MOVWF TICSR ;Valores de tiempo y cantidad de errores permisibles

dependiendo;de si estamos en modo CRC o Checksum

MOVLW .3MOVWF ERRRX

RETURN

NO_FMOVLW .200MOVWF TICSR

MOVLW .10

MOVWF ERRRXRETURN

RESOUTR ;Resetea los contadores y variables para el control de errores de recepción.

BANKSEL TICSRBTFSC AUXILIAR,FIRST_CHARGOTO NO_F2

MOVLW .60MOVWF TICSR

MOVLW .3MOVWF ERRRXRETURN

NO_F2MOVLW .200MOVWF TICSR

MOVLW .10MOVWF ERRRX

RETURN

ENAOUTT ;Habilitación de control de errores de transmisión

BSF COM_STATUS,ENA_TEMI

BTFSS COM_STATUS,ENA_TRECCALL ON_T

BANKSEL TICSTMOVLW .200MOVWF TICST

MOVLW .10MOVWF ERRTX

RETURN

INI_T ;Inicialización de Timer 0

BANKSEL OPTION_REGMOVLW H'47'MOVWF OPTION_REG

BANKSEL TICSTMOVLW .200MOVWF TICST

MOVLW .60MOVWF TICSR

MOVLW .10MOVWF ERRTX

MOVLW .3MOVWF ERRRX

RETURN

ON_T ;Carga del timer y reseteado de las interrupciones pertenecientes al mismo.

BANKSEL TMR0CLRF TMR0

BCF INTCON,T0IF

MOVLW H'3D' ;El valor h'3D' deberá provocar un desbordamiento de timer cada 50ms.

MOVWF TMR0BSF INTCON,T0IE

RETURN

OFF_T ;Deshabilitación de las interrupciones y reseteo del flag del timer.

BCF INTCON,T0IFBCF INTCON,T0IE

RETURN

OFF_RSI ;Deshabilitación de interrupciones de transmisión de USART.

BANKSEL PIE1BCF PIE1,TXIERETURN

ON_RSI ;Habilitación de interrupciones de transmisión de USART.

BANKSEL PIE1BSF PIE1,TXIERETURN

ACT_ADR ;Se carga la dirección de recepción de FLASH procedente de los punteros en los registros de

;direcciones.

BANKSEL PTRO_RECHMOVF PTRO_RECH,W

BANKSEL EEADRHMOVWF EEADRH

BANKSEL PTRO_RECLMOVF PTRO_RECL,W

BANKSEL EEADRMOVWF EEADR

BANKSEL DATOSMOVLW LONG_DATAMOVWF DATOS

RETURN

DRAM;El buffer general de recepción ocupa en el banco0 las direcciones

(20-6F) y en el banco1;(A0-C7). En total 128 bytes, que es el tamaño de paquete. Esta

rutina gestiona el puntero;que recorre todo el buffer.

BANKSEL PTRO_BUF_RCMOVF PTRO_BUF_RC,WMOVWF FSR

MOVF INDF,W

MOVWF STORE

INCF PTRO_BUF_RC,F

MOVLW H'70'XORWF PTRO_BUF_RC,WBTFSC STATUS,Z GOTO ENDB0

MOVLW H'D0'XORWF PTRO_BUF_RC,WBTFSC STATUS,Z GOTO ENDBUFRETURN

ENDB0MOVLW H'A0'MOVWF PTRO_BUF_RCRETURN

ENDBUFMOVLW H'20'MOVWF PTRO_BUF_RCRETURN

ERRORS1 ;Salto a esta rutina tras demasiados errores de tipo software.

CALL LA1ON ;Encendido permanente del LED.

SOFT1 NOPGOTO SOFT1

CONN

CALL INI_PB ;Configura el puerto en entradas y salidasCALL INIUST ;Configuraciones necesarias para la USART

BCF INTCON,GIE ;Inhibe interrupciones

CALL INI_T ;configuración previa del TMR0.

CALL INIEEAD ;inicialización de dirección del puntero que recorre la E2PROM.

BANKSEL CONTAMOVLW .2MOVWF CONTA

BANKSEL PORTBBCF PORTB,DTR ;Aserta Data Terminal Ready.BCF PORTB,RTS ;Aserta Request To Send.

BTFSC PORTB,DSR ;Esperamos hasta que Data Set Ready GOTO $-1 ;quede asertada.

CALL EEPROM ;Lee de EEPROM (en la posición PTRO_EEP) y ;coloca el dato en W.

CALL RUNUST ;Habilitación de envio y recepción de la USART.

CALL MANDA ;Envio del dato al buffer de envio de la USART.

MOVLW .5BANKSEL ITERACIONES ;Variable aplicada el timer para contar

unidades de tiempo.MOVWF ITERACIONES ;20,2ms * 5 = 101ms. Esta es la espera máxima

a partir de la ;cual sabemos que el modem no nos hará el ECO

de caracteres ;enviados debido a su configuración.

CALL ON_T2 ;Configura TMR0 para el temporizado de 20,2ms.

NO_TIM BTFSC INTCON,T0IFGOTO DECTIM

BANKSEL PIR1BTFSS PIR1,RCIFGOTO NO_TIM ;Es caso de recibir algun dato antes de

cumplirse el tiempo;consideramos que tendremos ECO, de lo

contrario volvemos al ;bucle.

GOTO REC

DECTIMCALL ON_T2BANKSEL ITERACIONESDECFSZ ITERACIONES,FGOTO NO_TIMGOTO NOECO ;En caso de cumplirse el tiempo máximo

consideramos que no ;habrá ECO.

REC

CALL REC_A_W

MOVWF AUXRC

BANKSEL EEDATAMOVF EEDATA,WXORWF AUXRC,WBTFSS STATUS,Z ;El dato producto del ECO debe coincidir con

el mandado para que GOTO FAULT ;se compruebe el entendimiento con el modem.

Si no es así tenemos ;un fallo de la comunicación debido a varias

posibles causas.

MAS_COM ;Envia caracter a caracter el comando ATZ contemplando la llegada de ECO's.

CALL EEPROM

CALL MANDA ;Enviamos un nuevo caracter.

CALL WAITRX ;Esperamos a recibir un nuevo caracter.CALL REC_A_W

MOVWF AUXRC

BANKSEL EEDATAMOVF EEDATA,WXORWF AUXRC,WBTFSS STATUS,ZGOTO FAULT

BANKSEL EEDATA ;Este bucle se repite hasta que se haya enviado y recibido

MOVLW CR ;el caracter CR (Retorno de Carro). Llegados a este punto, se

XORWF EEDATA,W ;ha enviado el comando ATZ.BTFSS STATUS,ZGOTO MAS_COM

MOVLW .130BANKSEL ITERACIONESMOVWF ITERACIONES

CALL ON_T2

WAITATZBTFSC INTCON,T0IF ;En caso de que pasen los 2,6 sec (130

iteraciones) y no se recibaGOTO DECTIM2 ;respuesta, el programa debe seguir

normalmente

BANKSEL PIR1BTFSC PIR1,RCIFGOTO RATZ ;Bucle de espera a una nueva recepción. La

recepción esperada seráGOTO WAITATZ ;la respuesta al comando ATZ y el tiempo que

tarde en recibirse;será el que emplee el modem en hacer el

RESET.

DECTIM2CALL ON_T2BANKSEL ITERACIONESDECFSZ ITERACIONES,FGOTO WAITATZGOTO ENV2

NOECO ;Envia sin esperar ECOS el primer comando (ATZ). Es decir, envia caracteres hasta

;encontrar un retorno de carro (CR).

CALL EEPROMCALL MANDA

MOVLW CRBANKSEL EEDATAXORWF EEDATA,WBTFSC STATUS,ZGOTO FUERA ;Sale del bucle, cuando ha enviado un retorno

de carro (CR).

CALL WAITTXGOTO NOECO

FUERACALL WAITRX

RATZ ;Se comprueba la recepción correcta tras el comando ATZ. Esta parte del código se ejecuta

;cuando se ha completado el ECO del comando o cuando se sabe que el modem no retornará

;ECO del comando.

BANKSEL PTRO_EEP ;Se posiciona el puntero de EEPROM correctamente de tal manera que

MOVLW H'6F' ;se vayan leyendo los caracteres que deben ser recibidos como

MOVWF PTRO_EEP ;respuesta. Por la naturaleza de la función, debemos introducir una

;posición anterior a la queremos leer.

RATZ2CALL EEPROM

CALL REC_A_W

MOVWF AUXRC

BANKSEL EEDATAMOVF EEDATA,WXORWF AUXRC,WBTFSS STATUS,ZGOTO FAULT ;Si los datos no coinciden, deberemos actuar

en consecuencia.

BANKSEL EEDATAMOVLW LFXORWF EEDATA,WBTFSC STATUS,ZGOTO DECREM ;Salta al código de contado decremental de

LF's.MASREC

CALL WAITRX ;Espera una recepción en la USARTGOTO RATZ2 ;Salto al código que comprueba la igualdad de

caracteres.

DECREMBANKSEL CONTA ;Esta variable controla el contado de la

recepción delDECFSZ CONTA,F ;caracter H'0A'=LF=Salto de línea. Al contar

2 LF's provocaGOTO MASREC ;la salida del bucle.

ENV2

MOVLW .30 ;Introducimos un retardo obligado de 600ms por cuestiones de

BANKSEL ITERACIONES ;estandarizaciones en uso de modems, ya que algunos requeriran

MOVWF ITERACIONES ;de este retardo para el correcto funcionamiento.

CALL ON_T2

BTFSS INTCON,T0IFGOTO $-1 ;Salta a PC-1 compiendo un bucle sin falta de

utilizar etiquetas.

BANKSEL PORTABTFSS PORTA,4GOTO AUTO2

BANKSEL PTRO_EEP ;Volvemos a reposicionar le puntero. Por la misma razón que las

MOVLW H'03' ;anteriores veces, es una posición menos a laque queremos leer

MOVWF PTRO_EEP ;que en realidad es la h'04' (h'2104').GOTO MAS_CM2

AUTO2BANKSEL PTRO_EEPMOVLW H'93'MOVWF PTRO_EEP

MAS_CM2CALL EEPROM ;Se envian caracteres del string inicial

(segundo comando).CALL MANDA

CALL WAITRX ;Se espera el ECO de cada caracter.CALL REC_A_W

MOVWF AUXRC

BANKSEL EEDATAMOVF EEDATA,W ;Los dos caracteres, el enviado y el

recibido, han de ser iguales.XORWF AUXRC,W ;Dado este caso, el modem recibe

correctamente.BTFSS STATUS,ZGOTO FAULT ;De no darse el caso tendremos un error y

deberemos actuar.

BANKSEL EEDATAMOVLW CR ;Al enviar el retorno de carro (CR) se acaba

el comando.XORWF EEDATA,W ;Al comprobar esto, se salta fuera del bucle

de envio.BTFSS STATUS,ZGOTO MAS_CM2

MOVLW .100 ;Como norma general, las respuestas del modemdeberan tardar

BANKSEL ITERACIONES ;como mucho 2 sec.MOVWF ITERACIONES

CALL ON_T2

NO_TIM2BTFSC INTCON,T0IF ;En caso de cumplirse el tiempo límite

tendremos un errorGOTO DECTIM3

BANKSEL PIR1BTFSC PIR1,RCIF ;En caso de que se reciba un caracter

tendremos una respuestaGOTO RCNUM ;con formato númerico referida al comando.

GOTO NO_TIM2 ;El bucle se mantendrá hasta que no se cumplan ninguno de los

;dos casos.

DECTIM3

CALL ON_T2BANKSEL ITERACIONESDECFSZ ITERACIONES,FGOTO NO_TIM2GOTO FAULT

RCNUM

CALL REC_A_W

MOVWF AUXRC

MOVLW H'30' ;El caracter recibido como respuesta deberá ser el 0. En código

XORWF AUXRC,W ;ASCII, corresponde al 30. Esto indica "OK", o lo que es lo mismo

BTFSS STATUS,Z ;que la instrucción se ha procesado con éxito.

GOTO FAULT

CALL WAITRX

CALL REC_A_W ;Después de toda respuesta se recibe un retorno de carro, que en

;código ASCII correponde al número 0D.MOVWF AUXRC

MOVLW H'0D'XORWF AUXRC,WBTFSS STATUS,ZGOTO FAULT

DIALING ;Se manda el comando de marcado seguido del número que se quiere marcar.

BANKSEL PORTABTFSS PORTA,4GOTO BYPASS

CALL EEPROM

CALL MANDA

BANKSEL EEDATA ;Como todos los comandos, este también estaráacabado en CR.

MOVLW CRXORWF EEDATA,WBTFSC STATUS,ZGOTO RCDIAL

GOTO DIALING

BYPASS

BANKSEL CONTA ;Tras entrar en el modo de comandos, el módemcontesta con un

MOVLW .2 ;2(0D). En total 2 veces.MOVWF CONTA

BYPASS2CALL WAITRX

MOVLW H'32'MOVWF AUXRC

CALL REC_A_W

XORWF AUXRC,W

BTFSS STATUS,ZGOTO FAULT

CALL WAITRX

MOVLW H'0D'MOVWF AUXRC

CALL REC_A_W

XORWF AUXRC,WBTFSS STATUS,ZGOTO FAULT

BANKSEL CONTADECFSZ CONTA,FGOTO BYPASS2

RCDIAL ;El modem dará una respuesta a nuestro marcado, bien se haya establecido la comunicación,

;o no se haya establecido. En esta respuesta ibtendremos información como, por ejemplo la

;la velocidad a la que se comunicará.

CALL WAITRXCALL EEPROMCALL REC_A_W

MOVWF AUXRC

BANKSEL EEDATAMOVF EEDATA,WXORWF AUXRC,WBTFSS STATUS,ZGOTO FAULT

BANKSEL EEDATA ;Este bucle se repite hasta que se haya enviado y recibido

MOVLW CR ;el caracter CR (Retorno de Carro). Llegados a este punto, se

XORWF EEDATA,W ;ha establecido la comunicación.BTFSS STATUS,ZGOTO RCDIAL

RETURN

FAULT

CALL INI_PA

FAULT2MOVLW .25 ;SALTA CADA 1/2SEGUNDOBANKSEL ITERACIONES ;Esperamos un tiempo de guarda de 300ms

aproximadamente.MOVWF ITERACIONES

FAULT3CALL ON_T2

BTFSS INTCON,T0IFGOTO $-1

BANKSEL ITERACIONESDECFSZ ITERACIONES,FGOTO FAULT3

CALL LA1INTGOTO FAULT2

DESCONN

BCF INTCON,GIE ;Deshabilita las interrupciones, pensado paralos puertos por

;interrupción.

CALL INI_T ;Inicilizamos el TMR0

BANKSEL AD_EEPMOVLW H'4F'MOVWF AD_EEPMOVWF PTRO_EEP

BANKSEL PORTBBCF PORTB,DTR ;Aserta Data Terminal Ready.BCF PORTB,RTS ;Aserta Request To Send.

MOVLW .15BANKSEL ITERACIONES ;Esperamos un tiempo de guarda de 300ms

aproximadamente.MOVWF ITERACIONES

GUARDACALL ON_T2

BTFSS INTCON,T0IF ;Pasado el tiempo de guarda el programa puedeseguir su curso.

GOTO $-1

BANKSEL ITERACIONESDECFSZ ITERACIONES,FGOTO GUARDA

CALL EEPROM ;Lee el caracter de la EEPROM

CALL RUNUST ;Habilita la USART

CALL MANDA ;Coloca el dato en el buffer de envío

VALORA

CALL EEPROM

BANKSEL EEDATAMOVLW CRXORWF EEDATA,W ;Comprueba que el dato a enviar no sea un CR,

de lo contrario saleBTFSC STATUS,Z ;del bucle SIN ENVIARLO.GOTO RECIBE

BANKSEL EEDATAMOVF EEDATA,WCALL MANDAGOTO VALORA

RECIBEBANKSEL CONTA ;Tras entrar en el modo de comandos, el módem

contesta con unMOVLW .2 ;0(0D). En total 2 caracteres.MOVWF CONTA

RECIBE2CALL WAITRX

CALL REC_A_W

MOVWF AUXRC

CALL EEPROM ;Valoramos si coincide con el valor escrito en la EEPROM.

XORWF AUXRC,WBTFSS STATUS,ZGOTO FAULT

BANKSEL CONTADECFSZ CONTA,FGOTO RECIBE2

BANKSEL CONTA ;Se envían 4 caracteres: ATH(OD).MOVLW .4MOVWF CONTA

CALL EEPROMRE

CALL MANDA

CALL EEPROM

BANKSEL CONTADECFSZ CONTA,FGOTO RE

RETURN

ON_T2 ;Coloca en el buffer del timer el valor de contado pertinente.

BANKSEL TMR0CLRF TMR0BCF INTCON,T0IF

MOVLW H'B1' ;El valor h'B1' deberá hacer que el timer se desbordecada 20,2 ms aprox.

MOVWF TMR0RETURN

MANDA ;Se espera a que se pueda transmitir un byte de información y en ese momento se envía

;este byte al registro correspondiente.

CALL WAITTXBANKSEL TXREGMOVWF TXREGRETURN

RUNUST ;Habilitación de la USART.

BANKSEL RCSTABSF RCSTA,CREN

BANKSEL TXSTABSF TXSTA,TXEN

RETURN

WAITRX ;Bucle de espera hasta que se recibe una entrada en la USART.

BANKSEL PIR1BTFSS PIR1,RCIFGOTO $-1RETURN

WAITTX ;Bucle de espera hasta que se vacia el buffer de envío de la USART.

BANKSEL PIR1BTFSS PIR1,TXIFGOTO $-1RETURN

REC_A_W

BANKSEL RCREGMOVF RCREG,W ;Envio del valor recibido por la USART a W

(Acumulador).RETURN

EEPROM ;Función que lee un valor de la EEPROM.

BANKSEL PTRO_EEPINCF PTRO_EEP,FMOVF PTRO_EEP,WBANKSEL EEADRMOVWF EEADRBANKSEL EECON1BCF EECON1,EEPGDBSF EECON1,RDBANKSEL EEDATAMOVF EEDATA,WRETURN

INIEEAD ;Inicialización del puntero de EEPROM.

BANKSEL PORTABTFSS PORTA,4 ;Si se lee un 0 se considera autorespuesta.GOTO AUTO

BANKSEL AD_EEPMOVLW H'FF'MOVWF AD_EEPMOVWF PTRO_EEPRETURN

AUTOBANKSEL AD_EEPMOVLW H'8F'MOVWF AD_EEPMOVWF PTRO_EEPRETURN

OUTFROMT;Extracción de un byte del buffer de transmisión (16 posiciones).

BTFSS BUFFERS,EMPTYTGOTO OKEBSF BUFFERS,RETORNORETURN

OKEBTFSC BUFFERS,FULLTBCF BUFFERS,FULLT

BSF STATUS,IRP

BANKSEL BTLMOVF BTL,WMOVWF FSR

MOVF INDF,WBANKSEL SNDMOVWF SNDCLRF INDF

BANKSEL BTLINCF BTL,FMOVF BTL,WXORWF BTMAX,WBTFSS STATUS,ZGOTO NOMIN2MOVF BTMIN,WMOVWF BTL

NOMIN2

MOVF BTL,WXORWF BTH,WBTFSC STATUS,ZBSF BUFFERS,EMPTYTBCF BUFFERS,RETORNORETURN

SND_BYTE;Función que escribe el byte que toca enviar en el registro SND.

CALL OUTFROMT ;Se lee del buffer de transmisión.BTFSS BUFFERS,RETORNO ;En caso de retornar 0 se ha producido la

lectura.GOTO OKRET ;En caso contrario el buffer está vacío.

;Si el buffer está vacío se rellena con caracteres "1A".

MOVLW H'1A'BANKSEL SNDMOVWF SND

OKRETBANKSEL DATOSDECFSZ DATOS,F ;Decremento en una unidad del contador de

datos (128 como máximo)RETURNINCF TX_STATUS,FRETURN

LLENADO;Función que establece un bucle de llenado y espera según haga falta

del buffer de

;transmisión

BANKSEL VALORMOVWF VALORINCF VALOR,F

LLENAMASDECFSZ VALOR,FGOTO LLENARETURN

LLENACALL LECTURACALL INTOT

VERFULLBTFSS BUFFERS,FULLTGOTO LLENAMASGOTO VERFULL

INTOT;Función que escribe en el buffer de transmisión.

BTFSS BUFFERS,FULLTGOTO OKFBSF BUFFERS,RETORNORETURN

OKFBTFSC BUFFERS,EMPTYTBCF BUFFERS,EMPTYT

BSF STATUS,IRP

BANKSEL BTHMOVF BTH,WMOVWF FSR

BANKSEL EEDATAMOVF EEDATA,WMOVWF INDF

BANKSEL BTHINCF BTH,FMOVF BTH,WXORWF BTMAX,WBTFSS STATUS,ZGOTO NOMINMOVF BTMIN,WMOVWF BTH

NOMIN

MOVF BTH,WXORWF BTL,WBTFSC STATUS,ZBSF BUFFERS,FULLT

BCF BUFFERS,RETORNORETURN

INTOR;Función que escribe en el buffer de recepción.

BTFSS BUFFERS,FULLRGOTO OKRBSF BUFFERS,RETORNORRETURN

OKRBTFSC BUFFERS,EMPTYRBCF BUFFERS,EMPTYR

BSF STATUS,IRP

BANKSEL BRHMOVF BRH,WMOVWF FSR

MOVF AUXRC,WMOVWF INDF

BANKSEL BRHINCF BRH,FMOVF BRH,WXORWF BRMAX,WBTFSS STATUS,ZGOTO NOMINRMOVF BRMIN,WMOVWF BRH

NOMINR

MOVF BRH,WXORWF BRL,WBTFSC STATUS,ZBSF BUFFERS,FULLR

BCF BUFFERS,RETORNORRETURN

OUTFROMR;Extracción de un byte del buffer de recepción (16 posiciones).

BTFSS BUFFERS,EMPTYRGOTO OKRBBSF BUFFERS,RETORNORRETURN

OKRBBTFSC BUFFERS,FULLRBCF BUFFERS,FULLR

BSF STATUS,IRP

BANKSEL BRLMOVF BRL,WMOVWF FSR

MOVF INDF,WMOVWF AUXRCCLRF INDF

BANKSEL BRLINCF BRL,FMOVF BRL,WXORWF BRMAX,WBTFSS STATUS,ZGOTO NOMIN3MOVF BRMIN,WMOVWF BRL

NOMIN3

MOVF BRL,WXORWF BRH,WBTFSC STATUS,ZBSF BUFFERS,EMPTYRBCF BUFFERS,RETORNORRETURN

CHEQUEA;Función que realiza una suma de comprobación completa del código

para detectar posibles;errores por el deterioro del uC

BANKSEL CHVALUEHCLRF CHVALUEH ;Inicilización del registro donde se guardará

el valor que se vaCLRF CHVALUEL ;calculando.

BANKSEL EEADRH ;Inicilización del valor de las direcciones para memoria FLASH.

CLRF EEADRHCLRF EEADR

OTRO2CALL LECTURA

BANKSEL EEDATAMOVF EEDATA,W

BANKSEL CHVALUEL ;Se suma el byte bajo.ADDWF CHVALUEL,F

BNC NOCARRY

INCF CHVALUEH,F ;Cálculo del acarreo entre el primer y el segundo byte.NOCARRY

BANKSEL EEDATHMOVF EEDATH,W

BANKSEL CHVALUEH

ADDWF CHVALUEH,F ;Se suma el byte alto.;Suma con resultado de 2 bytes.

BANKSEL EEADR ;Comprobamos que no haya llegado a límite inferior.

MOVF EEADR,W

XORLW @ENDDOWNBTFSS STATUS,ZGOTO OTRO2

BANKSEL EEADRHMOVF EEADRH,W

XORLW @ENDUPBTFSS STATUS,ZGOTO OTRO2

BANKSEL PTRO_EEP ;Se posiciona el puntero de la EEPROM en la pos. correcta.

MOVLW H'EF'MOVWF PTRO_EEP

CALL EEPROM

BANKSEL CHVALUEHXORWF CHVALUEH,WBTFSS STATUS,ZGOTO GRAVE

CALL EEPROM

BANKSEL CHVALUELXORWF CHVALUEL,WBTFSS STATUS,ZGOTO GRAVE

CALL LA1INTCALL LA0INTRETURN

GRAVE NOPGOTO GRAVE

END