Programación de la tarjeta CT6811 en lenguaje C

77
PROGRAMACION DE LA TARJETA CT6811 EN LENGUAJE C COMPILADOR CRUZADO DE C IMAGECRAFT V0.47 MICROBÓTICA S.L.

description

Manual práctico de programación de la tarjeta CT6811 en lenguaje C, usando el compilador cruzado de Imagecraft V0.47.Mayo 1997

Transcript of Programación de la tarjeta CT6811 en lenguaje C

Page 1: Programación de la tarjeta CT6811 en lenguaje C

PROGRAMACION DELA TARJETA CT6811 EN

LENGUAJE C

COMPILADOR CRUZADO DE CIMAGECRAFT V0.47

MICROBÓTICA S.L.

Page 2: Programación de la tarjeta CT6811 en lenguaje C

Programación de la tarjeta CT6811 en lenguaje C

2

Page 3: Programación de la tarjeta CT6811 en lenguaje C

Programación de la tarjeta CT6811 en lenguaje C

3

INDICE

PROLOGO................................................................................................................................... 51.- INTRODUCCION.................................................................................................................... 7 1.1.- ¿Qué es un compilador cruzado?........................................................................................ 7 1.2.- Lenguajes de alto nivel VS lenguaje ensamblador............................................................... 7 1.3.- Objetivos............................................................................................................................ 7 1.4.- Cómo leer este libro............................................................................................................ 7

2.- EL COMPILADOR DE C DE IMAGECRAFT...................................................................... 9 2.1.- Características del compilador........................................................................................... 9 2.2.- Ficheros que componen el compilador................................................................................ 9 2.3.- Funcionamiento del compilador......................................................................................... 9 2.4.- Fichero de arranque y configuración CRT.S....................................................................... 10 2.5.- Implementación de los tipos de variables............................................................................ 11 2.5.1.- Variables estáticas y automáticas............................................................................. 11 2.5.2.- Los tipos de variables CHAR e INT......................................................................... 12 2.6.- Interfaz entre el C y el lenguaje ensamblador...................................................................... 12 2.6.1.- Llamadas a funciones en ensamblador..................................................................... 12 2.6.2.- Inclusión de instrucciones en ensamblador en el código en C................................... 12 2.7.- Rutinas de servicio de interrupción..................................................................................... 13 2.7.1.- Cambio del vector de interrupción........................................................................... 13 2.7.2.- Activación de las interrupciones.............................................................................. 13 2.7.3.- Rutina de servicio de la interrupción........................................................................ 13 2.8.- Un ejemplo......................................................................................................................... 14

3.- PROGRAMACION DE LA CT6811 EN MODO ENTRENADOR....................................... 17 3.1.- INTRODUCCION.............................................................................................................. 17 3.2.- CONFIGURACION DEL COMPILADOR......................................................................... 17 3.2.1- El fichero de arranque y configuración CTRAMINT.S............................................. 17 3.2.2.- Unificación de programas en ensamblador............................................................... 18 3.2.3.- Situación de las variables al comienzo del fichero en ensamblador........................... 18 3.2.4.- Generación de archivos ejecutables .S19.................................................................. 19 3.2.5.- Resumen de los pasos necesarios para obtener ficheros ejecutables para la RAM interna.................................................................................................................. 19 3.2.6.- El archivo CINT.BAT para compilar programas en C para la RAM interna de la CT6811.................................................................................................................. 22 3.2.7.- Un ejemplo.............................................................................................................. 22 3.3.- REGISTROS DE CONTROL Y VECTORES DE INTERRUPCION................................. 25 3.3.1.- Acceso a los registros de control del 68HC11.......................................................... 25 3.3.2.- Acceso a los vectores de interrupción...................................................................... 26 3.4.- PROGRAMACION DE LOS RECURSOS DEL 68HC11.................................................. 29 3.4.1.- Introducción.......................................................................................................... 29 3.4.2.- Los puertos de ENTRADA/SALIDA...................................................................... 29 3.4.2.1.- Programación del puerto A...................................................................... 29 3.4.2.2.- Programación del puerto B...................................................................... 31 3.4.2.3.- Programación del puerto C...................................................................... 32 3.4.2.4.- Programación del puerto D...................................................................... 32 3.4.2.5.- Programación del puerto E...................................................................... 33 3.4.3.- Programación del SCI........................................................................................... 35 3.4.4.- Programación del SPI........................................................................................... 41 3.4.5.- Programación del temporizador principal............................................................. 45 3.4.6.- Programación de las interrupciones en tiempo real............................................... 47 3.4.7.- Programación de los comparadores...................................................................... 49 3.4.8.- Programación de los capturadores......................................................................... 53 3.4.9.- Programación del acumulador de pulsos............................................................... 55

Page 4: Programación de la tarjeta CT6811 en lenguaje C

Programación de la tarjeta CT6811 en lenguaje C

4

3.4.10.- Programación de la interrupción IRQ.................................................................. 57 3.4.11.- Programación del conversor analógico-digital (A/D)........................................... 59 3.4.12.- Programación de la EEPROM............................................................................. 61

4.- PROGRAMACION DE LA CT6811 EN MODO AUTONOMO.......................................... 63 4.1.- INTRODUCCION............................................................................................................. 63 4.2.- CONFIGURACION DEL COMPILADOR........................................................................ 63 4.2.1.- El fichero de arranque y configuración CTEEPROM.S........................................... 63 4.2.2.- Situación de las variables al comienzo del fichero en ensamblador.......................... 63 4.2.3.- Generación de archivos ejecutables .S19................................................................. 64 4.2.4.- Resumen de los pasos necesarios para obtener ficheros ejecutables para la memoria EEPROM............................................................................................................... 64 4.2.5.- El archivo CEEPROM.BAT para compilar programas para la EEPROM................ 64 4.3.- EJEMPLOS DE PROGRAMAS PARA LA EEPROM....................................................... 67 4.4.- CONSIDERACIONES A TENER EN CUENTA............................................................... 70

5.- LIBRERIAS EN ENSAMBLADOR........................................................................................ 73 5.1.- Librería SCIASM.H para manejo del SCI.......................................................................... 73 5.2.- Librería SPIASM.H para manejo del SPI........................................................................... 73 5.3.- Librería DELAYASM.H para realizar pausas.................................................................... 77

Page 5: Programación de la tarjeta CT6811 en lenguaje C

Programación de la tarjeta CT6811 en lenguaje C

5

PROLOGO

Desde que comenzamos con el microcontrolador 68HC11, allá por Marzo de1995, hemos ido desarrollando aplicaciones cada vez más complejas. Cada poco tiempo‘nacía’ una nueva tarjeta entrenadora que corregía los fallos de las anteriores y añadíamultitud de mejoras. El resultado final ha sido la tarjeta CT6811, que aunque parezca tanpequeña y simple, ha sido pensada hasta el último mílimetro. No hay nada que se hayaintroducido al azar, sino que todo ha sido fruto de una necesidad a nivel práctico.Podemos decir que desde nuestro punto de vista hemos creado la tarjeta “perfecta” paracubrir nuestras necesidades.

Cuando hablamos de la tarjeta CT6811 no sólo nos referimos al circuitoelectrónico, sino a todo el entorno software/hardware. Con el entorno desarrolladopodemos crear sistemas autónomos en muy poco tiempo: robots autónomos, circuitos decontrol de luces, relojes con despertador, adquisición de datos...

Con este libro queremos dar un paso más hacia adelante. Desde el punto de vistaHARDWARE hemos avanzado muchísimo. Así, tenemos la familia de tarjetas CT:CT6811, CT3216, CT3020, CT293 y la familia de periféricos PCT: PCT-595, PCT-293,PCT5916. Sin embargo desde el punto de vista SOFTWARE no hemos podido avanzarmucho. Teníamos una serie de librerías predefinidas en ensamblador y nada más. Coneste libro pretendemos dar un salto a nivel software. Queremos que nuestros sistemas sepuedan programar con un lenguaje de ‘alto nivel’ y queremos desarrollar unas libreríaspara poder controlar todos los recursos del 68HC11 así como los periféricos que sepueden conectar a la tarjeta CT6811.

Este libro se ha escrito fundamentalmente como una herramienta para nosotros.No obstante, pensamos que también le puede ser muy útil a otras personas y eso nos hallevado a difundirlo. Esperamos contribuir un poco más al acercamiento de losuniversitarios hacia el mundo de los microcontroladores. En este mundo, un pocodesconocido para el universitario, hay muchas cosas por hacer y hay muy poca gente quelas sepa hacer.

Nosotros apostamos por los sistemas autónomos e inteligentes, que poco a pocose van abriendo camino a todos los niveles.

GRUPO J&J. MAYO 19971

1 El Grupo J&J actualmente es parte integrante de la empresa MICROBÓTICA S.L.

Page 6: Programación de la tarjeta CT6811 en lenguaje C

Programación de la tarjeta CT6811 en lenguaje C

6

Page 7: Programación de la tarjeta CT6811 en lenguaje C

Programación de la tarjeta CT6811 en lenguaje C

7

1.- INTRODUCCION

1.1.- ¿Qué es un compilador cruzado de C?

Un compilador cruzado es un compilador que se ejecuta en un ordenador (Por ejemplo un PC)pero que genera código ejecutable para una CPU distinta a la del propio ordenador. Para el caso delcompilador cruzado de C utilizado en este libro, el compilador se ejecuta en un PC pero genera códigopara el microcontrolador 68HC11.

1.2.- Lenguajes de alto nivel VS lenguaje ensamblador

Normalmente los microcontroladores se programan en lenguaje ensamblador porque suelen serprogramas cortos y además es necesario conocer con un alto grado de detalle lo que ocupa el programa yla velocidad a la que se va a ejecutar. Al emplear un lenguaje de alto nivel ganamos en comodidad,abstracción, portabilidad, legibilidad y se necesita menor tiempo de codificación, pero por el contrario sepierde un poco la noción de qué es lo que está pasando dentro del microcontrolador. Además, elvolumen de código generado es mucho mayor que el que se hubiese obtenido programando el mismoprograma directamente en ensamblador.

Para obtener el mejor rendimiento a nuestros programas, lo ideal es utilizar cada lenguaje paraun propósito diferente: El lenguaje ensamblador será necesario utilizarlo cuando queramos optimizarrutinas en tiempo y espacio, situación que suele ser muy corriente en el mundo de losmicrocontroladores. Los lenguajes de alto nivel es mejor emplearlos para la descripción de algoritmosque se deban ejecutar en el micro, ya que su implementación directa en ensamblador puede resultar muytediosa de codificar y de depurar.

Finalmente, dentro de los lenguajes de alto nivel, el lenguaje C es el más adecuado para laprogramación de microcontroladores puesto que es un lenguaje que permite estar muy en contacto con lamáquina que hay debajo, a la vez que es un lenguaje de alto nivel.

1.3.- Objetivos

Los principales objetivos de este libro son:

- Describir brevemente cómo funciona el compilador de imagecraft.- Adaptar este compilador para trabajar con la tarjeta CT6811. (La configuración también será

válida para trabajar con tarjetas equivalentes, como la del MIT).- Presentar ejemplos de programación de los recursos del 68HC11- Presentar unas librerías optimizadas para la gestión de los recursos del 68HC11

1.4.- Cómo leer este libro

Este libro contiene dos partes diferenciadas. En una parte se muestra el funcionamiento delcompilador y cómo configurarlo para trabajar con la CT6811. En otra parte se muestran ejemplos deprogramación en C para la tarjeta CT6811. Si el lector sólo está interesado en saber cómo se compilay cómo hay que programar, puede saltar directamente a la sección 3.4.- PROGRAMACION DELOS RECURSOS DEL 68HC11. Si el lector está interesado en saber las caracterísitcas generales delcompilador y quiere aprender a configurarlo debe comenzar desde el principio.

Page 8: Programación de la tarjeta CT6811 en lenguaje C

Programación de la tarjeta CT6811 en lenguaje C

8

Page 9: Programación de la tarjeta CT6811 en lenguaje C

Programación de la tarjeta CT6811 en lenguaje C

9

2.- EL COMPILADOR DE C DE IMAGECRAFT

2.1.- Características del compilador

• Compilador exclusivo para el 68HC11: Otros compiladores de C están diseñados paragenerar código para microcontroladores y microprocesadores muy diversos, lo que complicaenormemente su utilización.

• Fácil llamada a rutinas en ensamblador: Es posible programar rutinas directamente enensamblador y llamarlas desde los programas en C

• Inserción de intrucciones en ensamblador: Es posible insertar instrucciones enensamblador en el propio código en C, utilizando la instrucción ASM.

• Generación de ficheros en ensamblador: Este compilador no generar archivos ejecutablesdirectamente, sino que crea archivos en ensamblador que luego se convierten en ejecutables.Estos archivos en ensamblador pueden ser modificados por el usuario lo que permiteoptimizar el código.

• Fichero ejecutable en formato .S19: El fichero ejecutable generado se encuentra en elformato .S19 que es el utilizado por los programas MCBOOT y DOWNMCU para envíarprogramas a la CT6811.

• Fácil configuración de la situación del código, pila y datos• El lenguaje soportado es ANSI C

2.2.- Ficheros que componen el compilador

• ICC11.EXE :Programa principal del compilador. Este programa se llama a todos losdemás.

• ICPP.EXE: Preprocesador de C• ICCOM11.EXE: Compilador de C propiamente dicho. Transforma archivos .C en archivos

en ensamblador con extensión .S• IASM11.EXE: Ensamblador utilizado para convertir los ficheros .S en fichero .S19• CRT.S: Fichero de Arranque y configuración

2.3.- Funcionamiento del compilador

El funcionamiento del compilador es como el indicado en la figura 1. Primero se toma unarchivo en C, se compila y se obtiene un archivo .S en ensamblador. Este archivo se vuelve a compilarutilizando el ensamblador y se crea un ejecutable con extensión .S19. En la figura 2 se muestra unejemplo de cómo se compilaría un programa llamado prueba.c. Utilizando el ejecutable ICC11 con elparámetro -S se compila el programa y se genera el fichero PRUEBA.S en ensamblador. Este programase ensambla utilizando el ensamblador IAS11.

El parámetro -S se utiliza para que el compilador sólo genere un fichero .s. En la figura 3 semuestra otra forma de compilar. En este caso sólo es necesario llamar al programa ICC11, el cual seencarga de llamar al resto de ejecutables (preprocesador, compilador y ensamblador). Se generadirectamente el archivo ejecutable PRUEBA.S19. Al utilizar esta segunda opción se incluye en elejecutable el archivo CRT.S que es un archivo en ensamblador que contiene el arranque y configuracióndel sistema. Al llamar al programa ICC11 se utiliza el parámetro -o prueba para que se genere el

Fichero fuente .C

COMPILADOR Ficheros en ensamblador.S

ENSAMBLADOR Fichero ejecutable.S19

Figura 1: Funcionamiento del compilador de C

Page 10: Programación de la tarjeta CT6811 en lenguaje C

Programación de la tarjeta CT6811 en lenguaje C

10

archivo PRUEBA.S19. La primera forma de compilar, la empleada en la figura 2, es laforma que más se utilizará.

2.4.- EL FICHERO DE ARRANQUE Y CONFIGURACION CRT.S

Antes de ejecutar programas en una tarjeta entrenadora es necesario configurarlos para quefuncionen correctamente en dicha entrenadora. Mas concretamente, tendremos que indicar la direcciónde comienzo del código, de los datos y de la pila. En la figura 4 se muestra un fragmento del ficheroCRT.S que viene por defecto con el compilador. Este archivo está pensado para trabajar con laentrenadora de motorola que incluye el programa BUFFALO grabado en la EEPROM.

Se pueden especificar dos tipos de segmentos: segmento de código y segmento de datos. Elsegmento de código es la porción de memoria en la que se va a encontrar el código. Este segmento quedaidentificado por la directiva sect 0. El segmento de datos es el que va a contener los datos. Quedaidentificado por la directiva sect 1. En el ejemplo de la figura 4 los datos se encuentran situados a partirde la dirección $8000 y el código a partir de la dirección $4000.

Siguiendo el ejemplo de la figura 4, el programa en sí comienza en la línea 11. Primero seconfigura la pila y después se realiza un salto al comienzo del programa, que está definido por laetiqueta _main. El resto del código que aparece son diferentes rutinas implementadas en ensambladorpara manejar la entrenadora de motorola.

C:\6811\ICC\PRUEBA>icc11 -S prueba.c

C:\6811\ICC\PRUEBA>ias11 prueba.s

C:\6811\ICC\PRUEBA>dir

Volumen en unidad C es GRUPO JJ Número de serie de volumen es 395D-1CD5 Directorio de C:\6811\ICC\PRUEBA

. <DIR> 04-20-97 8:22a

.. <DIR> 04-20-97 8:22aPRUEBA C 702 04-16-97 11:19aPRUEBA S19 36 04-20-97 8:23aPRUEBA S 59 04-20-97 8:23a 5 archivo(s) 797 bytes 739377152 bytes libres

C:\6811\ICC\PRUEBA>_

Figura 2: Ejemplo de compilación del programa PRUEBA.C

C:\6811\ICC\PRUEBA>icc11 prueba.c -o prueba

C:\6811\ICC\PRUEBA>dir

Volumen en unidad C es GRUPO JJ Número de serie de volumen es 395D-1CD5 Directorio de C:\6811\ICC\PRUEBA

. <DIR> 04-20-97 8:22a

.. <DIR> 04-20-97 8:22aPRUEBA C 702 04-16-97 11:19aPRUEBA S19 492 04-20-97 8:32aPRUEBA S 59 04-20-97 8:32aCRT S 1480 07-06-96 6:41a 6 archivo(s) 2733 bytes 735969280 bytes libres

C:\6811\ICC\PRUEBA>_

Figura 3: Otra forma de compilar el programa PRUEBA.C

Page 11: Programación de la tarjeta CT6811 en lenguaje C

Programación de la tarjeta CT6811 en lenguaje C

11

Para utilizar el comilador de C con la tarjeta CT6811 habrá que utilizar diferentes archivos deinicialización dependiendo de si estamos trabajando en modo entrenador, sólo con la memoria RAMinterna, o en modo autónomo, con la memoria RAM y EEPROM interna.

2.5.- IMPLEMENTACION DE LOS TIPOS DE VARIABLES

2.5.1.- Variables estáticas y automáticas

Desde un punto de vista de la situación de las variables en memoria, en C se definen dos tiposde variables: variables estáticas y varibles automáticas. Las variables variables estáticas conservan suvalor durante toda la ejecución del programa. Las variables automáticas desaparecen cuando se sale delámbito en el que se está trabajando.

Las variables automáticas se almacenan en la pila, de tal manera que al salir de losprocedimientos la pila se vacía y se pierde el valor de las variables. Las variables estáticas se sitúan enposiciones fijas de memoria. La situación de estas variables se configura en el fichero CRT.S.

Debido a estas implementaciones hay que tener en cuenta varias cosas. Al utilizar variablesestáticas se genera menor código y los programas son más cortos y rápidos. En contraposición seutiliza más cantidad de memoria puesto que todas las funciones tienen que tener sus variables enmemoria, se estén o no ejecutando. Las variables automáticas se almacenan en la pila y por tanto habráque tener en cuenta el tamaño de la pila y el tamaño de las variables automáticas para que no seproduzcan desbordamientos de la pila.

Por defecto todas las variables locales son automáticas y todas las variables globales sonestáticas. Las variables globales no pueden ser automáticas pero las locales sí pueden ser estáticas, noperdiendo su valor al finalizar la función.

Los parámetros de las funciones se pasan todos a través de la pila, con lo que también habrá quetenerlos en cuenta para calcular el tamaño de la pila.

Como regla general hay que decir que cuantas más variables estáticas se utilicen y cuantosmenos parámetros se pasen a las funciones, más optimo será el código en velocidad pero los datosocuparán más memoria. Y cuantas más variables locales y parámetros en las funciones se utilicen,menor sera la memoria empleada para variables pero el código será mayor y la ejecución más lenta.

* define starting addressessect 0 * code

org $4000sect 1 * data

org $8000stackbase equ $7ffb** start of code*

sect 0lds #stackbasejsr _mainswi

__lsrd: cpy #0beq __lsrd_donelsrddeybra __lsrd

Figura 4: Fragmento del fichero de arranque y configuraciónCRT.S

Page 12: Programación de la tarjeta CT6811 en lenguaje C

Programación de la tarjeta CT6811 en lenguaje C

12

2.5.2.- Los tipos de variables CHAR e INT.

Las variables de tipo char ocupan 1 byte de memoria. Las variables de tipo int ocupan 2 bytes.Es indiferente que se utilice el modificador short. Una variable del tipo short int también ocupará 2bytes. Todos los punteros ocupan 2 bytes.

2.6.- INTERFAZ ENTRE EL C Y EL LENGUAJE ENSAMBLADOR

2.6.1.- Llamadas a funciones en ensamblador

Es posible llamar a funciones realizadas en ensamblador directamente desde nuestrosprogramas en C. La única condición que se debe cumplir es que las etiquetas que definen el comienzo deuna función en ensamblador deben comenzar con el carácter _.

En la figura 5 se muestra un programa en C que simplemente llama a la funcion ledon( ) paraencender un led. La función ledon se ha implementado en ensamblador y su código se puede ver en lafigura 6. Obsérvese que en el programa fuente en C noha hecho falta especificar que la función ledon() esexterna. Al compilar el programa en C se generará unsalto a la etiqueta _ledon. Por ello al implementar estafunción en ensamblador deberemos especificar laetiqueta de entrada como _ledon, como se muestra en lafigura 6.

Si se definiese una función conparámetros de entrada la cosa sería un poco máscomplicada.

2.6.2.- Inclusión de instrucciones en ensamblador en el código en C

Algunas veces son necesarias ciertas instrucciones de control del 68HC11 que se encuentran enensamblador pero que no se definen en el compilador de C como por ejemplo RTI, WAIT, SWI... Parapoder incluir estas instrucciones en nuestro código en C el compilador dispone de la instrucción ASMque permite introducir una instrucción directamente en ensamblador. La sintaxis de esta instrucción esASM(“ línea en ensamblador”). Esta instrucción lo que hace es pasar directamente al ensamblador lacadena enviada. La cadena que se pasa como argumento a la instrucción ASM puede ser incorrecta. Elcompilador de C no la analizará. Simplemente la copiará tal cual en el programa en ensamblador. Seráel ensamblador en la etapa de ensamblado el que determinará si es o no correcta.

Hay una serie de reglas importantes a la hora de utilizar la instrucción ASM:

1. Si se escribe una instrucción en ensamblador hay que colocar por lo menos un espacio al comienzode la cadena, para indicar al ensamblador que es una instrucción y no una etiqueta. Ejemplos:

• Correcto: asm (“ RTI”);• Incorrecto: asm (“RTI”);

2. Las etiquetas se deben escribir justo a la izquierda de la cadena, sin espacios intermedios:• Correcto: asm (“bucle LDAA #$40”);• Incorrecto: asm (“ bucle LDAA #$40”);

main(){ ledon();}

Figura 5: Programa en C que llama a unafunción implementada en ensamblador

sect 0_ledon ; Comienzo rutina ledon()

LDAA #$40STAA $1000RTS

Figura 6: Implementación en ensamblador de lafunción ledon()

Page 13: Programación de la tarjeta CT6811 en lenguaje C

Programación de la tarjeta CT6811 en lenguaje C

13

Es posible hacer referencia a variables en c desde lainstrucción asm. Para ello utilizamos el carácter %. En lafigura 7 se muestra un ejemplo muy simple. Queremos cargaren el acumulador A el valor de la variable c. La instrucciónasm(“ LDAA %c”) lo soluciona. El carácter % hace que sele pase al ensamblador la etiqueta asociada a la variablesituada a continuación del carácter %, en vez del identificadorde la propia variable.

2.7.- RUTINAS DE SERVICIO DE INTERRUPCION

A la hora de hacer rutinas de servicio de interrupción hay que tener en cuenta los tres puntossiguientes:

1. Cambio del vector de interrupción2. Activación de las interrupciones3. Codificación de la rutina de servicio de interrupción

En la figura 8 semuestra el modelo a seguir parala puesta en funcionamiento delas rutinas de servicio deinterrupción.

2.7.1.- Cambio del vector deinterrupción

En el modelo de lafigura 8 se ha modificado elvector de interrupción de ladirección 0xFFD6 para queapunte a la rutina de servicio deinterrupción rsi(). Primero sedefine la situación del vector deinterrupción por medio de unainstrucción define. Lo queestamos indicando alcompilador es que vint es unaconstante que representa unvalor entero que debe estar situado en la dirección 0xFFD6. Para hacer que este valor apunte a la rutinaque nosotros queramos simplemente se realiza la asignación vint = (unsigned int)rsi; que introduce ladirección de comienzo de la función rsi() en la dirección 0xFFD6.

2.7.2.- Activación de las interrupciones

Una vez que se ha cambiado el vector de interrupción es necesario activar las interrupciones.No existe ninguna instrucción en el estándar ANSI C que permita hacer eso, por lo que se recurre aescribir directamente la instrucción en ensamblador mediante la instrucción asm (“ CLI”). Si se quiereninhibir las interrupciones bastará con escribir asm(“ SEI”);

2.7.3.- Rutina de servicio de la interrupción

Las rutinas de atención a las interrupciones deben terminar con la instrucción RTI, en lugar dela instrucción RTS que es la utilizada para retornar de una subrutina. En el estándar ANSI C no se

main(){ static char c;

c=leer_car(); asm (“ LDAA %c”); . .}

Figura 7: Ejemplo de carga de lavariable c en el acumulador A

/* Vector de interrupción */#define vint (*(unsigned int *)0xFFD6)

/* Rutina de servicio de interrupción */void rsi(){ . . . asm (“ RTI”);}

main(){ /* Cambiar vector de interrupción */ vint = (unsigned int)rsi;

/* Activar las interrupciones */ asm (“ CLI”); . . .}

Figura 8: Programa modelo de una rutina de servicio deinterrupción

Page 14: Programación de la tarjeta CT6811 en lenguaje C

Programación de la tarjeta CT6811 en lenguaje C

14

contempla ninguna palabra reservada para indicar al compilador que una función en C esuna rutina de servicio de interrupción y que por tanto debe finalizar con la instrucción RTI en lugar deRTS. Por ello es necesario introducir directamente la instrucción RTI al final de la rutina de servicio deinterrupción por medio de la instrucción asm (“ RTI”). Pero esto tiene problemas. El compilar puedehaber generado un código que utilice la pila. Antes de salir de la rutina de interrupción habrá que vaciarpor completo la pila o de lo contrario llegará un momento que se desbordará.

Para solucionar esto se utiliza el truco de la subrutina de servicio de interrupción. Para cadainterrupción que tomemos se definen dos funciones. Una función será la rutina de servicio deinterrupción y la otra será la subrutina de servicio de interrupción. El nuevo vector de interrupción semodificará para que apunte a la rutina de servicio de interrupción, la cual debe acabar con la instrucciónasm (“ RTI”). En la subrutina de servicio de interrupción se introduce el código necesario para atendera la interrupción. A continuación se muestra un esquema de funcionamiento:

2.8.- UN EJEMPLO

A continuación se muestra un pequeño programa en C que sirve para hacer que un led situadoen el bit 6 del puerto A se ponga a parpadear. Este ejemplo no está adaptado a ninguna entrenadora,simplemente se compila el archivo .C y se genera el archivo equivalente .S. Para que funcione con unaentrenadora concreta, como por ejemplo la CT6811, habrá que utilizar un archivo de configuraciónespecial y realizar algunas modificaciones en los ficheros .S. Esto se trata en el apartado 3:Programación de la tarjeta CT6811 en modo entrenador.

En la figura 9 se muestra el codigo en C.

void ssi()/* Subrutina de servicio de interrupción */{ /* Codigo */ ... ...}

void rsi()/* Rutina de servicio de interrupción */{ ssi(); /* Llamar a la subrutina de servicio de interrupción */ asm (“ RTI”); /* Retorno de interrupción */}

main(){ /* Cambiar el vector de interrupción para que apunte a rsi() */ ... ...}

Page 15: Programación de la tarjeta CT6811 en lenguaje C

Programación de la tarjeta CT6811 en lenguaje C

15

En la figura 10 se puede ver el archivo en ensamblador (LEDP.S) generado. Para generarlo se hatecleado: ICC11 -S ledp.c

Obsérvese que existen dos secciones.En la sección 0 se encuentra el código. En lasección 1 se encuentra la única variable quehay en el programa. Esta variable es global.

Ensamblando directamente elprograma LEDP.S no conseguimos obtener elejecutable LEDP.S19 deseado. Debemosensamblarlo junto con un fichero .S deconfiguración que indique la posicón enmemoria de las dos secciones.

/* +------------------------------------------------------------------------+ ¦ LEDP.C (C) GRUPO J&J. ABRIL 1997 ¦ ¦------------------------------------------------------------------------¦ ¦ Programa ejemplo para ser ejecutado en la tarjeta CT6811. ¦ ¦ Este programa se debe cargar en la RAM interna del 6811. ¦ ¦ ¦ ¦ Ejemplo para encender el led de la tarjeta CT6811. ¦ +------------------------------------------------------------------------+ */

#define PORTA (*(unsigned char *)0x1000)

unsigned int i;

main(){ for (;;) { PORTA^=0x40; for (i=0; i<0x8000; i++); }}

Figura 9: Programa LEDP.C

sect 0_main:L2.ledp:

ldab 4096clraeorb #64stab 4096ldd #0std _ijmp L9.ledp

L6.ledp:L7.ledp:

ldd _iaddd #1std _i

L9.ledp:ldd _icpd #-32768blo L6.ledpjmp L2.ledp

L1.ledp:sect 1

_i:RMB 2

Figura 10: Fichero LEDP.S

Page 16: Programación de la tarjeta CT6811 en lenguaje C

Programación de la tarjeta CT6811 en lenguaje C

16

Page 17: Programación de la tarjeta CT6811 en lenguaje C

Programación de la tarjeta CT6811 en lenguaje C

17

3.- PROGRAMACION DE LA CT6811 EN MODOENTRENADOR

3.1.- INTRODUCCION

El objetivo es configurar el compilador de C para quefuncione con los 256 bytes de RAM de la CT6811. Lo que sequiere es crear programas en C para ser probados en la RAMinterna del 68HC11, es decir, en el modo entrenador de latarjeta CT6811.

El mapa de memoria de la tarjeta CT6811 se muestraen la figura 11. Al trabajar en modo entrenador lo que nosinteresa son los 256 bytes de RAM interna, situados desde ladirección $00 hasta la $FF, y los registros de control.

Para poder utilizar el compilador de C tendremos queconfigurarlo para que se genere código para este mapa dememoria. El código debe empezar en la dirección $0000 y nopuede sobrepasar la dirección $FF, o de lo contrariodesbordaremos la memoria interna del 68HC11.

Tanto el código, como los datos y la pila se debensituar en la RAM interna. Por ello podemos hablar de unúnico segmento de trabajo.

3.2.- CONFIGURACION DEL COMPILADOR

3.2.1.- El fichero de arranque y configuración CTRAMINT.S

El fichero de arranque y configuración empleado se muestra en la figura 12. Se ha llamadoCTRAMINT.S para indica que es para generar código y datos para la ram interna de la CT6811

En este archivo se sitúa el comienzo de todos los programas a partir de la dirección $0000 quees donde empieza la RAM interna. Este programa realiza un salto a la etiqueta _main que es el nombreque recibe la etique de comienzo del programa principal. Si se retorna del programa principal, se entraen un bucle infinito para que el 68HC11 no ejecute instrucciones al azar.

$0000

$1000

$B600

$E000

RAM INTERNA

RGISTROSDE CONTROL

EEPROM

ROM

BOOTSTRAPROM

Figura 11: Mapa de memoria de laCT6811

* +------------------------------------------------------------------------+* ¦ CTRAMINT.S (C) GRUPO J&J. ABRIL 1997 ¦* ¦------------------------------------------------------------------------¦* ¦ Fichero de arranque y configuración para trabajar con la tarjeta ¦* ¦ CT6811 en modo entrenador. ¦* +------------------------------------------------------------------------+ */

ORG $0000 ; Comienzo de la RAM interna

jsr _main ; Saltar al programa principalinf bra inf ; ¡Bucle infinito!

Figura 12: Fichero de arranque y configuración para trabajar con la CT6811 en modoentrenador

Page 18: Programación de la tarjeta CT6811 en lenguaje C

Programación de la tarjeta CT6811 en lenguaje C

18

Este archivo de configuración puede ser modificado. Por ejemplo, si el propioprograma principal en C nunca termina, lo que suele ser habitual, se puede eliminar la última línea delarchivo CTRAMINT.S con lo que se ahorran bytes de memoria. Teniendo únicamente 256 bytes dememoria hay que aprovechas hasta el último byte.

Puesto que para que la CT6811 funcione en modo entrenador ,el 68HC11 debe arrancar en elmodo BOOTSTRAP, con lo que la pila ya se encuentra inicializada en la dirección $FF y no seránecesario inicializarla en el archivo de arranque y configuración.

Obsérvese que en el fichero de arranque y configuración no se han definido secciones. Esto esdebido a que el código, los datos y la pila se deben situar dentro de la misma sección. Un programa deestas características es lo que denominaremos programa unificado.

3.2.2.- Unificación de programas en ensamblador

El código en ensamblador generado por el compilador de C no se encuentra unificado. Esdecir, que las variables se sitúan en la sección 1 y el código en la sección 0. Para solucionar esto seutiliza el programa UNIFICA.EXE desarrollado por el Grupo J&J. Este programa simplemente toma unfichero en ensamblador y genera otro fichero igual que el original pero en el que se han eliminado todaslas secciones. En la figura 13 se muestra un ejemplo de utilización. A partir del programa prueba.s nounificado se genera el fichero pruebau.s ya unificado.

Será con los programas unificados con los que se trabajará cuando queramos utilizar la CT6811en modo entrenador.

3.2.3.- Situación de las variables al comienzo del fichero en ensamblador

No se pueden ensamblar los archivos unificados junto con el archivo de arranque yconfiguración para generar un ejecutable con extensión .S19 que se pueda cargar en la RAM interna dela CT6811. Es necesario realizar una transformación más al archivo en ensamblador. El compiladorsitúa todas las variables estáticas al final del fichero en ensamblador. Para poder ensamblar un programade estas caracteristicas que comience en la RAM interna, es necesario que las variables se sitúen alcomienzo del código. Los programas que comiencen en otras direcciones de memoria fuera de la RAMinterna no sufrirán esta restricción, sus variables podrán estar en cualquier sitio. Sin embargo, losprogramas para la RAM interna deben sufrir estas restricciones por motivos que están fuera de losobjetivos de este libro.2

Para solucionar esto se utiliza el programa GETVARS.EXE, también desarrollado por elGrupo J&J, que sirve para ‘extraer’ todas las variables de un fichero en ensamblador. En la figura 14 semuestra cómo funciona este programa. Con el primer comando se genera el fichero prueba.s sinvariables a partir del fichero pruebau.s. El programa getvars imprime en pantalla la única variable queha encontrado. Con el siguiente comando se hace lo mismo pero se guarda la variable extraida en el

2Cuando se trabaja en la RAM interna, el ensamblador genera un código más optimizado puesto que el68HC11 permite utilizar direccionamiento directo.

C:\6811\ICC\CT68INT>unifica prueba.s pruebau.s

UNIFICA V1.0 (C) GRUPO J&J. Abril 1997.Generación de código unificado en ensamblador

Fichero a Filtrar: prueba.sFichero destino : pruebau.s

C:\6811\ICC\CT68INT>

Figura 13: Generación del fichero unificado pruebau.s a partir del fichero nounificado prueba.s

Page 19: Programación de la tarjeta CT6811 en lenguaje C

Programación de la tarjeta CT6811 en lenguaje C

19

fichero vars. Finalmente, con el último comando se genera el archivo pruebaf.s que ya estálisto para ser ensamblado junto con el archivo de arranque y configuración ctramint.s

3.2.4.- Generación de archivos ejecutables .S19

Una vez que se tienen todos los ficheros .S y se quiere obtener el fichero ejecutable conextensión .S19, se utilizará el ensamblador IAS11.EXE según se muestra en la figura 15. En eseejemplo se genera el fichero PROGRAMA.S19 a partir de los ficheros en ensamblador PRUEBA1.S,PRUEBA2.S y el fichero de arranque y configuración CTRAMINT.S. El parámetro -o seguido porprograma indica al ensamblador que se genera un archivo ejecutable con nombre programa.s19. Si nose especifica este parámetro el ensamblador generará el fichero ejecutable con el nombre del primerarchivo .S que se haya pasado como argumento.

3.2.5.- Resumen de los pasos necesario para obtener ficheros ejecutables para la RAM interna

En la figura 16 se muestra un esquema con todos los pasos que hay que realizar aplicados alprograma ledp.C para generar el fichero ejecutable ledp.S19.

Los pasos que hay que realizar en general son:

• Compilar todos los archivos .C que integren el programa final. Para ello utilizar: ICC11 -S fichero.cCon esto conseguimos tener una serie de archivos .S en ensamblador.• Aplicar a cada archivo .S la unificación mediante el programa UNIFICA.EXE• Situar todas las variables al comienzo del código con el progrma GETVARS.EXE• Ensamblar todos los ficheros .S ya modificados junto con el archivo de arranque y configuración

CTRAMINT.S• Ya se dispone de un archivo .S19 listo para ser enviado a la tarjeta CT6811.

C:\6811\ICC\CT68INT>getvars pruebau.s prueba.s_i: RMB 2

C:\6811\ICC\CT68INT>getvars pruebau.s prueba.s > vars

C:\6811\ICC\CT68INT>copy vars+prueba.s pruebaf.sVARSPRUEBA.S 1 archivo(s) copiado(s)

C:\6811\ICC\CT68INT>_

Figura 14: Generación del fichero pruebaf.s con las variables al comienzo

C:\6811\ICC\CT68INT>ias11 -o programa ctramint.s prueba1.s prueba2.s

C:\6811\ICC\CT68INT>dir programa.s19

Volumen en unidad C es GRUPO JJ Número de serie de volumen es 395D-1CD5 Directorio de C:\6811\ICC\CT68INT

PROGRAMA S19 152 04-27-97 10:15a 1 archivo(s) 152 bytes 728432640 bytes libres

C:\6811\ICC\CT68INT>_

Figura 15: Generación del fichero ejecutable programa.s19 a partir de los ficherosprueba1.s, prueba2.s y ctramint.s.

Page 20: Programación de la tarjeta CT6811 en lenguaje C

Programación de la tarjeta CT6811 en lenguaje C

20

Por si el lector tiene curiosidad, se van a presentar los distintos ficheros intermedios generadosen el ejemplo de la figura 16. En la figura 17 se muestra el programa ledp.C y en la figura 18 el ficheroledp.S ya compilado.

COMPILADORDE C

ICC11 -S ledp.c

UNIFICACION

UNIFICA ledp.s ledpu.s

MODIFICACION DEVARIABLES

ENSAMBLADOR

getvars ledpu.s ledpv.s > varscopy vars+ledpv ledpf

IAS11 -o ledp ctramint.s ledpfFichero ledp.S19

Fichero ledp.c

Figura 16: Pasos a realizar para crear el fichero ledp.S19 a partir del fichero ledp.C

/* +------------------------------------------------------------------------+ ¦ LEDP.C (C) GRUPO J&J. ABRIL 1997 ¦ ¦------------------------------------------------------------------------¦ ¦ Programa ejemplo para ser ejecutado en la tarjeta CT6811. ¦ ¦ Este programa se debe cargar en la RAM interna del 6811. ¦ ¦ ¦ ¦ Ejemplo para encender el led de la tarjeta CT6811. ¦ +------------------------------------------------------------------------+ */

#define PORTA (*(unsigned char *)0x1000)

unsigned int i;

main(){ for (;;) { PORTA^=0x40; for (i=0; i<0x8000; i++); }}

Figura 17: Programa LEDP.C

sect 0_main:L2.ledp:

ldab 4096clraeorb #64stab 4096ldd #0std _ijmp L9.ledp

L6.ledp:L7.ledp:

ldd _iaddd #1std _i

L9.ledp:ldd _icpd #-32768blo L6.ledpjmp L2.ledp

L1.ledp:sect 1

_i:RMB 2

Figura 18: Fichero LEDP.S recién compilado

Page 21: Programación de la tarjeta CT6811 en lenguaje C

Programación de la tarjeta CT6811 en lenguaje C

21

En la figura 19 se muestra el programa ledpu.s que ya ha sido unificado. La únicadiferencia es que se han suprimido las directivas sect 0 y sect 1.

En la figura 20 se muestra el archivo LEDPF.S. Es igual que el archivo unificado LEDPU.Scon la diferencia que la variable está definida al comienzo en vez de al final.

_main:L2.ledp:

ldab 4096clraeorb #64stab 4096ldd #0std _ijmp L9.ledp

L6.ledp:L7.ledp:

ldd _iaddd #1std _i

L9.ledp:ldd _icpd #-32768blo L6.ledpjmp L2.ledp

L1.ledp:

_i:RMB 2

Figura 19: Fichero LEDPU.S

_i:RMB 2

_main:L2.ledp:

ldab 4096clraeorb #64stab 4096ldd #0std _ijmp L9.ledp

L6.ledp:L7.ledp:

ldd _iaddd #1std _i

L9.ledp:ldd _icpd #-32768blo L6.ledpjmp L2.ledp

L1.ledp:

Figura 20: Fichero LEDPF.S listo para ser ensamblado

Page 22: Programación de la tarjeta CT6811 en lenguaje C

Programación de la tarjeta CT6811 en lenguaje C

22

3.2.6.- El archivo CINT.BAT para compilar programas en C para la RAM interna de la CT6811

En la figura 21 se muestra el archivo .BAT creado para realizar la compilación automática delos programas en C.

Con este archivo, que puede ser modificado por el usuario para adaptarlo a sus necesidades, esmuy fácil generar archivos ejecutables .S19 directamente. En el apartado 3.2.7 se muestra cómocompilar el archivo LEDP.C para generar el archivo LEDP.S19 que será enviado a la tarjeta CT6811.

3.2.7.- Un ejemplo

En la figura 22 se muestran los comandos necesarios para compilar el programa LEDP.C,mostrado en la figura 17, generar el archivo LEDP.S19 y enviárselo a la CT6811 por medio delprograma DOWNMCU.EXE. En el ejemplo se supone que la CT6811 se encuentra conectada alCOM2.

A partir de ahora ya disponemos de las herramientas necesarias para empezar a generarprograma en C para el 68HC11.

@REM@REM ------------- Compilar de .c a .s ------------------@REM@icc11 -S %1.c@REM@REM ------------ Generar fichero en ensamblador unificado -------@REM@unifica %1.s temp.s@REM@REM ------------ Eliminación de las variables RMB ---------------@REM@getvars temp.s temp2.s > %1.var@REM@REM ------------ Generación del fichero .s final -----------------@REM@copy %1.var+temp2.s %1.s > NUL@REM@REM ------------- Borrar ficheros temporales --------@del temp.s > NUL@del temp2.s > NUL@REM@REM ------------ Generar fichero .S19 ---------------------@REM@ias11 -o %1 ctramint.s %1.s

Figura 21: Fichero CINT.BAT para la compilación automática de los programas en C

Page 23: Programación de la tarjeta CT6811 en lenguaje C

Programación de la tarjeta CT6811 en lenguaje C

23

C:\6811\ICC\CT68INT>cint ledp

UNIFICA V1.0 (C) GRUPO J&J. Abril 1997.Generación de código unificado en ensamblador

Fichero a Filtrar: ledp.sFichero destino : temp.s

C:\6811\ICC\CT68INT>C:\6811\ICC\CT68INT>downmcu ledp -com2

DOWN-MCU. V1.0 (C) GRUPO J&J. Noviembre-1996.Envío de programas a la entrenadora

Fichero a enviar: .\ledp.S19Puerto serie: COM2

Pulse reset en la entrenadora...Transmitiendo: >>>>>..>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>......................................................................................................................................................................................................................OK!Envío correctoTamaño del programa: 40 bytes

C:\6811\ICC\CT68INT>

Figura 22: Ejemplo de compilación del programa LEDP.C y envío a la CT6811

Page 24: Programación de la tarjeta CT6811 en lenguaje C

Programación de la tarjeta CT6811 en lenguaje C

24

Page 25: Programación de la tarjeta CT6811 en lenguaje C

Programación de la tarjeta CT6811 en lenguaje C

25

3.3.- REGISTROS DE CONTROL Y VECTORES DE INTERRUPCION

3.3.1.- Acceso a los registros de control del 68HC11

Para controlar cualquier recurso interno del 68HC11 es necesario acceder a los registros decontrol que se encuentran situados en el mapa de memoria entre las direcciones $1000 y $103F. Laforma más optimizada de acceder a estos registros es como se indica en la figura 23. En este ejemplo seenvía el valor $FF al puerto A y se vuelve a leer.

Para facilitar el acceso a todos los registros de control, se han incluido todas las definiciones enel fichero REGS6811.H, que se muestra a continuación.

/* +------------------------------------------------------------------------+ ¦ REGS6811.H (C) GRUPO J&J. ABRIL 1997 ¦ ¦------------------------------------------------------------------------¦ ¦ Fichero que contiene todos los registros internos del 68HC11. ¦ ¦ ¦ +------------------------------------------------------------------------+ */

#define PORTA (*(unsigned char *)0x1000)#define PIOC (*(unsigned char *)0x1002)#define PORTC (*(unsigned char *)0x1003)#define PORTB (*(unsigned char *)0x1004)#define PORTCL (*(unsigned char *)0x1005)#define DDRC (*(unsigned char *)0x1007)#define PORTD (*(unsigned char *)0x1008)#define DDRD (*(unsigned char *)0x1009)#define PORTE (*(unsigned char *)0x100A)#define CFORC (*(unsigned char *)0x100B)#define OC1M (*(unsigned char *)0x100C)#define OC1D (*(unsigned char *)0x100D)

#define TCNT (*(unsigned int *)0x100E)#define TIC1 (*(unsigned int *)0x1010)#define TIC2 (*(unsigned int *)0x1012)#define TIC3 (*(unsigned int *)0x1014)#define TOC1 (*(unsigned int *)0x1016)#define TOC2 (*(unsigned int *)0x1018)#define TOC3 (*(unsigned int *)0x101A)#define TOC4 (*(unsigned int *)0x101C)#define TOC5 (*(unsigned int *)0x101E)

#define TCTL1 (*(unsigned char *)0x1020)#define TCTL2 (*(unsigned char *)0x1021)#define TMSK1 (*(unsigned char *)0x1022)#define TFLG1 (*(unsigned char *)0x1023)#define TMSK2 (*(unsigned char *)0x1024)#define TFLG2 (*(unsigned char *)0x1025)#define PACTL (*(unsigned char *)0x1026)#define PACNT (*(unsigned char *)0x1027)#define SPCR (*(unsigned char *)0x1028)#define SPSR (*(unsigned char *)0x1029)#define SPDR (*(unsigned char *)0x102A)#define BAUD (*(unsigned char *)0x102B)#define SCCR1 (*(unsigned char *)0x102C)#define SCCR2 (*(unsigned char *)0x102D)#define SCSR (*(unsigned char *)0x102E)#define SCDR (*(unsigned char *)0x102F)#define ADCTL (*(unsigned char *)0x1030)#define ADR1 (*(unsigned char *)0x1031)

#define porta (*(unsigned char *)0x1000)

char i;

main(){ porta=0xFF; /* Envio de datos al puerto A */ i=porta; /* Lectura de datos del puerto A */}

Figura 23: Ejemplo de acceso a los registros de control . Se envía el valor $FF al puerto A

Page 26: Programación de la tarjeta CT6811 en lenguaje C

Programación de la tarjeta CT6811 en lenguaje C

26

#define ADR2 (*(unsigned char *)0x1032)#define ADR3 (*(unsigned char *)0x1033)#define ADR4 (*(unsigned char *)0x1034)#define OPTION (*(unsigned char *)0x1039)#define COPRST (*(unsigned char *)0x103A)#define PPROG (*(unsigned char *)0x103B)#define HPRIO (*(unsigned char *)0x103C)#define INIT (*(unsigned char *)0x103D)#define TEST1 (*(unsigned char *)0x103E)#define CONFIG (*(unsigned char *)0x103F)

Los nombres utilizados para los registros de control son los mismo que se encuentran en elmanual del 68HC11 original. Utilizando el archivo REGS6811.H el programa de la figura 23 queraríacomo se muestra en la figura 24.

3.3.2.- Acceso a los vectores de interrupción.

Cuando se trabaja con la CT6811 tanto en modo entrenador como autónomo, el 68HC11arranca en modo bootstrap. En este modo los vectores de interrupción se encuentran en la memoriaROM de arranque, y están apuntando a direcciones de la RAM interna. Las direcciones a las queapuntan van desde la $00C4 hasta la $00FF. Cada ‘vector de interrupción’ en RAM está compuesto por3 bytes libres. El primer byte se reserva para situar una instrucción JMP y los dos siguientes para situarla dirección de la rutina de servicio de interrupción. Por ello, para cambiar un vector de interrupción, sedeben realizar dos pasos. En el primer paso se sitúa la instrucción JMP. En el segundo paso se sitúa ladirección de la rutina de servicio.

Supongamos que queremos utilizar la interrupción del SCI, que se encuentra en la dirección$00C4. Cada vez que se produzca un acontecimiento en el SCI, y si las interrupciones están habilitadas,el 68HC11 realizará un salto a la dirección $00C4. En esta dirección se deberá situar la instrucción JMP.En la dirección $00C5 el byte alto de la dirección de comienzo de la rutina de atención a la interrupcióny en la dirección $00C6 el byte bajo de la dirección de la rutina de atención a la interrupción. En lafigura 25 se muestra un ejemplo (no completo) de cómo es posible hacer esto.

#include “REGS6811.H”

char i;

main(){ PORTA=0xFF; /* Envio de datos al puerto A */ i=PORTA; /* Lectura de datos del puerto A */}

Figura 24: Ejemplo de utilización del fichero de definición de registros internos REGS6811.H

#define visci1 (*(char *)0xC4) /* SCI */#define visci2 (*(unsigned int *)0xC5)

void rsisci()/* Rutina de atención a la interrupción del SCI */{ ...... ......

asm (" RTI");}

main(){ visci1=0x7E; /* Colocar instrucción JMP */ visci2=(unsigned int)rsisci; /* Colocar dirección rutina servicio */ .... ....}

Figura 25: Ejemplo de cambio del vector de interrupción de la interrupción del SCI

Page 27: Programación de la tarjeta CT6811 en lenguaje C

Programación de la tarjeta CT6811 en lenguaje C

27

El programa de la figura 25 se comentará con un poco más de detalle. Obsérveseque se han realizado dos “defines”. Se han definido el objeto visci1 y el objeto visci2. Los números 1 y 2hacen referencia al byte del vector de interrupción. Para el caso del SCI, el primer byte (que debecontener la instrucción JMP) se encuentra en la dirección $00C4. El segundo byte se encuentra en ladirección $00C5. El nombre visci significa Vector Interrupción del SCI.

La rutina de atención a la interrupción se ha denominado rsisci (Rutina de Servicio deInterrupción del SCI). El programa principal lo primero que hace es modificar el vector de interrupcióndel SCI. Con la primera instrucción se sitúa el código 0x7E en la dirección $00C4. Este código secorresponde con el código de la instrucción JMP. La siguiente instrucción sitúa la dirección de la rutinade atención de interrupción, que es rsisci.

Para la implementación de la rutina de servicio de interrupción hay que utilizar el ‘truco’ de lasubrutina de servicio de interrupción, tal como se comentó en el punto 2.7.4.

En el fichero VECTINT.H se encuentran definidos todos los vectores de interrupción de todaslas interrupciones del 68HC11. Todas las constantes definidas comienzan por vi indicando vector deinterrupción. Todas acaban en un 1 ó en un 2 indicando si se trata del byte para la instrucción JMP o delentero que contiene la dirección de la rutina de atención.

/* +------------------------------------------------------------------------+ ¦ VECTINT.H (C) GRUPO J&J. ABRIL 1997 ¦ ¦------------------------------------------------------------------------¦ ¦ Vectores de interrupción del modo BOOTSTRAP. ¦ ¦ Por cada vector se dan dos direcciones. La primera corresponde al ¦ ¦ espacio reservado para colocar una instrucción JUMP. La segunda se ¦ ¦ corresponde con la dirección del vector de interrupcion. La conjun- ¦ ¦ ción de ambas provoca una intrucción de la forma JMP dir en el vector ¦ ¦ especificado. ¦ +------------------------------------------------------------------------+ */

#define visci1 (*(char *)0xC4) /* SCI */#define visci2 (*(unsigned int *)0xC5)

#define vispi1 (*(char *)0xC7) /* SPI */#define vispi2 (*(unsigned int *)0xC8)

#define viap1 (*(char *)0xCA) /* Acumulador de Pulsos */#define viap2 (*(unsigned int *)0xCB)

#define vioap1 (*(char *)0xCD) /* Overflow en acumulador de pulsos */#define vioap2 (*(unsigned int *)0xCE)

#define viot1 (*(char *)0xD0) /* Overflow en temporizador */#define viot3 (*(unsigned int *)0xD1)

#define vioc51 (*(char *)0xD3) /* Comparador 5 */#define vioc52 (*(unsigned int *)0xD4)

#define vioc41 (*(char *)0xD6) /* Comparador 4 */#define vioc42 (*(unsigned int *)0xD7)

#define vioc31 (*(char *)0xD9) /* Comparador 3 */#define vioc32 (*(unsigned int *)0xDA)

#define vioc21 (*(char *)0xDC) /* Comparador 2 */#define vioc22 (*(unsigned int *)0xDD)

#define vioc11 (*(char *)0xDF) /* Comparador 1 */#define vioc12 (*(unsigned int *)0xE0)

#define viic31 (*(char *)0xE2) /* Capturador 3 */#define viic32 (*(unsigned int *)0xE3)

#define viic21 (*(char *)0xE5) /* Capturador 2 */#define viic22 (*(unsigned int *)0xE6)

#define viic11 (*(char *)0xE8) /* Capturador 1 */#define viic12 (*(unsigned int *)0xE9)

#define virti1 (*(char *)0xEB) /* Tiempo real */#define virti2 (*(unsigned int *)0xEC)

Page 28: Programación de la tarjeta CT6811 en lenguaje C

Programación de la tarjeta CT6811 en lenguaje C

28

#define viirq1 (*(char *)0xEE) /* IRQ */#define viirq2 (*(unsigned int *)0xEF)

#define vixirq1 (*(char *)0xF1) /* XIRQ */#define vixirq2 (*(unsigned int *)0xF2)

#define viswi1 (*(char *)0xF4) /* Interrupción Software */#define viswi2 (*(unsigned int *)0xF5)

#define viiop1 (*(char *)0xF7) /* Instrucción ilegal */#define viiop2 (*(unsigned int *)0xF6)

#define visf1 (*(char *)0xFA) /* Fallo del sistema */#define visf2 (*(unsigned int *)0xFB)

#define vicopf1 (*(char *)0xFD) /* Fallo en el monitor del reloj */#define vicopf2 (*(unsigned int *)0xFE)

En la figura 26 se muestra el mismo ejemplo que en la figura 25 pero utilizando el archivoVECTINT.H

#include “VECTINT.H”

void rsisci()/* Rutina de atención a la interrupción del SCI */{ ...... ......

asm (" RTI");}

main(){ visci1=0x7E; /* Colocar instrucción JMP */ visci2=(unsigned int)rsisci; /* Colocar dirección rutina servicio */ .... ....}

Figura 26: Cambio del vector de interrupción del SCI utilizando el archivo VECTINT.H

Page 29: Programación de la tarjeta CT6811 en lenguaje C

Programación de la tarjeta CT6811 en lenguaje C

29

3.4.- PROGRAMACION DE LOS RECURSOS DEL 68HC11

3.4.1.- INTRODUCCION

En esta sección se va a comenzar a programar todos los recursos del 68HC11. Los programasestán pensados para ser ejecutados en la RAM interna del 68HC11, pero si se quieren adaptar parafuncionar en memoria externa o en la memoria EEPROM lo único que habrá que modificar será elarchivo de arranque y configuración.

A partir de aqui ya disponemos de las herramientas necesarias para empezar a programar. Paracompilar los programas simplemente habrá que utilizar el archivo CINT.BAT:

C:> CINT fichero_fuente (sin extensión)

A la hora de realizar los programas se utilizarán los archivos REGS6811.H y VECTINT.Hdefinidos en las secciones 3.3.1 y 3.3.2 respectivamente.

En los ejemplos que se muestran en toda la sección se van a ir construyendo librerías paratrabajar con los recursos internos del 68HC11. La primera versión de las librerías siempre estará en C.Sin embargo, para optimizar memoria es mejor realizar algunas librerías directamente enensamblador. Como se verá más adelante, con ello conseguiremos un enorme ahorro de memoria. Laslibrerías en ensamblador tienen el mismo interfaz de cara a nuestros programas en C pero se hanprogramado utilizando la directiva ASM del compilador de C.

3.4.2.- LOS PUERTOS DE ENTRADA/SALIDA

3.4.2.1.- PROGRAMACION DEL PUERTO A

EJEMPLO 1: Encender el led de la tarjeta CT6811

El primer ejemplo va a ser el más sencillo posible. Simplemente se va a encender el led de laCT6811, que se encuentra en el bit 6 del puerto A (Bit PA6). Para recapitular ideas, este va a ser unejemplo completo. Se va a mostrar el código fuente en C y los comandos utilizados para compilar yenviar el programa ejecutable a la CT6811, que se supondrá que se encuentra situada en el puertoCOM2.

/* +------------------------------------------------------------------------+ ¦ LEDON.C (C) GRUPO J&J. ABRIL 1997 ¦ ¦------------------------------------------------------------------------¦ ¦ Programa ejemplo para ser ejecutado en la tarjeta CT6811. ¦ ¦ Este programa se debe cargar en la RAM interna del 6811. ¦ ¦ ¦ ¦ Ejemplo para encender el led de la tarjeta CT6811. ¦ +------------------------------------------------------------------------+ */

#include “REGS6811.H”

main(){ PORTA=0x40;}

Lo primero que se hace es incluir el archivo REGS6811.H que contiene todas las definicionesde los registros de control del 68HC11. Entre ellas está la definición del puerto A. El programa principalsimplemente envía el valor 0x40 al puerto A, con lo que se encenderá el led de la CT6811. En la figura27 se muestran todos los pasos que hay que realizar para compilar y para enviar el programa a laCT6811.

Page 30: Programación de la tarjeta CT6811 en lenguaje C

Programación de la tarjeta CT6811 en lenguaje C

30

EJEMPLO 2: Hacer parpadear el LED de la tarjeta CT6811

Este ejemplo simplemente hace parpadear el LED de la tarjeta CT6811. La novedad que seintroduce en este programa es que se ha definido la variable global i.

/* +------------------------------------------------------------------------+ ¦ LEDP.C (C) GRUPO J&J. ABRIL 1997 ¦ ¦------------------------------------------------------------------------¦ ¦ Programa ejemplo para ser ejecutado en la tarjeta CT6811. ¦ ¦ Este programa se debe cargar en la RAM interna del 6811. ¦ ¦ ¦ ¦ Ejemplo para encender el led de la tarjeta CT6811. ¦ +------------------------------------------------------------------------+ */

#include "REGS6811.H"

unsigned int i;

main(){ for (;;) { PORTA^=0x40; /* Cambiar de estado PA6 */ for (i=0; i<0x8000; i++); /* Realizar una pausa */ }}

EJEMPLO 3: Utilización del bit 7 del puerto A como salida

El bit 7 del puerto A por defecto está configurado como entrada. En este ejemplo se configuracomo salida y se activa, de tal forma que si se conecta un led se enciende.

/* +------------------------------------------------------------------------+ ¦ PA7.C (C) GRUPO J&J. ABRIL 1997 ¦ ¦------------------------------------------------------------------------¦ ¦ Programa ejemplo para ser ejecutado en la tarjeta CT6811. ¦ ¦ Este programa se debe cargar en la RAM interna del 6811. ¦ ¦ ¦ ¦ Se configura el bit 7 del puerto A para salida y se activa con ¦ ¦ un '1'. ¦

C:\6811\ICC\CT68INT>cint ledon

UNIFICA V1.0 (C) GRUPO J&J. Abril 1997.Generación de código unificado en ensamblador

Fichero a Filtrar: ledon.sFichero destino : temp.s

C:\6811\ICC\CT68INT>C:\6811\ICC\CT68INT>downmcu ledon -com2

DOWN-MCU. V1.0 (C) GRUPO J&J. Noviembre-1996.Envío de programas a la entrenadora

Fichero a enviar: .\ledon.S19Puerto serie: COM2

Pulse reset en la entrenadora...Transmitiendo: >>>>>>>>>>>.....................................................................................................................................................................................................................................................OK!Envío correctoTamaño del programa: 11 bytes

C:\6811\ICC\CT68INT>_

Figura 27: Compilando y cargando el programa LEDON.C

Page 31: Programación de la tarjeta CT6811 en lenguaje C

Programación de la tarjeta CT6811 en lenguaje C

31

+------------------------------------------------------------------------+ */

#include "REGS6811.H"

main(){ PACTL=0x80; /* Poner bit 7 del registro PACTL a '1' para configurar */ /* el bit 7 del puerto A como salida */ PORTA=0x80; /* Mandar un '1' por el bit 7 del puerto A */}

EJEMPLO 4: Lectura y escritura en el puerto A.

En este ejemplo se refleja el estado del bit PA0 (bit de entrada) sobre el bit PA6 de salida. Si la entradaPA0 se pone a ‘1’, el bit de salida PA6 se pondrá a ‘1’. Lo mismo con el estado ‘0’.

/* +------------------------------------------------------------------------+ ¦ PA0.C (C) GRUPO J&J. ABRIL 1997 ¦ ¦------------------------------------------------------------------------¦ ¦ Programa ejemplo para ser ejecutado en la tarjeta CT6811. ¦ ¦ Este programa se debe cargar en la RAM interna del 6811. ¦ ¦ ¦ ¦ Programa ejemplo de la lectura del bit PA0. El estado de esta bit ¦ ¦ se refleja sobre el bit de salida PA6. ¦ +------------------------------------------------------------------------+ */

#include "REGS6811.H"

char pa0;

main(){ for (;;) { pa0=PORTA & 0x01; /* Leer bit 0 del puerto A */ PORTA=(pa0 << 6); /* Enviar bit leido por el bit 6 del puerto A */ }}

3.4.2.2.- PROGRAMACION DEL PUERTO B

El puerto B es un puerto de 8 bits de salida.

EJEMPLO 1: Activación rotativa de los 8 bits de l puerto B. En este ejemplo se activa primero el bit0 del puerto B, después el 1,.... hasta el bit 8. Después se vuelve a comenzar.

/* +------------------------------------------------------------------------+ ¦ PUERTOB.C (C) GRUPO J&J. ABRIL 1997 ¦ ¦------------------------------------------------------------------------¦ ¦ Programa ejemplo para ser ejecutado en la tarjeta CT6811. ¦ ¦ Este programa se debe cargar en la RAM interna del 6811. ¦ ¦ ¦ ¦ Activación rotativa de los bits del puerto B. ¦ +------------------------------------------------------------------------+ */

#include "REGS6811.H"

unsigned int i;char b;

main(){ b=0x01; for (;;) { PORTB=b; /* Actualizar puerto B */ for (i=0; i<0x8000; i++); /* Realizar una pausa */ b=b<<1; if (b==0) b=1; }}

Page 32: Programación de la tarjeta CT6811 en lenguaje C

Programación de la tarjeta CT6811 en lenguaje C

32

3.4.2.3.- PROGRAMACION DEL PUERTO C

El puerto C es un puerto de 8 bits configurables como entrada o salida.

EJEMPLO 1: Lectura y escritura con el puerto C. En este ejemplo se sonfiguran los 4 bits de menorpeso del puerto C para entradas y los 4 bits de mayor peso para salidas. El estado de las entradas serefleja sobre los bits de salida.

/* +------------------------------------------------------------------------+ ¦ PUERTOC.C (C) GRUPO J&J. ABRIL 1997 ¦ ¦------------------------------------------------------------------------¦ ¦ Programa ejemplo para ser ejecutado en la tarjeta CT6811. ¦ ¦ Este programa se debe cargar en la RAM interna del 6811. ¦ ¦ ¦ ¦ Los 4 bits de menor peso del puerto C se configuran para entrada y ¦ ¦ los 4 bits de mayor peso del puerto C se configuran para salida. El ¦ ¦ estado de la entrada se refleja sobre los bits de salida. ¦ +------------------------------------------------------------------------+ */

#include "REGS6811.H"

char c;

main(){ DDRC=0xF0; /* Configurar el puerto C: Bits 0,1,2,3 entrada */ /* Los bits 4,5,6 y 7 para entradas */ for (;;) { c=PORTC & 0x0F; /* Leer puerto C */ PORTC=(c << 4); /* Escribir en puerto C */ }}

3.4.2.4.- PROGRAMACION DEL PUERTO D

El puerto D es un puerto de 6 bits de E/S.

EJEMPLO 1: Lectura y escritura del puerto D. Lectura del estado del bit PD2 y escritura sobre el bitPD3.

/* +------------------------------------------------------------------------+ ¦ PUERTOD.C (C) GRUPO J&J. ABRIL 1997 ¦ ¦------------------------------------------------------------------------¦ ¦ Programa ejemplo para ser ejecutado en la tarjeta CT6811. ¦ ¦ Este programa se debe cargar en la RAM interna del 6811. ¦ ¦ ¦ ¦ Se configura el bit 2 del puerto D como entrada y el bit 3 como ¦ ¦ salida. El estado del bit de entrada se refleja sobre el bit de ¦ ¦ salida. ¦ +------------------------------------------------------------------------+ */

#include "REGS6811.H"

char d;

main(){ DDRD=0x08; /* Configurar el puerto D: Bit 3 salida. Resto entradas */ for (;;) { d=PORTD & 0x04; /* Leer puerto D */ PORTD=(d << 1); /* Escribir en puerto D */ }}

Page 33: Programación de la tarjeta CT6811 en lenguaje C

Programación de la tarjeta CT6811 en lenguaje C

33

3.4.2.5.- PROGRAMACION DEL PUERTO E

EJEMPLO 1: Reflejo del estado del bit PE0 sobre el bit PA6.

/* +------------------------------------------------------------------------+ ¦ PUERTOE.C (C) GRUPO J&J. ABRIL 1997 ¦ ¦------------------------------------------------------------------------¦ ¦ Programa ejemplo para ser ejecutado en la tarjeta CT6811. ¦ ¦ Este programa se debe cargar en la RAM interna del 6811. ¦ ¦ ¦ ¦ El estado del bit 0 del puerto E se refleja sobre el led de la ¦ ¦ tarjeta CT6811. ¦ +------------------------------------------------------------------------+ */

#include "REGS6811.H"

char e;

main(){ for (;;) { e=PORTE & 0x01; /* Leer puerto E */ PORTA=(e << 6); /* Escribir en puerto A */ }}

Page 34: Programación de la tarjeta CT6811 en lenguaje C

Programación de la tarjeta CT6811 en lenguaje C

34

Page 35: Programación de la tarjeta CT6811 en lenguaje C

Programación de la tarjeta CT6811 en lenguaje C

35

3.4.3.- PROGRAMACION DEL SCI

Primero se van a presentar unos ejemplos de manejo del SCI. Después se van a extrar algunasde las rutinas de los ejemplos para crear una libreria de comunicaciones serie llamada SCI.H. Con estalibreria se van a realizar algunos ejemplos. Finalmente se van a presentar ejemplos de manejo del SCImediante interrupciones. Todos los ejemplos que utilicen la librería SCI.H también pueden utilizar lalibrería SCIASM.H. Ambas tienen el mismo interfaz pero la segunda está implementada enensamblador por lo que es más rápida y ocupa menos memoria.

EJEMPLO 1: Lectura y escribura de datos por el puerto serie.

En este ejemplo se presentan las funciones leer_car y enviar_car que sirven para leer datos delpuerto serie y para enviar datos por él. Estas dos funciones van a formar parte de la librería SCI.H. Elejemplo simplemente realiza un eco de los caracteres recibidos. Este mismo ejemplo se presenta másadelante pero utilizando la librería SCI.H

/* +------------------------------------------------------------------------+ ¦ SCI1.C (C) GRUPO J&J. ABRIL 1997 ¦ ¦------------------------------------------------------------------------¦ ¦ Programa ejemplo para ser ejecutado en la tarjeta CT6811. ¦ ¦ Este programa se debe cargar en la RAM interna del 6811. ¦ ¦ ¦ ¦ Ejemplo manejo del SCI del 68HC11. Se hace 'eco' de todos los ¦ ¦ caracteres recibidos por el SCI ¦ +------------------------------------------------------------------------+ */

#include "regs6811.h"

char leer_car()/* +--------------------------------------------------------+ ¦ Función que devuelve el carácter recibido por el SCI ¦ +--------------------------------------------------------+ */{ while(!(SCSR & 0x10)); return SCDR;}

void enviar_car(char c)/* +------------------------------------------+ ¦ Enviar un carácter por el puerto serie. ¦ +------------------------------------------+ */{ while (!(SCSR & 0x40)); SCDR = c;}

char c;

main(){ for (;;) { c=leer_car(); /* Esperar a que venga un carácter por el SCI */ PORTA^=0x40; /* Cambiar el led de estado */ enviar_car(c); /* Hacer eco del caracter recibido */ }}

EJEMPLO 2: Librería SCI.H para comunicaciones serie mediante espera activa

A continuación se presenta la librería SCI.H que contiene las tres funciones siguientes:

• enviar_car : Función para enviar un carácter por el puerto Serie. Es la misma que la utilizada en elejemplo 1

• leer_car : Función para esperar a que se reciba un carácter por el puerto serie. Es la misma que lautilizada en el ejemplo 2.

• enviar : Función para enviar una cadena por el puerto serie.

Page 36: Programación de la tarjeta CT6811 en lenguaje C

Programación de la tarjeta CT6811 en lenguaje C

36

/* +------------------------------------------------------------------------+ ¦ SCI.H (C) GRUPO J&J. ABRIL 1997 ¦ ¦------------------------------------------------------------------------¦ ¦ Rutinas de manejo del SCI mediante espera activa. ¦ ¦ ¦ ¦ leer_car() -----> Leer el carácter que venga por el SCI. ¦ ¦ enviar_car(c) --> Enviar un carácter por el SCI ¦ ¦ enviar(cad) ----> Enviar una cadena de caracteres por el SCI ¦ ¦ ¦ +------------------------------------------------------------------------+ */

#include "regs6811.h"

char leer_car()/* +--------------------------------------------------------+ ¦ Función que devuelve el carácter recibido por el SCI ¦ +--------------------------------------------------------+ */{ while(!(SCSR & 0x10)); return SCDR;}

void enviar_car(char c)/* +------------------------------------------+ ¦ Enviar un carácter por el puerto serie. ¦ +------------------------------------------+ */{ while (!(SCSR & 0x40)); SCDR = c;}

void enviar(char *cad)/* +-------------------------------+ ¦ Enviar una cadena por el SCI ¦ +-------------------------------+ */{ static unsigned char i;

i=0; while (cad[i]) { enviar_car(cad[i]); i++; }}

En los siguientes ejemplos se muestra cómo utilizar esta librería.

EJEMPLO 3: Eco por el puerto serie. Se trata del mismo ejemplo que el 1 pero se utiliza la libreríaSCI.H

/* +------------------------------------------------------------------------+ ¦ ECO.C (C) GRUPO J&J. ABRIL 1997 ¦ ¦------------------------------------------------------------------------¦ ¦ Programa ejemplo para ser ejecutado en la tarjeta CT6811. ¦ ¦ Este programa se debe cargar en la RAM interna del 6811. ¦ ¦ ¦ ¦ Ejemplo manejo del SCI del 68HC11. Se hace 'eco' de todos los ¦ ¦ caracteres recibidos por el SCI ¦ +------------------------------------------------------------------------+ */

#include "regs6811.h"#include "sci.h"

char c;

main(){ for (;;) { c=leer_car(); /* Esperar a que venga un carácter por el SCI */ PORTA^=0x40; /* Cambiar el led de estado */ enviar_car(c); /* Hacer eco del caracter recibido */ }}

Page 37: Programación de la tarjeta CT6811 en lenguaje C

Programación de la tarjeta CT6811 en lenguaje C

37

Este programa ocupa 149 bytes.

EJEMPLO 4: Envío de cadenas por el SCI. En este ejemplo se utiliza la función enviar de la libreríaSCI.H para enviar la cadena ‘hola como estas’ cada vez que se reciba un carácter por el puerto serie.

/* +------------------------------------------------------------------------+ ¦ SCICAD.C (C) GRUPO J&J. ABRIL 1997 ¦ ¦------------------------------------------------------------------------¦ ¦ Programa ejemplo para ser ejecutado en la tarjeta CT6811. ¦ ¦ Este programa se debe cargar en la RAM interna del 6811. ¦ ¦ ¦ ¦ Envio de cadenas por el puerto serie. Cada vez que se recibe un ¦ ¦ caracter por el SCI se responde enviando un mensaje ¦ +------------------------------------------------------------------------+ */

#include "regs6811.h"#include "sci.h"

main(){ for (;;) { leer_car(); /* Esperar a que venga un carácter por el SCI */ PORTA^=0x40; /* Cambiar el led de estado */ enviar("Hola como estas"); /* Enviar una cadena */ }}

Este programa ocupa 159 bytes.

EJEMPLO 5: Interacción con el usuario. Este ejemplo presenta un menu al usuario con dos opciones.Una opción sirve para cambiar el estado del led de la CT6811. Cada vez que se pulsa la otra opción seenvía por los 4 bits del puerto C un número. (Si se tiene conectado un display de 7 segmentos en elpuerto C se podrá observar el número enviado).

/* +------------------------------------------------------------------------+ ¦ SCIMENU.C (C) GRUPO J&J. ABRIL 1997 ¦ ¦------------------------------------------------------------------------¦ ¦ Programa ejemplo para ser ejecutado en la tarjeta CT6811. ¦ ¦ Este programa se debe cargar en la RAM interna del 6811. ¦ ¦ ¦ ¦ Se presenta un pequeño menu de opciones. Ejemplo de programa inte- ¦ ¦ ractivo con el usuario. ¦ +------------------------------------------------------------------------+ */

#include "regs6811.h"#include "sci.h"

char c;char i;

main(){ DDRC=0xF0; /* Configuración del puerto C para la tarjeta PCT-S47 */ i=0; enviar("\n\r1-Led"); enviar("\n\r2-Display\n\r"); for (;;) { c=leer_car(); switch(c) { case '1': PORTA^=0x40; break; case '2': PORTC=i; i+=16; } }}

Este programa ocupa 239 bytes.

EJEMPLO 6: Utilización de las librerías optimizadas SCIASM.H. En todos los ejemplos mostradosanteriormente se utilizaba la librería SCI.H. Si en cualquiera de esos ejemplos se sustituye #include

Page 38: Programación de la tarjeta CT6811 en lenguaje C

Programación de la tarjeta CT6811 en lenguaje C

38

“SCI.H” por #include “SCIASM.H” los programas seguirán funcionando igual peroocuparán mucho menos. A continuación se presenta el programa eco.c que utiliza la librería SCIASM.H.Este programa ocupa 99 bytes. Con la librería SCI.H ocupaba 149 bytes. ¡¡¡Utilizando la libreríaSCIASM.H conseguimos un ahorro de 50 bytes!!!!

La única diferencia se encuentra al compilar los programas. Al utilizar la librería SCIASM.Haparecerá un Warning. No hay que preocuparse. Simplemente hay que ignorarlo.

/* +------------------------------------------------------------------------+ ¦ ECOASM.C (C) GRUPO J&J. ABRIL 1997 ¦ ¦------------------------------------------------------------------------¦ ¦ Programa ejemplo para ser ejecutado en la tarjeta CT6811. ¦ ¦ Este programa se debe cargar en la RAM interna del 6811. ¦ ¦ ¦ ¦ Este programa hace lo mismo que el programa ECO.C pero se utilizan ¦ ¦ las rutinas de la librería SCIASM.H en vez de SCI.H ¦ +------------------------------------------------------------------------+ */

#include "regs6811.h"#include "sciasm.h" /* SE HA SUSTITUIDO POR #include “SCI.H” */

char c;

main(){ for (;;) { c=leer_car(); /* Esperar a que venga un carácter por el SCI */ PORTA^=0x40; /* Cambiar el led de estado */ enviar_car(c); /* Hacer eco del caracter recibido */ }}

Puesto que el interfaz que ‘ve’ nuestro programa principal es el mismo para las dos librerías,pero con la librería SCIASM.H conseguimos un ahorro de 50 bytes, es mejor utilizar esta librería. Estalibrería se describe con más detalle más adelante.

EJEMPLO 7: Utilización de las interrupciones del SCI.

En este ejemplo cada vez que se recibe un carácter por el SCI se cambia el estado del LED de laCT6811. Obsérverse que le programa principal entra en un bucle infinito y no hace nada. En este buclese podría estar ejecutando un trozo de código mientras que el led se sigue encendiendo y apagando cadavez que se recibe un carácter por el SCI.

/* +------------------------------------------------------------------------+ ¦ SCILED.C (C) GRUPO J&J. ABRIL 1997 ¦ ¦------------------------------------------------------------------------¦ ¦ Programa ejemplo para ser ejecutado en la tarjeta CT6811. ¦ ¦ Este programa se debe cargar en la RAM interna del 6811. ¦ ¦ ¦ ¦ Ejemplo de utilización del SCI mediante interrupciones. Cada vez ¦ ¦ que se recibe un caracter se cambia el estado del led mediante ¦ ¦ interrupciones ¦ +------------------------------------------------------------------------+ */

#include "regs6811.h"#include "vectint.h"

void ssisci()/* +------------------------------------------------+ ¦ Subrutina de servicio de interrupción del SCI ¦ +------------------------------------------------+ */{ static char c;

c=SCSR; /* Quitar flag de interrupción */ c=SCDR;

PORTA^=0x40; /* Cambiar de estado el led */}

Page 39: Programación de la tarjeta CT6811 en lenguaje C

Programación de la tarjeta CT6811 en lenguaje C

39

void rsisci()/* +------------------------------------------------+ ¦ Subrutina de servicio de interrupción del SCI ¦ +------------------------------------------------+ */{ ssisci(); /* Llamar a la subrutina de servicio de interrupción */ asm (" RTI");}

main(){ /* ----------- Cambiar vector de interrupción del SCI ------------------ */ visci1=0x7E; /* Colocar instrucción JMP */ visci2=(unsigned int)rsisci; /* Colocar dirección rutina servicio */

SCCR2 |= 0x20; /* Activar interrupción de DATO recibido del SCI */ asm (" CLI"); /* Permitir las interrupciones */

for (;;) ; /* Bucle infinito */}

Page 40: Programación de la tarjeta CT6811 en lenguaje C

Programación de la tarjeta CT6811 en lenguaje C

40

Page 41: Programación de la tarjeta CT6811 en lenguaje C

Programación de la tarjeta CT6811 en lenguaje C

41

3.4.4.- PROGRAMACION DEL SPI

Se van a presentar una serie de ejemplos de manejo del SPI. Todos ejemplos se han pensadopara conectar dos tarjetas CT6811 a través del SPI. Un 68HC11 se configura como maestro y el otrocomo esclavo. Cada uno ejecuta un programa diferente.

Las rutinas de manejo del SPI se encuentran en la librería SPI.H. La librería SPIASM.Hcontiene exactamente las mismas funciones pero implementadas en ensamblador por lo que se ahorramemoria. Todos los ejemplos se han realizado con la librería SPIASM.H. Para utilizar la otrasimplemente habrá que cambiar en los ejemplos la línea #include “SPIASM.H” por #include “SPI.H”

EJEMPLO 1: La librería SPI.H para comunicaciones por el SPI

/* +------------------------------------------------------------------------+ ¦ SPI.H (C) GRUPO J&J. ABRIL 1997 ¦ ¦------------------------------------------------------------------------¦ ¦ Rutinas de manejo del SPI mediante espera activa. ¦ ¦ ¦ ¦ spi(c) --> Función que realizar un 'intercambio' por el SPI. Envía ¦ ¦ El carácter c y devuelve lo que se reciba por el SPI. ¦ ¦ spi_maestro() -> Macro para configurar el SPI en modo maestro. ¦ ¦ spi_esclavo() -> Macro para configurar el SPI en modo esclavo ¦ ¦ ¦ +------------------------------------------------------------------------+ */#include "REGS6811.H"

/* +-------------------------------+ --------------------¦ Macros para configurar el SPI ¦----------------- +-------------------------------+ */#define spi_maestro() DDRD=0x38; SPCR=0x54; PORTD=0x00#define spi_esclavo() DDRD=0x04; SPCR=0x44

char spi(char c)/* +--------------------------------------------------------+ ¦ Esta función realizar un 'intercambio' de información ¦ ¦ por el SPI: Se envía el carácter indicado y se devuel- ¦ ¦ ve lo que venga por el SPI. ¦ +--------------------------------------------------------+ */{ SPDR=c; /* Enviar dato */ while (!(SPSR & 0x80)); /* Esperar a que el dato se envíe */ return SPDR; /* Devolver el dato recibido */}

Lo que más llama la atención de estas rutinas es que no exiten las típicas funciones de enviar yrecibir datos. Sólo existe una única función que realiza el intercambio de información. En los siguientesejemplos se muestra cómo se emplea esta función para enviar y recibir datos.

EJEMPLO 2: Envío de datos del maestro al esclavo. En este ejemplo se envían datos desde el maestroal esclavo. El esclavo cambia de estado el led cada vez que recibe un dato por el SPI. Además, si se tieneconectado un display de 7 segmentos en los 4 bits más significativos del puerto C se podrán ver los datosrecibidos. El programa maestro toma los datos del puerto serie. De esta forma, para que el probar que elprograma funciona correctamente el usuario envía los datos desde el teclado del PC hasta el 68HC11maestro por medio del SCI. De aquí son enviados al 68HC11 esclavo vía el SPI.

PROGRAMA MAESTRO

/* +------------------------------------------------------------------------+ ¦ SPILEDM.C (C) GRUPO J&J. Abril 1997 ¦ ¦------------------------------------------------------------------------¦ ¦ Programa ejemplo para ser ejecutado en la tarjeta CT6811. ¦ ¦ Este programa se debe cargar en la RAM interna del 6811. ¦ ¦ ¦ ¦ Programa ejemplo de manejo del SPI. El micro se configura como ¦ ¦ MAESTRO. Todos caracteres que se reciben por el SCI se envían a ¦ ¦ través del SPI. ¦ ¦ ¦ +------------------------------------------------------------------------+

Page 42: Programación de la tarjeta CT6811 en lenguaje C

Programación de la tarjeta CT6811 en lenguaje C

42

*/

#include "REGS6811.H"#include "SCIASM.H"#include "SPIASM.H"

char c;

main(){ spi_maestro(); /* Configurar micro como maestro */ for (;;) { c=leer_car(); /* Esperar a que se reciba un dato por SCI */ spi(c); /* Enviar carácter por el SPI */ }}

PROGRAMA ESCLAVO:

/* +------------------------------------------------------------------------+ ¦ SPILEDE.C (C) GRUPO J&J. Febrero 1997 ¦ ¦------------------------------------------------------------------------¦ ¦ Programa ejemplo para ser ejecutado en la tarjeta CT6811. ¦ ¦ Este programa se debe cargar en la RAM interna del 6811. ¦ ¦ ¦ ¦ PROGRAMA ESCLAVO ¦ ¦ ¦ ¦ Cada vez que se recibe un carácter por el SPI se cambia el estado ¦ ¦ del led. Los 4 bits más bajos de carácter recibido se envían por los ¦ ¦ 4 bits más altos del puerto C de tal manera que si se ha conectado ¦ ¦ un display de 7 segmentos se pueden ver los números recibidos. ¦ +------------------------------------------------------------------------+*/

#include "REGS6811.H"#include "SPIASM.H"

char c;

main(){ DDRC=0xF0; /* Configurar puerto C: Bits 7,6,5 y 4 salidas. */ PORTC=0x80; /* Mandar un 8 al display para que se encienda */

spi_esclavo(); /* Configurar micro como esclavo */

for (;;) { c=spi(0); /* Recibir dato del maestro */ PORTC=(c << 4); /* Mandar dato al display 7-seg */ PORTA^=0x40; /* Cambiar led de estado */ }}

Obsérverse cómo funciona la función spi. En el caso del maestro lo que queremos es transmitirun dato. Por ello simplemente se llama a la función pasando como parámetro el dato a enviar: spi(c). Enel caso del esclavo lo que se quiere es recibir. La función spi() transmite y recibe a la vez. Por ello pararecibir un carácter transmitirmos un carácter ‘basura’ cualquiera. En el ejemplo se ha transmitido elcarácter 0: c=spi(0). Pero se podría haber transmitido cualquiera puesto que el maestro los ignora.

EJEMPLO 3: Envío de datos al esclavo y obtención de la respuesta del esclavo.

Es muy común que después de enviar datos al esclavo, el maestro se quede esperando a recibiruna respuesta del esclavo. En este ejemplo la respuesta del esclavo es un eco modificado de lo recibidopor el SPI. La modificación consiste en sumar una unidad al carácter recibido. De esta forma, si elmaestro envía una ‘A’, recibirá como eco una ‘B’ (‘B’ = ‘A’ + 1).

PROGRAMA MAESTRO

/* +------------------------------------------------------------------------+ ¦ SPIECOM.C (C) GRUPO J&J. Abril 1997 ¦ ¦------------------------------------------------------------------------¦

Page 43: Programación de la tarjeta CT6811 en lenguaje C

Programación de la tarjeta CT6811 en lenguaje C

43

¦ Programa ejemplo para ser ejecutado en la tarjeta CT6811. ¦ ¦ Este programa se debe cargar en la RAM interna del 6811. ¦ ¦ ¦ ¦ Programa ejemplo de manejo del SPI. El micro se configura como ¦ ¦ MAESTRO. Todos caracteres que se reciben por el SCI se envían a ¦ ¦ través del SPI. La respuesta del esclavo se envía a través del SCI ¦ ¦ ¦ +------------------------------------------------------------------------+*/

#include "REGS6811.H"#include "SCIASM.H"#include "SPIASM.H"

char c;unsigned int i;

main(){ spi_maestro(); /* Configurar micro como maestro */ for (;;) { c=leer_car(); /* Esperar carácter por el SCI */ spi(c); /* Enviar el carácter leido */

for (i=0; i<2; i++); /* Pequeña pausa para que al esclavo tenga tiempo */ /* de procesar el dato */ c=spi(0); /* Recibir dato del esclavo */ enviar_car(c); /* Enviar dato por el SCI */ }}

PROGRAMA ESCLAVO

/* +------------------------------------------------------------------------+ ¦ SPIECOE.C (C) GRUPO J&J. Febrero 1997 ¦ ¦------------------------------------------------------------------------¦ ¦ Programa ejemplo para ser ejecutado en la tarjeta CT6811. ¦ ¦ Este programa se debe cargar en la RAM interna del 6811. ¦ ¦ ¦ ¦ PROGRAMA ESCLAVO: ¦ ¦ ¦ ¦ Se lee lo que viene por el SPI y se hace un ECO. El caracter enviado ¦ ¦ es el recibido incrementado en una unidad. Si se recibe el carácter ¦ ¦ 'A' se envía el carácter 'B'. Los 4 bits de menor peso del carácter ¦ ¦ recibido se envían por los 4 bits de mayor peso del puerto C. Se ¦ ¦ modifica el estado del led por cada carácter recibido por el SPI ¦ ¦ ¦ +------------------------------------------------------------------------+*/

#include "REGS6811.H"#include "SPIASM.H"

char c;

main(){ DDRC=0xF0; /* Configurar puerto C: 4 bits mayor peso como salidas */ PORTC=0x80; /* Enviar un 8 al display de 7 segmentos */

spi_esclavo(); /* Configurar micro como esclavo */

for (;;) { c=spi(0); /* Recibir dato del maestro */ PORTC=(c << 4); /* Mandar dato al display 7-seg */ PORTA^=0x40; c++; /* Incrementar carácter recibido */ spi(c); /* Enviar nuevo carácter al maestro */ }}

Page 44: Programación de la tarjeta CT6811 en lenguaje C

Programación de la tarjeta CT6811 en lenguaje C

44

Page 45: Programación de la tarjeta CT6811 en lenguaje C

Programación de la tarjeta CT6811 en lenguaje C

45

3.4.5.- PROGRAMACION DEL TEMPORIZADOR PRINCIPAL

EJEMPLO 1: Lectura del temporizador. En este ejemplo se muestra cómo leer el temporizadorprincipal. Cada vez que se recibe un carácter por el SCI, el 68HC11 devuelve el valor del byte bajo deltemporizador principal.

/* +------------------------------------------------------------------------+ ¦ TIMER.C (C) GRUPO J&J. ABRIL 1997 ¦ ¦------------------------------------------------------------------------¦ ¦ Programa ejemplo para ser ejecutado en la tarjeta CT6811. ¦ ¦ Este programa se debe cargar en la RAM interna del 6811. ¦ ¦ ¦ ¦ Ejemplo de lectura del temporizador principal. Cuando se recibe ¦ ¦ un carácter por el SCI se devuelve el valor del byte bajo del ¦ ¦ temporizador principal. ¦ +------------------------------------------------------------------------+ */

#include "REGS6811.H"#include "SCIASM.H"

unsigned int tempo;char c;

main(){ for (;;) { leer_car(); tempo=TCNT; /* Leer valor del temporizador */ c=(char) (tempo & 0x00FF); /* Quedarse con el byte bajo del temporizador */ enviar_car(c); }}

EJEMPLO 2: Modificación de la frecuencia del temporizador. En este ejemplo se modifica eltemporizador para que se incremente a la velocidad de E/16. Para la tarjeta CT6811 esta velocidad es de125KHZ. El estado del bit más significativo del temporizador se presenta en el led de la CT6811.

/* +------------------------------------------------------------------------+ ¦ TIMER2.C (C) GRUPO J&J. ABRIL 1997 ¦ ¦------------------------------------------------------------------------¦ ¦ Programa ejemplo para ser ejecutado en la tarjeta CT6811. ¦ ¦ Este programa se debe cargar en la RAM interna del 6811. ¦ ¦ ¦ ¦ Modificación de la frecuencia de funcionamiento del temporizador. ¦ ¦ Se configura para trabajar a una frecuencia de 125KHZ. El bit de ¦ ¦ mayor peso del temporizador se utiliza para hacer parpadear el led. ¦ ¦ ¦ +------------------------------------------------------------------------+ */

#include "REGS6811.H"

unsigned int tempo;

main(){ TMSK2|=0x03; /* Divir la señal E por 16 */

for (;;) { tempo=TCNT; /* Leer valor del temporizador */ if (tempo & 0x8000) /* Si bit de mayor peso activo... */ PORTA=0x40; /* Encender el led. */ else PORTA=0x00; /* sino apagar el led. */ }}

EJEMPLO 3: Interrupción de overflow del temporizador. Se utiliza la interrupción de overflow deltemporizador para hacer parpadear el LED de la CT6811.

/* +------------------------------------------------------------------------+ ¦ OVERFLOW.C (C) GRUPO J&J. ABRIL 1997 ¦ ¦------------------------------------------------------------------------¦ ¦ Programa ejemplo para ser ejecutado en la tarjeta CT6811. ¦

Page 46: Programación de la tarjeta CT6811 en lenguaje C

Programación de la tarjeta CT6811 en lenguaje C

46

¦ Este programa se debe cargar en la RAM interna del 6811. ¦ ¦ ¦ ¦ Ejemplo del temporizador principal. Se utiliza la interrupción de ¦ ¦ overflow del temporizador para hacer parpadear el LED de la CT6811. ¦ ¦ Cada vez que el temporizador alcanza el valor $FFFF se cambia de ¦ ¦ estado el led. Se configura el temporizador para que se produzca ¦ ¦ overflow cada 524.3ms. ¦ ¦ ¦ +------------------------------------------------------------------------+ */

#include "regs6811.h"#include "vectint.h"

void ssioverf()/* +------------------------------------------------------+ ¦ Subrutina de servicio de interrupción del overflow ¦ +------------------------------------------------------+ */{ TFLG2|=0x80; /* Quitar flag de interrupción */ PORTA^=0x40; /* Cambiar de estado el led */}

void rsioverf()/* +---------------------------------------------------+ ¦ Rutina de servicio de interrupción del overflow ¦ +---------------------------------------------------+ */{ ssioverf(); /* Llamar a la subrutina de servicio de interrupción */ asm (" RTI");}

main(){ TMSK2|=0x03; /* Velocidad del temporizador: E/16 */

/* ----------- Cambiar vector de interrupción ------------------ */ viot1=0x7E; /* Colocar instrucción JMP */ viot2=(unsigned int)rsioverf; /* Colocar dirección rutina servicio */

TMSK2|=0x80; /* Activar interrupción de overflow */ asm (" CLI"); /* Permitir las interrupciones */

for (;;) ; /* Bucle infinito */}

Page 47: Programación de la tarjeta CT6811 en lenguaje C

Programación de la tarjeta CT6811 en lenguaje C

47

3.4.6.- PROGRAMACION DE LAS INTERRUPCIONES EN TIEMPO REAL

EJEMPLO 1: Interrupción en tiempo real mediante espera activa. Este programa hace cambiar deestado el led de la tarjeta CT611 cada 32.7ms. Se realiza utilizando las interrupciones en tiempo realmediante espera activa. En realidad no se utilizan interrupciones, sino que se trabaja con el flag deinterrupción. Cuando se pone a 1 quiere decir que han pasado 32.7ms.

/* +------------------------------------------------------------------------+ ¦ RTI.C (C) GRUPO J&J. ABRIL 1997 ¦ ¦------------------------------------------------------------------------¦ ¦ Programa ejemplo para ser ejecutado en la tarjeta CT6811. ¦ ¦ Este programa se debe cargar en la RAM interna del 6811. ¦ ¦ ¦ ¦ Ejemplo de la interrupción en tiempo real. Se cambia el estado del ¦ ¦ led cada 32.7ms. Se hace mediante espera activa. ¦ +------------------------------------------------------------------------+ */

#include "REGS6811.H"

main(){ PACTL|=0x03; /* Interrupciones en tiempo real cada 32.7ms */ for (;;) { while (!(TFLG2 & 0x40)); /* Esperar a que se active flag */ TFLG2|=0x40; /* Quitar flag. */ PORTA^=0x40; /* Cambiar de estado el led */ }}

EJEMPLO 2: Interrupciones en tiempo real con interrupciones. Mismo programa que el anteriorpero realizado mediante interrupciones.

/* +------------------------------------------------------------------------+ ¦ RTII.C (C) GRUPO J&J. ABRIL 1997 ¦ ¦------------------------------------------------------------------------¦ ¦ Programa ejemplo para ser ejecutado en la tarjeta CT6811. ¦ ¦ Este programa se debe cargar en la RAM interna del 6811. ¦ ¦ ¦ ¦ Ejemplo de las interrupciones en tiempo real. Se cambia el estado ¦ ¦ del led cada 32.7ms. Se hace mediante interrupciones. ¦ ¦ ¦ +------------------------------------------------------------------------+ */

#include "regs6811.h"#include "vectint.h"

void ssirti()/* +------------------------------------------------------+ ¦ Subrutina de servicio de interrupción en tiempo real ¦ +------------------------------------------------------+ */{ TFLG2|=0x40; /* Quitar flag de interrupción */ PORTA^=0x40; /* Cambiar de estado el led */}

void rsirti()/* +---------------------------------------------------+ ¦ Rutina de servicio de interrupción en tiempo real ¦ +---------------------------------------------------+ */{ ssirti(); /* Llamar a la subrutina de servicio de interrupción */ asm (" RTI");}

main(){ PACTL|=0x03; /* Int. tiempo real cada 32.7ms */

/* ----------- Cambiar vector de interrupción ------------------ */ virti1=0x7E; /* Colocar instrucción JMP */ virti2=(unsigned int)rsirti; /* Colocar dirección rutina servicio */

Page 48: Programación de la tarjeta CT6811 en lenguaje C

Programación de la tarjeta CT6811 en lenguaje C

48

TMSK2|=0x40; /* Activar interrupción de Tiempo real */ asm (" CLI"); /* Permitir las interrupciones */

for (;;) ; /* Bucle infinito */}

Page 49: Programación de la tarjeta CT6811 en lenguaje C

Programación de la tarjeta CT6811 en lenguaje C

49

3.4.7.- PROGRAMACION DE LOS COMPARADORES

EJEMPLO 1: Utilización de los comparadores para realizar una pausa. LIBRERIA DELAY.H

En este ejemplo se presenta la función delay() que realiza una pausa, mediante espera activa, deun número determinado de milisegundos. Esta función forma parte de la libreria DELAY.H

/* +------------------------------------------------------------------------+ ¦ DELAY.H (C) GRUPO J&J. ABRIL 1997 ¦ ¦------------------------------------------------------------------------¦ ¦ Librería para realizar pausas. ¦ ¦ ¦ ¦ delay(t) --> Realizar una pausa de t milisegundo. ¦ ¦ t=1000 Pausa de 1 segundo ¦ ¦ ¦ +------------------------------------------------------------------------+ */

#include "REGS6811.H"

#define T1_MS 2000 /* Número de tics de reloj necesarios para generar un */ /* retraso de 1ms */

void delay(unsigned int time){ while (time!=0) { time--; TOC5=TCNT+T1_MS; /* Iniciar el comparador para que se active al cabo */ /* de 1ms de tiempo */ TFLG1|=0x08; /* Poner a cero flag del comparador 5 */ while (!(TFLG1 & 0x08)) ; /* Espear a que se active el flag */ }}

EJEMPLO 2: Utilización de la función delay() de la librería DELAY.H. En este ejemplo se cambiael estado del led de la CT6811 cada segundo exacto. Para ello se llama a la función delay con unargumento de 1000 (1segundo = 1000 milisegundos).

/* +------------------------------------------------------------------------+ ¦ DELAY.C (C) GRUPO J&J. ABRIL 1997 ¦ ¦------------------------------------------------------------------------¦ ¦ Programa ejemplo para ser ejecutado en la tarjeta CT6811. ¦ ¦ Este programa se debe cargar en la RAM interna del 6811. ¦ ¦ ¦ ¦ Ejemplo de la librería de pausa. Se cambia el estado del led de la ¦ ¦ CT6811 cada 1 segundo. ¦ +------------------------------------------------------------------------+ */

#include "REGS6811.H"#include "DELAY.H"

main(){ for (;;) { PORTA^=0x40; /* Cambiar led de estado */ delay(1000); /* Esperar un segundo */ }}

EJEMPLO 3: Temporización mediante interrupciones. El programa enciende el led, activas lasinterrupciones del comparador 4 y ejecuta un bucle infinito. Mediante interrupciones se temporizan 2segundos y se apaga el led. El programa principal podría estar ejecutando cualquier otra operación. Alcabo de 2 segundos el led se apagaría.

/* +------------------------------------------------------------------------+ ¦ TEMPO.C (C) GRUPO J&J. ABRIL 1997 ¦ ¦------------------------------------------------------------------------¦ ¦ Programa ejemplo para ser ejecutado en la tarjeta CT6811. ¦ ¦ Este programa se debe cargar en la RAM interna del 6811. ¦ ¦ ¦ ¦ Ejemplo de utilización del comparador 4 para realizar temporiza- ¦ ¦ ciones mediante interrupciones. El programa principal enciende el led,¦

Page 50: Programación de la tarjeta CT6811 en lenguaje C

Programación de la tarjeta CT6811 en lenguaje C

50

¦ activa la temporización y ejecuta un bucle infinito. Al cabo de 2 ¦ ¦ segundos el led se apagará. ¦ ¦ ¦ +------------------------------------------------------------------------+ */

#include "regs6811.h"#include "vectint.h"

#define T1_MS 2000

unsigned int tiempo;

void ssioc4()/* +---------------------------------------------------------+ ¦ Subrutina de servicio de interrupción del comparador 4 ¦ +---------------------------------------------------------+ */{ TFLG1|=0x10; /* Quitar flag de interrupción */ TOC4=TCNT+T1_MS; /* Activar comparador 4 para que se dispare cada 1 ms */

if (tiempo==0) { PORTA=0x00; /* Apagar el led */ TMSK1&=~0x10; /* Desactivar interrupción comparador 4 */ } else tiempo--;

}

void rsioc4()/* +-----------------------------------------------------+ ¦ Rutina de servicio de interrupción del comparador 4 ¦ +-----------------------------------------------------+ */{ ssioc4(); /* Llamar a subrutina de servicio de interrupción */ asm (" RTI");}

main(){ /* ----------- Cambiar vector de interrupción ------------------ */ vioc41=0x7E; /* Colocar instrucción JMP */ vioc42=(unsigned int)rsioc4; /* Colocar dirección rutina servicio */

TMSK1|=0x10; /* Permitir las interrupciones del comparador 4 */ PORTA=0x40; /* Encender el led */ tiempo=2000; /* Esperar 2 segundos */ asm (" CLI"); /* Permitir las interrupciones */

for (;;) ; /* Bucle infinito */}

EJEMPLO 4: Generación de señales cuadradas mediante interrupciones y salida hardware.

/* +------------------------------------------------------------------------+ ¦ ONDCUAD.C (C) GRUPO J&J. ABRIL 1997 ¦ ¦------------------------------------------------------------------------¦ ¦ Programa ejemplo para ser ejecutado en la tarjeta CT6811. ¦ ¦ Este programa se debe cargar en la RAM interna del 6811. ¦ ¦ ¦ ¦ Ejemplo de utilización del comparador 2 con salida hardware para ¦ ¦ generar señales cuadradas de una frecuencia determinada mediante ¦ ¦ interrupciones. ¦ ¦ ¦ +------------------------------------------------------------------------+ */

#include "regs6811.h"#include "vectint.h"

#define TIEMPO 60000

void ssioc2()/* +---------------------------------------------------------+ ¦ Subrutina de servicio de interrupción del comparador 2 ¦ +---------------------------------------------------------+ */

Page 51: Programación de la tarjeta CT6811 en lenguaje C

Programación de la tarjeta CT6811 en lenguaje C

51

{ TFLG1|=0x40; /* Quitar flag de interrupción */ TOC2=TCNT+TIEMPO; /* Activar comparador 2 */ asm (" RTI");}

void rsioc2()/* +-----------------------------------------------------+ ¦ Rutina de servicio de interrupción del comparador 2 ¦ +-----------------------------------------------------+ */{ ssioc2(); /* Llamar a la subrutina de servicio de interrupción */ asm (" RTI");}

main(){ /* ----------- Cambiar vector de interrupción ------------------ */ vioc21=0x7E; /* Colocar instrucción JMP */ vioc22=(unsigned int)rsioc2; /* Colocar dirección rutina servicio */

TCTL1|=0x40; /* Activar salida hardware del comparador 2 */ TMSK1|=0x40; /* Permitir las interrupciones del comparador 4 */ asm (" CLI"); /* Permitir las interrupciones */

for (;;) ; /* Bucle infinito */}

Page 52: Programación de la tarjeta CT6811 en lenguaje C

Programación de la tarjeta CT6811 en lenguaje C

52

Page 53: Programación de la tarjeta CT6811 en lenguaje C

Programación de la tarjeta CT6811 en lenguaje C

53

3.4.8.- PROGRAMACION DE LOS CAPTURADORES

EJEMPLO 1: Interrupción en flanco de bajada. En este ejemplo se utiliza el capturador 3 paracapturar flancos de bajada. Cada vez que se obtiene un flanco de bajada por el bit PA0 se cambia elestado del led. Se hace mediante interrupciones.

/* +------------------------------------------------------------------------+ ¦ CAP.C (C) GRUPO J&J. ABRIL 1997 ¦ ¦------------------------------------------------------------------------¦ ¦ Programa ejemplo para ser ejecutado en la tarjeta CT6811. ¦ ¦ Este programa se debe cargar en la RAM interna del 6811. ¦ ¦ ¦ ¦ Ejemplo de utilización del capturador de entrada 2 como entrada de ¦ ¦ interrupciones configurada en flanco de bajada. Cada vez que se ¦ ¦ obtenga un flanco de bajada por el pin PA1 se cambia el estado del ¦ ¦ led. ¦ +------------------------------------------------------------------------+ */

#include "regs6811.h"#include "vectint.h"

void ssiic2()/* +---------------------------------------------------------+ ¦ Subrutina de servicio de interrupción del capturador 2 ¦ +---------------------------------------------------------+ */{ TFLG1|=0x02; /* Quitar flag de interrupción */ PORTA^=0x40;}

void rsiic2()/* +-----------------------------------------------------+ ¦ Rutina de servicio de interrupción del capturador 2 ¦ +-----------------------------------------------------+ */{ ssiic2(); asm (" RTI");}

main(){ /* ----------- Cambiar vector de interrupción ------------------ */ viic21=0x7E; /* Colocar instrucción JMP */ viic22=(unsigned int)rsiic2; /* Colocar dirección rutina servicio */

TCTL2|=0x08; /* Configurar capturador 2 para flanco de bajada */ TMSK1|=0x02; /* Permitir las interrupciones del capturador 2 */ asm (" CLI"); /* Permitir las interrupciones */

for (;;) ; /* Bucle infinito */}

EJEMPLO 2: Utilización del comparador 2 para contar flancos de bajada. Cada vez que se reciban5 flancos de bajada por el pin PA1 el led cambiará de estado.

/* +------------------------------------------------------------------------+ ¦ CAP2.C (C) GRUPO J&J. ABRIL 1997 ¦ ¦------------------------------------------------------------------------¦ ¦ Programa ejemplo para ser ejecutado en la tarjeta CT6811. ¦ ¦ Este programa se debe cargar en la RAM interna del 6811. ¦ ¦ ¦ ¦ Ejemplo de utilización del capturador de entrada 2 como entrada de ¦ ¦ interrupciones configurada en flanco de bajada. Cada vez que se ¦ ¦ obtienen 5 flancos de bajada se cambia el estado del led. ¦ ¦ ¦ +------------------------------------------------------------------------+ */

#include "regs6811.h"#include "vectint.h"

Page 54: Programación de la tarjeta CT6811 en lenguaje C

Programación de la tarjeta CT6811 en lenguaje C

54

char cuenta;

void ssiic2()/* +---------------------------------------------------------+ ¦ Subrutina de servicio de interrupción del capturador 2 ¦ +---------------------------------------------------------+ */{ TFLG1|=0x02; /* Quitar flag de interrupción */ cuenta--; if (cuenta==0) { PORTA^=0x40; cuenta=5; }}

void rsiic2()/* +-----------------------------------------------------+ ¦ Rutina de servicio de interrupción del capturador 2 ¦ +-----------------------------------------------------+ */{ ssiic2(); asm (" RTI");}

main(){ /* ----------- Cambiar vector de interrupción ------------------ */ viic21=0x7E; /* Colocar instrucción JMP */ viic22=(unsigned int)rsiic2; /* Colocar dirección rutina servicio */

TCTL2|=0x08; /* Configurar capturador 2 para flanco de bajada */ TMSK1|=0x02; /* Permitir las interrupciones del capturador 2 */ cuenta=5; PORTC=cuenta << 4; asm (" CLI"); /* Permitir las interrupciones */

for (;;) ; /* Bucle infinito */}

Page 55: Programación de la tarjeta CT6811 en lenguaje C

Programación de la tarjeta CT6811 en lenguaje C

55

3.4.9.- PROGRAMACIÓN DEL ACUMULADOR DE PULSOS

EJEMPLO 1: Cuenta de 5 flancos de bajada. En este ejemplo cada 5 flancos de bajada recibidos porel pin PA7 se cambia el estado del led.

/* +------------------------------------------------------------------------+ ¦ ACUM.C (C) GRUPO J&J. MAYO 1997 ¦ ¦------------------------------------------------------------------------¦ ¦ Programa ejemplo para ser ejecutado en la tarjeta CT6811. ¦ ¦ Este programa se debe cargar en la RAM interna del 6811. ¦ ¦ ¦ ¦ Ejemplo de utilización del acumulador de pulsos. Cada 5 flancos de ¦ ¦ bajada en el pin PA7 se cambia el estado del led. ¦ ¦ ¦ +------------------------------------------------------------------------+ */

#include "regs6811.h"#include "vectint.h"

void ssiap()/* +------------------------------------------------------------------+ ¦ Subrutina de servicio de interrupción del acumulador de pulsos ¦ +------------------------------------------------------------------+ */{ TFLG1|=0x10; if (PACNT==5) { /* Si se han producido 5 flancos de bajada */ PORTA^=0x40; /* Cambiar el estado del led */ PACNT=0; /* Inicializar acumulador de pulsos */ }}

void rsiap()/* +--------------------------------------------------------------+ ¦ Rutina de servicio de interrupción del acumulador de pulsos ¦ +--------------------------------------------------------------+ */{ ssiap(); /* Llamar a subrutina de servicio de interrupción */ asm (" RTI");}

main(){ /* ----------- Cambiar vector de interrupción ------------------ */ viap1=0x7E; /* Colocar instrucción JMP */ viap2=(unsigned int)rsiap; /* Colocar dirección rutina servicio */

PACNT=0; /* Poner a cero el acumulador de pulsos */ PACTL|=0x40; /* Activar acumulador de pulsos. Modo cuenta de pulsos */ /* en flanco de bajada */ TMSK2|=0x10; /* Activar la interrupción del acumulador */ asm (" CLI"); /* Permitir las interrupciones */

for (;;) ; /* Bucle infinito */}

EJEMPLO 2: Interrupción de overflow del acumulador de pulsos. En este ejemplo se cambia elestado del led cada vez que se produce un desbordamiento en el acumulador de pulsos. Losdesbordamientos se producen cada 256 pulsos. Para hacer que ocurran sólo cada 5 pulsos se inicializa elacumulador de pulsos con el valor $FB.

/* +------------------------------------------------------------------------+ ¦ ACUM2.C (C) GRUPO J&J. MAYO 1997 ¦ ¦------------------------------------------------------------------------¦ ¦ Programa ejemplo para ser ejecutado en la tarjeta CT6811. ¦ ¦ Este programa se debe cargar en la RAM interna del 6811. ¦ ¦ ¦ ¦ Ejemplo de utilización de la interrupción de overflow del acumula- ¦ ¦ dor de pulsos. Cada vez que se produce overflow se cambia el estado ¦ ¦ del led. El overflow se produce cada 256 flancos de bajada. Para ¦ ¦ facilitar la prueba del programa, cada vez que se produce un over- ¦ ¦ flow se coloca el valor $FB en el acumulador de pulsos para que se ¦ ¦ produzca overflow cada 5 pulsos. ¦

Page 56: Programación de la tarjeta CT6811 en lenguaje C

Programación de la tarjeta CT6811 en lenguaje C

56

¦ ¦ +------------------------------------------------------------------------+ */

#include "regs6811.h"#include "vectint.h"

void ssioap()/* +------------------------------------------------------------------+ ¦ Subrutina de servicio de interrupción del overflow del acumulador¦ +------------------------------------------------------------------+ */{ TFLG2|=0x20; PORTA^=0x40; PACNT=0xFB;}

void rsioap()/* +-----------------------------------------------------------------+ ¦ Rutina de servicio de interrupción del overflow del acumulador ¦ +-----------------------------------------------------------------+ */{ ssioap(); /* Llamar a subrutina de servicio de interrupción */ asm (" RTI");}

main(){ /* ----------- Cambiar vector de interrupción ------------------ */ vioap1=0x7E; /* Colocar instrucción JMP */ vioap2=(unsigned int)rsioap; /* Colocar dirección rutina servicio */

PACNT=0xFB; /* Inicializar acumulador de pulsos */ PACTL|=0x40; /* Configurar acumulador de pulsos */ TMSK2|=0x20; /* Permitir la interrupción de overflow del acumulador */

asm (" CLI"); /* Permitir las interrupciones */

for (;;) ; /* Bucle infinito */}

Page 57: Programación de la tarjeta CT6811 en lenguaje C

Programación de la tarjeta CT6811 en lenguaje C

57

3.4.10.- LA INTERRUPCION EXTERNA IRQ

EJEMPLO: IRQ configurada para flanco de bajada

/* +------------------------------------------------------------------------+ ¦ IRQ.C (C) GRUPO J&J. MAYO 1997 ¦ ¦------------------------------------------------------------------------¦ ¦ Programa ejemplo para ser ejecutado en la tarjeta CT6811. ¦ ¦ Este programa se debe cargar en la RAM interna del 6811. ¦ ¦ ¦ ¦ Ejemplo de utilización de la interrupción IRQ. Cada vez que se ¦ ¦ recibe un flanco de bajada se cambia el estado del led. ¦ ¦ ¦ +------------------------------------------------------------------------+ */

#include "regs6811.h"#include "vectint.h"

void ssiirq()/* +------------------------------------------------+ ¦ Subrutina de servicio de la interrupción irq ¦ +------------------------------------------------+ */{ PORTA^=0x40;}

void rsiirq()/* +--------------------------------------------+ ¦ Rutina de servicio de la interrupción irq ¦ +--------------------------------------------+ */{ ssiirq(); /* Llamar a subrutina de servicio de interrupción */ asm (" RTI");}

main(){ /* ----------- Cambiar vector de interrupción ------------------ */ viirq1=0x7E; /* Colocar instrucción JMP */ viirq2=(unsigned int)rsiirq; /* Colocar dirección rutina servicio */

OPTION|=0x20; asm (" CLI"); /* Permitir las interrupciones */

for (;;) ; /* Bucle infinito */}

Page 58: Programación de la tarjeta CT6811 en lenguaje C

Programación de la tarjeta CT6811 en lenguaje C

58

Page 59: Programación de la tarjeta CT6811 en lenguaje C

Programación de la tarjeta CT6811 en lenguaje C

59

3.4.11.- CONVERSOR ANALOGICO-DIGITAL (A/D)

EJEMPLO 1: En el siguiente ejemplo se toman muestras a través del canal 1 del conversor A/D. Estasmuestas se envían al PC a través del SCI.

/* +------------------------------------------------------------------------+ ¦ ADSCI.C (C) GRUPO J&J. MAYO 1997 ¦ ¦------------------------------------------------------------------------¦ ¦ Programa ejemplo para ser ejecutado en la tarjeta CT6811. ¦ ¦ Este programa se debe cargar en la RAM interna del 6811. ¦ ¦ ¦ ¦ Ejemplo de utilización del conversor A/D. Se leen muestras y se ¦ ¦ envían a través del SCI. ¦ ¦ ¦ +------------------------------------------------------------------------+ */

#include "regs6811.h"#include "SCI.H"

main(){ OPTION|=0x80; /* Encender el conversor */ ADCTL|=0x20; /* Configurar el conversor */

for (;;) { while (!(ADCTL & 0x80)); /* Esperar a que termine conversion */ enviar_car(ADR1); /* Enviar muestra leida por el SCI */ }}

EJEMPLO 2: Cuando la tensión de entrada supera un cierto umbral (2.5 voltios) se enciende el led. Encaso contrario se apaga.

/* +------------------------------------------------------------------------+ ¦ ADLED.C (C) GRUPO J&J. MAYO 1997 ¦ ¦------------------------------------------------------------------------¦ ¦ Programa ejemplo para ser ejecutado en la tarjeta CT6811. ¦ ¦ Este programa se debe cargar en la RAM interna del 6811. ¦ ¦ ¦ ¦ Ejemplo de utilización del conversor A/D. Cuando la tensión supere ¦ ¦ los 2.5 voltios se enciende el led. ¦ ¦ ¦ +------------------------------------------------------------------------+ */

#include "regs6811.h"

main(){ OPTION|=0x80; /* Encender el conversor */ ADCTL|=0x20; /* Configurar el conversor */

for (;;) { while (!(ADCTL & 0x80)); /* Esperar a que termine conversion */ if (ADR1>0x7F) PORTA=0x40; else PORTA=0x00; }}

Page 60: Programación de la tarjeta CT6811 en lenguaje C

Programación de la tarjeta CT6811 en lenguaje C

60

Page 61: Programación de la tarjeta CT6811 en lenguaje C

Programación de la tarjeta CT6811 en lenguaje C

61

3.4.12.- PROGRAMACION DE LA EEPROM

EJEMPLO 1: Librería EEPROM.H para programación de la EEPROM

/* +------------------------------------------------------------------------+ ¦ EEPROM.H (C) GRUPO J&J. MAYO 1997 ¦ ¦------------------------------------------------------------------------¦ ¦ Librería para programación de la memoria EEPROM. ¦ ¦ ¦ ¦ * grabar(dato,dir) --> Grabar un dato en la dirección de EEPROM ¦ ¦ especificada ¦ ¦ * borrar(dir) --> Borrar la posición de EEPROM especificada ¦ ¦ * borrar_eeprom() --> Borrar la eeprom completamente. ¦ ¦ ¦ +------------------------------------------------------------------------+ */

#include "regs6811.h"#include "delay.h"

void grabar(dato,dir)char dato;char *dir;/* +------------------------------------------------------+ ¦ Grabar un byte en la dirección de EEPROM indicada. ¦ +------------------------------------------------------+ */{ PPROG=0x02; *dir=dato; PPROG=0x03; delay(10); PPROG=0x00;}

void borrar(dir)char *dir;/* +------------------------------------------------------+ ¦ Borrar un byte de la dirección de EEPROM indicada. ¦ +------------------------------------------------------+ */{ PPROG=0x16; *dir=0; PPROG=0x17; delay(10); PPROG=0x00;}

void borrar_eeprom()/* +-----------------------------+ ¦ Borrar la EEPROM entera. ¦ +-----------------------------+ */{ PPROG=0x06; (*(unsigned char *)0xB600)=0; PPROG=0x07; delay(10); PPROG=00;}

EJEMPLO 2: Manejo de la librería EEPROM.H

/* +------------------------------------------------------------------------+ ¦ EEPROM.C (C) GRUPO J&J. ABRIL 1997 ¦ ¦------------------------------------------------------------------------¦ ¦ Programa ejemplo para ser ejecutado en la tarjeta CT6811. ¦ ¦ Este programa se debe cargar en la RAM interna del 6811. ¦ ¦ ¦ ¦ Ejemplo de manejo de la librería de programación de la EEPROM. ¦ ¦ Se borra la EEPROM completamente y se graban datos. ¦ +------------------------------------------------------------------------+ */

#include "regs6811.h"#include "eeprom.h"

unsigned char i;

main()

Page 62: Programación de la tarjeta CT6811 en lenguaje C

Programación de la tarjeta CT6811 en lenguaje C

62

{ borrar_eeprom(); /* Borrar la eeprom entera */

for (i=0; i<0xFF; i++) { grabar(i,0xB600+i); }}

Page 63: Programación de la tarjeta CT6811 en lenguaje C

Programación de la tarjeta CT6811 en lenguaje C

63

4.- PROGRAMACION DE LA CT6811 EN MODOAUTONOMO

4.1.- INTRODUCCION

Cuando se quiere que la tarjeta CT6811 funcione en modo autónomo es preciso grabar el códigoen la memoria EEPROM. Las variables y la pila se deben situar en la memoria RAM interna. Por ello,el código ya no está unificado. Se debe reservar un segmento en la RAM interna para las variables y unsegmentos en la EEPROM para el código.

Cuando se programa directamente en ensamblador es preciso modificar el código fuente paraadaptarlo a la memoria EEPROM. Sin embargo, cuando programamos en C el compilador hace todo eltrabajo por nosotros. El mismo código fuente en C servirá tanto para la RAM interna como para laEEPROM. La única diferencia consistirá en la forma de compilar. Para compilar código para la RAMinterna se utilizará el fichero CINT.BAT. Para compilar para la EEPROM se utilizará el archivoCEEPROM.BAT.

4.2.- CONFIGURACION DEL COMPILADOR

4.2.1.- El fichero de arranque y configuración CTEEPROM.S

En la figura 28 se muestra el fichero CTEEPROM.S. Se definen dos secciones. La sección 0 secorresponde con el segmento de código que lo situamos al comienzo de la EEPROM (Dirección $B600).La sección 1 se corresponde con las variables que se sitúan en el comienzo de la RAM interna(Dirección $0000).

El programa comienza en la línea 14 con la directiva SECT 0. Con esto se indica que lo queviene a contianuación es código que se debe situar en el segmento de código. El código lo único que hacees llamar al programa principal _main y después entrar en un bucle infinito.

4.2.2.- Situación de las variables al comienzo del fichero en ensamblador

Los programas para la EEPROM no deben estar unificados. Ya no es necesario utilizar elprograma UNIFICA.EXE para situar código y datos en el mismo segmento. Ahora el código se situaráen un segmento y los datos en otro.

Sin embargo, las variables siguen teniendo que estar al comienzo del fichero en ensamblador.Por ello sigue siendo preciso utilizar el programa GETVARS.EXE. Pero esta vez habrá que utilizar elparámetro -s para que aparezca la directiva SECT 1 justo delante de las variables.. En la figura 29 semuestra cómo situar las variables al comienzo del archivo prueba.s

* +------------------------------------------------------------------------+* ¦ CTEEPROM.S (C) GRUPO J&J. MAYO 1997 ¦* ¦------------------------------------------------------------------------¦* ¦ Fichero de arranque y configuración para trabajar con la tarjeta ¦* ¦ CT6811 en modo autónomo. ¦* +------------------------------------------------------------------------+ */

SECT 0 ; Sección 0 : Segmento para el código ORG $B600 ; El código se sitúa en la eeprom

SECT 1 ; Sección 1 : Segmento para los datos ORG $0000 Los datos se sitúan en la RAM interna

SECT 0

jsr _main ; Saltar al programa principalinf bra inf ; ¡Bucle infinito!

Figura 28: El fichero de arranque y configuración CTEEPROM.S

Page 64: Programación de la tarjeta CT6811 en lenguaje C

Programación de la tarjeta CT6811 en lenguaje C

64

4.2.3.- Generación de archivos ejecutables .S19

Para generar el archivo .S19 final que se cargará en la EEPROM habrá que ensamblar losficheros .S junto con el archivo de arranque y configuración CTEEPROM.S. En la figura 30 se muestraun ejemplo de generación del archivo prueba.s19 a partir del archivo prueba.s, que ya tiene lasvariables al comienzo, y del fichero cteeprom.S

También en la figura 30 se muestra el contenido del archivo prueba.S19. Si el lector entiendeeste formato podrá comprobar que todas las direcciones están situadas en la memoria EEPROM. Estasdirecciones se han escrito en negrita.

4.2.4.- Resumen de los pasos necesarios para obtener ficheros ejecutables para la memoriaEEPROM.

• Compilar todos los archivos .C que integren el programa final. Para ello utilizar: ICC11 -S fichero.c• Situar todas las variables al comienzo del código con el programa GETVARS.EXE• Ensamblar todos los ficheros .S ya modificados junto con el archivo de arranque y configuración

CTEEPROM.S• Ya se dispone de un archivo .S19 listo para ser grabado en la memoria EEPROM.

4.2.5.- El archivo CEEPROM.BAT para compilar programas para la EEPROM

En la figura 31 se muestra el archivo CEEPROM.BAT que se utilizará para generar códigoejecutable para ser grabado en la memoria EEPROM del 68HC11. El usuario puede utilizar este archivoy se puede olvidar de todos los pasos intermedios.

Si se utiliza el archivo CINT.BAT se compilarán programas para la RAM interna. Una vezque estos programas hayan sido probados y funcionen se compilarán con el programa CEEPROM.BATy se podrán grabar en la memoria EEPROM. En el apartado 4.3 se muestra un ejemplo completo decompilación de programas para la EEPROM y su grabación utilizando el programa CTDIALOG.

C:\6811\ICC\CT68INT>getvars prueba.s temp.s -s > vars

C:\6811\ICC\CT68INT>type vars SECT 1_i: RMB 2

C:\6811\ICC\CT68INT>copy vars+temp.s prueba.sVARSTEMP.S 1 archivo(s) copiado(s)

C:\6811\ICC\CT68INT>_

Figura 29: Situación de las variables al comienzo del fichero prueba.s

C:\6811\ICC\CT68INT>ias11 -o prueba cteeprom.s prueba.s

C:\6811\ICC\CT68INT>type prueba.s19S108B600BDB60520FEABS123B605F610004FC840F71000CC0000DD007EB61DDC00C30001DD00DC001A83800025F137S106B6257EB605E5S9030000FC

C:\6811\ICC\CT68INT>_

Figura 30: Generación del archivo ejecutable PRUEBA.S19

Page 65: Programación de la tarjeta CT6811 en lenguaje C

Programación de la tarjeta CT6811 en lenguaje C

65

@REM@REM ------------- Compilar de .c a .s ------------------@REM@icc11 -S %1.c@REM@REM ------------ Eliminación de las variables RMB ---------------@REM@getvars %1.s temp.s -s > %1.var@REM@REM ------------ Generación del fichero .s final -----------------@REM@copy %1.var+temp.s %1.s > NUL@REM@REM ------------- Borrar ficheros temporales --------@REM del temp.s > NUL@REM@REM ------------ Generar fichero .S19 ---------------------@REM@ias11 -o %1 cteeprom.s %1.s

Figura 31: Fichero CEEPROM.BAT para compilar programas en C para la EEPROM

Page 66: Programación de la tarjeta CT6811 en lenguaje C

Programación de la tarjeta CT6811 en lenguaje C

66

Page 67: Programación de la tarjeta CT6811 en lenguaje C

Programación de la tarjeta CT6811 en lenguaje C

67

4.3.- EJEMPLOS DE PROGRAMAS PARA LA EEPROM

Todos los ejemplos desarrollados en la sección 3 sirven para ser grabados en la EEPROM. Enesta sección se va a presentar un ejemplo completo.

El programa de ejemplo a utilizar va a ser el programa TEMPO.C. Este programa se hapresentado en la sección 3.4.7 como ejemplo de manejo de los comparadores mediante interrupciones. Elprograma simplemente enciende un led y lo apaga al cabo de 2 segundos. Se ha elegido este programaejemplo para ser grabado en la eeprom porque utiliza interrupciones.

A continuación se presenta el código en C.

/* +------------------------------------------------------------------------+ ¦ TEMPO.C (C) GRUPO J&J. ABRIL 1997 ¦ ¦------------------------------------------------------------------------¦ ¦ Programa ejemplo para ser ejecutado en la tarjeta CT6811. ¦ ¦ Este programa se debe cargar en la RAM interna del 6811. ¦ ¦ ¦ ¦ Ejemplo de utilización del comparador 4 para realizar temporiza- ¦ ¦ ciones mediante interrupciones. El programa principal enciende el led,¦ ¦ activa la temporización y ejecuta un bucle infinito. Al cabo de 2 ¦ ¦ segundos el led se apagará. ¦ ¦ ¦ +------------------------------------------------------------------------+ */

#include "regs6811.h"#include "vectint.h"

#define T1_MS 2000

unsigned int tiempo;

void ssioc4()/* +---------------------------------------------------------+ ¦ Subrutina de servicio de interrupción del comparador 4 ¦ +---------------------------------------------------------+ */{ TFLG1|=0x10; /* Quitar flag de interrupción */ TOC4=TCNT+T1_MS; /* Activar comparador 4 para que se dispare cada 1 ms */

if (tiempo==0) { PORTA=0x00; /* Apagar el led */ TMSK1&=~0x10; /* Desactivar interrupción comparador 4 */ } else tiempo--;

}

void rsioc4()/* +-----------------------------------------------------+ ¦ Rutina de servicio de interrupción del comparador 4 ¦ +-----------------------------------------------------+ */{ ssioc4(); /* Llamar a subrutina de servicio de interrupción */ asm (" RTI");}

main(){ /* ----------- Cambiar vector de interrupción ------------------ */ vioc41=0x7E; /* Colocar instrucción JMP */ vioc42=(unsigned int)rsioc4; /* Colocar dirección rutina servicio */

TMSK1|=0x10; /* Permitir las interrupciones del comparador 4 */ PORTA=0x40; /* Encender el led */ tiempo=2000; /* Esperar 2 segundos */ asm (" CLI"); /* Permitir las interrupciones */

for (;;) ; /* Bucle infinito */}

Page 68: Programación de la tarjeta CT6811 en lenguaje C

Programación de la tarjeta CT6811 en lenguaje C

68

En la figura 32 se muestra cómo compilar este programa para la ram interna ycomo enviarlo a la CT6811 para ser ejecutado.

Ahora se quiere grabar este programa en la EEPROM para que la CT6811 se convierta en unatarjeta autónoma, independiente del PC. Primero se compila el programa utilizando el archivoCEEPROM.BAT. Con ello obtenemos el archivo TEMPO.S19 listo para ser grabado en la EEPROM.Para grabarlo en la eeprom se utilizará el programa CTDIALOG desarrollado por el Grupo J&J. Paraejecutar este programa primero es preciso enviar a la CT6811 el programa servidor CTSERVER. Unavez dentro del CTDIALOG, con el comando eeprom podremos grabar programas en la eeprom. En lafigura 33 se muestra el proceso completo.

Una vez grabado el programa en la eeprom, la CT6811 se convierte en una tarjeta autónoma.Ahora, cada vez que se pulse el botón de reset3 se ejecutará el programa grabado en la EEPROM. Si seha grabado el ejemplo TEMPO.S19, cada vez que se pulse el botón de reset se encenderá el led y seapagará al cabo de 2 segundos.

La figura 33 se encuentra en la siguiente página.

3Se supone que el usuario a colocado el jumper JP5 de la CT6811 para configurarla en modo autónomo

C:\6811\ICC\CT68INT>cint tempo

UNIFICA V1.0 (C) GRUPO J&J. Abril 1997.Generación de código unificado en ensamblador

Fichero a Filtrar: tempo.sFichero destino : temp.s

C:\6811\ICC\CT68INT>C:\6811\ICC\CT68INT>downmcu tempo -com2

DOWN-MCU. V1.0 (C) GRUPO J&J. Noviembre-1996.Envío de programas a la entrenadora

Fichero a enviar: .\tempo.S19Puerto serie: COM2

Pulse reset en la entrenadora...Transmitiendo:>>>>>..>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>................................................................................................................................................................OK!Envío correctoTamaño del programa: 94 bytes

C:\6811\ICC\CT68INT>_

Figura 32: Compilación del programa TEMPO.C para la RAM interna y posteriorenvío a la CT6811

Page 69: Programación de la tarjeta CT6811 en lenguaje C

Programación de la tarjeta CT6811 en lenguaje C

69

C:\6811\ICC\CT68INT>ceeprom tempo

C:\6811\ICC\CT68INT>downmcu ctserver -com2

DOWN-MCU. V1.0 (C) GRUPO J&J. Noviembre-1996.Envío de programas a la entrenadora

Fichero a enviar: .\ctserver.S19Puerto serie: COM2

Pulse reset en la entrenadora...Transmitiendo: >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>......OK!Envío correctoTamaño del programa: 250 bytes

C:\6811\ICC\CT68INT>ctdialog -com2

CTDIALOG Versión 1.0 (C) GRUPO J&J. Diciembre 1996Teclee HELP para obtener ayuda

Puerto actual: COM2Estableciendo conexión con tarjeta..... conexión establecida

>eeprom tempoFichero a grabar en memoria EEPROM: TEMPO.S19Transmitiendo: »---------------------------»»»Grabación terminadaNúmero bytes grabados: 95

>g b600Conexión perdida

*>quitPrograma terminado

C:\6811\ICC\CT68INT>_

Figura 33: Compilando y granbando en la EEPROM el programa TEMPO.C

Page 70: Programación de la tarjeta CT6811 en lenguaje C

Programación de la tarjeta CT6811 en lenguaje C

70

4.4.- CONSIDERACIONES A TENER EN CUENTA

La única precaución a tener en cuenta al generar programas para la EEPROM es que lasvariables no se puden inicializar en su declaración, sino que se deben inicializar en el propio código.A contianucación se muestra un fragmento de código que funcionaría bien para la RAM interna peroque no se podría grabar en la EEPROM.

Si se envía a la RAM interna de la CT6811 el programa funciona correctamente y el led seenciende. Sin embargo si se compila para la EEPROM y se intenta grabar utiliando el programaCTDIALOG se obtendrá un mensaje de error como el indicado en la figura 35.

El programa correcto debe ser como el indicado en la figura 36:

La única diferencia está en que en el primer programa se ha inicializado la variable c en elmomento de la inicialización. En el segundo programa la inicialización se hace en el propio código.

#include "REGS6811.H"

static char c=5;

main(){ if (c==5) PORTA=0x40;}

Figura 34: Ejemplo de programa que no se puede grabar en la EEPROM.

C:\6811\ICC\CT68INT>ctdialog -com2

CTDIALOG Versión 1.0 (C) GRUPO J&J. Diciembre 1996Teclee HELP para obtener ayuda

Puerto actual: COM2Estableciendo conexión con tarjeta..... conexión establecida

>eeprom wrongFichero a grabar en memoria EEPROM: WRONG.S19Transmitiendo: -----»Dirección 0000: Intento de acceso a memoria no EEPROMGrabación no completada

>quitConexión terminada

C:\6811\ICC\CT68INT>

Figura 35: Mensaje de error al intentar grabar un programa incorrecto en la memoria EEPROM.

#include "REGS6811.H"

static char c;

main(){ c=5;

if (c==5) PORTA=0x40;}

Figura 36: Programa corregido para poder ser grabado en la EEPROM.

Page 71: Programación de la tarjeta CT6811 en lenguaje C

Programación de la tarjeta CT6811 en lenguaje C

71

En la figura 37 se muestran los fichero .S19 correspondientes a los dos programasanteriores.

Se han escrito en negrita las direcciones en las que se sitúa el código. En el caso del programaincorrecto aparece código en la RAM interna (dirección $0000). En el caso del programa correcto todaslas direcciones se encuentran dentro de la EEPROM.

C:\6811\ICC\CT68INT>type wrong.s19S108B600BDB60520FEABS104000005F6S116B605D6004F5D2A01431A8300052605C640F71000392BS9030000FC

C:\6811\ICC\CT68INT>type right.s19S108B600BDB60520FEABS11AB605C605D700D6004F5D2A01431A8300052605C640F710003985S9030000FC

C:\6811\ICC\CT68INT>

Figura 37: Comparación de los ejecutables incorrecto y correcto para ser grabados en laEEPROM.

Page 72: Programación de la tarjeta CT6811 en lenguaje C

Programación de la tarjeta CT6811 en lenguaje C

72

Page 73: Programación de la tarjeta CT6811 en lenguaje C

Programación de la tarjeta CT6811 en lenguaje C

73

5.- LIBRERIAS EN ENSAMBLADOREn esta sección se muestran una serie de librerías codificadas en ensamblador y adaptadas para

funcionar con el compilador de C. Estas librerías ocupan menos espacio que las correspondientescodificadas en C. El interfaz para las librerías en C y en ASM es el mismo y por tanto se pueden usarindistintamente unas u otras. No obstante, si se está trabajando con la RAM interna del 68HC11 o con laEEPROM es conveniente uitlizar las librerías en ensamblador para ahorrar espacio.

5.1.- LIBRERIA SCIASM.H PARA MANEJO DEL SCI

Esta es la librería equivalente a SCI.H pero codificada en ensamblador. El interfaz esexactamente el mismo para las dos librerías.

/* +------------------------------------------------------------------------+ ¦ SCIASM.H (C) GRUPO J&J. ABRIL 1997 ¦ ¦------------------------------------------------------------------------¦ ¦ Rutinas de manejo del SCI mediante espera activa. ¦ ¦ Las rutians tienen un interfaz en C pero están implementadas directa- ¦ ¦ mente en ensamblador, por lo que estan MUY OPTIMIZADAS. ¦ ¦ ¦ ¦ leer_car() -----> Leer el carácter que venga por el SCI. ¦ ¦ enviar_car(c) --> Enviar un carácter por el SCI ¦ ¦ enviar(cad) ----> Enviar una cadena de caracteres por el SCI ¦ ¦ ¦ +------------------------------------------------------------------------+ */

char leer_car()/* +--------------------------------------------------------+ ¦ Función que devuelve el carácter recibido por el SCI ¦ +--------------------------------------------------------+ */{ asm (" PSHY"); asm (" LDY #$102E"); asm ("leer_car BRCLR 0,Y $10 leer_car"); asm (" LDAB $102F"); asm (" PULY");}

void enviar_car(char c)/* +------------------------------------------+ ¦ Enviar un carácter por el puerto serie. ¦ +------------------------------------------+ */{ asm(" PSHY"); asm(" LDY #$102E"); asm("enviar BRCLR 0,Y $80 enviar"); asm(" LDAB %c"); asm(" STAB 1,Y"); asm(" PULY ");}

void enviar(char *cad)/* +-------------------------------+ ¦ Enviar una cadena por el SCI ¦ +-------------------------------+ */{ asm (" LDY %cad "); asm ("otro_car: "); asm (" LDAB 0,Y"); asm (" TSTB "); asm (" BEQ fin_enviar"); asm (" PSHX"); asm (" TSX"); asm (" STD 0,X"); asm (" JSR _enviar_car"); asm (" PULX"); asm (" INY"); asm (" BRA otro_car"); asm ("fin_enviar");}

Page 74: Programación de la tarjeta CT6811 en lenguaje C

Programación de la tarjeta CT6811 en lenguaje C

74

A continuación se presenta la librería SCI.H. El ahorro en bytes que se consigueutilizando la librería SCIASM.H en vez de SCI.H es de 50 bytes. Por el contrario la librería SCI.H esmucho más legible y entendible.

/* +------------------------------------------------------------------------+ ¦ SCI.H (C) GRUPO J&J. ABRIL 1997 ¦ ¦------------------------------------------------------------------------¦ ¦ Rutinas de manejo del SCI mediante espera activa. ¦ ¦ ¦ ¦ leer_car() -----> Leer el carácter que venga por el SCI. ¦ ¦ enviar_car(c) --> Enviar un carácter por el SCI ¦ ¦ enviar(cad) ----> Enviar una cadena de caracteres por el SCI ¦ ¦ ¦ +------------------------------------------------------------------------+ */

#include "regs6811.h"

char leer_car()/* +--------------------------------------------------------+ ¦ Función que devuelve el carácter recibido por el SCI ¦ +--------------------------------------------------------+ */{ while(!(SCSR & 0x10)); return SCDR;}

void enviar_car(char c)/* +------------------------------------------+ ¦ Enviar un carácter por el puerto serie. ¦ +------------------------------------------+ */{ while (!(SCSR & 0x40)); SCDR = c;}

void enviar(char *cad)/* +-------------------------------+ ¦ Enviar una cadena por el SCI ¦ +-------------------------------+ */{ static unsigned char i;

i=0; while (cad[i]) { enviar_car(cad[i]); i++; }}

Page 75: Programación de la tarjeta CT6811 en lenguaje C

Programación de la tarjeta CT6811 en lenguaje C

75

5.2.- LIBRERIA SPIASM.H PARA MANEJO DEL SPI

/* +------------------------------------------------------------------------+ ¦ SPI.H (C) GRUPO J&J. ABRIL 1997 ¦ ¦------------------------------------------------------------------------¦ ¦ Rutinas de manejo del SPI mediante espera activa. ¦ ¦ ¦ ¦ spi(c) --> Función que realizar un 'intercambio' por el SPI. Envía ¦ ¦ El carácter c y devuelve lo que se reciba por el SPI. ¦ ¦ spi_maestro() -> Macro para configurar el SPI en modo maestro. ¦ ¦ spi_esclavo() -> Macro para configurar el SPI en modo esclavo ¦ ¦ ¦ +------------------------------------------------------------------------+ */#include "REGS6811.H"

/* +-------------------------------+ --------------------¦ Macros para configurar el SPI ¦----------------- +-------------------------------+ */#define spi_maestro() DDRD=0x38; SPCR=0x54; PORTD=0x00#define spi_esclavo() DDRD=0x04; SPCR=0x44

char spi(char c)/* +--------------------------------------------------------+ ¦ Esta función realizar un 'intercambio' de información ¦ ¦ por el SPI: Se envía el carácter indicado y se devuel- ¦ ¦ ve lo que venga por el SPI. ¦ +--------------------------------------------------------+ */{ asm (" PSHY"); asm (" LDY #$1029"); asm (" LDAA %c"); asm (" STAA 1,Y"); asm ("wspi BRCLR 0,Y $80 wspi"); asm (" LDAB 1,Y"); asm (" PULY");}

Con esta librería se consigue un ahorro de 12 bytes.A continuación se reproduce la librería SPI.H codificada en C.

/* +------------------------------------------------------------------------+ ¦ SPI.H (C) GRUPO J&J. ABRIL 1997 ¦ ¦------------------------------------------------------------------------¦ ¦ Rutinas de manejo del SPI mediante espera activa. ¦ ¦ ¦ ¦ spi(c) --> Función que realizar un 'intercambio' por el SPI. Envía ¦ ¦ El carácter c y devuelve lo que se reciba por el SPI. ¦ ¦ spi_maestro() -> Macro para configurar el SPI en modo maestro. ¦ ¦ spi_esclavo() -> Macro para configurar el SPI en modo esclavo ¦ ¦ ¦ +------------------------------------------------------------------------+ */#include "REGS6811.H"

/* +-------------------------------+ --------------------¦ Macros para configurar el SPI ¦----------------- +-------------------------------+ */#define spi_maestro() DDRD=0x38; SPCR=0x54; PORTD=0x00#define spi_esclavo() DDRD=0x04; SPCR=0x44

char spi(char c)/* +--------------------------------------------------------+ ¦ Esta función realizar un 'intercambio' de información ¦ ¦ por el SPI: Se envía el carácter indicado y se devuel- ¦ ¦ ve lo que venga por el SPI. ¦ +--------------------------------------------------------+ */{ SPDR=c; /* Enviar dato */ while (!(SPSR & 0x80)); /* Esperar a que el dato se envíe */ return SPDR; /* Devolver el dato recibido */}

Page 76: Programación de la tarjeta CT6811 en lenguaje C

Programación de la tarjeta CT6811 en lenguaje C

76

Page 77: Programación de la tarjeta CT6811 en lenguaje C

Programación de la tarjeta CT6811 en lenguaje C

77

5.3.- LIBRERIA DELAYASM.H PARA REALIZAR PAUSAS

/* +------------------------------------------------------------------------+ ¦ DELAYASM.H (C) GRUPO J&J. ABRIL 1997 ¦ ¦------------------------------------------------------------------------¦ ¦ Librería para realizar pausas. Se han implementado directamente ¦ ¦ en ensamblador. ¦ ¦ Se utiliza el comparador 5. ¦ ¦ ¦ ¦ delay(t) --> Realizar una pausa de t milisegundo. ¦ ¦ t=1000 Pausa de 1 segundo ¦ ¦ ¦ +------------------------------------------------------------------------+ */

void delay(unsigned int time){ asm (" PSHY"); asm ("bucle_oc5"); asm (" LDY %time"); asm (" CPY #0"); asm (" BEQ fin_delay"); asm (" DEY"); asm (" STY %time"); asm (" LDD $100E"); asm (" ADDD #2000"); asm (" STD $101E"); asm (" LDY #$1023"); asm (" BSET 0,Y $08"); asm ("oc5 BRCLR 0,Y $08 oc5"); asm (" BRA bucle_oc5"); asm ("fin_delay "); asm (" PULY"); asm (" RTS");}

Esta librería NO COMPENSA implementarla en ensamblador. El ahorro sólo es de 6 bytes y esmucho más complicada de implementar que en C. A continuación se muestra la librería DELAY.H

/* +------------------------------------------------------------------------+ ¦ DELAY.H (C) GRUPO J&J. ABRIL 1997 ¦ ¦------------------------------------------------------------------------¦ ¦ Librería para realizar pausas. ¦ ¦ ¦ ¦ delay(t) --> Realizar una pausa de t milisegundo. ¦ ¦ t=1000 Pausa de 1 segundo ¦ ¦ ¦ +------------------------------------------------------------------------+ */

#include "REGS6811.H"

#define T1_MS 2000 /* Número de tics de reloj necesarios para generar un */ /* retraso de 1ms */

void delay(unsigned int time){ while (time!=0) { time--; TOC5=TCNT+T1_MS; /* Iniciar el comparador para que se active al cabo */ /* de 1ms de tiempo */ TFLG1|=0x08; /* Poner a cero flag del comparador 5 */ while (!(TFLG1 & 0x08)) ; /* Espear a que se active el flag */ }}