Está en la página 1de 413

Sistemas Electrónicos Basados en

Microprocesadores y
Microcontroladores
(6800 y 68HC11)

Bonifacio Martín del Brío

Area de Tecnología Electrónica


Depto. de Ingeniería Electrónica y
Comunicaciones
Universidad de Zaragoza

Revisión de Abril de 1999

Editorial Prensas Universitarias de Zaragoza (España)


ISBN 84-7733-516-8. Puede adquirirse en papel:
http://puz.unizar.es/colecciones/21/62-Textos+Docentes%3A+Tecnol%F3gicas.html
Prólogo

Este texto constituye un curso de introducción al desarrollo de sistemas


electrónicos basados en microprocesadores y microcontroladores, tal y como
podría impartirse en una asignatura relacionada con la electrónica industrial
dentro de una carrera universitaria de tipo técnico.
La construcción de sistemas basados en microprocesador involucra tanto el
desarrollo del hardware (sistema electrónico) como del software (programa), por
lo que un curso donde se estudie este tipo de sistemas debe tratar con suficiente
profundidad ambos aspectos. Por ello, y sin dejar de lado los importantes temas
de arquitectura y programación, que son tratados en los primeros capítulos (y que
suelen ser objeto de asignaturas específicas de mayor contenido informático,
como «Arquitectura/Organización de Computadores»), se incidirá aquí de forma
muy especial en el empleo del microprocesador como herramienta útil para
desempeñar tareas de instrumentación y control, es decir, en las cuestiones
relativas al diseño y realización de sistemas microprocesadores, y a su interacción
con el exterior (interfacing).
Este texto se ha tratado de orientar de manera que se estudien conceptos
generales, que puedan aplicarse en la mayor parte de los sistemas
microprocesadores existentes en el mercado. No obstante, se requiere seleccionar
uno o más microprocesadores reales que ilustren la implementación y manejo
práctico de dichos conceptos generales. En este sentido, no nos hemos decantado
por microprocesadores típicos de 16 o 32 bits, como el 68000, muy pedagógico, o
algún miembro de la omnipresente familia 80x86, sino por microprocesadores
mucho más sencillos, de 8 bits, que son los que se siguen empleando en la
mayoría de las aplicaciones industriales (en la era de los microprocesadores de 32
y 64 bits, prácticamente la mitad de las unidades vendidas en el mundo siguen
siendo de 8 bits).
Por otro lado, dentro de la electrónica industrial el tipo de microprocesador
más empleado es el microcontrolador, que integra en una única pastilla CPU,
memoria, puertos y algunos periféricos, por lo que podríamos estar tentados a
limitar nuestro estudio a él; sin embargo, pensamos que de esta manera un alumno
sin conocimientos previos (generales) de microprocesadores podría adquirir una
perspectiva un tanto sesgada. Creemos necesario en una asignatura de corte
generalista que el alumno asimile primero los conceptos fundamentales de los
sistemas microprocesadores, para luego presentar y estudiar en profundidad el
microcontrolador como un tipo especial de microprocesador que integra en la
VIII Microprocesadores y microcontroladores

pastilla la mayor parte del sistema, y que está especialmente orientado a tareas de
instrumentación y control específicos.
Conjugando estas ideas hemos seleccionado un microprocesador y un
microcontrolador de la familia 68XX de 8 bits de Motorola. Esta familia, además
de ser la líder indiscutible del mercado mundial de los 8 bits, se ha distinguido
siempre por su pedagogía, gracias a su arquitectura sencilla y «lineal».
Así, emplearemos el clásico M6800 (antecesor del M68000) para ilustrar los
conceptos generales relativos al desarrollo de sistemas electrónicos basados en
microprocesadores. El 6800 (de la misma época que el 6502, Z80 o 8085), nos
permitirá estudiar todos los conceptos fundamentales relativos a la programación,
sistema de buses, conexión con periféricos, interrupciones, etc.; gracias a la
sencillez de su arquitectura, un alumno sin conocimientos previos de
microprocesadores podrá asimilarlo sin dificultad en el muy limitado espacio de
tiempo asignado a las actuales asignaturas universitarias cuatrimestrales.
Aunque el 6800 nos resultará de utilidad para aprender los conceptos
generales sobre microprocesadores, en la práctica el actual profesional de la
electrónica en la mayor parte de las ocasiones no construye sistemas basados en el
6800 (ni en el 8085 o el Z80), sino, más bien, en microcontroladores. Por ello,
introducidos los conceptos genéricos sobre sistemas microprocesadores, nos
centraremos en los microcontroladores. En este caso, emplearemos como
ilustración el M68HC11 de Motorola, un potente y bien conocido
microcontrolador de 8 bits, utilizado en infinidad de universidades de todo el
mundo para la enseñanza y desarrollo de proyectos. El núcleo interno del
68HC11 es un 6800 mejorado, por lo que todo lo aprendido para el 6800 se aplica
de forma directa al 68HC11 (en particular, el juego de instrucciones del HC11 es
una ampliación del del 6800), con lo que al alumno no le cuesta un esfuerzo
adicional su aprendizaje. Por lo tanto, el tándem 6800-68HC11 resulta
pedagógico y perfectamente representativo de los sistemas microprocesadores y
microcontroladores reales.
Además, el 68HC11 no sólo es un potente microcontrolador (de entre los más
empleados en el mundo); asimismo resulta una excelente herramienta educativa
que permite enseñar una enorme variedad de conceptos, gracias a los numerosos
periféricos que integra. Por otro lado, resulta extremadamente sencillo construir
un sistema mínimo basado en un 68HC11, y la grabación de un programa de
aplicación en su EEPROM interna desde un PC convencional resulta muy simple
y no requiere hardware adicional. Como su precio es relativamente asequible, el
alumno interesado puede experimentar con él con tan sólo un pequeño
desembolso económico (veáse el Apéndice C dedicado al «Kit del 68HC11»).
Prólogo IX

En definitiva, este libro no es un manual de empleo del microprocesador


6800 o del microcontrolador 68HC11, sino que hace uso de los citados
dispositivos para ilustrar los conceptos generales sobre el desarrollo de este tipo
de sistemas electrónicos. Por este motivo, no estudiaremos a fondo todos los
bloques internos del 68HC11, lo que merecería un libro aparte (de hecho, el
manual de referencia del 68HC11 de Motorola [Motorola 91] requiere para ello
más de 500 páginas de apretada información). A dicho manual y a libros como
[Driscoll 94, Huang 96, Lipovski 88, Miller 93, Spasov 96], que tratan el 68HC11
de forma exclusiva y en profundidad, remitimos al lector interesado.
Para concluir, y sin olvidar nuestro objetivo de disponer de un texto para una
asignatura generalista sobre microprocesadores, consideramos que resulta también
importante no perder de vista los grandes microprocesadores incorporados en los
actuales computadores. Por ello, incluimos un capítulo final dedicado al
panorama actual del campo de los microprocesadores, centrado en los de altas
prestaciones. En él se introducen ideas como las relativas a las arquitecturas
CISC y RISC, las unidades segmentadas (pipeline), los sistemas multiprocesador,
e incluso dos temas «de moda», como las redes neuronales y los sistemas
borrosos. También dedicaremos una sección a los procesadores digitales de señal
(DSP), que, aunque inicialmente centrados más en los campos de
telecomunicaciones y multimedia, empiezan también a aplicarse en tareas de
electrónica industrial (como en el control de máquinas eléctricas). Este último
tema no tiene como pretensión que el alumno asimile en su totalidad todos estos
conceptos «avanzados»; su intención es meramente informativa, de modo que el
interesado podrá profundizar en ellos siguiendo las referencias que se indican.

Conocimientos previos
Para poder seguir sin problemas este texto se requiere que el lector se
desenvuelva con soltura en el campo de la electrónica digital, resultando además
de utilidad conocimientos básicos de electrónica analógica. No es necesario
disponer de experiencia previa en programación.
Este libro representaría la continuación natural de un curso de electrónica
digital básica (como sucede en nuestra Escuela). En este sentido, nuestra obra
podría considerarse la segunda parte del libro de Tomás Pollán Santamaría
titulado Electrónica Digital [Pollán 94], al que en numerosas ocasiones haremos
referencia. En [Pollán 94] se introduce al alumno tanto en el diseño lógico como
en aspectos más electrónicos, tratándose al final las arquitecturas orientadas a bus,
memorias y conversión A/D y D/A; estos conocimientos se darán aquí por
Capítulo 1
Introducción y conceptos previos

1.1. Introducción: el ubicuo microprocesador


A mediados del presente siglo, tras el desarrollo de la bomba atómica y las
centrales nucleares, imperaba la idea de que la humanidad se adentraba en la
denominada «Era atómica»; algo más adelante, cuando el hombre pisó por
primera vez la Luna, se hablaba de la «Era espacial». Sin embargo, y sin ningún
género de duda, nuestra época está resultando ser la Era de la información, debido
fundamentalmente a la expansión de la informática y las telecomunicaciones,
sustentadas por el enorme desarrollo de las tecnologías electrónicas (a las que se
van sumando las ópticas). Para ratificarlo, solamente tenemos que pensar en la
radio, la televisión, el teletexto, el vídeo, los satélites de comunicaciones,
teléfonos convencionales y móviles, el fax, y, sobre todo, el omnipresente
computador, del que cada vez más depende nuestra sociedad (automatización de
plantas industriales, control del tráfico por tierra, mar y aire, gestión de las
empresas y bancos, Internet, diseño en ingeniería, cálculos científicos, etc.).
La electrónica ha sido (y es) el causante y soporte de esta verdadera
revolución de nuestra sociedad, pero dentro del campo de la electrónica el
microprocesador es con frecuencia el gran protagonista. A este hecho no es ajeno
el ciudadano medio, que habla sin problemas de su nuevo flamante Pentium II, o
de su MacIntosh con procesador PowerPC. No obstante, la mayor parte de los
microprocesadores no residen en los computadores, sino ocultos en cualquier
dispositivo electrónico, que el usuario utiliza sin ser consciente de ello.
El desarrollo de los microprocesadores (un relativamente reciente invento
introducido comercialmente en 1971) ha revolucionado las áreas más importantes
de la electrónica. La mayor parte de los instrumentos electrónicos incorporan en
la actualidad por lo menos un microprocesador (µP), aunque es habitual que
hagan uso de varios de ellos. La electrónica de consumo (audio y vídeo,
electrodomésticos) y las telecomunicaciones hacen un insistente uso de
microprocesadores; también éstos han permitido que los computadores personales
sean económicamente viables. Su impacto está siendo tan importante como lo
fueron hace unos años el de las válvulas de vacío, el transistor o el circuito
integrado.
2 Microprocesadores y microcontroladores

Como vamos a ir viendo poco a poco, el µP es un producto que surge del


«matrimonio» de las tecnologías microelectrónicas y de la arquitectura de
computadores, y conforme progresa la tecnología de integración se van
incorporando a él más y más rasgos, antes solamente incluidos en la estructura de
los grandes ordenadores.
Los primeros circuitos integrados (CI o chips) comerciales fueron
introducidos hacia 1960. Con tan sólo unos cuantos transistores por CI, resultó
fácil construir circuitos digitales de propósito general (puertas lógicas, biestables,
registros...). En los años siguientes, el número de transistores que podían
integrarse en un CI se incrementó rápidamente. Recordemos que los CI suelen
clasificarse atendiendo al número de transistores por chip de la siguiente manera:
• Integración a pequeña escala o SSI (small-scale integration): hasta 100
transistores por chip.
• Integración a media escala o MSI (medium-scale integration): de 100 a 1.000.
• Integración a gran escala o LSI (large-scale integration): de 1.000 a 10.000.
• Integración a muy alta escala o VLSI (very large-scale integration): 10.000 o
más.
Mientras que los circuitos integrados SSI (como los correspondientes a
biestables) incluyen del orden de 10 o 12 puertas lógicas, la integración MSI hizo
posible integrar bloques más complejos, como contadores, registros de
desplazamiento, multiplexores, etc. Con la integración LSI se comenzaron a
realizar circuitos a medida (custom), específicos para ciertas aplicaciones, como
controladores de pantallas de vídeo. Sin embargo, el coste de su desarrollo era
muy alto, de modo que su uso se limitaba a aplicaciones de alto volumen de
ventas. A finales de los sesenta no estaba claro qué CI estándar LSI compuesto
por cientos o miles de puertas podría ser de utilidad tan general que poseyera un
mercado amplio (aparte de los chip de memoria).
Por la época (1969) la compañía japonesa Busicom (fabricante de
calculadoras) encargó a Intel (una nueva compañía del valle del Silicio
especializada en la fabricación de memorias) la realización del circuito de control
de un nuevo modelo de calculadora de sobremesa. El primer diseño resultó tan
complejo que Ted Hoff, ingeniero de Intel, pensó que las minicomputadoras de la
época poseían una complejidad similar, pero haciendo uso de una arquitectura
mucho más simple. A raíz de ello, Hoff rediseñó completamente el sistema
basándose en la estructura de los computadores: existiría un chip que integraría
una CPU (Central Processing Unit) sencilla, que ejecutaría un programa de
control que se guardaría en una pastilla de memoria ROM, emplearía una RAM
Introducción y conceptos previos 3

para almacenamiento de datos y un registro como puerto de entrada/salida. Por lo


tanto, el nuevo diseño era un conjunto de cuatro chips, que implementaban al
completo la estructura de un computador, de modo que cambiando el programa
podría dedicarse a realizar tareas muy diferentes. La realización práctica del
sistema de cuatro circuitos integrados fue en gran parte obra de Federico Faggin,
en aquella época recién incorporado a Intel.
Desde que se contrató a Intel hasta que el diseño resultó operativo pasaron
muchos meses, durante los cuales los precios habían caído y el valor del contrato
inicial resultaba desorbitado para los parámetros de principios de los setenta, por
lo que Busicom pidió a Intel una rebaja en el precio. Intel aceptó a cambio de
quedarse con los derechos del conjunto de circuitos integrados construidos, la
familia 4000, para poderlos comercializar por su cuenta, a lo cual Busicom
accedió sin demasiados problemas. Finalmente, Intel introdujo el chip
programable desarrollado, el 4004, en sus catálogos en noviembre de 1971 y
comenzó a desarrollar una gran labor de marketing para dar a conocer el nuevo
«invento», bautizado como microprocesador, que ellos pensaban les ayudaría a
vender memorias, su principal área de negocio entonces.
En este punto, es importante hacer notar que aunque realmente implementaba
la unidad de procesamiento central o CPU de un computador, Intel no pensó en el
4004 como un bloque para construir computadores (resultaba aún demasiado
lento), sino más bien para reemplazar lógica cableada convencional (aquella
cuyas conexiones determinan la función). En lógica programada, basada en
sistemas microprocesadores, se hace uso de bloques estándar e interconexiones
(hardware), pero el programa (software) es el que determina la función.
El 4004 y el resto de los primeros microprocesadores, construidos con
tecnologías LSI (PMOS), eran tan primitivos y lentos que, aunque resultaban
útiles para tareas de control, no podían competir con la potencia de los
computadores de la época. No obstante, el avance de las nuevas tecnologías de
integración VLSI (NMOS y, algo más adelante, CMOS) y las nuevas
arquitecturas lograron pronto construir potentes dispositivos de cálculo basados
en microprocesadores, los microordenadores y estaciones de trabajo, que poco a
poco han ido sustituyendo a muchas de las computadoras tradicionales.
4 Microprocesadores y microcontroladores

1.1.1. El desarrollo de los microprocesadores


Antes de proseguir, propondremos la siguiente definición:
Definición de microprocesador: componente electrónico que realiza en una
única pastilla el procesador (CPU) de una máquina programable de tratamiento
de la información.
Es decir, el µP es un componente electrónico complejo que incorpora las
funciones típicas de todo un computador. La clave del éxito de los
microprocesadores como componente electrónico reside en que modificando el
programa almacenado en memoria pueden adaptarse a numerosas y diferentes
aplicaciones, de manera que en la actualidad, debido a su creciente potencia de
cálculo y variedad de funciones integradas, se han convertido en el estándar para
la implementación de tareas, tanto de cálculo como de control. De este modo, los
microprocesadores no sólo se utilizan para construir potentes computadoras,
quizás su aplicación más espectacular y conocida, sino también para la realización
de tareas de control en sistemas de aplicación específica (por ejemplo, el control
de un horno microondas, un teléfono móvil o unos frenos ABS), sustituyendo
circuitería convencional.
El espectacular desarrollo de las prestaciones de los µP durante los últimos
veinticinco años se ha producido por dos circunstancias, que denominaremos
«leyes» de los microprocesadores:
a) Ley de Moore: «El número de transistores que pueden integrarse
económicamente dentro de un chip se duplica aproximadamente cada 18 meses».
Gordon Moore, cofundador de Intel, realizó esta observación ya en los años
sesenta cuando trabajaba para Fairchild, y 30 años después todavía se sigue
cumpliendo (y parece que continuará por lo menos hasta comienzos del siglo
XXI). En este sentido, es interesante hacer notar que el i4004 original (1971)
incluía 2300 transistores, mientras que el 80486 (1990) contiene más de un millón
y el Pentium (1993) más de tres millones; el reciente Pentium II (1997) incluye ya
siete millones. Esta ley se debe a dos circunstancias: por una parte, al aumento
de la densidad de integración, causado por la constante disminución en el tamaño
del transistor (se suele dar como cifra la anchura de canal, que en la actualidad se
sitúa muy por debajo de la media micra); por otra, el constante aumento del
tamaño de la propia pastilla.
Introducción y conceptos previos 5

transistores
100000000
10000000 Pentium

1000000 486
386
100000 80286
8085 8086
10000 8080
8008
1000
4004
100
1970 1975 1980 1985 1990 1995

año

FIGURA 1.1. Ilustración de la ley de Moore mediante la familia 80x86 de Intel. El eje de ordenadas
se representa en escala logarítmica, por lo que la recta que aparece como tendencia seguida indica
en realidad un crecimiento exponencial del número de transistores por chip.

b) Ley de los microprocesadores: «Cada buena idea que se ha mostrado


eficaz en los ordenadores centrales o miniordenadores se traslada al µP».
Lo cual viene a decir que muchos de los logros arquitecturales introducidos
para construir grandes computadores, años más tarde, y cuando la tecnología
permite integrar más bloques y mayores velocidades de operación, se incorporan
en el diseño de microprocesadores de nueva generación.

1.1.2. Aplicaciones de los microprocesadores


Los microprocesadores cuentan con múltiples aplicaciones, pertenecientes a
dos ámbitos diferentes: por un lado, la construcción de computadoras; por otro, la
realización de tareas de control e instrumentación, sustituyendo lógica
convencional.
En el primer caso (el más conocido para los profanos en la materia) se
emplean microprocesadores actuales de nueva generación, optimizados para la
realización de tratamiento de datos. Por ejemplo, los µP de las series Alpha de
Digital, o PowerPC de Motorola e IBM, se emplean en la realización de
poderosos computadores denominados estaciones de trabajo, que están orientadas
al cálculo científico y diseño en ingeniería. Otros, como el Pentium de Intel, se
orientan más bien al desarrollo de ordenadores personales, cuyas prestaciones, no
obstante, son comparables a las de los grandes ordenadores de hace unos pocos
6 Microprocesadores y microcontroladores

años, pero a un precio asequible al ciudadano medio (aunque Intel fabrica ya


microprocesadores muy potentes destinados también al nicho de mercado de los
servidores y estaciones de trabajo, como el Pentium II Xeon o el futuro Merced).

FIGURA 1.2. Algunos campos de aplicación de los microprocesadores.

En el segundo caso suelen emplearse microcontroladores, microprocesadores


especiales, generalmente de menores prestaciones de cálculo, pues están
optimizados para tareas de control (entendido en un sentido amplio), con
numerosos dispositivos integrados en una única pastilla, como memoria, puertos
de entrada/salida o diversos periféricos. Éstos se emplean en el desarrollo de
sistemas industriales (por ejemplo, robótica, autómatas programables o tarjetas de
control industrial), aplicaciones de consumo (como lavadoras, hornos microondas,
audio y vídeo, cámaras fotográficas o videojuegos), telecomunicaciones (como
teléfonos móviles), automoción (frenos ABS, inyección electrónica, ordenador de
a bordo, etc.). La sustitución de lógica convencional por microcontroladores
permite reducir el tamaño de los diseños, disminuir el tiempo de desarrollo y
también el coste final del producto. La consecuencia es que estos
microprocesadores especiales se aplican a ámbitos considerados no rentables con
Introducción y conceptos previos 7

anterioridad, e impensables hasta hace poco tiempo. Por ejemplo, en un


automóvil moderno pueden encontrarse del orden de quince microprocesadores
realizando distintas tareas. Como dato curioso podemos decir que las impresoras
láser actuales, al incluir potentes microprocesadores RISC de 32 bits, encierran
una potencia de cálculo superior a la de los PC de hace unos pocos años. En
resumen, el ciudadano medio puede emplear, sin él mismo saberlo, del orden de
una docena de µP al día (lo que se suele denominar computación oculta).

1.1.3. Ventajas del uso de microprocesadores


Las ventajas del uso de microprocesadores en el diseño de sistemas digitales,
sustituyendo lógica convencional, son las siguientes:
a) Reducción del número de componentes, lo que conlleva la miniaturización del
sistema, reducción de consumo y aumento de fiabilidad.
b) Programabilidad, que permite la simplificación del diseño y reducción del
tiempo de desarrollo.
c) Disminución de costes, causado por los aspectos descritos en los puntos a) y
b), y por la fabricación de series de muchas unidades de un mismo µP, pues
podrá aplicarse a muchos diferentes problemas sin más que reprogramarlo.

FIGURA 1.3. Algunas aplicaciones de los microprocesadores en el automóvil.


8 Microprocesadores y microcontroladores

1.2. Sistemas electrónicos industriales


Introducida la figura del microprocesador, centraremos a continuación las
principales ideas que guiarán el presente texto. Observemos la fig. 1.4: en ella se
muestra el esquema genérico de un sistema electrónico industrial, cuyo objetivo
es la monitorización y control por procedimientos electrónicos de un determinado
sistema exterior, como pueda ser una máquina, proceso o incluso toda una planta
industrial.
Supongamos a modo de ejemplo que se trata de supervisar y controlar una
máquina industrial. El sistema electrónico que se requiere puede ser dividido en
tres módulos. El primero es el subsistema de adquisición de datos, esencialmente
de tipo analógico, compuesto por: un conjunto de sensores, que detectan el estado
de la máquina; circuitería de acondicionamiento de señal, que amplifica y adapta
la señal para su posterior tratamiento; por último, etapa de conversión A/D,
encargada de transformar las señales analógicas en valores digitales. El segundo
módulo es el sistema digital de procesamiento, que se ocupa de tomar los valores
digitalizados de las señales (así como las señales puramente digitales que pueden
existir), procesarlas, presentarlas al exterior o registrarlas y, posteriormente,
enviar las órdenes de las acciones a realizar sobre la máquina controlada.
Finalmente, el tercero bloque es el subsistema de actuación, encargado de
convertir las señales digitales de control en valores analógicos y actuar sobre la
máquina.
En este esquema pueden contemplarse distintas disciplinas electrónicas del
campo de la electrónica industrial: electrónica analógica e instrumentación
electrónica, especialmente en las etapas más directamente conectadas con el
exterior; electrónica de potencia, esencialmente en la etapa de actuación sobre el
exterior, y en las fuentes de alimentación; electrónica digital, especialmente en el
sistema microprocesador. Además, también pueden considerarse las siguientes
disciplinas relacionadas con la electrónica industrial: regulación de máquinas
eléctricas, regulación automática (control), informática y computadores.
El esquema propuesto para lo que hemos denominado sistema electrónico
industrial en realidad representa un sistema electrónico genérico, que puede ser
aplicado a numerosas situaciones diferentes, como un pequeño termostato
electrónico, un sistema de frenado ABS, una máquina expendedora de refrescos,
una lavadora, el automatismo de control de una granja o incluso el control de toda
una planta industrial. En estos casos, el control digital se realiza con
microprocesador, aunque, en ocasiones, éste puede estar incluido dentro de un
autómata programable (PLC) o de un ordenador. Por ejemplo, en el caso de la
planta industrial, una serie de autómatas programables (PLC) recogen señales y
Introducción y conceptos previos 9

controlan maquinaria, siendo todos ellos monitorizados por un ordenador PC a


través de líneas de transmisión de datos en serie.
Otro ejemplo es el de la fig. 1.5, en el que se muestra de forma detallada el
esquema de una tarjeta de adquisición de datos típica, que puede emplearse en la
industria, en un laboratorio de medida y test, o en un laboratorio científico. Este
esquema es en realidad una versión detallada del subsistema de adquisición de
datos de la fig. 1.4, en el que se especifican algunos de los módulos incluidos en
el bloque de acondicionamiento: amplificador, filtro pasa baja y etapa de
muestreo y mantenimiento (sample and hold, S&H).

Subsistema de Adquisición de Datos


Información

Sensor
Procesamiento
Acondicionador Procesamiento
Digital Transmisión de
Acondicionador C. A/D Digital (mP) Acondicionador
datos
(µC, DSP)

Procesamiento
Proceso Procesamiento
Digital
(µP, µC, DSP,
Digital (mP)
computador)

Subsistema de Actuación

Actuador/ Actuación
Carga
Procesamiento
Acondicionador/ Procesamiento
Digital Transmisión de
Acondicionador
Potencia C. D/A Digital (mP) Acondicionador
datos
(µC, DSP)

Fuente de energía

FIGURA 1.4. Diagrama de bloques de un sistema electrónico industrial o genérico.


10 Microprocesadores y microcontroladores

FIGURA 1.5. Diagrama de bloques de un sistema de adquisición de datos. La lógica de control a


menudo se implementa mediante algún tipo de microprocesador.

1.3. Sistemas programables: la arquitectura von Neumann


De lo expuesto podemos deducir que el microprocesador, además de ser el
componente central de los computadores actuales, también constituye el elemento
básico empleado en la realización de sistemas electrónicos industriales, aparatos
de consumo, telecomunicaciones, etc., desempeñando tareas que podemos
denominar de instrumentación y control. Va a ser precisamente el punto de vista
del microprocesador como elemento que sustituye lógica convencional el que a
nosotros más nos va a interesar en adelante.

1.3.1. Sistemas electrónicos complejos. Diseño descendente


De los subsistemas incluidos en un sistema electrónico industrial (fig. 1.4),
nos centraremos en el bloque de procesamiento. Se trata de un sistema digital de
alta complejidad, cuyo papel principal es llevar a cabo el tratamiento del conjunto
de datos procedentes del exterior (sistema bajo control). Es decir, podemos
considerar este gran bloque digital como un procesador, que deberá incluir cierta
cantidad de memoria (conjunto de registros) para el almacenamiento de datos.
Introducción y conceptos previos 11

Supongamos que debemos realizar el sistema digital que constituye dicho


procesador, el cual se tratará de un sistema electrónico de elevada complejidad.
Para abordar un diseño de este tipo, se hace necesario emplear una metodología
que ayude a manejar dicha complejidad (debe tenerse en cuenta que las
tecnologías microelectrónicas permiten en la actualidad construir sistemas
compuestos por millones de transistores). La metodología que permite manejar
dicha complejidad se denomina diseño descendente (top-down), consistente en
dividir el diseño de alto nivel en partes más pequeñas («divide y vencerás»), para
posteriormente abordar por separado el diseño interno de cada una de ellas.
En el caso que nos ocupa, el procesador queda dividido en una parte
operativa y una parte de control (fig. 1.6). La parte operativa, o unidad de
procesamiento, contiene el conjunto de recursos operativos que el procesador
requiere. Así, suele incluir un conjunto de registros para almacenamiento de
datos y resultados, biestables que indican ciertas condiciones que pueden darse,
contadores, y multiplexores que permiten seleccionar entre diferentes rutas de
datos o registros. La unidad de procesamiento con frecuencia incluirá además una
unidad lógico-aritmética (ALU) de propósito más o menos general, dependiendo
de la aplicación.

FIGURA 1.6. Esquema de los grandes bloques que componen un procesador digital genérico.
12 Microprocesadores y microcontroladores

FIGURA 1.7. Componentes esenciales de la unidad de procesamiento.

Por otro lado, la parte de control (o unidad de control) establecerá la


secuencia de pasos que el procesador debe llevar a cabo en cada momento,
controlando, entre otros, los elementos de la parte operativa. La unidad de control
puede sintetizarse a partir de la máquina de estados del sistema, haciendo uso para
ello de los métodos generales de los sistemas secuenciales (ver, p.e., [Pollán 94]);
no obstante, debe tenerse en cuenta que este procedimiento puede en ocasiones
resultar difícil de llevar a la práctica a causa de la complejidad del sistema a
diseñar. Debido a que esta máquina de estados representa la transcripción directa
del algoritmo de control de la máquina, que suele consistir en una serie de estados
sucesivos y saltos condicionales, recibe el nombre de máquina algorítmica.
Una ampliación de los conceptos aquí expuestos, junto al proceso de diseño
de un sistema digital complejo, puede encontrarse en el capítulo XIV del libro
Electrónica Digital, de Tomás Pollán [Pollán 94] (allí se presenta como
ilustración el ejemplo de un multiplicador de números binarios de 64 bits).

1.3.2. Máquinas gobernadas por programa (programables).


Arquitectura von Neumann
Por lo tanto, denominaremos máquinas algorítmicas o de tratamiento de
información a aquellas máquinas que implementan un algoritmo. En ellas,
además de la parte operativa o unidad de procesamiento (UP), y de la de control o
unidad de control (UC), se considera un tercer subsistema adicional, el de
entradas y salidas (E/S), encargado de recibir y enviar datos desde y hacia el
exterior.
Introducción y conceptos previos 13

FIGURA 1.8. Estructura básica de una máquina de tratamiento de la información (tanto específica
como programable).

En este punto es importante distinguir entre máquinas específicas y máquinas


de propósito general. Las máquinas específicas se diseñan expresamente para
resolver un problema determinado y concreto (por ejemplo, un sistema que
multiplique dos números binarios de 64 bits). Por otra parte, las máquinas de
propósito general se diseñan para que puedan resolver muchos tipos diferentes de
problemas, sin más que adaptarlas a cada caso particular. Tanto unas como otras
responden al mismo esquema genérico descrito: UP + UC + E/S.
La que se considera primera computadora electrónica de la historia, Colossus,
desarrollada por el gobierno británico para descifrar las órdenes enviadas por
radio a los submarinos alemanes durante la segunda guerra mundial, es un
ejemplo de máquina específica. Por otra parte, el famoso ENIAC, empleado por
los americanos en el desarrollo de la bomba atómica y en el cálculo de
trayectorias balísticas, es un ejemplo de máquina de propósito general (véase el
apéndice al final del capítulo). Efectivamente, algunas de las primeras
computadoras electrónicas de propósito general de los años cuarenta, como
ENIAC, podían realizar diferentes tareas organizando miles de interruptores de
posición múltiple y conectando una enorme cantidad de enchufes con una maraña
de cables (como en las antiguas centralitas telefónicas). Estas máquinas eran
«programables», en el sentido de que podían cambiar su funcionalidad, pero ello
requería cambios en el propio hardware de la máquina (conexiones físicas reales)
que resultaban complejos, tediosos y lentos.
Con posterioridad se propuso un procedimiento que permitiese cambiar la
funcionalidad de la máquina y que resultase más eficiente (sencilla y rápida) que
tener que modificar una maraña de conexiones: establecer la operación de la
máquina (los pasos y operaciones que debía llevar a cabo) mediante unos
14 Microprocesadores y microcontroladores

contenidos almacenados en una determinada zona de su memoria, los cuales


representan la secuencia de instrucciones que deberá ejecutar, lo que constituye el
programa. Este tipo de máquina de propósito general que ejecuta un programa
almacenado en memoria se denomina máquina controlada por programa o
programable. De esta manera puede disponerse de una máquina de propósito
general, cuya función puede ser cambiada sin más que modificar los contenidos
de una zona de memoria (programación), lo cual resulta mucho más sencillo que
modificar su propia estructura de conexiones.
Así, en una máquina gobernada por programa la UP (compuesta por una
unidad lógico-aritmética, o ALU, y por registros de almacenamiento de datos) es
de propósito general, mientras que la UC es un órgano encargado de leer el
programa que se guarda en memoria, interpretarlo y ejecutarlo. Las instrucciones
que componen el programa se codifican en binario, de manera que cada
instrucción (por ejemplo, «Sumar A y B») viene definida por un conjunto de bits
denominado código de operación o, abreviadamente, opcode (operation code). El
programa, es decir, la secuencia de códigos de operación binarios, se almacena en
la memoria.
Si, dado el esquema de máquina programable anterior, compuesta por UP,
UC y E/S, consideramos el conjunto de la memoria como un elemento adicional
diferenciado, la memoria central o principal (dentro de la cual almacenamos el
programa y los datos), obtendremos la denominada arquitectura von Neumann.
Por otra parte, el conjunto de UP y UC constituye el procesador o CPU (Central
Processing Unit, unidad de procesamiento central).
El nombre de arquitectura von Neumann procede del matemático de origen
húngaro John von Neumann, que ya había participado activamente en el
desarrollo de diversas computadoras electrónicas. A von Neumann se le ocurrió
la idea de representar el programa en forma digital en la memoria de la
computadora (como ya se hacía con los datos), y además propuso sustituir la
aritmética decimal empleada en el ENIAC (con cada dígito representado por diez
válvulas, una encendida y nueve apagadas) por la aritmética binaria paralela, más
eficaz. Estas ideas sentaron las bases de las máquinas de cómputo modernas:
desde las máquinas EDSAC e IAS (finales de los años cuarenta y principios de los
cincuenta, véase el apéndice), la mayoría de los computadores siguen este
esquema (o alguna variante).
Introducción y conceptos previos 15

FIGURA 1.9. Máquina de von Neumann

En resumen, se considera la arquitectura von Neumann compuesta por los


siguientes cinco elementos básicos:
a) Dispositivos de entrada, como el teclado. Sirven para introducir en memoria
instrucciones y datos.
b) Memoria. Almacena tanto el programa como los datos.
c) Unidad de control. Decodifica las instrucciones y genera las señales necesarias
para que la unidad de procesamiento y el resto de los elementos del sistema
cumplan las tareas encomendadas.
d) Unidad de procesamiento. Realiza las operaciones lógicas y aritméticas.
Incluye una ALU y registros.
e) Dispositivos de salida, como la pantalla o la impresora. Presentan los
resultados.
En el proceso de ejecución de instrucciones la máquina debe realizar dos
fases fundamentales: la de búsqueda y decodificación, en la que la unidad de
control toma una instrucción de memoria y la decodifica, y la de ejecución, en la
que la unidad de control ejecuta la instrucción, enviando las señales pertinentes a
la UP y al sistema de E/S.
En resumen, la importancia conceptual de la arquitectura von Neumann
reside en que puede disponerse de una máquina de procesamiento completamente
general, la cual, sin más que cambiar el programa que almacena en su memoria,
16 Microprocesadores y microcontroladores

puede desempeñar distintas funciones (desde realizar declaraciones de la renta a


editar textos, controlar una lavadora o implementar un juego de marcianos).

1.4. Microprocesadores y microcontroladores


Una vez estudiado el concepto de máquina programable y de arquitectura von
Neumann, recordemos la definición de microprocesador propuesta con
anterioridad:
Microprocesador: componente electrónico que realiza en una única pastilla el
procesador (CPU) de una máquina programable de tratamiento de la
información.
Por lo tanto, el microprocesador no es otra cosa que la integración electrónica
(normalmente VLSI) en una única pastilla de toda la CPU de una máquina
programable. Es decir, el µP incluye en un solo chip dos de las partes
constituyentes de la arquitectura von Neumann, la UC y la UP (ver fig. 1.10a).
Más aún, gracias al aumento en la capacidad de integración se han podido
introducir más elementos de la estructura von Neumann dentro de un único
circuito. Así, algunos microprocesadores convencionales incluyen también en el
mismo chip cierta cantidad de memoria (por ejemplo, la memoria caché),
controladores de DMA (que forma parte del subsistema de E/S) y otros elementos
Por otra parte, un tipo de microprocesador denominado microcontrolador
(µC) o microcomputador en una única pastilla (single-chip computer), incorpora
la totalidad de la estructura von Neumann en su interior (fig. 1.10b), pues, además
de la CPU (UC más UP), integra en el mismo chip cierta cantidad de memoria
(ROM, RAM, EPROM...) y diversos elementos del subsistema de E/S, como
puertos y dispositivos periféricos (contadores, temporizadores, conversores A/D,
etc.). De este modo, los microcontroladores permiten incorporar la práctica
totalidad de un sistema computador en un espacio muy reducido, por lo que se
emplean en la construcción de sistemas específicos, en los que el espacio
ocupado, consumo y precio deben ser mínimos. Por su importancia en los
campos relacionados con la electrónica industrial y de consumo, el
microcontrolador será uno de los objetos de estudio centrales en este curso (por
ejemplo, para construir el control de una lavadora automática se recurre a un
microcontrolador, en vez de a un microprocesador convencional).
Introducción y conceptos previos 17

FIGURA 1.10. Microprocesador y microcontrolador.

1.4.1. Clasificación de los microprocesadores


Según su propósito, podemos distinguir:
1) µP de propósito general. Válidos para múltiples tareas diferentes de
tratamiento de la información. Son los que se emplean fundamentalmente para
construir computadores o máquinas de propósito general (editar, realizar
cálculos, diseñar, etc.).
2) µP de propósito específico. Son los que se programan para llevar a cabo una
tarea o aplicación específica, es decir, se programan una sola vez y después
siempre ejecutan el mismo programa, que se guarda en ROM. Un caso ya
conocido es el microcontrolador, cuyo diseño está orientado al control de
dispositivos, como su nombre indica (por ejemplo, los frenos ABS de un
automóvil están controlados por un µC, que siempre ejecuta el mismo
programa). Otro ejemplo es el de los procesadores digitales de señal (DSP),
diseñados para multimedia y telecomunicaciones.
En resumen, los µP de propósito general se utilizan esencialmente para
construir computadores, y los de propósito específico para llevar a cabo siempre
una misma tarea repetitiva, que de otro modo tendría que realizarse mediante un
sistema electrónico cableado, en general mucho más complejo y caro.
Por otra parte, podemos clasificar los µP atendiendo a una característica que
describiremos como número de bits, con la que denotaremos el tamaño (en bits)
de los datos que un microprocesador es capaz de procesar en paralelo (a la vez),
número que suele coincidir con la anchura del bus de datos y con el tamaño de los
18 Microprocesadores y microcontroladores

datos con los que opera su ALU. Así, se habla de µP de 4, 8, 16, 32 o 64 bits.
Generalmente, un mayor número de bits indica un µP más potente, pues es capaz
de procesar más cantidad de información a la vez, pero también resultará más
complejo y caro. Por ello, para cada aplicación particular debe elegirse el mP que
mejor se adapte a ella, es decir, con mejor relación prestaciones/precio.
Los µP también pueden clasificarse por el número de instrucciones que
incorporan en su repertorio. Así, se distingue entre microprocesadores CISC y
RISC:
a) CISC (Complex Instruction Set Computer). Computadores de extenso (amplio)
conjunto de instrucciones, es decir, aquellos µP que incluyen muchas
instrucciones diferentes (del orden de cien). El ejemplo clásico es la familia
Intel 80x86.
b) RISC (Reduced Instruction Set Computer). Son las máquinas de conjunto de
instrucciones reducido, es decir, incluyen relativamente pocas instrucciones en
su repertorio (del orden de treinta). Ejemplos de ello son las familias Alpha,
SPARC y PowerPC.
La distinción únicamente en cuanto al número de instrucciones que un µP
incorpora no permite apreciar a primera vista la gran trascendencia que conlleva,
que ha sido causa de una dura batalla en el estilo de diseño de µP en los últimos
años. Aunque uno pueda pensar que un microprocesador será más potente si
incorpora muchas más instrucciones, la tendencia actual parece mostrar lo
contrario. Profundizaremos en esta cuestión mucho más adelante en el curso.

1.4.2. Importancia e interés de los microprocesadores


¿Por qué, pese a la complejidad de diseño e implementación de un µP (que
puede integrar millones de transistores), su coste resulta relativamente reducido?
Debido al carácter general del µP, en muchos casos no es necesario diseñar
hardware especial para cada aplicación, sino que puede utilizarse un µP estándar,
que será programado para la aplicación específica. Por esta razón muchísimos
sistemas diferentes pueden utilizar un mismo tipo de circuito, lo que permite su
fabricación en grandes cantidades, de lo que se deriva un coste por unidad muy
reducido (existen µP cuyo coste es inferior a las cien pesetas si se compran miles
de ejemplares). De este modo, la utilización de un µP puede suponer una alta
reducción en el coste del sistema, además de una importante disminución de
tiempo de diseño.
Introducción y conceptos previos 19

Por otro lado, la funcionalidad del circuito cambia al modificar el programa,


por lo que pueden introducirse cambios en la actuación del sistema con relativa
facilidad, reprogramando el microprocesador, lo cual implica que el µP permite
introducir cierta flexibilidad en los sistemas.
En el curso estudiaremos el µP desde dos puntos de vista:
a) Como componente electrónico. Se trata de un componente algo peculiar, pues
posee un aspecto hardware y otro software o de programación.
b) Como ladrillo básico en la construcción de sistemas de procesamiento de datos
(computadores), o de control (sistemas específicos), que sustituye a sistemas
cableados.

1.5. Apéndice. Breve historia de las máquinas de cálculo


En este apéndice vamos a exponer brevemente los hitos fundamentales en el
desarrollo de máquinas de cálculo (o, en general, de procesamiento), que llevaron
finalmente a la introducción del microprocesador a comienzos de los años setenta.
Para realizar este apéndice hemos seguido en buena parte el conocido texto de
[Tanenbaum 92], aunque el de [Stallings 87] es también muy recomendable. Por
otro lado, el libro de [Malone 96] resulta una interesante y amena historia de los
microprocesadores.
Como es habitual, dividiremos la historia del desarrollo de máquinas de
cálculo en generaciones, cada una de las cuales se caracteriza por la tecnología
empleada (elementos mecánicos, electromecánicos, válvulas, transistores o
circuitos integrados).

1.5.1. Generación 0. Computadoras mecánicas y electromecánicas


(1642-1945)
El ser humano ha sentido la necesidad de realizar cálculos desde los mismos
albores de la civilización. Uno de los primeros instrumentos de los que se valió
fue el ábaco (un marco rectangular de madera con cuentas insertadas en ejes
colocados transversalmente), probablemente inventado en Babilonia hace unos
cinco mil años. Durante muchos siglos el ábaco ha sido el calculador más
empleado, siendo desbancado tan sólo en las últimas décadas con la introducción
masiva en el mercado de las calculadoras electrónicas de bolsillo. Aunque este
tipo de instrumento de cálculo puede considerarse parte de la prehistoria de la
computación, todavía se emplea en algunos lugares del mundo, como Rusia y
China (en un documental recientemente emitido en la televisión se observaba
20 Microprocesadores y microcontroladores

cómo en una estación del ferrocarril en China el expendedor de billetes empleaba


un ábaco para calcular los importes y cambios).
Precursores más directos de las actuales computadoras son las calculadoras
mecánicas realizadas mediante ejes y engranajes realizadas a partir del siglo XVII
La primera de ellas fue la calculadora del filósofo y matemático francés Blaise
Pascal, que era capaz de realizar sumas y restas. Pascal (en cuyo honor se bautizó
el conocido lenguaje de programación) la construyó en 1642, cuando contaba con
tan sólo 19 años, para ayudar a su padre, recaudador de impuestos. Se trataba de
un aparato construido con engranajes y accionado con una manivela. Unos treinta
años más tarde, el alemán Gottfried Leibnitz (1671) construyó otra calculadora,
esta vez con capacidad de multiplicar y dividir.
El siguiente gran hito sucede a finales del siglo XVIII, pero en este caso
dentro del muy incipiente campo del «control industrial». Por esta época, la
confección de tejidos con dibujos era un proceso manual, tedioso y sujeto a
errores. Hacia 1750 se extiende la costumbre de perforar códigos en tarjetas, que
especificaban los patrones a representar en el tejido, y que el obrero (con
frecuencia un niño) debía interpretar. La lentitud del proceso y los errores de
interpretación hicieron que no mucho más tarde el proceso fuese automatizado, de
modo que las tarjetas perforadas eran introducidas en la propia máquina de tejer,
que ella misma interpretaba y ejecutaba. El último paso lo da Joseph Jacquard
(1801), al construir un telar completamente automático, enteramente controlado
por estas tarjetas perforadas, y cuya energía era suministrada por una máquina de
vapor. La presencia o ausencia de agujero en determinado lugar de la tarjeta
implicaba el movimiento o no de determinadas partes de la máquina, para así
crear el patrón deseado. Es decir, el telar de Jacquard era una máquina controlada
por programa, el cual era suministrado en la forma de una pila de tarjetas
perforadas, lo que inspiró una manera de introducir datos y programas a las
máquinas que sería ampliamente empleada hasta épocas recientes.
Ya a mitad del siglo XIX Charles Babbage (1793-1871), profesor de
matemáticas en la Universidad de Cambridge, proyecta una serie de computadoras
mecánicas. Por aquella época se disponía de tablas numéricas para cálculo
matemático (funciones trigonométricas, logarítmicas, etc.), tablas para la
navegación, etc., cuyos valores numéricos eran calculados por seres humanos y
transcritos a papel. En ellas, lógicamente, aparecían muchos errores, cuyas
consecuencias podían resultar graves, por lo que Babbage decidió construir una
máquina capaz de generar e imprimir dichas tablas automáticamente.
Introducción y conceptos previos 21

FIGURA 1.11. Calculadora de Pascal. Grabado y fotografía.

La primera de ellas, la denominada máquina diferencial (proyectada hacia


1833), realizaba un algoritmo denominado método de las diferencias finitas, capaz
de calcular valores de polinomios simplemente mediante el empleo de sumas y
restas, y cuyos resultados eran ofrecidos perforando con un troquel de acero sobre
un plato de cobre. Se trataba, por lo tanto, de una máquina de propósito
específico. Esta máquina solamente pudo realizarse en parte, debido a diversos
problemas, más económicos y de gestión que tecnológicos (Babbage invirtió
buena parte de su tiempo y fortuna familiar en sus proyectos, que, dada su gran
magnitud, precisaron también de la financiación de la corona británica, la cual fue
años después retirada debido a lo dilatado del proyecto).
Más adelante, Babbage proyectó una segunda máquina diferencial, versión
mejorada y de menores dimensiones que la primera, que no llegó a construir. Esta
máquina fue realizada en 1991 por el Museo de Ciencias de Londres, en la
conmemoración del bicentenario del nacimiento de Babbage, haciendo uso de
elementos mecánicos construidos con la misma precisión que Babbage pudo
disponer en su época. Para que la máquina funcionase perfectamente solamente
fueron precisas mínimas correcciones sobre el proyecto original de Babbage. El
ingenio construido mide dos metros de altura y tres de longitud, consta de 4.000
22 Microprocesadores y microcontroladores

piezas y pesa tres toneladas; para su confección se invirtieron nada menos que
600.000 dólares. Cabe señalar que, si la primera máquina de diferencias se
hubiese construido al completo, habría ocupado la superficie de un campo de
fútbol y debería haber sido impulsada mediante una máquina de vapor.

FIGURA 1.12. Charles Babbage y proyecto de máquina de diferencias.

Babbage también proyectó una computadora de propósito general, que


denominó máquina analítica. Ésta se dividía en cuatro partes: el almacén
(memoria), el taller (unidad de cálculo, capaz de realizar las cuatro operaciones
básicas), la sección de entrada (una lectora de tarjetas perforadas) y la de salida
(perforadas e impresas). La máquina leería las instrucciones perforadas en
tarjetas y luego las ejecutaría; todo este esquema recuerda poderosamente a los
modernos computadores electrónicos. Ada Lovelace, hija de Lord Byron y
consejera de Babbage en este proyecto, sugirió que las instrucciones escritas en
un rudimentario lenguaje ensamblador podrían enviarse a la máquina mediante
tarjetas perforadas, por lo que algunos la consideran la precursora de los actuales
programadores (en su honor se ha bautizado el moderno lenguaje Ada). Babbage
es considerado, con todo merecimiento, el «abuelo» de la moderna computación;
Introducción y conceptos previos 23

por otra parte, la figura de Ada está envuelta en un halo de misterio (quizás fruto
de la época romántica en la que vivió). Al parecer, buena parte de las
descripciones de la máquina analítica no proceden de Babbage sino de Ada, quien
pudo transcribir sus ideas.

FIGURA 1.13. Máquina de diferencias construida en 1991 por el Museo de Ciencias de Londres, en
la conmemoración del bicentenario del nacimiento de Babbage.

Ya en los años treinta del presente siglo el alemán Konrad Zuse, estudiante
de ingeniería, y al parecer sin disponer de conocimiento previo sobre los trabajos
de Babbage, construyó las primeras máquinas electromecánicas de cálculo
(haciendo amplio uso de relés). Buena parte de ellas fueron destruidas por el
bombardeo aliado sobre Berlín en 1944, y, aunque con posterioridad algunas
fueron instaladas en Europa, su trabajo no tuvo repercusión en el futuro, siendo
éste reconocido en sus justos términos muchos años después.
J. Astanasoff y C. Berry, físicos de la Universidad de Iowa, construyeron
también en los años treinta una máquina sorprendentemente avanzada para su
época, el ABC (Astanasoff-Berry Computer, 1939), en la que introdujeron
técnicas que serían implementadas en las computadoras posteriores, como el
empleo de aritmética binaria o un tipo de memoria basada en un tambor de
condensadores que debían ser refrescados periódicamente, precursores de las
actuales memorias dinámicas. El ABC permaneció en el olvido durante mucho
24 Microprocesadores y microcontroladores

tiempo, saliendo a la luz en los últimos años por un problema sobre la propiedad
de la patente original del computador. A raíz de ello, una sentencia judicial en
Estados Unidos estableció en los años setenta que el primer computador de las
historia con derecho a patente no es ENIAC (del que hablaremos más adelante),
como hasta entonces se daba por sentado, sino precisamente la máquina de
Astanasoff, de la que John Mauchley (uno de los autores de ENIAC) se comprobó
que tomó muchas ideas.
La última computadora mecánica a la que haremos referencia es el Mark I,
construida por Howard Aitken, la cual se concluyó en Harvard en 1944, siendo la
primera computadora de propósito general desarrollada en Estados Unidos.
Aitken construyó con relés lo que Babbage proyectó con ruedas dentadas,
alcanzando su máquina unas dimensiones finales de 17 metros de largo y 2,5 de
altura. Más adelante Aitken construyó la Mark II, pero cuando la concluyó las
computadoras electromecánicas eran ya obsoletas, pues había comenzado la era
de la electrónica.

1.5.2. Generación 1. Válvulas electrónicas (1945-1955)


La segunda guerra mundial supuso un enorme impulso en el desarrollo de las
computadoras electrónicas, basadas en válvulas electrónicas, como el triodo
(inventado en 1906). Las válvulas tenían como ventaja frente a los relés y
engranajes la ausencia de partes móviles (cuya inercia limitaba la velocidad de
proceso), así como un menor tamaño y mayor fiabilidad. Los dispositivos
construidos con válvulas resultaban así más rápidos, fiables y baratos.
La primera computadora electrónica (aunque de propósito específico) fue
Colossus, desarrollada por el ejército británico. Durante la segunda guerra
Mundial los submarinos alemanes representaban una gran amenaza para los
barcos británicos; las órdenes del almirantazgo alemán eran enviadas por radio
desde Berlín, pero codificadas por medio de una máquina denominada Enigma.
La inteligencia polaca consiguió robar una máquina Enigma a los alemanes, y de
ellos pasó a los británicos, con lo que éstos descubrieron la manera como los
alemanes codificaban los mensajes. El problema era que para descifrar el código
se necesitaba realizar una enorme cantidad de cálculos en muy corto espacio de
tiempo, para lo que se construyó Colossus (1943), en cuyo diseño participó el
matemático Alan Turing, que ya hacia 1937 había sentado las bases teóricas de la
computación.
Por su parte, el ejército americano necesitaba calcular tablas de tiro para
apuntar su artillería pesada (¡solamente el 20% de las bombas caían en un rango
de 300 metros del objetivo!). John Mauchley, profesor de física de la Universidad
Introducción y conceptos previos 25

de Pensilvania, y conocedor del trabajo de Astanasoff, propuso al ejército el


desarrollo de una computadora electrónica, la cual fue aceptada en 1943. Así,
Mauchley, junto con su alumno P. Eckert, construyeron la primera computadora
electrónica de propósito general del mundo, ENIAC (Electrical Numerical
Integrator And Computer). ENIAC constaba de 18.000 válvulas, 1.500 relés,
pesaba 30 toneladas, consumía 140 kW y ocupaba 1.400 metros cuadrados. Su
construcción se concluyó completamente en 1946, aunque ya antes fue empleada
en la realización de cálculos que llevaron al desarrollo de la bomba atómica.
ENIAC operaba con aritmética decimal y su programación se realizaba mediante
interruptores y conectando y desconectando cables (como en las antiguas
centralitas telefónicas), lo cual resultaba extremadamente tedioso e incómodo.
En 1945 John von Neumann, consciente de los problemas de la programación
del ENIAC, publica la idea de controlar los procesos a ejecutar por la
computadora mediante un programa almacenado en memoria (idea, al parecer,
desarrollada más o menos a la vez por Turing), en una propuesta para el proyecto
de una nueva máquina, EDVAC (Electronic Discrete Variable Computer).
Mauchley y Eckert comienzan su desarrollo, pero éste queda finalmente truncado.
En 1949 Maurice Wilkes concluye el EDSAC, construido tomando como base la
misma idea, por lo que resultó ser la primera máquina operativa que funcionaba
controlada por programa almacenado. En 1946 von Neumann y sus colegas
comenzaron en el Instituto de Estudios Avanzados de Princeton el desarrollo de
otra máquina controlada por programa almacenado, la IAS, su propia versión del
EDVAC. Aunque no fue completado hasta 1952, IAS representa el prototipo de
todos los ordenadores de propósito general posteriores.
Por su parte, Eckert y Mauchley emprenden una actividad empresarial
construyendo la primera de una serie de computadoras, el UNIVAC I (1951), el
primer ordenador electrónico de gran éxito comercial, inaugurando así la era
comercial de las computadoras. Mientras tanto, la International Business
Machines Corporation, más conocida por sus siglas, IBM (por entonces pequeña
empresa dedicada a la fabricación de máquinas lectoras de tarjetas perforadas y
clasificadoras, y que ya aportó parte de la financiación de las máquinas de
Aitken), construye sus primeras computadoras, las IBM 701 (1953) y 704. La
709 (1958) fue su última máquina de válvulas, y además una de las primeras
máquinas pensadas para trabajar con sistemas operativos.
26 Microprocesadores y microcontroladores

FIGURA 1.14. Programando el ENIAC.

Figura 1.15. John Von Neumann.

1.5.3. Generación 2. Transistores (1955-1965)


En 1948, J. Bardeen, W. Brattain y W. Shockley, de los laboratorios Bell,
inventan un dispositivo que causará una verdadera revolución, el transistor (por
ello fueron galardonados con el Premio Nobel de Física en 1956). El transistor es
más pequeño que una válvula de vacío, disipa menos potencia y es más barato,
por lo que en 10 años desbancaron a las válvulas en la confección de
computadores (y en muchas otras tareas).
Introducción y conceptos previos 27

Uno de los hechos más destacados de esta segunda generación es la irrupción


en escena en 1957 de Digital Equipment Corporation, DEC, que poco tiempo más
tarde comercializaron la primera minicomputadora, la PDP-1 (1961). Aunque
contaba con menores prestaciones que las máquinas de IBM, costaba tan sólo
120.000 dólares (frente al millón de una IBM 7090), por lo que DEC vendió
docenas de PDP-1 (algo más tarde introdujeron la PDP-8, por tan sólo 16.000
dólares, de la que vendieron más de 50.000 unidades).
Mientras tanto, IBM se convertía en una de las más importantes compañías,
gracias a la 7094, que dominó la computación científica a principio de los sesenta,
y a la 1401, una pequeña computadora orientada a gestión. De ambas se
vendieron numerosas unidades.
De entre las muchas otras máquinas de la época destacaremos la B5000 de
Burroughs. Mientras que otras compañías se centraban en el hardware,
esforzándose en la construcción de máquinas baratas (DEC), o rápidas (IBM), los
diseñadores de la B5000 pensaron que el software también era importante, por lo
que la idearon de forma que pudiera ser programada en Algol 60, el primer
lenguaje de alto nivel. No obstante, esta tendencia tuvo que esperar unos años
antes de que fuera explotada al máximo.

1.5.4. Generación 3. Circuitos integrados SSI y MSI (1965-1971)


Algunas computadoras de la segunda generación podían incluir hasta 10.000
transistores, los cuales se agrupaban en tarjetas de circuito impreso, de decímetros
de tamaño. El siguiente paso importante consistió en integrar diversos
transistores en un único fragmento de silicio, realizando así un circuito integrado
(CI o chip): Jack Kilby (Texas instruments) y Robert Noyce (Fairchild, y luego,
junto con Gordon Moore, cofundador de Intel) son los responsables del invento.
Pronto todas las computadoras se construyeron mediante CI, que eran más
pequeños, más rápidos, más baratos y de menor consumo que las tarjetas. Los
primeros CI se denominaban de pequeña escala de integración o SSI, al incluir
menos de 100 transistores. Los siguientes eran ya de media escala o MSI,
pudiendo incluir hasta mil transistores.
Empleando ya circuitos integrados, IBM introduce la serie 360, como una
sola línea de productos destinada a sustituir las máquinas 7094 y 1401, orientada
tanto hacia el cálculo científico como a gestión. La idea de comercializar una
familia, en la que cada miembro contaba con distintas características particulares
sobre un núcleo común, siendo el software compatible hacia arriba (un programa
escrito para una máquina de gama baja podría ejecutarse en otra de gama más
alta), se volvió popular de inmediato. Otra novedad de la 360 era la posibilidad
28 Microprocesadores y microcontroladores

de trabajo multitarea y su operación con números de 32 bits. La 360 fue el gran


éxito comercial de la década, cimentando el aplastante liderazgo de IBM en el
campo de las computadoras (llegó a dominar en aquella época el 70% del
mercado). La arquitectura 360 es el origen de las grandes computadoras o
mainframes de IBM.
DEC introduce en 1965 la minicomputadora ya citada PDP-8, de la que se
vendieron más de 50.000 unidades; de esa época arranca la fortuna de DEC. La
PDP-8 contaba con la gran innovación de su estructuración alrededor de un bus
(el denominado omnibus), frente a las basadas en la IAS, como las IBM, de
estructura centralizada; esta estructura en buses ha sido desde entonces
universalmente adoptada por todos los mini y micro ordenadores. Posteriormente
apareció la PDP-11, sustituto de 16 bits de la PDP-8. La PDP-11 puede
considerarse por sus características la hermana menor de la 360, teniendo un gran
éxito comercial, sobre todo en las universidades, lo que sostuvo el liderazgo de
DEC en el mercado de las minicomputadoras.

1.5.5. Generación 4. Alta escala de integración (LSI) (1971-1977)


A partir de la tercera no existe un acuerdo general sobre la denominación y
delimitación temporal de las siguientes generaciones. Nosotros consideraremos
que una cuarta generación comienza con el desarrollo de la alta escala de
integración o LSI (más de 1.000 transistores en un CI) a principios de los setenta,
y que una quinta generación comienza con el advenimiento de la muy alta escala
de integración o VLSI (más de 10.000 transistores), a finales de los setenta.
A finales de los años sesenta y comienzos de los setenta el gran desarrollo de
la integración microelectrónica permite la realización de chips de memoria
(memoria de semiconductores). Recordemos que hasta entonces la memoria
central se construía mediante pequeños anillos de ferritas, que almacenaban un ‘0’
o un ‘1’ dependiendo de su estado de magnetización. También se empleaban
tarjetas perforadas, cintas de papel y magnéticas.
La integración LSI permite ya a principios de los setenta integrar toda una
unidad de procesamiento central, o CPU, en una única pastilla de silicio, es decir,
la confección de microprocesadores. Así, en 1971 Intel comercializa el primer
microprocesador de la historia, el 4004, de 4 bits y tecnología PMOS, y poco
tiempo después los primeros de 8 bits, el 8008 (1972) y, sobre todo, el 8080
(1974), el cual es considerado el verdadero primer microprocesador de propósito
general. Motorola realiza el 6800 en 1974 (NMOS), y otras muchas compañías,
como Zilog, Texas Instruments, Fairchild, etc., comienzan también a desarrollar
sus propios microprocesadores. Aunque en origen éstos se idearon para
Introducción y conceptos previos 29

desempeñar tareas de control, sustituyendo electrónica convencional, poco más


adelante se empezaron a construir los primeros microordenadores basados en
ellos, que, a un precio reducidísimo, poco a poco fueron adquiriendo mayor
popularidad.
A la par que los primeros sistemas basados en microprocesadores, por esta
época se siguen desarrollando minicomputadores (como los de DEC) y grandes
computadoras, como las de IBM. Por su relativamente reducido precio y su
orientación a tiempo real, los minicomputadores se emplean en tareas de control
industrial (entre otras).

1.5.6. Generación 5. Muy alta escala de integración (VLSI) (1977-)


Con la llegada de la integración a muy alta escala, o VLSI, los
microprocesadores que pueden fabricarse a finales de los setenta y principios de
los ochenta resultan cada vez más potentes. De entre ellos cabe destacar el
8086/88 de Intel (1978) y el 68000 de Motorola (1979), ambos de 16 bits y
tecnología CMOS, y que darán lugar a las famosas familias 80x86 y 68K,
respectivamente.
La adopción del 8088 de Intel como microprocesador de la nueva línea de
computadores personales PC de IBM (Personal Computer, 1980), y del MS-DOS
de Microsoft como su sistema operativo, resultará decisiva para ambas modestas
compañías (en principio, el 68000 de Motorola era mejor y más potente que el
8086/88, pero...). La enorme popularidad con la que contó el PC desde sus
comienzos hizo que Intel y Microsoft se convirtiesen en pocos años en los dos
gigantes que hoy en día son. Curiosamente, IBM entró sin demasiado
convencimiento en el incipiente mercado de pequeños ordenadores, pero el primer
año ya vendió 300.000 unidades del PC y el segundo 600.000.
Con anterioridad, solamente los grandes centros de cálculo podían abordar la
compra de un computador. Con el advenimiento de los ordenadores personales o
microcomputadores, basados en microprocesadores, el precio de un ordenador
personal resultaba asequible al ciudadano medio, por lo que el PC se ha
convertido en un objeto de consumo, estando presente en numerosos hogares.
Hay en día un PC posee tanta potencia de cálculo como un mainframe de los años
sesenta, a un coste infinitamente inferior.
30 Microprocesadores y microcontroladores

Tipo de computador Ejemplos Aplicaciones

Ordenadores personales (PC) PC, MacIntosh Edición, hojas de cálculo, etc.

Miniordenadores VAX 8600 Control en tiempo real

Estaciones de trabajo (workstations) Sun, HP-Apollo, Alpha Diseño y cálculo. Servidores

Ordenadores centrales (mainframes) IBM 3090/400 Gestión

Supercomputadores Cray XMP Cálculo científico intensivo

TABLA 1.1. Tipos de computadores.

En la actualidad, la potencia de los microprocesadores es tan grande que


eclipsa a muchos de los computadores centrales o minicomputadoras, creándose
un nuevo tipo de computador, las estaciones de trabajo (workstations), de muy
elevadas prestaciones, orientadas a diseño en ingeniería y cálculo científico.
Ejemplos de éstas son las Sparc de Sun Microsystems, las HP-Apollo de Hewlet-
Packard, o las Alpha de DEC. Una estación de trabajo permite disponer de un
miniordenador de sobremesa a un precio muy reducido. Dichas estaciones se
basan en el empleo de microprocesadores de tipo RISC, como el SPARC, PA-
RISC o PowerPC, que parecen haber ganado la batalla de las altas prestaciones a
los CISC, como los clásicos 68000 u 8086.
La era actual se distingue por la convivencia de diversos tipos de
computadores. Así, ordenadores personales y estaciones de trabajo coexisten con
minicomputadoras, super-mini-computadoras (como el clásico VAX de DEC,
sucesor de los PDP), supercomputadores (como los Cray, de la compañía Cray
Research, orientados al cálculo científico), y con los grandes sistemas o
mainframes (gestión). No obstante, la distinción entre los distintos tipos de
computadores disponibles es cada día más difusa; por ejemplo, el término
minicomputador está cayendo en desuso en favor de estación de trabajo, mientras
que los PC de altas prestaciones (basados en potentísimos microprocesadores
como el Pentium III) rivalizan en potencia con muchas estaciones de trabajo.
Otros rasgos que caracterizan nuestra época son la creciente importancia del
software, la tendencia en contra de los grandes sistemas y a favor de las redes de
ordenadores (arquitectura cliente-servidor), el amplio trabajo en computación
paralela, desarrollo de la inteligencia artificial, el PC como equipo de consumo,
las tecnologías multimedia y, por supuesto, Internet (que, como verdadera punta
de lanza de lo que será el siglo XXI, ha empezado a cambiar ya el mundo).
Introducción y conceptos previos 31

Generación 0. Computadoras mecánicas y electromecánicas (1642-1945)


1642 Calculadora Pascal Primera calculadora mecánica
1834 Máq. dif. y analítica Babbage Primeras computadoras mecánicas
1936 Z1 Zuse Primera computadora electromecánica (relés)
1939 ABC Astanasoff-Brerry Introduce técnicas importantes en el futuro
1944 Mark I Aitken Primera computadora electromecánica americana
Generación 1. Válvulas electrónicas (1945-1955)
1943 Colossus Turing-Gobierno G.B. Primera computadora electrónica
1946 ENIAC I Mauchley/Eckert Comienzo de la historia de la computación
1949 EDSAC Wilkes Primera computadora por programa almacenado
1952 IAS von Neumann El diseño seguido por la mayoría de las máquinas
1951 UNIVAC 1 Eckert/Mauchley Primera computadora vendida comercialmente
1953- 701, 704, 709 IBM Despegue de IBM. Sistemas operativos (709)
Generación 2. Transistores (1955-1965)
1960 PDP-1 DEC Primera minicomputadora
1961 1401 IBM Pequeña máquina de gestión
1961 7094 IBM Dominio de la computación científica
1963 B5000 Burroughs Lenguajes de alto nivel (Algol 60)
Generación 3. Circuitos integrados SSI y MSI (1965-1971)
1964 360 IBM Primera línea de productos. Reinado de IBM
1965 PDP-8 DEC Primera minicomputadora vendida masivamente
1970 PDP-11 DEC Dominio de la computación en los setenta
Generación 4. Alta escala de integración (LSI) (1971-1977)
1971 4004 Intel El primer microprocesador
1974 8080 Intel Primer microprocesador de propósito general
1974 6800 Motorola Primero de Motorola, padre de la familia 68XX
Generación 5. Muy alta escala de integración (VLSI) (1977-)
1978 VAX DEC Primera superminicomputadora de 32 bits
1978 8086 Intel Padre de la familia 80x86 (PC compatibles)
1979 68000 Motorola Padre de la familia 68K (Apple MacIntosh y WS)
1980 PC IBM El microordenador cambiará la historia
Supercomputadores Cray Cálculo científico intensivo
µP RISC Dominio de los µP RISC frente a los CISC
Estaciones de trabajo Sun, HP, DEC, IBM Redes de ordenadores. Arq. cliente-servidor
Inteligencia artificial, Internet, multimedia

TABLA 1.2. Historia de la computación (adaptado de [Tanenbaum 92]).


32 Microprocesadores y microcontroladores

La electricidad (s. XVIII y XIX)


XVIII - La electricidad Coulomb, Ohm, Ampère, Se sientan las bases de la electricidad
XIX Gauss

Siglo La ingeniería eléctrica Faraday, Hertz, Edison, Ingeniería eléctrica: «paso de partículas
XIX Marconi cargadas a través de los metales».
El electrón (finales siglo S. XIX)
1885 Postulado del electrón H.A. Lorentz
Su descubrimiento J.J. Thonsom Descubrimiento experimental
Válvulas de vacío (principios S. XX)
1904 Diodo Fleming 1.ª válvula de vacío (det. señales inalámbr.)
1906 Triodo De Forest Como amplificador de señales
1920 KDKA Westinghouse 1.ª emisora de radiodifusión (Pittsburgh).
En 1924 hay ya 500 en EE.UU.
1930 TV en blanco y negro Radio y TV, impulsores de la electrónica
Transistores
1940 Bell labs. Tras el «amplificador de estado sólido»
1947 Prototipo de transistor Brattain, Bardeen, Shockley Inventan el transistor
1947 Transistor BJT Shockley Perfecciona el prototipo.
1951 Comercialización del BJT Bell, y otras La Bell no guarda en secreto la tecnología
El transistor FET Shockley Propuesta (todavía es pronto).
1954 Transistores de silicio Texas Instr.
1956 Premio Nobel de Física Brattain, Bardeen, Shockley 1.er Premio Nobel dispositivo ingeniería
Circuitos integrados SSI, MSI y LSI (1965-1977)
1958 El circuito integrado (CI) J. Kilby y R. Noyce Texas Instruments y Fairchild
1958 Primer transistor por Hoerni (Fairchild) Proceso planar y fotolitografía, se abren las
difusión moderno puertas a los MOSFET
1960 El primer MOSFET Kahng y Atalla Bell
1961 Comercialización del CI Texas Instruments, Fairchild Integración SSI (<100 transistores)
1964 Ley de Moore. CI lineales
1966 MSI (de 100 a 1.000)
1969 LSI (de 1.000 a 10.000)
1970 RAM Intel, Fairchild Comercialización de pastillas de RAM
1971 Microprocesadores Intel El i4004
Muy alta escala de integración (VLSI) (1977-hoy)
1977 VLSI (>10.000) µP de altas prestaciones, entre otros
1979 El PC
Electrónica e Informática Era de la información y comunicaciones

TABLA 1.3. Principales hitos en la historia de la electrónica.


Capítulo 2
Componentes del sistema microprocesador

2.1. El sistema microprocesador


En este capítulo estudiaremos las partes que componen un sistema
microprocesador. Describiremos primero de una manera general (sin tener en
cuenta ningún µP concreto) los bloques fundamentales del hardware del sistema
(CPU, memoria central y entradas y salidas), para realizar después una primera
incursión en el campo del software, proporcionando unas cuantas ideas sobre las
bases en las que éste se asienta (utilizaremos siempre los términos anglosajones
hardware y software, ya que se han impuesto en nuestra lengua). Ofrecida una
perspectiva genérica, en el capítulo siguiente profundizaremos ya en los casos
concretos del M6800 y del M68HC11, los microprocesadores de Motorola que
nos servirán como ilustración a lo largo del texto.
Aunque en este capítulo hablaremos en términos generales, sin tener en
cuenta ninguna CPU en concreto, queremos advertir que nuestra mayor fuente de
inspiración serán los clásicos microprocesadores de 8 bits. Pese a que el
computador es el ejemplo de sistema basado en microprocesador más conocido
por todos, también son sistemas microprocesadores el circuito de control de una
lavadora automática, el sistema de frenado ABS o el control de un aparato de
vídeo. A una persona ajena al campo de la electrónica industrial o de consumo
los µP de 8 bits pueden parecerle obsoletos, especialmente cuando sus
prestaciones se comparan con las de los potentes µP de 32 o 64 bits, base de los
actuales computadores; sin embargo, los µP más sencillos siguen siendo los más
vendidos en el mercado (alrededor del 80% son de 4 y 8 bits [Bursky 95], aunque
el volumen de negocio de los microprocesadores de altas prestaciones es mayor,
debido a su muy elevado coste). La razón de que los más sencillos sean los más
vendidos radica en que la mayor parte de los sistemas electrónicos incorporan en
la actualidad un microprocesador (normalmente, un microcontrolador), y para las
aplicaciones sencillas y medias un procesador de 4 u 8 bits es la mejor solución si
atendemos a la relación prestaciones/precio. Así, cuando un ingeniero debe
desarrollar un sistema electrónico industrial, muy a menudo debe trabajar con un
microcontrolador de 8 bits.
34 Microprocesadores y microcontroladores

CPU (Microprocesador)

Unidad de Unidad de
Procesamiento Control Entradas/
Memoria Central
Salidas

Bus de Datos

Bus de Direcciones

Bus de Control

FIGURA 2.1. Bloques generales de un sistema microprocesador, y estructura de buses.

Por otra parte, comprender el funcionamiento de un µP de 8 bits resulta más


sencillo que el de un gran µP de 32 o 64 bits, en los cuales los nuevos logros
tecnológicos y de arquitectura (unidades en paralelo, ejecución desordenada de las
instrucciones, etc.) ocultan la comprensión de los principios más básicos de
funcionamiento (por ejemplo, el clásico ciclo carga instrucción y ejecuta).
Además, algunas familias de µP de 8 bits, como la 68XX de Motorola, incorporan
muchas de las características que luego vuelven a aparecer en los µP más
potentes. Finalmente, desarrollar aplicaciones y realizar montajes con µP
sencillos, en especial con µC, resultará relativamente sencillo para el estudiante.
Por todas estas razones consideramos que los µP de 8 bits son los más idóneos
desde el punto de vista pedagógico para el primer contacto de un estudiante de
ingeniería con este campo.

2.1.1. Microprocesadores y sistemas microprocesadores


Como ya sabemos, el microprocesador es el circuito integrado (chip) que
materializa al completo una unidad de procesamiento central (CPU). Pero para
que la CPU pueda funcionar se precisa de un conjunto adicional de elementos, los
cuales conforman el sistema microprocesador, en el que el µP es la pieza central.
Los componentes del sistema microprocesador que estudiaremos en este capítulo
son, por este orden, memoria, subsistema de entradas/salidas (E/S) y CPU, los
cuales se conectan entre sí por medio de buses. Ésta va a ser nuestra primera
perspectiva general sobre el sistema µP; un lector sin conocimientos previos sobre
Componentes del sistema microprocesador 35

el tema puede que no llegue a comprender todos los detalles que


proporcionaremos a continuación, pero no debe preocuparse por ello, pues la
mayor parte de las cuestiones se volverán a abordar más profundidamente a lo
largo del texto, de modo que las podrá ir asimilando gradualmente.

2.2. Buses del sistema


Recordemos en primer lugar que los sistemas digitales complejos, en los que
se debe trabajar con una elevada cantidad de información (como los µP), se
estructuran de una manera peculiar que facilita enormemente su diseño y
realización. En ellos se considera que la información se organiza en palabras
digitales, con frecuencia de 8 bits (byte); cada palabra (byte) se almacena en un
registro y a cada registro se le asigna una dirección. El conjunto de los registros
constituyen la memoria del sistema. Buena parte de la operación del sistema
digital consiste en desplazar datos entre los registros, pero en vez de conectar cada
registro con todos los demás, lo que crearía una maraña de conexiones
difícilmente manejable, se introducen unos canales o líneas por los que transita la
información, los buses, en torno a los cuales se organizan los registros, pudiendo
cada uno en un momento dado conectarse o bien permanecer desconectado. De
todos los registros acoplados a los buses, en cada instante solamente se conectarán
de forma efectiva el registro que desea enviar un dato y el que debe recibirlo
[Pollán 94].
Por lo tanto, un bus es un conjunto de líneas de comunicación de señales y
datos que es compartido por varios bloques digitales. Cada subsistema digital
acoplado al sistema de buses puede en un momento dado estar conectado al bus
(habilitado) o desconectado (deshabilitado); en este último caso se dice que el
bloque digital se halla en un estado lógico especial denominado de alta
impedancia (de modo que los dispositivos se dicen tri-estado, al poder enviar por
su salida un ‘0’, un ‘1’ o permanecer en alta impedancia, lo que se denota como
estado de salida ‘Z’).
El sistema microprocesador se vertebra en torno a tres buses diferentes, el bus
de datos (BDat, bidireccional), el bus de direcciones (BDir, unidireccional, que
parte de la CPU) y el bus de control (BCon, con diferentes líneas y sentidos de
propagación de las señales). El concepto de bus permite organizar la memoria en
el sistema microprocesador de una forma muy simple: cada registro (de memoria
o de puerto de E/S) tiene asignada una dirección de memoria; cuando el maestro
del bus (normalmente la CPU) desea acceder a uno de ellos, coloca en el BDir la
dirección del registro que desea leer o escribir, el cual queda seleccionado o
habilitado, pasando entonces sus líneas de datos de un estado de alta impedancia
36 Microprocesadores y microcontroladores

‘Z’ a conectarse de forma efectiva al bus de datos; el dato circulará por BDat en el
sentido indicado por una línea especial denominada de lectura/escritura (desde la
CPU hacia la memoria en caso de escritura, al revés en una lectura); esta última
línea y otras (como la de reloj) constituyen el bus de control, cuyo papel básico es
el de sincronizar la transferencia de la información.
El número de líneas del bus de datos determina la cantidad de información
(bits) que el microprocesador es capaz de mover en un solo paso. La CPU
contiene un bus de datos interno cuya anchura suele coincidir con el número de
bits de su ALU (unidad lógico-aritmética), cifra que se suele utilizar como
parámetro característico de la CPU (4, 8, 16, 32, 64 bits). Normalmente el bus de
datos externo, que constituye el bus del sistema, no es otra cosa que la
prolongación del interno, por lo que suelen tener la misma anchura; así, un
microprocesador de 8 bits suele tener un bus de datos externo de 8 bits (aunque en
algunos casos concretos ambos números no coinciden, p.e., el 8088 es un µP de
16 bits, pero su bus de datos externo posee tan sólo 8 líneas).
Por su parte, el bus de direcciones suele incluir un número más elevado de
líneas, p.e., en el caso de la mayoría de los µP de 8 bits este número es de 16, que
permiten acceder a 65536 registros de memoria (de 8 bits), es decir, 64 KB; en
general un BDir de n líneas puede acceder a 2n casillas de memoria. En
ocasiones, y para ahorrar patillas en el encapsulado del µP, las líneas de datos y
direcciones aparecen multiplexadas (p.e., en el 8085 o en el 68HC11), y
normalmente se demultiplexan mediante un registro de retención como el 74373.
En este sentido, se debe tener en cuenta que con frecuencia los buses que salen
directamente del microprocesador deben pasar por determinados circuitos
(registros, buffers, puertas lógicas) antes de configurar los buses del sistema (p.e.,
el bus del PC original no es el bus del 8088, sino que se deriva de él a partir de
circuitería); así, con una adecuada circuitería de conversión de buses, µP
diferentes pueden dar lugar a un mismo bus del sistema (un bus estándar).
Por último, las líneas del bus de control varían de un µP a otro. No obstante,
siempre habrá una o más líneas de reloj CLK o φ; una o más líneas de
lectura/escritura; y alguna línea de validación de direcciones VDIR y/o de datos
VDAT, que indican cuándo en el BDir existe una dirección válida, y cuándo en el
BDat existe un dato válido, respectivamente (todas estas líneas pueden recibir
denominaciones diferentes). En este sentido, existe un «estilo Intel» y un «estilo
Motorola» para los buses, claramente diferenciados.
Componentes del sistema microprocesador 37

FIGURA 2.2. Señales de bus estilo Intel y generación de las líneas del bus ISA.

FIGURA 2.3. Señales de bus estilo Motorola.

En el «estilo Intel», por un lado se agrupan los registros de memoria (mapa


de memoria) y por otro los puertos de entrada/salida (mapa de E/S). Los µP de
Intel disponen de un conjunto de tres señales: la IO/M (Input-Output/Memory)
indica con un ‘1’ que se va a proceder a realizar una lectura o escritura sobre un
puerto de E/S, mientras que un ‘0’ indica una lectura o escritura sobre un registro
de memoria (en el 8085 es así, pero en el caso del 8086 la señal se denomina
M/IO y opera al revés); por su parte, las señales /RD y /WR determinan si se va a
leer o a escribir, respectivamente, y cuándo, lo que viene indicado por un cambio
de ‘1’ (reposo) a ‘0’ (a lo largo del libro indicaremos que una señal es activa en
estado ‘0’ precediéndola con el símbolo ‘/’, p.e., ‘/WR’), portando así tanto
información del sentido de los datos por BDat (lectura/escritura) como temporal
(cuándo debe ejecutarse la acción). Muchos puertos y memorias estándar
disponen de dos entradas, /RE (read enable, a veces denominada /OE, output
enable) y /WE (write enable), las cuales se generan a partir de las tres señales del
µP, según se indica en la fig. 2.2 (en ella /MEMRD y /MEMWR indican lectura y
escritura en memoria, respectivamente, y /IORD y /IOWR en un puerto de E/S,
nomenclatura empleada en el BCon de los conocidos buses estándar ISA y EISA
de los ordenadores clásicos PC compatibles).
38 Microprocesadores y microcontroladores

Por otra parte, en el «estilo Motorola» registros de memoria y puertos de


entrada/salida comparten un mismo mapa de memoria: es lo que se denomina
entradas/salidas mapeadas en memoria. Además, por un lado existe en el bus de
control una sola señal que indica el sentido de circulación de los datos por el
BDat, la señal de lectura/escritura R/W (Read/Write), donde R/W=‘1’ indica
lectura, y ‘0’ escritura; hay otra señal diferente que transporta la información
temporal, es decir, en qué momento preciso debe ejecutarse la acción, la línea E
(read/write enable) o reloj E. Los periféricos de la familia 68XX de Motorola
están pensados para conectarse directamente a estas dos líneas R/W y E; para
poder establecer conexión con chips con entradas /RE y /WE hay que realizar la
conversión que se indica en la fig. 2.3.
La conexión de los diversos dispositivos al bus debe estudiarse
cuidadosamente. Normalmente existe un máster (maestro) del bus (la CPU), que
lo dirige y que envía o solicita datos a otro dispositivo esclavo (una memoria, un
puerto, etc.). En cada momento debe existir un solo dispositivo que envía datos y
otro que los recibe. Bajo ningún concepto puede haber dos dispositivos que
traten de enviar a la vez un dato por los buses; en este caso se dice que se tiene
un conflicto de bus (imaginemos un circuito electrónico que trata de poner un ‘0’
en una línea y otro a la vez que trata de poner un ‘1’, ¿cuál será el estado final de
la línea?: este tipo de indeterminación no se admite). Por este motivo los
dispositivos que se conectan a los buses son siempre de tipo triestado, y
solamente son habilitados cuando su dirección exacta es colocada en el bus
correspondiente. Cuando un dispositivo no está habilitado se comportará como si
estuviera desconectado del bus.
Por último, recordemos que el dispositivo que se conecta al bus no es un
sistema lógico ideal, pues posee en realidad unas determinadas características
eléctricas de impedancia, capacidad de absorber/inyectar corriente y capacidad
eléctrica. Los dispositivos receptores «cargan» el bus y los que envían señales
tienen una capacidad de suministrar corriente limitada. Por lo tanto, si se acoplan
muchos dispositivos a un bus, habrá que hacer uso de amplificadores drivers
(unidireccionales) o transceivers (bidireccionales), circuitos capaces de trabajar
con mayores intensidades, que permitirán construir sistemas con un más elevado
número de elementos. Estos conceptos, que también pueden repasarse en el libro
Electrónica Digital de T. Pollán [Pollán 94], serán tratados más adelante.
Componentes del sistema microprocesador 39

Microprocesador Habilitación
(CPU) Decod. Habilitación
Direcc. Habilitación

RAM ROM E/S

R/W
VAL (lectura/ R/W R/W
(Validación) escritura)

Bus Datos

Bus Direcciones

Bus Control

FIGURA 2.4. Estructura de los buses de un sistema microprocesador; los bloques de memoria RAM,
ROM y entradas/salidas solamente se conectan al bus de datos cuando son habilitados por la línea
correspondiente del decodificador de direcciones (es decir, cuando en el bus de direcciones aparece
la dirección asignada a cada uno).

2.3. Memoria principal (central)


La memoria es el lugar donde se almacena tanto el programa que ejecutará la
CPU, como los datos requeridos. Todo lo relacionado con la memoria en los
sistemas digitales se considerará estudiado a fondo en un curso previo de
electrónica digital (ver, por ejemplo, [Pollán 94]), por lo que aquí solamente
realizaremos un repaso a los aspectos más importantes (en [Slater 89] puede
encontrarse abundante información práctica adicional sobre el tema).

2.3.1. Tipos de pastillas de memoria


Distinguiremos en este apartado entre la memoria de tipo volátil y la no
volátil. La memoria volátil o RAM (Random Access Memory), pierde la
información que almacena cuando se desconecta su alimentación; los diversos
tipos de memoria RAM se tratan en detalle en [Pollán 94]. Así, se tiene la
denominada RAM estática o SRAM (Static RAM), en la que cada bit de
información se almacena en un biestable. Las celdas básicas de una pastilla
SRAM se organizan internamente en matrices, cuya lectura y escritura se gestiona
(de forma transparente para el usuario) mediante una línea interna de fila y otra de
40 Microprocesadores y microcontroladores

columna. En la fig. 2.5 (izda.) se muestra una celda básica de SRAM construida
en tecnología CMOS, compuesta por un biestable (los cuatro transistores más
internos), cuyas dos salidas Q y /Q (salida Q negada o invertida) se encuentran
conectadas a través de sendos transistores de paso a las líneas que enlazan con la
columna correspondiente: cuando se selecciona la fila en que se encuentra dicho
biestable, los transistores de paso conducen y conectan las dos salidas del
biestable con las líneas de columna, permitiendo una operación de lectura o de
escritura sobre él. Las SRAM se fabrican en chips de 2 KB, 8 KB y 32 KB, entre
otros formatos.
Para reducir el tamaño de la celda básica, y consiguientemente aumentar la
capacidad de almacenamiento de una pastilla, se integran memorias RAM
dinámicas o DRAM (Dynamic RAM, fig. 2.5, dcha.), en cuya celda básica el
biestable se sustituye por un condensador que almacena el valor booleano
(condensador cargado=estado ‘1’, descargado=‘0’). Estos condensadores
equivalen a la capacidad de puerta de los transistores MOS (unos 0,1 pF); debido
a pérdidas en el condensador, la conservación de la tensión por efecto capacitivo
no es indefinida, por lo que las memorias DRAM, aunque de elevada capacidad,
precisan de un refresco periódico (leer y volver a escribir) para no perder la
información almacenada en el condensador. En [Pollán 94, Slater 89] se describe
con mayor detalle los mecanismos de lectura y escritura en pastillas DRAM; aquí
simplemente haremos notar que la peculiar distribución de las pastillas de los
chips de memoria DRAM complica la construcción de circuitos. Por otro lado,
señalaremos que es común comercializar este tipo de memoria en forma de
módulos DRAM, que incluyen varias pastillas sobre una pequeña tarjeta dotada de
conectores estándar (se emplean en la memoria central de los computadores,
donde se necesita un gran volumen de memoria).
En resumen, la SRAM es una memoria rápida que no requiere refresco; por
contra, resulta cara debido a que requiere 6 transistores por celda básica. En
cambio, la DRAM es una memoria mucho más barata, que permite almacenar
grandes cantidades de memoria en un solo chip, pero requiere de refresco y su
manejo resulta bastante más complejo. Cuando se requieren cantidades grandes
de memoria RAM (como en los ordenadores) se emplea DRAM. Recientemente
se ha comercializado un tipo especial de memoria DRAM denominada DRAM
síncrona o SDRAM, que se emplea en los computadores; la SDRAM no debe
confundirse con la memoria SRAM, pues se trata de RAM dinámica cuyos
procesos de lectura y escritura se marcan por flancos de señales en vez de por
niveles (como es usual), con el fin de reducir los tiempos de acceso.
Componentes del sistema microprocesador 41

Vcc

/Q Q

Selección
de fila Selección de fila

Línea de bit /Q Línea de bit Q Línea de bit Q

FIGURA 2.5. Celda básica de una pastilla SRAM (izda.) y de una DRAM (dcha.).

Vcc

+Vcc o 0V +Vcc o 0V

Selección de fila Selección de fila Selección de fila

Línea de bit Q Línea de bit Q Línea de bit Q

FIGURA 2.6. Celda básica de un chip de memoria ROM (izda.), PROM (centro) y EPROM (dcha.).

Dentro del grupo de memorias volátiles se incluye también la RAM de vídeo


o VRAM, específica para monitores de vídeo. Las VRAM se basan en una
memoria DRAM que almacena la imagen a visualizar, más un registro de
desplazamiento muy largo y rápido, que recibe en paralelo un bloque de
información de la DRAM y la presenta en serie al circuito que realiza el barrido
del monitor.
El otro gran grupo de pastillas de memoria es el de la memoria no volátil,
genéricamente conocida como ROM (Read Only Memory), la cual mantiene la
información cuando su alimentación es desconectada. La celda básica de una
pastilla de ROM programada de fábrica o ROM de máscara (mask-programmed
ROM) tiene la apariencia de la fig. 2.6 (izquierda); la conexión a 0 o +Vcc se
realiza en la factoría diseñando una máscara específica que se empleará en la
42 Microprocesadores y microcontroladores

fabricación del circuito integrado (lo cual sólo resulta rentable para una serie
elevada, de miles de circuitos). La densidad de almacenamiento de una ROM
programable por máscara es obviamente muy elevada y, cuando se fabrican por
miles de unidades, resulta muy barata.
Para permitir que un usuario cualquiera pudiera programarse sus propias
memorias ROM, se introdujeron las ROM programables o PROM (Programmable
ROM). En éstas la eliminación de un fusible (fig. 2.6, centro) mediante pulsos de
elevada corriente (suministrada mediante un aparato programador de memorias)
determina el estado ‘1’ o ‘0’ a almacenar. Obviamente, la programación de este
tipo de memorias tiene un carácter destructivo, de modo que solamente pueden
programarse una vez.
Las EPROM (Erasable PROM), por contra, son memorias PROM borrables
y, por tanto, programables repetidas veces. Éstas se basan en transistores MOS de
doble puerta (fig. 2.6, derecha), una de ellas flotante entre la convencional y el
substrato, la cual puede almacenar una carga cuando la puerta convencional es
sometida a una tensión relativamente elevada (unos 20 voltios). La operación de
borrado se basa en la pérdida de la carga almacenada en la puerta central al ser
irradiada por luz ultravioleta; para ello el encapsulado de las memorias EPROM
(que es cerámico) está dotado de una ventana de cristal de cuarzo. Así, una
EPROM convencional puede re-programarse unas 100 veces, aunque, por contra,
resulta bastante más cara que una PROM. Se comercializan chips EPROM de 2
KB, 4 KB, 8 KB, 16 KB, 32 KB y 64 KB.
Otro tipo de memoria no volátil es la EEPROM (Electricaly Erasable
PROM); se trata de PROM borrables y grabables eléctricamente, basadas en un
principio parecido a las EPROM, sólo que permiten también su borrado mediante
pulsos de tensión de signo contrario a los de programación. Aunque
funcionalmente la EEPROM se comporta como una RAM, pues resulta escribible
y borrable eléctricamente, en realidad sus tiempos de re-escritura o borrado son
mucho mayores que los de un chip RAM convencional (del orden de 10
milisegundos). Una EEPROM puede re-programarse unas 10.000 veces, y los
chips modernos integran también la circuitería necesaria para generar la tensión
de programación a partir de la alimentación de 5 voltios (bomba de carga). Se
comercializan chips EEPROM de 2 KB, 8 KB, y 32 KB, entre otros.
Recientemente se ha introducido un nuevo tipo de memoria ROM
denominada flash (o flash EEPROM), que cuenta con una creciente popularidad.
Al igual que los chips EEPROM tradicionales, resulta ser escribible y borrable
eléctricamente, pero su organización es más sencilla, por lo que puede integrarse
en cantidades mucho mayores (prácticamente, como la EPROM), aunque como
contrapartida su grabación no puede realizarse sobre bytes individuales, sino que
Componentes del sistema microprocesador 43

debe efectuarse por bloques de bytes (eso sí, en tiempos inferiores a los de la
EEPROM). Este tipo de memoria suele emplearse para almacenar programas de
tamaño grande, comercializándose incluso los denominados «discos flash», que
pueden contener cientos de KB de información, comportándose como un «disco
duro de silicio», y que resulta muy útil en el caso de los sistemas pequeños o
donde se requiera de una robustez mecánica que no ofrecen los discos duros
tradicionales.
Existen algunos tipos de memoria a caballo entre las volátiles y las no
volátiles. Por ejemplo, las pastillas RAM con batería de respaldo, o battery-
backed RAM, son circuitos integrados que incorporan una pequeña batería de litio
que asegura el mantenimiento de la información en ausencia de alimentación
externa durante unos 10 años. Esta memoria está dotada de un circuito que
cuando detecta la pérdida de tensión conmuta la alimentación de la memoria a la
batería de respaldo. Otro tipo son las denominadas RAM no volátiles o NVRAM,
que integran por cada celda RAM una de EEPROM de respaldo; normalmente se
trabaja con las celdas RAM, pero cuando se aprecia un principio de caída en la
tensión de alimentación se procede a guardar el contenido de la RAM en las
celdas EEPROM. La compañía Xicor está especializada en este tipo de
dispositivos de memoria (http://www.xicor.com).
En la fig. 2.7 se muestra el patillaje de algunas pastillas de memoria
comerciales. Hay que tener en cuenta que afortunadamente existe una
denominación y patillaje estándar para los diversos circuitos de memoria que
comercializan los distintos fabricantes. Por ejemplo, las pastillas EPROM suelen
comenzar con el código ‘27’, mientras que las de EEPROM empiezan por ‘28’.

2.3.2. Modelo de funcionamiento de una pastilla de memoria


En la fig. 2.8 se muestra el modelo de funcionamiento de un chip de memoria
genérico, que emplearemos para describir la operación del sistema
microprocesador. Normalmente, en las pastillas de memoria la información se
almacena en grupos de 8 bits, lo que se denomina 1 byte; así, y con independencia
de la organización física interna (circuito) que en realidad posea cada tipo de
pastilla, podemos imaginar la memoria como una sucesión de casillas o registros,
cada una con una dirección asignada y conteniendo 1 byte de información. Si una
memoria posee n líneas de direccionamiento (A0, A1,..., A(n−1)), contendrá 2n
bytes. Así, una memoria con 12 líneas contiene 4 Kbytes (KB) registros, 16 se
corresponden con 64 KB, 20 con 1 MB y 24 con 16 MB.
44 Microprocesadores y microcontroladores

RAM 128 Bytes RAM 2 KB RAM 8 KB EPROM 2KB EPROM 8KB

FIGURA 2.7. Diversas pastillas de memoria SRAM y EPROM de baja capacidad.

FIGURA 2.8. Modelo de la estructura interna de una pastilla de memoria, y conexión a los buses del
sistema microprocesador.
Componentes del sistema microprocesador 45

Si cada casilla de memoria contiene 8 bits, la pastilla requiere de 8 líneas de


datos (D0 a D7). La pastilla posee también una línea de habilitación de chip, /CS
(chip select) o /CE (chip enable), a menudo activas a ‘0’, que si se mantiene a ‘1’
hace que tanto las líneas de direcciones como de datos de la pastilla de memoria
se encuentren desconectadas de los buses, permaneciendo el chip en un estado de
espera (standby), de bajo consumo. Cuando se coloca la línea de selección de
pastilla a ‘0’, ésta queda ya habilitada y sus líneas se conectan a los buses del
sistema. Algunas pastillas tienen varias líneas de selección (/CS0, /CS1...); para
que este tipo de pastillas quede habilitada hay que mantener en el estado lógico
activo todas sus líneas de selección.
En el caso de una pastilla de memoria RAM, ésta debe incluir alguna línea
que indique si se va a leer o a escribir. En algunas ocasiones se tiene una sola
línea de lectura/escritura R/W, aunque con frecuencia ésta aparece desdoblada en
dos, una de habilitación de lectura /RE y otra de habilitación de escritura /WE o
/OE (ver sección anterior). En este último caso se pueden dar las siguientes
posibilidades:
a) /CE=‘1’, pastilla deshabilitada, en modo de bajo consumo; líneas de
direcciones y datos en alta impedancia.
b) CE=‘0’, /WE=‘0’, /RE=‘1’, modo escritura.
c) CE=‘0’, /WE=‘1’, /RE=‘0’, modo lectura.
d) CE=‘0’, /WE=‘1’, /RE=‘1’, pastilla habilitada, con sus líneas de direcciones
habilitadas, pero con las líneas de datos en alta impedancia.
A diferencia de las memorias RAM, en el caso de las memorias de tipo ROM
se tiene una única línea /RE (o /OE). Las memorias tipo ROM programables
mediante una tensión externa elevada (PROM, EPROM...) incluyen además una
patilla adicional Vpp, donde debe colocarse la tensión de programación (por
ejemplo, 20V).
Consideraremos que la pastilla de memoria internamente contiene un registro
de direcciones de memoria MAR (Memory Address Register) conectado al bus de
direcciones, en el cual se almacena el número de la casilla o registro de las pastilla
de memoria cuyo contenido se pretende leer o escribir; un decodificador interno
es el encargado de seleccionar dicho registro apuntado por el valor de MAR. Por
su parte, el registro de datos de memoria MDR (Memory Data Register),
conectado al bus de datos, contendrá el dato leído de la casilla apuntada por
MAR, o bien el que va a ser escrito en ella.
46 Microprocesadores y microcontroladores

En la operación de una pastilla de memoria debe atenderse al cronograma de


las señales involucradas en los procesos de lectura y escritura. Los tiempos
típicos que se contemplan, y que aparecen en las hojas de características de cada
pastilla, pueden consultarse en [Pollán 94, Slater 89]. Muy brevemente,
recordemos que el tiempo de acceso de lectura mide el tiempo que transcurre
desde que se activa las líneas adecuadas hasta que aparece el dato válido por las
líneas de datos del chip. De la misma manera, existe un tiempo de acceso de
escritura, que en una RAM suele ser prácticamente igual que el de lectura; por
ello se habla con frecuencia simplemente del tiempo de acceso que caracteriza una
determinada pastilla de memoria (200 ns, 100 ns, 25 ns, 10 ns...).

2.3.3. Configuración circuital de mapas de memoria


Habitualmente sucede que un determinado microprocesador puede
direccionar más casillas de memoria que las que pueda proporcionar una sola
pastilla; además, en un sistema se precisa la inclusión de distintos tipos de
memoria (RAM, EPROM, EEPROM, etc.), pues cada una tiene su utilidad
específica (almacenamiento de variables en RAM, programa y rutinas en ROM,
etc.). Por ambas razones el denominado mapa de memoria del sistema µP, o
esquema en el que aparecen los distintos tipos de memoria empleados y su
ubicación concreta, normalmente se realiza físicamente mediante varios chips de
memoria, cada uno de los cuales abarcará una zona del mapa.
El diseño y realización del circuito electrónico que sitúa los distintos
elementos de memoria en su posición adecuada se denomina configuración
circuital de mapas de memoria. Unos cuantos ejemplos de realización se
muestran en [Pollán 94]; más adelante presentaremos algún ejemplo concreto para
los microprocesadores de Motorola que estudiaremos. En general, las líneas de
direccionamiento de las pastillas de memoria (A0, A1, ... A(m−1)) se conectan
directamente a las líneas homónimas del bus de direcciones; las restantes, hasta
completar las n líneas totales del bus de direcciones, son las que se emplearán
para distinguir de entre todas las pastillas cuál es la que en un momento dado está
activa, para lo cual se emplea un bloque denominado decodificador de
direcciones. La decodificación de direcciones puede realizarse:
a) Mediante puertas lógicas individuales (NAND, inversores, etc.), si el sistema
incluye un número reducido de pastillas (p.e., dos o tres chips de memoria).
b) Si el sistema incluye más elementos de memoria (p.e., 6 u 8 chips de
memoria), suele resultar más cómodo emplear decodificadores integrados (fig.
2.9).
Componentes del sistema microprocesador 47

c) Si el decodificador de memoria resulta ser excesivamente complejo, puede


realizarse físicamente programando su esquema lógico sobre dispositivos
lógicos programables, como una PAL.
Ejemplos de circuitos decodificadores de direcciones típicos de amplio uso
son el 74138 (3 a 8), el 74139 (dos decodificadores 2 a 4 integrados) o el 74154
(4 a 16); éstos, para que no añadan excesivo retraso en la propagación de las
señales, deben pertenecer a familias lógicas suficientemente rápidas, como la LS,
ALS, etc. (en función de la frecuencia de reloj del bus).

Decodificador 3 a 8 2 decodificadores 2 a 4 Decodificador 4 a 16

FIGURA 2.9. Algunos circuitos integrados codificadores de dirección típicos.

Habilitación
Habilitación
Microprocesador Decod. Habilitación
(CPU) Direcc. Habilitación

RAM 1 RAM 2 ROM 1 ROM 2


(2K) (2K) (2K) (2K)
A0-A15
A11-A15 A0-A10 A0-A10 A0-A10 A0-A10

R/W
VAL R/W R/W R/W
A11-A15

Bus Datos
A0-A15 A0-A10 A0-A10 A0-A10 A0-A10

Bus Direcciones

Bus Control

FIGURA 2.10. Decodificación del bus de direcciones y selección de las pastillas de memoria.
48 Microprocesadores y microcontroladores

Una cuestión a considerar es que la selección del chip de memoria debe


llevarse a efecto solamente cuando tanto los datos presentes en el BDat como la
dirección en el BDir sean válidos (perfectamente estables), para no ocasionar
lecturas de datos no válidos o escrituras incorrectas. Para ello hay que atender a
determinadas líneas de los buses que hacen el papel de líneas de validación de
direcciones y/o datos. Por simplicidad, en adelante consideraremos una única
línea genérica de validación que denominaremos VAL (ver fig. 2.8).
Por otro lado, debe tenerse en cuenta que en los sistemas microprocesadores
y microcontroladores destinados a instrumentación y control industrial
normalmente se requiere de una reducida cantidad de memoria (p.e., 8 K de ROM
y 2 K de RAM), por lo que el mapa de memoria (p.e., de 64 K) puede encontrarse
prácticamente vacío. En este caso no es necesario llevar a cabo una
decodificación total, teniendo en cuenta el estado de todas y cada una de las líneas
de direcciones (y por la cual cada registro de memoria tendrá asignada una
dirección y sólo una), pues ello requiere con frecuencia de un circuito de cierta
complejidad. En este caso suele ser preferible realizar una decodificación parcial,
decodificando tan solo el número de líneas de dirección suficientes que permitan
distinguir todas las pastillas de memoria del mapa.
Por ejemplo, si nuestro sistema contiene 2 pastillas de 2 K ROM y 2 de 2 K
RAM (con líneas A0 a A10, ver fig. 2.10), en una decodificación total el bloque
decodificador debería tener como entradas las líneas de direcciones A11, A12,
A13, A14 y A15, con lo que se requeriría de un complejo decodificador de 5
entradas. Sin embargo, basta decodificar 2 líneas de direcciones para distinguir
entre las cuatro pastillas, por lo que podríamos emplear un sencillo decodificador
de direcciones que interprete tan sólo A14 y A15, por ejemplo. En este último
caso, el decodificador necesario será mucho más sencillo, aunque como
contrapartida cada registro tendrá asignadas varias posiciones dentro del mapa de
memoria (pues un determinado chip queda seleccionado con independencia del
valor de A11, A12 y A13, que no son tenidas en cuenta en la decodificación),
circunstancia ésta que normalmente no tiene por qué causar problemas.

2.3.4. Modelo del funcionamiento de la memoria en lenguaje RTL


Para describir de una forma clara y compacta el flujo de datos en un sistema
microprocesador suele emplearse el denominado lenguaje de transferencia de
registros o RTL (Register Transfer Language). En RTL registros y buses se
denotan mediante letras mayúsculas: por ejemplo, A sería un «registro A», BDat
representaría el bus de datos y BDir el de direcciones; por otro lado, una casilla de
memoria se denota mediante el número que indica su dirección, por ejemplo,
1000. El dato contenido en un registro, el que circula por un bus o el contenido
Componentes del sistema microprocesador 49

en una casilla de memoria, se indica colocando su nombre o número entre


paréntesis; por ejemplo, si el registro A almacena el número 15, entonces (A)
valdrá 15, si la casilla número 1000 almacena un 4, entonces (1000) valdrá 4.
La transferencia de un dato entre registros o buses se representa mediante
flechas. Por ejemplo, BDat←(A) indica que el contenido del registro A se envía
al bus de datos. En estas expresiones a la derecha de la flecha siempre habrá un
dato (o algo que se interpretará como dato), mientras que a la izquierda debe
figurar una dirección, o el nombre de un bus o registro
dirección_destino ← dato nombre_destino ← dato
Las operaciones entre datos se denotan mediante los símbolos usuales +, −, ×,
/, así BDat←(A)+(1000) indica que el contenido de la dirección mil de memoria
se suma al contenido del registro A, y el resultado se coloca en el bus de datos.
Empleando el lenguaje RTL, podemos expresar el funcionamiento de una
pastilla de memoria RAM de la siguiente manera (se sugiere seguir la trayectoria
de los datos sobre la fig. 2.8):
a) LECTURA
MAR←(BDir) * el contenido del BDir (la dirección) pasa a MAR
MDR←((MAR)) * el contenido de MAR, (MAR), es la dirección donde
está el dato; por lo tanto ((MAR)), es el propio dato,
el cual se envía a MDR
BDat←(MDR) * MDR contiene el dato, que es colocado en el bus
Este proceso se lleva a cabo cuando R/W señala lectura y VAL (validación)
está activada. De todos los tiempos que aparecen en el cronograma de lectura de
memoria, caracterizaremos esta operación de lectura con el tiempo de acceso de
lectura.
b) ESCRITURA
MAR←(BDir) , MDR←(BDat) * en RTL dos acciones colocadas en una
misma línea se ejecutan en paralelo
(MAR)←(MDR) * el dato almacenado en MDR pasa a la
dirección apuntada por MAR, (MAR)
50 Microprocesadores y microcontroladores

Este proceso se lleva a cabo cuando R/W señala escritura y VAL (validación)
está activada. De los múltiples tiempos que pueden tomarse en consideración,
caracterizaremos la operación de escritura con el tiempo de acceso de escritura.
Como ya se ha comentado, la magnitud de los dos tiempos de acceso citados es
parecida, por lo que se suele dar un tiempo de acceso que caracteriza
genéricamente la memoria.

2.3.5. Jerarquía de memoria


A menudo hay que adoptar en el desarrollo de un sistema un compromiso
entre tamaño y velocidad, que en el caso de la memoria se traduce de la siguiente
forma: a igualdad de tecnología, una pastilla memoria de más capacidad también
resultará más lenta. Mientras que tradicionalmente se ha tratado de optimizar la
memoria en el sentido de lograr una máxima capacidad, sacrificando velocidad, la
tendencia en el caso de la CPU ha sido alcanzar mayores velocidades de proceso,
por lo que poco a poco se ha venido abriendo una brecha (cada vez más grande)
entre la velocidad a la que el microprocesador procesa datos y el ritmo al que la
memoria convencional puede suministrarlos. El resultado es que se dispone de
CPU cada vez más rápidas, pero la velocidad de operación de las memorias no
sigue el mismo ritmo de aumento, frenando así el rendimiento global del sistema.
Por ello, se ha dicho tradicionalmente que la memoria es más lenta que la
CPU, de modo que cuando la CPU solicita un dato a memoria normalmente debe
esperar durante cierto tiempo hasta que la memoria responda. El problema no es
de tecnología sino de economía, pues realmente se sabe cómo construir memorias
rápidas, pero resultan tan caras que equipar un sistema con varios megabytes
resultaría prohibitivo (excepto para supercomputadoras, con las que se pretende
obtener un rendimiento extraordinario a cualquier precio). Por ello, se prefiere
trabajar con una memoria más lenta, pero que resulte mucho más barata, de
manera que se pueda incorporar una gran cantidad de ella. El inconveniente es
que la velocidad de operación global del sistema será inferior a la que en principio
podría alcanzarse dadas las prestaciones de la CPU.
La solución adoptada en los sistemas microprocesadores (especialmente en
los computadores) consiste en construir estructuras de memoria jerárquicas. Así,
la memoria que hemos denominado central (la RAM y ROM convencional del
sistema) está construida mediante semiconductores, por lo que su velocidad y
coste son medios. A la par, existe un sistema de almacenamiento masivo (de tipo
magnético u óptico, como discos, cintas, CD-ROM, etc.), que es una clase de
memoria más lenta que la de semiconductores, pero mucho más barata, por lo que
pueden construirse económicamente dispositivos de muy alta capacidad. Esta
memoria masiva barata (por ejemplo, un disco duro) se utiliza para almacenar
Componentes del sistema microprocesador 51

grandes cantidades de datos o programas. Cuando la CPU necesita una parte de


esta información (por ejemplo, un programa), ésta puede ser cargada de la
memoria masiva a la central de semiconductores, que por ser mucho más rápida
en comparación, es la empleada por el µP para trabajar regularmente. Para tener
una idea de los órdenes de magnitud, en los PC compatibles la memoria central
(RAM dinámica o DRAM) consta de varios megabytes (16, 64, 128 MB),
mientras que la masiva suele ser de varios gigabytes (p.e., 4 GB).
Por último, las modernas CPU de altas prestaciones son capaces de procesar
datos a grandes velocidades, de modo que incluso la memoria central de
semiconductores resulta demasiado lenta en comparación. Por este motivo, en
estos sistemas se incorpora una memoria intermedia denominada caché (término
que procede del participio del verbo francés cacher, esconder; por lo tanto,
significa literalmente memoria «escondida», lo que hace referencia a su frecuente
localización interna al µP, fig. 2.11), basada también en semiconductores, pero
organizada de muy diferente forma a la convencional. Esta memoria resulta ser
muy rápida, de tipo estático en vez de dinámico, y de relativamente reducida
capacidad por su alto coste (p.e., 32 KB, 512 KB). La caché se coloca muy cerca
de la CPU, comunicándose con ella a una muy elevada velocidad (superior a la
del bus convencional); la caché de nivel 1 (denominada L1) suele integrarse en el
mismo chip que la CPU, mientras que la de nivel 2 (L2) suele ser otro chip de
silicio muy próximo al µP, conectándose a él con un bus específico.

Placa CPU

Microprocesador
(CPU)

Módulo de Memoria

Memoria Masiva
Memoria Central (disco duro ...)
Memoria
Caché

Bus de Datos

FIGURA 2.11. Estructura jerárquica de la memoria de un gran sistema (computador).


52 Microprocesadores y microcontroladores

A grandes rasgos, la operación de la caché se basa en el hecho de que la


instrucción que se va ejecutar tras la actual frecuentemente se sitúa en sus
inmediaciones (normalmente a continuación). Para comprender el porqué,
pensemos que en un programa sin saltos ni llamadas a procedimientos las
instrucciones se extraen para su ejecución de posiciones consecutivas, o que en el
caso de los bucles un conjunto de instrucciones próximas en la memoria se
ejecutan repetidamente varias veces.
Así, cuando un µP con caché debe tomar una instrucción de memoria
(hablaremos de instrucciones, pero se aplicaría también a datos), primero la busca
en la caché (rápida); si no está allí, la toma de la memoria central (lenta) y la
guarda en la caché para el futuro. Si poco después la CPU necesita de nuevo
dicha instrucción (por ejemplo, en el caso de un bucle), la buscará primero en la
caché (rápida, muy próxima a la CPU y comunicada con ésta mediante un canal
muy veloz) y la ejecutará, y no necesitará acudir ya a la más lenta memoria
central. En otras ocasiones el µP carga en la caché no solamente la instrucción (o
dato) actual, sino que almacena todo un bloque procedente de memoria, dentro del
cual está incluida la instrucción (o dato) en curso, de modo que con una alta
probabilidad las siguientes instrucciones a ejecutar estarán en ese mismo bloque,
y la CPU no necesitará acudir a la lenta memoria central. Remitimos al lector
interesado en profundizar en los detalles de la operación de la memoria caché al
libro de Tanenbaum Organización de Computadoras [Tanenbaum 92].

2.4. Unidad de entrada/salida (E/S)


La unidad de entrada/salida (E/S) se encarga de poner en comunicación el
sistema microprocesador con el exterior. Para la CPU la unidad de E/S se
comporta como un conjunto de registros, denominados puertos (ports), sobre los
que puede leer o escribir, registros que son algo especiales, pues se conectan al
exterior a través de sus líneas, de modo que estas acciones de lectura/escritura
tienen su repercusión sobre un periférico externo (encender un LED, leer un
interruptor, imprimir un carácter, etc.). Por ejemplo, cada uno de los biestables
que componen el registro de un puerto de salida se corresponde con una línea que
va hacia el exterior, y, si la CPU graba un ‘1’ en ese biestable, ese ‘1’ sale por la
línea hacia el exterior en la forma de una tensión próxima a + 5 voltios, que
podría encender un LED o actuar sobre cualquier otro dispositivo externo.
Podemos interpretar esta unidad de E/S, bien como una parte más de la
memoria, bien como una zona perfectamente diferenciada. En todo caso, en vez
de hablar de casillas de memoria se habla de puertos, clasificados en:
Componentes del sistema microprocesador 53

a) Puertos de entrada. Equivale a un registro de sólo lectura, cuyos datos


provienen del exterior. Un ejemplo de puerto de entrada sería el que comunica
con un teclado.
b) Puertos de salida. En este caso, un puerto equivale a un registro de sólo
escritura, que envía los datos al exterior, por ejemplo, a una impresora.
c) Puertos programables de entrada/salida. Se trata de puertos cuyas líneas que
comunican con el exterior poseen tanto posibilidad de lectura (recibir datos)
como de escritura (enviar), según se programen.
Las entradas y salidas se pueden llevar a cabo en serie o en paralelo. En el
primer caso, los bits que componen los datos se envían o reciben a través de una
línea secuencialmente, uno tras otro. En el segundo caso, los datos se envían o
reciben por medio de varias líneas a la vez, por ejemplo, en grupos de 8 (byte).
Como ya se ha explicado, en algunos sistemas a los puertos de E/S se les
asigna una determinada dirección dentro del espacio de memoria del sistema,
como si de casillas convencionales de memoria se tratasen, técnica denominada
entrada/salida mapeada en memoria, la cual es empleada en los µP de Motorola.
En otros sistemas, cada puerto posee una dirección dentro de un mapa de E/S
específico, separado del de memoria; ésta es la técnica utilizada por Intel.
El tratamiento de las E/S es algo diferente del de los registros de memoria
convencional. La memoria suele ser un sistema más o menos homogéneo, cuyos
elementos se comportan de una forma parecida y trabajan dentro de órdenes
temporales similares. Sin embargo, en el caso de las E/S hay que tratar con
periféricos de características muy dispares (por ejemplo, una impresora y una
pantalla de vídeo). Además, las E/S deben poner en relación un sistema
electrónico que funciona en tiempos del orden de un microsegundo o menos
(frecuencias de reloj de MHz) con periféricos que pueden operar en fracciones de
segundo, o bien deben esperar a decisiones de un ser humano, que pueden tener
todavía un mayor tiempo de reacción. En este caso, la CPU no puede estar
continuamente «mirando» al exterior a través de un puerto de E/S (técnica de E/S
denominada modo bloqueado o bucle de espera) esperando algún evento, pues
resultaría en una terrible pérdida de tiempo. Para resolverlo, se introducen
técnicas como las interrupciones y el acceso directo a memoria (DMA, Direct
Memory Access). Estas técnicas, pensadas para optimizar el rendimiento de la
CPU al tratar con E/S, serán estudiadas con amplitud más adelante.
54 Microprocesadores y microcontroladores

2.5. Unidad de procesamiento central (CPU)


La unidad de procesamiento central o CPU (Central Processing Unit) es el
corazón del sistema, quien controla y ordena la ejecución de todas las acciones
necesarias y realiza las tareas de procesamiento de la información. Antiguamente
(ver apéndice del capítulo 1), la CPU estaba constituida por un conjunto de
dispositivos electrónicos diferenciados que ocupaban un espacio considerable.
Sin embargo, en la actualidad la CPU se presenta integrada en un único chip
denominado microprocesador, por lo que en ocasiones empleamos
indistintamente los términos CPU y microprocesador.
A continuación describiremos la organización de una CPU o microprocesador
típicos, para en el siguiente capítulo describir la estructura y funcionamiento de
un microprocesador concreto. Como vimos en el capítulo anterior, distinguiremos
dos partes en la CPU, la unidad de procesamiento (UP) y la unidad de control
(UC), que pasamos a continuación a estudiar. De nuevo debe recordarse que,
aunque las estructuras genéricas que se presentarán están en buena parte
inspiradas en los µP de 8 bits, los principios expuestos pueden aplicarse en
realidad a la CPU de casi cualquier µP.

2.5.1. Unidad de procesamiento (UP)


La unidad de procesamiento es la parte de la CPU encargada de llevar a cabo
el tratamiento de la información. Se compone de:
a) Unidad lógico aritmética o ALU (Arithmetic-Logical Unit), circuito
combinacional que lleva a cabo las operaciones lógicas y aritméticas; el
tamaño en número de bits de los datos con los que trabaja suele dar la potencia
de procesamiento del µP (se habla de µP de 4 bits, 8, 16, 32, etc.). Un µP de 8
bits suele realizar operaciones aritméticas de suma y resta en complemento a
dos, y quizás también en decimal (BCD), mientras que µP más potentes suelen
multiplicar, dividir o realizar operaciones en punto flotante (aunque, en
ocasiones, para ello se haga uso de una unidad específica denominada
coprocesador matemático, que en algunos µP es un chip diferente al de la
CPU, como el 8087, coprocesador del 8086, mientras que en otros va
integrado en la misma pastilla, como en el caso del 80486DX).
b) Registros, empleados para depositar transitoriamente operandos (datos) y
direcciones de operandos. Podemos distinguir entre los registros de propósito
general, que almacenan datos de cualquier tipo, y los registros específicos, que
poseen un cometido muy concreto (punteros de memoria, indicación de estado,
etc.). En los microprocesadores de 16 y 32 bits suele haber un grupo de
Componentes del sistema microprocesador 55

registros de propósito general, equivalentes entre sí, que se denomina banco de


registros. Sin embargo, en los de 8 bits (como el 6800 y 8085) hay tan sólo
unos pocos registros generales, y con frecuencia un registro de este tipo
denominado acumulador se utiliza como fuente implícita de uno de los
operandos y destino del resultado. De entre los registros de propósito
específico podemos destacar el registro de estado, compuesto por biestables
denominados indicadores o flags (banderas), que se activan cuando se
cumplen ciertas condiciones en los operandos o resultado (que un resultado es
cero, que se ha producido acarreo en una suma, desbordamiento, etc.). Dos
tipos de registros específicos habituales son el puntero de pila o SP (stack
pointer), que apunta a la dirección donde comienza la pila del sistema, y uno o
más registros índices (index register), que se utilizan también como punteros
de memoria para el manejo de tablas de datos. Por último, puede existir un
registro de desplazamiento, que realiza las operaciones de desplazamiento de
bits típicas.
La arquitectura interna de una CPU puede estructurarse en torno a uno o más
buses internos, que comunican ALU, registros y el resto de los bloques. En una
arquitectura de tres buses, las instrucciones precisarán tres direcciones que
especifiquen dónde se hallan los dos operandos y dónde colocar el resultado. Un
ejemplo de instrucción de tres direcciones sería la siguiente:
ADD R1, R2, R3 R3←(R1)+(R2)
que lleva a cabo la suma (ADDition) del contenido del registro R1, que contiene el
operando uno, con el del registro R2, que contiene el operando dos; el resultado lo
almacena en el registro R3 (R1, R2 y R3 pueden interpretarse como registros
internos del µP y/o casillas de memoria). Esta arquitectura suele ser la adoptada
por las CPU de 16 y 32 bits.
Por otra parte, en una arquitectura de bus único o basada en acumulador,
como la de los clásicos de 8 bits (p.e., 6800 y 8085) las instrucciones son de una
sola dirección. Siguiendo con el ejemplo anterior, se tendría la siguiente
instrucción:
ADD R1
En este caso, la operación suma se llevaría a cabo implícitamente sobre un
registro acumulador, que denotaremos por A (fig. 2.12), motivo por el cual
expresaremos esta instrucción como ADDA:
ADDA R1 A←(A)+(R1)
56 Microprocesadores y microcontroladores

FIGURA 2.12. Estructura de una UP de bus único (arquitectura basada en acumulador).

FIGURA 2.13. Estructura simplificada de una UP de tres buses. El grupo de registros de propósito
general suele denominarse banco de registros.

Si con una ALU de este tipo se desea llevar a cabo una suma de tres
operandos, como la del caso anterior, ésta habría que «simularla» cargando en el
acumulador A el primer operando mediante una instrucción LDAA (LoaD
Accumulator A), sumando el segundo operando con ADDA y guardando el
Componentes del sistema microprocesador 57

resultado en cierto registro mediante una instrucción de almacenamiento STAA


(STore Accumulator A):
LDAA R1 A←(R1)
ADDA R2 A←(A)+(R2)
STAA R3 R3←(A)
La ventaja de diseñar una UP con instrucciones de tres direcciones es que los
programas resultarán más cortos; como contrapartida, la UP será más compleja y
ocupará más área de silicio en el chip. Por otra parte, las instrucciones de una
sola dirección serán más pequeñas, la UP será más simple, pero el sistema será
globalmente más lento, pues habrá que emplear en general más instrucciones,
como acabamos de ver. Por motivos tecnológicos o económicos (ocupación de
área de silicio), muchos microprocesadores de 8 bits incorporan instrucciones de
una sola dirección (o poseen arquitectura basada en acumulador), mientras que
otros más potentes incorporan instrucciones de tres direcciones.
Otras formas de mejorar las prestaciones de una UP consisten en introducir
varios acumuladores, más registros de propósito general o incluso una pequeña
memoria local (interna). Por supuesto, recurrir a bloques ALU de 16 o de 32 bits,
o unidades de punto flotante, representa un drástico aumento en sus prestaciones.

2.5.2. Unidad de control (UC)


La unidad de control o UC se encarga de controlar el funcionamiento de la
totalidad del sistema; en particular, deberá buscar en memoria la siguiente
instrucción a ejecutar, cargarla en un registro interno, decodificarla y generar las
órdenes que permitan su ejecución. La UC se compone de las siguientes partes:
a) Decodificador, sistema combinacional que decodifica la instrucción que se va
a ejecutar e informa del tipo de instrucción a un segundo módulo, el
secuenciador.
b) Secuenciador, circuito secuencial que implementa la máquina de estados del
sistema. A partir del resultado de la decodificación de la instrucción, genera
de una forma ordenada en el tiempo las señales que permiten ejecutar la
instrucción en curso (señales que seleccionan los registros internos adecuados
o indican la dirección de memoria cuyo dato se va a tomar, comunican a la
ALU el tipo de operación que ha de ejecutar, etc.).
c) Registros. Incluyen un contador de programa o PC (Program Counter), que
almacena la dirección de memoria donde se encuentra la siguiente instrucción
a ejecutar, y un registro de instrucciones o IR (Instruction Register), donde la
58 Microprocesadores y microcontroladores

UC carga el código de operación de la instrucción en curso cuando la lee de


memoria (cada instrucción viene representada por un número binario
denominado de esta manera). Puede incluir además otros registros auxiliares
o temporales, que sirven para el almacenamiento temporal de operandos, o
direcciones de operandos, como, por ejemplo, el registro de direcciones o AR
(Address Register), en el que se guarda la dirección efectiva que se enviará por
el bus de direcciones externo, y el registro de datos o DR (Data Register),
conectado al bus de datos, que en primera instancia recibe de él un dato o lo
envía. Estos registros son necesarios para el funcionamiento de la CPU, pero
no son directamente accesibles al usuario. En un µP de 8 bits los códigos de
operación y datos suelen ser de 8 bits, mientras que las direcciones suelen ser
de 16 bits (abarcando, por tanto, un espacio de 64 Kbytes de memoria, de la
0000 a la FFFF, en hexadecimal), por lo que los registros que trabajan con
datos suelen ser de 8 bits (acumulador, IR, DR) y los de direcciones de 16 (PC,
AR) (no obstante, microprocesadores de 8 bits más potentes incluyen registros
de datos de 16 bits).
La UC puede realizarse cableada o microprogramada. En las UC cableadas,
la UC es un circuito electrónico cuyo secuenciador, realizado con puertas y
biestables, se ha diseñado directamente a partir del grafo de estados de la máquina
siguiendo las técnicas ya conocidas de diseño digital [Pollán 94]. El problema de
esta forma de realización de la UC reside en su gran complejidad de diseño y en
las dificultades que aparecen si se plantea algún tipo de modificación en él, como
pueda ser incorporar nuevas instrucciones.
Estos problemas pueden resolverse realizando la UC microprogramada. En
este caso, existe una ROM de control dentro del secuenciador, la cual contiene en
los registros que la componen el valor de las señales (ceros y unos) que se deben
generar para cada instrucción en cada instante de tiempo. Esta ROM interna de la
CPU es completamente transparente para el usuario (no se debe confundir con la
pastilla de ROM externa, conectada a los buses del sistema, pues no tiene nada
que ver), y su contenido constituye el microprograma o firmware (por oposición
al hardware, o sistema físico, y al software, o programa almacenado en memoria
externa). En ocasiones el tamaño de esta ROM es tan grande que se sustituye por
dos bloques de ROM diferenciados, uno de las cuales contiene «micro-rutinas»
compartidas por muchas instrucciones, de modo que la «micro-ROM» principal
para ejecutar una instrucción simplemente debe realizar llamadas a la segunda
«nano-ROM»; este esquema se denomina nanoprogramación [Tanenbaum 92].
Componentes del sistema microprocesador 59

FIGURA 2.14. Esquema de la unidad de control.

En resumen, una UC cableada será difícil de diseñar, pero muy compacta y


rápida, mientras que una UC microprogramada (o nanoprogramada) será más fácil
de realizar, pero ocupará mucho más espacio de silicio y será más lenta. Por estas
razones, en los microprocesadores cuyo cometido es realizar un gran número de
operaciones a la máxima velocidad suelen emplearse UC cableadas (el ejemplo
típico son los denominados microprocesadores RISC), mientras que en
microprocesadores con cometidos más «modestos», o simplemente porque la
complejidad del diseño no permite otra opción, se suele emplear la
microprogramación. En la primera época de los µP, todas las UC eran
microprogramadas, puesto que incluían un elevado número de instrucciones (60,
70, 100...) que hacían inviable la construcción de UC cableadas; estos
microprocesadores se denominaban CISC (Complex Instruction Set Computer). A
mitad de los años ochenta se introdujeron las arquitecturas RISC (Reduced
Instruction Set Computer), en las que se incluía un reducido número de
instrucciones, lo que permitía la realización de las UC cableadas, ocupando menos
tamaño y elevando enormemente la velocidad de operación. Los clásicos 6800,
80x86 y 68000, y buena parte de los microcontroladores, son de tipo CISC,
mientras que los µP más modernos, como PowerPC, Sparc o ALPHA, son de tipo
RISC (el Pentium puede considerarse un híbrido). Las características que
diferencian los microprocesadores RISC y los CISC se estudiarán con mayor
amplitud en el capítulo final del libro.
60 Microprocesadores y microcontroladores

2.6. Funcionamiento global del sistema: ciclo


carga/ejecución
En este apartado estudiaremos el funcionamiento global de un sistema
microprocesador, que incluye CPU (UC más UP) y memoria central, y que
responde al esquema de máquina de von Neumann estudiado. La CPU es el
órgano encargado de ejecutar las instrucciones de programa almacenadas en
memoria: en primer lugar debe acudir a memoria y cargar la instrucción, para a
continuación ejecutarla; esto constituye el clásico ciclo carga/ejecuta
(fetch/execute). Pero antes de proseguir, expongamos una primera idea de en qué
consiste una instrucción de programa.
Una instrucción posee dos partes diferenciadas, un código de operación u
opcode (operation code), y quizás uno o varios operandos. El código de
operación es un conjunto de bits que representa una instrucción (cargar un dato en
cierto registro, leer una posición de memoria, sumar el contenido de dos registros,
etc.). A continuación del opcode, y si la instrucción lo requiere, aparecen los
operandos o la dirección de memoria donde los operandos se encuentran (los
operandos se proporcionan de una forma o de otra dependiendo del modo de
direccionamiento que se emplee, como estudiaremos más adelante).

a) b)
casilla de memoria
IR opcode y contenido
dirección

DR dato (8 bits)
14 1000

A (acumulador) dato (8 bits) :

opcode B6 2000 LDAA 1000


PC 20 00 dirección H 10 2001
dirección L 00 2002
PCH PCL
opcode 7E 2003 JMP 2007
dirección H 20 2004
AR dirección (16 bits)
dirección L 07 2005
ARH ARL 2006
2007

FIGURA 2.15. a) Registros de la CPU: de instrucciones IR, auxiliares DR y AR, acumulador A y


contador de programa PC (los sufijos H y L indican, respectivamente, parte alta (High) y baja (Low) de
un número de 16 bits). b) Memoria del µP conteniendo dos instrucciones de programa.
Componentes del sistema microprocesador 61

En un µP de 8 bits, el opcode suele ser un único byte, por lo que puede


disponer de hasta 256 instrucciones, y las instrucciones operan implícitamente con
el dato contenido en un registro acumulador A más otro dato adicional,
depositando el resultado en A. Por lo tanto, en la zona de memoria de programa
cada instrucción viene representada por un opcode (1 byte) más 1 o 2 bytes
adicionales que representan, bien el propio dato, bien su dirección. Por ejemplo,
la instrucción LDAA 1000 carga en el acumulador A (LoaD Accumulator A) el
dato contenido en la dirección 1000 (hexadecimal) de memoria (es decir, en este
caso no se da el operando, sino su dirección). En el caso del 6800, el código de
operación de esta instrucción en este modo de direccionamiento es B6 en
hexadecimal, de forma que la instrucción se aloja en memoria en tres casillas
consecutivas formando la secuencia B6 10 00, ocupando un total de 3 bytes (ver
fig. 2.15). Debe tenerse en cuenta que la CPU, en definitiva, no sabe de números
hexadecimales, sino de unos y ceros, de modo que para ella la instrucción descrita
es la secuencia 1011 0110 0001 0000 0000 0000.
Retornemos al objetivo de esta sección, explicar el proceso de ejecución de
instrucciones por un µP. Éste debe acudir a memoria y recoger la instrucción
para, una vez la ha depositado en un registro interno, ejecutarla. Este ciclo
carga/ejecución puede subdividirse en cuatro fases básicas: búsqueda del código
de operación de la instrucción, decodificación, carga de los operandos y
ejecución. Cada una de estas fases se subdivide a su vez en diversas acciones, que
pasamos a describir brevemente. Debe tenerse de nuevo en cuenta que, aunque
consideraremos un sistema microprocesador de 8 bits genérico, de modo que un
acceso a memoria consiste en enviar o tomar un grupo de 8 bits, los principios que
describimos representan la base de cualquier tipo de µP.
1) Búsqueda de la instrucción (fetch). La CPU acude a la dirección de memoria
apuntada por el PC para tomar el código de operación u opcode (operation
code) de la instrucción a ejecutar (supuesto de 8 bits). Dicho opcode será
depositado en el registro de instrucciones IR. Por último, se lleva a cabo el
incremento del PC, para que apunte ya a la siguiente casilla de memoria.
2) Decodificación. El bloque decodificador de la UC lee el opcode de la
instrucción, almacenado en el IR en la fase de búsqueda, y comunica al
secuenciador la instrucción de la que se trata y el modo de direccionamiento
(de dónde tomar los operandos) que utiliza.
3) Búsqueda de los operandos. Decodificada la instrucción, el bloque
secuenciador va marcando la secuencia de pasos a seguir para su ejecución
(activar la línea R/W, conectar un determinado registro al bus, indicar a la
62 Microprocesadores y microcontroladores

ALU la operación a realizar, etc.). En primer lugar, realizará la carga de los


operandos de memoria o de algún puerto de E/S, si la instrucción lo requiere.
4) Ejecución. Una vez los operandos están también en la CPU, se lleva a cabo la
ejecución de la instrucción y se almacena el resultado. Cada uno de los pasos
los marca el secuenciador.
Las dos primeras fases, búsqueda y decodificación, son comunes a todas las
instrucciones, las otras dos dependen de la instrucción concreta. Expondremos
como ejemplo los detalles de la ejecución de dos instrucciones, almacenadas en
memoria tal y como se muestra en la fig. 2.15 (recomendamos seguir el proceso
sobre la fig. 2.16). En este apartado nos hemos inspirado en [Silva 80].

2.6.1. Ejecución de la primera instrucción


El contador de programa PC contiene la dirección 2000 (supondremos
valores hexadecimales mientras no se diga lo contrario), por lo que la instrucción
alojada a partir de esa dirección será la próxima que la CPU ejecutará (fig. 2.15).
Dicha instrucción es la siguiente:
LDAA 1000 A←(1000)
Esta instrucción carga (LoaD) en el Acumulador A (LDAA) el contenido de
la casilla de memoria número 1000. En primer lugar, la CPU debe cargar el
opcode de la instrucción e incrementar el PC en uno para que apunte ya a la
siguiente casilla. El proceso de carga del opcode puede expresarse
detalladamente en lenguaje RTL de la siguiente manera:
a) BDir←(PC)
b) MAR←(BDir) comienza la lectura de memoria
c) MDR←((MAR)) el chip de memoria envía el opcode
d) BDat←(MDR), PC←(PC)+1 carga opcode y actualiza PC
e) IR←(BDat) carga opcode en el IR
pasos que pueden resumirse de la siguiente forma
IR←((PC)) , PC←(PC)+1
Estas cinco acciones son comunes a la ejecución de toda instrucción, pues
siempre el primer paso consistirá precisamente en cargarla de memoria. El
conjunto de acciones que conllevan la lectura o escritura de un dato de o en
memoria se denomina ciclo de bus.
Componentes del sistema microprocesador 63

FIGURA 2.16. Esquema global del sistema microprocesador, e ilustración de la fase de carga del
código de operación (pasos (a) a (e)) descrita en el texto.

A continuación se procederá a decodificar el opcode. El opcode informa


siempre sobre el tipo de instrucción y dónde se encuentra la información que
manejará, lo que se conoce por modo de direccionamiento. El decodificador
observa el valor B6, e indica al secuenciador que se trata de una instrucción de
cargar un dato de memoria en el acumulador A; la dirección de la casilla de
memoria se desconoce por el momento, pero del valor B6 se deduce también que
64 Microprocesadores y microcontroladores

se encuentra justo a continuación del opcode, en las casillas 2001 y 2002, por lo
que deberá buscarla y traerla por el bus de datos. Como el BDat es de 8 bits y la
dirección es de 16, deberá traerla en dos pasos, primero la parte alta H (high) y
luego la baja L (low). Este proceso de búsqueda de la dirección se llevará a cabo
de la siguiente manera para la parte alta de la dirección (recordemos que el PC
apunta ya a la casilla 2001):
f) BDir←(PC)
g) MAR←(BDir)
h) MDR←((MAR))
i) BDat←(MDR) , PC←(PC)+1
j) ARH←(BDat) Carga 10 en la parte alta de AR (reg. aux. direc.)
y el mismo proceso para la parte baja de la dirección:
k) BDir←(PC)
l) MAR←(BDir)
m) MDR←((MAR))
n) BDat←(MDR) , PC←(PC)+1
ñ) ARL←(BDat) Carga 00 en la parte baja de AR (reg. aux. direc.)
En este preciso instante el secuenciador sabe ya que el dato se encuentra
almacenado en la casilla 1000 de memoria (contenido del registro auxiliar de
direcciones AR=ARH:ARL). Procedería entonces a ejecutar la instrucción,
tomando el contenido de la casilla 1000 de memoria y depositándolo en A, para lo
que ejecutará los siguientes pasos
o) BDir←(AR) Toma del AR la direc. donde está el dato (1000)
p) MAR←(BDir) Lectura de memoria
q) MDR←((MAR))
r) BDat←(MDR)
s) A←(BDat) Carga dato en casilla 1000 (14) en el registro A

2.6.2. Ejecución de la segunda instrucción


El contador de programa apunta ya a la dirección 2003, por lo que ejecutará
la instrucción colocada a partir de allí (fig. 2.15). La CPU tomará el dato
almacenado, 7E, y al decodificarlo encontrará que se trata de una instrucción de
Componentes del sistema microprocesador 65

salto JMP (JuMP), que salta a la dirección de memoria colocada justo a


continuación, rompiéndose de esta manera la secuencia normal de ejecución. La
instrucción completa es:
JMP 2007 PC←2007
En este caso los pasos a seguir son, de nuevo, búsqueda del opcode,
decodificación, búsqueda de operando (dirección alta), búsqueda de operando
(dirección baja) y ejecución. Los cuatro primeros (pasos a) a ñ)) son comunes a la
instrucción anterior, mientras que en este segundo caso la fase de ejecución queda
simplemente:

o) PC←(AR)
2.6.3. Cuestiones finales (avanzadas)
En la literatura de organización de microprocesadores y computadores (ver,
p.e., [Aleksandridis 84, Stallings 97]) un acceso a memoria como los descritos se
denomina ciclo de bus o de máquina. Como hemos visto en el ejemplo anterior,
la ejecución de una instrucción implica varios ciclos de bus (accesos a memoria),
y cada uno de ellos comprende a su vez varios pasos más elementales, que se
denominan estados de la máquina. Un estado representa, visto desde fuera de la
CPU, la «unidad mínima de actividad de la máquina» (estados son «captura de
opcode», «acción de reset», «estado de interrupción», etc.), y todos tienen la
misma duración, un ciclo de reloj. Cada estado comprende a su vez la ejecución
de una o más microoperaciones, como las descritas en el apartado anterior.
Como hemos señalado, un ciclo de bus puede comprender uno o más estados,
por lo que distintos tipos de ciclos de bus («carga de instrucción», «lectura de
memoria», «lectura de un puerto de E/S», etc.) pueden tener una duración
diferente (uno o más ciclos de reloj, a menudo de 2 a 8). Por ejemplo, se tiene
que en el clásico 8086 un acceso a memoria comprende varios estados, cada uno
de un ciclo de reloj, con lo que cada acceso a bus requiere varios ciclos de reloj.
Por contra, en el caso del 6800 que estudiaremos a fondo a continuación (y
que ha inspirado la descripción realizada de la CPU genérica), ciclo de bus y
estado es lo mismo, por lo que un acceso a memoria se realiza en un solo ciclo de
reloj. En el 6800 se contemplan tan sólo tres tipos de ciclos de máquina: lectura
(la CPU toma un byte de memoria), escritura (la CPU lleva un byte a memoria) y
operación interrumpida (la CPU está ocupada y no accede a los buses).
66 Microprocesadores y microcontroladores

2.7. Juego de instrucciones del microprocesador


Dado un algoritmo que deseamos sea ejecutado por una máquina
programable (por ejemplo, un microprocesador), éste debe ser previamente
transformado en un conjunto de órdenes comprensibles por la máquina. La
secuencia de estas órdenes conforma el programa, y las transformación del
algoritmo en programa constituye el proceso denominado codificación o
programación. De alguna manera, el programa finalmente deberá ser transcrito a
números binarios («ceros y unos»), que es lo que realmente entiende la máquina.
Por otra parte, se denomina juego de instrucciones de una máquina
(instrucción set) al conjunto de órdenes ejecutables por ella, con las cuales pueden
codificarse algoritmos. Así, cada máquina (o µP) se caracteriza no sólo por una
estructura hardware (organización de la UP y de la UC, estructura de los buses,
sistema µP, etc.), sino también por el conjunto de instrucciones que puede
ejecutar. Los tipos básicos de instrucciones más habituales son:
a) Instrucciones de transferencia de información (cargar, almacenar...).
b) Instrucciones aritméticas (sumar, restar, ...) y lógicas (AND, OR...).
c) Instrucciones de control de programa (saltar, si/entonces...).
d) Instrucciones de entrada/salida (enviar, recibir...).
f) Instrucciones de control del hardware (detener, esperar, desconectar...).
Se debe tener presente que, aunque hagamos referencia a instrucciones
denotadas por un nombre simbólico (por ejemplo, ADDA 1000), la CPU
solamente es capaz de trabajar con ceros y unos, por lo que toda instrucción se
debe codificar de esta manera. Por ejemplo, la secuencia 1001 0101 podría
significar para cierta máquina «incrementar el registro acumulador», que
representaríamos mediante el mnemónico INCA, que nos resulta más fácil de
recordar que grupos de unos y ceros. Cuando escribimos con símbolos
mnemónicos se dice que estamos programando en lenguaje ensamblador
(assembler). Para que la máquina pueda comprender el programa, habrá que
traducirlo previamente a código binario o código máquina, es decir, a ceros y
unos. Esta acción de traducir se denomina compilar, aunque cuando se compila
código ensamblador se suele hablar de ensamblar, y el programa que se encarga
de realizar esta transformación suele denominarse también programa
ensamblador.
Todos estos aspectos relacionados con la programación del microprocesador
los comentaremos más extensamente en capítulos posteriores.
Capítulo 3
6800 y 68HC11

3.1. Introducción
Establecidos ya los conceptos generales de la estructura de un
microprocesador genérico de 8 bits y los elementos que componen el sistema, en
este capítulo trataremos el caso concreto del M6800, como ejemplo típico de un
microprocesador de 8 bits. Tras el 6800 estudiaremos el microcontrolador
M68HC11. Ambos microprocesadores son miembros de la famosa familia 68 (de
8 bits) de Motorola.
Antes de comenzar en materia nos gustaría realizar un comentario previo. En
la actualidad nunca se empleará un microprocesador de 8 bits como el 6800 (ni el
8085 o el Z80) para resolver una aplicación real; únicamente estudiaremos el
6800 por motivos pedagógicos, como medio de introducir al alumno en los
detalles del desarrollo de sistemas microprocesadores. En la práctica real se
empleará un microcontrolador como el 68HC11 (o el 6805, o el 8051, o un PIC),
mucho más moderno, potente y con memoria y periféricos integrados, que
simplifican enormemente el desarrollo de una aplicación relacionada con la
electrónica industrial o de consumo.

3.2. El microprocesador M6800


3.2.1. ¿Por qué estudiar el MC6800?
Recordemos que en 1971 Intel introdujo el primer µP, el 4004 (de tecnología
PMOS), que posteriormente dio paso al 8008, y éste al 8080. Intel fue la primera
casa fabricante de µP, pero otras compañías como Motorola, National, Texas, etc.,
pronto decidieron no quedarse atrás en relación a este nuevo producto de la
industria electrónica. Así, Motorola introdujo hacia 1975 su primer µP, el
M6800, aproximadamente un año después que Intel el 8080. Tanto el 6800, como
el 8080, 8085, Z80 y 6502, los más destacados de la mitad de los años setenta, son
denominados microprocesadores de segunda generación (NMOS).
Por lo tanto, el M6800 puede considerarse como un µP clásico (o antiguo,
según se mire), por lo que el lector puede formularse la siguiente pregunta, ¿por
68 Microprocesadores y microcontroladores

qué tomarlo como referente en un curso de µP si ha sido claramente superado por


los modernos potentes µP? Nosotros tenemos dos importantes razones:
a) Por motivos pedagógicos, pues su sencillez, simplicidad y linealidad, facilita
una primera aproximación de un alumno de electrónica al mundo de los µP.
Estudiando en detalle el M6800 y los sistemas basados en él, el estudiante
podrá comprender con facilidad la mayor parte de las «grandes cuestiones» del
diseño con µP. No obstante, debe tenerse muy en cuenta que cuando uno deba
montar en la práctica un sistema µP no utilizará un M6800: si se trata de
construir un sistema de procesamiento (como un computador), se hará uso de
µP más modernos y potentes (desde los 80x86 y Pentium, a los de la familia
68K y PowerPC), y, si se debe construir un sistema electrónico específico (más
habitual en electrónica industrial), se deberá recurrir a un microcontrolador.
b) El M6800 es el «padre» de la familia 68 de microcontroladores de 8 bits de
Motorola, la de más amplio uso en el mundo, de modo que aprendiendo sus
características hardware y software, además de aprender y comprender el
funcionamiento de un sistema µP, estaremos preparando el camino para el caso
de los microcontroladores (más interesante para nuestros objetivos). Por
ejemplo, las muy conocidas familias 6805 y 68HC11 de µC de Motorola
resultan ser derivados directos del 6800, compartiendo toda su línea de
circuitos periféricos, y manteniendo una alta compatibilidad software (los
juegos de instrucciones son muy similares; en el caso particular del 6800 y del
68HC11, el repertorio del primero es un subconjunto del segundo).
Para completar la visión de la familia de microprocesadores y
microcontroladores de Motorola, diremos que el conocido 68000 y toda la familia
denominada 68K (68020, 68030, 68040, etc.) son descendientes más lejanos del
6800. A finales de los setenta, cuando se iniciaba la nueva generación de
microprocesadores de 16 bits, Motorola realizó una fuerte apuesta al introducir el
68000, que, para hacer un mejor aprovechamiento de las nuevas tecnologías y
logros arquitecturales, se diseñó rompiendo totalmente con la familia 68. Ello
choca frontalmente con la orientación de otras casas, como Intel, que defendiendo
la compatibilidad a ultranza lastran de una manera importante los nuevos diseños
con «el peso de la historia».

3.2.2. Generalidades del M6800


Se trata de un típico microprocesador de 8 bits, implementado en tecnología
NMOS y comercializado hacia 1975. Se presenta en un encapsulado DIP de 40
patillas (de señales compatibles TTL), y se alimenta con una fuente de +5 voltios.
Su frecuencia máxima de reloj es de 1 MHz; debido al almacenamiento dinámico
6800 y 68HC11 69

de datos que utiliza, sus registros internos deben ser refrescados periódicamente,
por lo que se exige que siempre opere a una frecuencia superior a 0,1 MHz. Otras
versiones permiten trabajar a frecuencias más altas, p.e., el MC68A00 puede
operar hasta a 1,5 MHz, y el MC68B00 alcanza los 2 MHz.
Estas frecuencias de reloj no deben llevar a engaño, pues, aunque algunos
microprocesadores de similares características, como el Z80 o los de Intel,
trabajan a frecuencias sensiblemente más altas (varios MHz), el 6800 lleva a cabo
un ciclo de bus (una lectura o escritura en memoria) en un solo ciclo de reloj,
mientras que, por ejemplo, el Z80 precisa de 3 o 4 ciclos de reloj, por lo que la
velocidad efectiva de un 6800 a 1 MHz es similar a la de un Z80 a 4 MHz.
El M6800 posee 8 líneas de datos y 16 líneas de direcciones, por lo que
puede direccionar un espacio de memoria de 64K bytes. Posee 7 modos de
direccionamiento y 72 instrucciones de diferentes longitudes, compuestas por lo
menos por un código de operación de 8 bits, pudiendo incluir a continuación un
dato o dirección de 8 o 16 bits (por lo tanto, una instrucción puede incluir en total
uno, dos o tres bytes). Opera en aritmética entera de 8 bits en complemento a dos
y, a diferencia de otros (como los de la familia Intel), el 6800 es un µP con pocos
registros, realizando muchas de las operaciones directamente sobre datos de
memoria, apoyándose en uno de sus dos registros acumuladores A y B.

3.2.3. Organización del MC6800


Estudiaremos a continuación los dos bloques que componen el
microprocesador M6800, unidad de control y unidad de procesamiento (fig. 3.1).
Se recomienda la consulta de las hojas de características proporcionadas por
Motorola para profundizar en los detalles (ante la duda, y salvo esporádicos
errores, las hojas de características proporcionadas por el fabricante suelen
constituir la información más fiable).
1) La unidad de control incluye:
• Contador de programa PC (Program Counter, 16 bits). El PC indica la
dirección de memoria donde se encuentra la próxima instrucción a ejecutar.
• Registro de instrucciones IR (Instruction Register, 8 bits). Es el lugar donde
se almacena el código de operación (de 8 bits) de la instrucción a ejecutar.
• Decodificador y secuenciador, que responde a las características descritas en el
capítulo 2.
70 Microprocesadores y microcontroladores

FIGURA 3.1. Diagrama interno del M6800 y patillas.

2) La unidad de procesamiento incluye:


• ALU de 8 bits complemento a dos, con capacidad de suma, resta, operaciones
lógicas convencionales (AND, OR, etc.) y desplazamiento de registros.
• Dos registros acumuladores de propósito general A y B (8 bits), que muchas
instrucciones utilizan implícitamente para realizar operaciones.
• Registro índice IX (IndeX, 16 bits), o simplemente X, que se puede utilizar
para almacenar un dato de 16 bits, o bien almacena una dirección de memoria,
tomando el papel de puntero de memoria, y que es empleado en el modo de
direccionamiento indexado para el manejo de tablas de datos o matrices.
• Puntero de pila SP (Stack Pointer, 16 bits), que indica el lugar dentro del
mapa de memoria donde se encuentra el primer registro libre de la pila del
sistema. La pila debe situarse siempre en una zona de memoria de acceso
aleatorio con posibilidad de lectura y escritura (RAM).
• Registro de estado CCR (Condition Code Register, 8 bits), cuyos bits
individuales indican con un ‘1’ o un ‘0’ distintas condiciones que se han
6800 y 68HC11 71

producido en una operación lógico-aritmética. En el CCR del 6800 los bits 6 y


7 no se emplean, permaneciendo siempre a ‘1’; el resto posee nombres propios
con distinto significado, que exponemos brevemente a continuación (los
trataremos más ampliamente en el capítulo 4):
C (Carry), se activa cuando se produce acarreo en una suma (carry), o
préstamo (borrow) en una resta.
V (oVerflow), indica desbordamiento en una suma interpretada como
complemento a dos.
Z (Zero), se activa (Z=‘1’) cuando el resultado de una operación es 0.
N (Negative), indica que se ha producido un resultado negativo.
I (Interrupt mask), este bit no indica circunstancia alguna sobre
operaciones lógico-aritméticas, sino que actúa como máscara de la
interrupción enmascarable IRQ, de modo que si I=‘1’ se inhabilita la
aparición de este tipo de interrupción (se «enmascara»).
H (Half-carry), o «acarreo a la mitad», indicando que en una suma se
ha producido un acarreo entre los bit 3 y 4, es decir, entre los dos
nibble que componen un byte (recordemos que se denomina nibble a
una agrupación de 4 bits, de la misma forma que byte son 8). Se
emplea en la conversión de datos binarios a BCD.
• Buffer triestado del bus de direcciones (16 bits), conectado al registro auxiliar
de direcciones AR, almacena temporalmente direcciones de 16 bits que se
envían al bus. Es transparente para el programador.
• Buffer triestado del bus de datos (8 bits), conectado al registro auxiliar de
datos DR, almacena temporalmente los datos que se envían al bus o recibe de
él. Es transparente para el programador.
• Bus interno. Por el que circula la información en el interior del µP.
En la fig. 3.2 se muestra el denominado modelo para el programador del
6800, o conjunto de registros a los que el programador del sistema tiene acceso, el
PC, SP, A, B, IX, y CCR en el caso del 6800, los cuales determinan
completamente el estado de la CPU en un instante dado. El resto de los registros,
como el de instrucciones IR, o los auxiliares AR y DR, aunque imprescindibles
para el funcionamiento de la CPU, resultan completamente transparentes para el
programador (no pueden ser manipulados).
72 Microprocesadores y microcontroladores

SP

PC

CCR 1 1 H I N Z V C

FIGURA 3.2. Registros del M6800 accesibles al programador («modelo del programador»).

3.2.4. Patillaje del MC6800


El MC6800 posee 40 pines (fig. 3.3), divididos en líneas de direcciones,
datos, control y alimentación; parte de ellas constituirán los buses del sistema. El
papel del bus de datos y el de direcciones ya es bien conocido. Por su parte, las
líneas del bus de control gobiernan la transferencia de datos a través del bus de
datos, permiten ceder el control del bus a dispositivos externos (DMA) o
gestionan las interrupciones causadas por los periféricos del sistema. Pasamos a
describir las patillas del M6800 con cierto detalle:
• A0-A15 (Address), líneas de direcciones (salidas). Dieciséis líneas que
constituyen el bus de direcciones del sistema, que permiten direccionar hasta
216=64 Kbytes.
• D0-D7 (Data), líneas de datos (bidireccionales). Constituyen el bus de datos
de 8 bits del sistema. Son bidireccionales, permitiendo la lectura o escritura de
datos.
• R/W (Read/Write), línea de lectura/escritura (salida), indica el sentido de las
señales que circulan por el bus de datos.
• VMA (Valid Memory Address), dirección válida de memoria (salida). Indica
con un ‘1’ que se ha colocado una dirección de memoria en el bus de
direcciones, marcando así el comienzo de una transferencia de datos, actuando
como una línea de petición de datos durante una lectura, o de datos preparados
durante una escritura (en el capítulo anterior la denominábamos genéricamente
VAL).
6800 y 68HC11 73

• φ1 y φ2, son las entradas del reloj. El M6800 precisa de un reloj de dos fases
no solapadas (fig. 3.4), que serán generadas por un circuito externo de reloj.
Una versión posterior denominada 6808 incorporaba CPU y circuito de reloj
(éste no debe confundirse con el moderno microcontrolador 68HC08).
• /HALT y BA (Bus Available), líneas de alto (entrada) y bus disponible (salida).
Son líneas de petición y confirmación de DMA, respectivamente. Cuando un
dispositivo externo quiere realizar una DMA, activa la línea /HALT
(/HALT=‘0’), el µP, al reconocer la solicitud de DMA, y una vez ha concluido
la ejecución de la instrucción en curso (por lo que puede demorarse varios
ciclos de reloj), pone en alta impedancia las líneas VMA y R/W, y activa la
línea de «bus disponible» BA (BA=‘1’), indicando al dispositivo solicitante
que puede tomar el control del bus del sistema.
• TSC (Tri-State Control) y DBE (Data Bus Enable), entradas de control tri-
estado y de habilitación del bus de datos. Cuando se activa TSC, las líneas de
direccionamiento y R/W se ponen en alta impedancia. DBE cumple el mismo
papel para el bus de datos, de modo que es necesario mantener DBE activa
para que las líneas de datos permanezcan habilitadas, por lo que en operación
normal debe mantenerse conectada a φ2. TSC y DBE también intervienen en
ciertas operaciones de DMA.
• /IRQ (Interrupt ReQuest) y /NMI (Non-Maskable Interrupt), líneas de solicitud
de interrupción enmascarable y no enmascarable (entradas). Cuando un
dispositivo periférico activa la interrupción enmascarable (/IRQ=‘0’), si I=‘0’,
se ejecuta su rutina de servicio. /NMI se suele reservar para responder a
condiciones de emergencia, como, por ejemplo, fallos en la alimentación.
/IRQ es sensible a niveles, /NMI a flancos.
• /RESET, entrada de reset. Sirve para arrancar o iniciar el microprocesador,
colocando a cero sus registros, y cargando en el PC los dos bytes almacenados
en las casillas $FFFE y $FFFF, los cuales representan la dirección donde se
encuentra la primera instrucción a ejecutar (en la nomenclatura empleada por
Motorola el símbolo ‘$’ indica que un número es hexadecimal, y ‘%’ binario).
• Vss (dos pines) y Vcc. Líneas de tierra y alimentación (+5 voltios).
• Existen dos patillas adicionales no conectadas (aparecen como N.C. en las
hojas de características).
Remitimos al lector interesado en más detalles a las hojas de características
del M6800 [Motorola 75, 76].
74 Microprocesadores y microcontroladores

FIGURA 3.3. Patillaje del microprocesador M6800 (formato DIP-40).

FIGURA 3.4. Las dos fases de reloj (no solapadas) del M6800.

3.3. Sistemas basados en el M6800


En esta sección estudiaremos cómo construir sistemas basados en el M6800.
Para ello, deberá tenerse en cuenta que la capacidad de carga del M6800 es
limitada, por lo que existe un límite en el número de dispositivos que pueden
conectarse a él (sus buses pueden proporcionar una corriente de alrededor de 2
mA tan sólo). En este sentido, denominaremos sistema mínimo a aquel que
cuenta con un número de elementos tal que no se superan las limitaciones de
6800 y 68HC11 75

carga de la CPU, de modo que no es necesario introducir amplificadores (buffers)


en los buses del sistema.
Hablando en términos generales (cada línea presenta sus particularidades
[Motorola 76]), podemos decir que la limitación en la carga del 6800 se cifra en
unos 130 pF, más una carga TTL estándar (o 4 de tipo LS). Así, un sistema
mínimo basado en un M6800 puede incluir entre 7 y 10 pastillas MOS,
dependiendo de la capacidad eléctrica concreta que aporte cada una a los buses
(unos 10 µA y 10 pF son valores típicos): por ejemplo, tres pastillas RAM, dos
ROM, dos adaptadores paralelos PIA 6821 (Peripheral Interface Adapter; como
veremos más adelante, cada uno con dos puertos paralelos) y un puerto serie
ACIA 6850 (Asyncrhronous Communications Interface Adapter, adaptador
asíncrono de tipo UART). Se debe tener presente que si bien en todo momento
hay un dispositivo que coloca datos en el bus (por ejemplo, el microprocesador) y
uno que los recoge (por ejemplo, una pastilla de memoria), aunque el resto de los
circuitos permanecen en situación de alta impedancia, siguen presentando cierta
capacidad eléctrica de entrada y cierta corriente de fugas, por lo que siguen
representando una carga sobre el bus; por ello, debe sumarse la carga de todos los
dispositivos conectados a los buses, incluidos los que se mantienen en alta
impedancia. En el capítulo 7 se tratará este asunto en mayor profundidad.

3.3.1. Ejemplo de sistema mínimo. Realización circuital de un mapa


de memoria
Consideraremos a continuación un sencillo ejemplo de desarrollo de un
sistema mínimo, lo cual ilustrará cómo deben conectarse todas las líneas del 6800.
En primer lugar, el M6800 se alimenta mediante una fuente de 5 voltios; sus dos
pines Vss deben colocarse a tierra y el Vcc a +5 V. Como se tratará de un sistema
sencillo, sin capacidad de DMA (acceso directo a memoria; se estudiará en el
capítulo 6), deberá conectarse la patilla TSC a tierra (líneas de direcciones y R/W
siempre habilitadas), y la /HALT a +5 V (petición de DMA inhibida); por su
parte, DBE se conectará a la fase φ2 del reloj (dicha fase vale ‘1’ siempre que el
6800 accede a memoria, por lo que el bus de datos debe estar habilitado justo
entonces), y la salida BA no se empleará, por lo que puede dejarse al aire. Estas
conexiones, mientras no se requiera DMA, deben realizarse siempre de la manera
indicada.
Las líneas de reset e interrupción, /RESET, /IRQ y /NMI, normalmente deben
mantenerse en estado alto (inactivas), por lo que se conectarán a +5 V por medio
de una resistencia de unos 4 K7 (como recomienda el fabricante).
76 Microprocesadores y microcontroladores

FIGURA 3.5. Circuito generador de reloj MC6870A de Motorola (dos fases de 2MHz; incluye cristal
de cuarzo y circuitería).

El M6800 no incluye en la pastilla circuito de reloj; para generar las fases


debe emplearse un circuito de la familia como el MC6870A (fig. 3.5), que en un
único encapsulado incluye el cristal de cuarzo y la circuitería necesaria para
generar las dos fases del reloj φ1 y φ2 (NMOS), que pueden conectarse
directamente al M6800, así como una φ2 adicional compatible TTL, que
convenientemente amplificada se envía al sistema (se trata de una señal crítica,
que debe llegar con suficiente «fuerza» a todos los dispositivos). La fase φ2 en
ocasiones se denomina reloj E, siendo la que se emplea como reloj del sistema
microprocesador, para la sincronización de las lecturas y escrituras en memoria o
puertos (acciones que se ejecutan cuando E=‘1’, es decir, en su fase activa).
En definitiva, los buses del sistema 6800 quedarán constituidos como sigue:
a) Bus de datos, por las líneas D0 a D7.
b) Bus de direcciones, por las líneasA0 a A15.
c) Bus de control, por las líneas de reloj φ1 y φ2, línea de validación de
direcciones VMA, y línea de lectura/escritura R/W.
Pasaremos a continuación a describir la conexión de memorias y puertos a los
buses (fig. 3.6). Como ya es sabido, normalmente los requisitos de memoria de
un sistema hacen necesaria la inclusión de varias pastillas (p.e., un chip de ROM y
otro de RAM), cada una de las cuales estará colocada en una determinada
posición dentro del mapa de memoria. Por lo tanto, la primera tarea consiste en
proponer un mapa de memoria, es decir, la distribución de los distintos elementos
de memoria (RAM, ROM, puertos de E/S, etc.) dentro del espacio de direcciones
total. Recordemos que en la familia 68 de Motorola, y a diferencia de lo que
sucede con los µP de Intel, las E/S están mapeadas en memoria, es decir, el
espacio de memoria es compartido tanto por las pastillas de memoria como por
los puertos de E/S.
Supongamos que incluimos la pastilla de RAM estática de 128 bytes
denominada 6810. Recordemos que cada chip de RAM de 2n×8 bits posee un
6800 y 68HC11 77

conjunto de n líneas de direccionamiento, de A0 a A(n−1), donde n será menor


que el número de líneas del bus de direcciones del sistema; en nuestro caso, se
tienen 7 líneas, A0-A6, número menor que 16. Además, la 6810 incluye 8 líneas
de datos, D0 a D7, una línea de lectura/escritura R/W (otras pastillas poseen dos
líneas, una de habilitación de escritura /WE, y otra de lectura /OE) y 6 líneas de
selección de chip CS, unas activas en alto y otras en bajo, pero todas ellas deberán
mantenerse activadas para que la pastilla quede seleccionada (en otras pastillas de
memoria existe una única línea de selección, denominada CS o CE).
La conexión a los buses del sistema se lleva a cabo de la siguiente manera.
Cada una de las 8 líneas de datos D0 a D7 se conectarán directamente al bus de
datos, mientras que el pin R/W será la línea del mismo nombre incluida en el bus
de control; debido a que muchas pastillas de memoria disponen de entradas /WE y
/OE (en vez de R/W), estas dos pueden generarse directamente de la R/W y del
reloj E (φ2) siguiendo el esquema ya conocido (fig. 3.7).

FIGURA 3.6. Sistema basado en el M6800.


78 Microprocesadores y microcontroladores

Normalmente, las n líneas más bajas del bus de direcciones se conectan a los
terminales A0 a A(n−1) de cada pastilla, y el resto servirán de entradas al
decodificador de direcciones del sistema, cuya salida se encargará de activar las
líneas de selección de cada chip solamente cuando en el bus de direcciones
aparezca alguna de las direcciones que han sido asignadas a la pastilla concreta.
Como es bien sabido, el decodificador de direcciones es un bloque
combinacional, que para el caso de sistemas con un pequeño número de elementos
(uno o dos) se suele construir haciendo uso de simples puertas lógicas, mientras
que, si se debe seleccionar un número mayor de elementos (por ejemplo, ocho),
suele emplearse un decodificador integrado, como los 74138, 74139 y 74154.
Por otro lado, algunas pastillas poseen varias líneas de selección /CS o /CE, que
pueden ser empleadas para la decodificación ahorrando puertas o incluso todo el
bloque decodificador. También para simplificar la circuitería suele realizarse una
decodificación parcial (sobre un número reducido de líneas de direcciones), como
se comentó ya en el capítulo anterior, aunque deberá tenerse en cuenta que en este
caso a cada registro le corresponderá más de una dirección en el mapa de memoria
(lo cual no tiene por qué causar problemas).
Aunque podía haberse realizado la decodificación directamente con puertas,
en el diagrama de la fig. 3.6 se ha empleado un esquema de decodificación parcial
basado en un 74138, para así ilustrar la situación más habitual. El 74138 dispone
de tres entradas de habilitación, G1, /G2A y /G2B (todas deben ser activadas), y
tres entradas, A, B y C, que permiten seleccionar uno de 8 dispositivos (salidas de
selección activas en bajo).
Para completar el cuadro debe tenerse presente que la selección de una
pastilla de memoria en un sistema microprocesador solamente debe hacerse
efectiva cuando tanto en el bus de direcciones como en el de datos las señales
presentes sean válidas. En el M6800 esta situación se corresponde con que la fase
φ2 del reloj esté activa (fase en la que se realizan los accesos al exterior) y que la
señal VMA (dirección de memoria válida) esté también en alto. Por lo tanto,
ambas líneas, φ2 y VMA, deben utilizarse también para seleccionar una pastilla de
memoria (o, en general, cualquier dispositivo conectado al bus, como pueda ser
un puerto de E/S), de modo que, si suponemos una única patilla de habilitación
/CS, la condición de selección de chip será la siguiente:

CS = VMA. φ 2. DIR
siendo DIR una hipotética línea de salida de un bloque decodificador de
direcciones, que valdrá ‘1’ cuando la dirección presente en el bus se corresponda
6800 y 68HC11 79

con alguna de las asignadas al chip en el mapa de memoria (en la práctica, los
decodificadores de direcciones suelen enviar señales activas en ‘0’).
Finalmente, obsérvese que en la fig. 3.6 la señal φ2 de tipo TTL que parte del
circuito generador de reloj se amplifica antes de ser llevada al resto de los
circuitos del sistema (φ2 amplificada suele denominarse reloj E). Por su gran
importancia, queremos remarcar que ésta es una práctica habitual para que la
señal de reloj, de papel fundamental en la sincronía de los elementos del sistema,
llegue con suficiente «fuerza» a todos los integrados, y que además impida la
posible transferencia de ruido, sobreoscilaciones o cualquier otra perturbación
desde el sistema al microprocesador.
Con todos los datos ya sobre la mesa, procedamos a la conexión de una
pastilla de 128 bytes de RAM (6810), otra de 2 K EPROM (2716) y un adaptador
paralelo PIA 6821 (que incluye cuatro registros, seleccionables con las líneas RS0
y RS1, es decir, equivale a efectos de decodificación a una pastilla de 4
direcciones de memoria). Por los motivos que estudiaremos algo más adelante, la
RAM de un sistema 68 usualmente se coloca en la parte baja del mapa de
memoria (a partir de la dirección 0, o $0000 en hexadecimal), la ROM/EPROM
en la parte alta (hasta la última casilla de memoria, la 65536 o $FFFF), y los
puertos de entrada/salida en zonas intermedias. Por lo tanto, podemos proponer el
siguiente mapa de memoria:

Dirección A15 A14 A13 A12 A11 A10 A9 A8 A7 A6 A5 A4 A3 A2 A1 A0

RAM 0000 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
007F 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1
PIA 8000 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
8003 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1
ROM F800 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0
FFFF 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1

Para discriminar tres elementos (RAM, EPROM, PIA), bastan dos líneas de
direcciones; del esquema anterior seleccionamos A15 y A14, cuyas
combinaciones 00, 10 y 11 permiten distinguirlos (decodificación parcial). Estas
dos líneas, por lo tanto, serán las entradas del bloque decodificador. Si utilizamos
80 Microprocesadores y microcontroladores

un 74138, por lo tanto conectamos A14 a la entrada menos significativa A, A15 a


la B, y conectamos la C a tierra. En consecuencia, la selección de los tres
elementos se realizará con las salidas indicadas en la fig. 3.7.
Pero la selección de los chips de memoria y puertos solamente debe llevarse a
cabo cuando VMA y E valgan ‘1’; por lo tanto, estas señales deben participar en
la decodificación. Para ello utilizaremos las entradas de habilitación del 74138 de
la manera indicada en la fig. 3.7; así cualquier pastilla o puerto quedará
seleccionado sólo cuando se coloque su dirección en el bus y VMA=‘1’ y E=‘1’.
Por último, ahora podremos comprender fácilmente que, al realizar una
decodificación parcial (dos líneas en nuestro caso), un mismo registro puede ser
habilitado mediante diversas direcciones; p.e., el chip EPROM quedará
seleccionado si se coloca una dirección comprendida entre $F800 y $FFFF, como
se deduce del mapa, pero también con una dirección entre $C800 y $CFFF o
$E800 y $EFFF (recordemos de nuevo que ‘$’ indica número hexadecimal).

Conviene tener presente que...


• La decodificación debe ser tal que nunca haya más de un chip de memoria o
puerto seleccionados a la vez. Siempre habrá un solo dispositivo que coloque
datos en los buses, y normalmente uno sólo que los lea.
• Las lecturas y escrituras solamente pueden llevarse a cabo durante la fase
activa de φ2, estando además VMA en estado alto.

FIGURA 3.7. Ejemplo de decodificación de direcciones y selección de chips de memoria y puertos.


6800 y 68HC11 81

Nota (nivel avanzado). ¿Qué sucede si no se emplea VMA en la selección de una


pastilla de memoria o puerto? En las siguientes situaciones concretas acarrearía
lecturas o escrituras erróneas, o pérdida de atención a interrupciones: a) Si se
activan las líneas /HALT o TSC, o se ejecuta una instrucción WAI, las líneas de
direcciones y R/W quedan flotantes, por lo que el 6800 pone VMA a ‘0’ para
evitar escrituras erróneas; por lo tanto, si no se ha utilizado VMA en la
decodificación de una RAM o de un puerto, pueden efectuarse escrituras erróneas
en ellas en estos casos (en una ROM no habría problemas). b) Cuando el 6800
ejecuta operaciones internas sin acceder a los buses, hay períodos de reloj en los
que los buses de direcciones y datos permanecen en alta impedancia, por lo que el
6800 mantiene R/W a ‘1’ para evitar escrituras falsas, pero se pueden producir
lecturas erróneas y, como veremos, al leer el registro de un puerto como la PIA, se
borran los señalizadores de interrupciones, con lo que algunas interrupciones
pueden quedar desatendidas (en la PIA 6821 existe una línea para el reloj E, y
suele emplearse una de las tres de selección de chip para VMA; no se recomienda
actuar directamente con una señal E.VMA ya que durante una situación de «alto»,
/HALT=‘0’, VMA se mantiene a ‘0’, con lo que la PIA no recibe reloj alguno y,
por ejemplo, no reconocería interrupciones, que se perderían).
En resumen, aunque conviene que en la selección de memoria y puertos
intervengan tanto E como VMA, si se obvia una señal, por ejemplo, VMA, sólo
aparecen problemas en situaciones muy concretas.

3.3.2. Cronogramas de lectura y escritura


En esta sección estudiaremos la forma en la que el 6800 realiza las lecturas y
escrituras en memoria (o puertos de E/S). Los accesos a memoria vienen
sincronizados por las dos fases de reloj: cuando el reloj φ1 está activo, la CPU
prepara el acceso a memoria, y, cuando el activo es φ2 (E), se lleva a cabo la
lectura o escritura efectiva del dato. El denominado ciclo de bus, un acceso a
memoria, comprende en el 6800 un único ciclo de reloj (1 microsegundo
trabajando a 1 MHz).
Los pasos que el 6800 lleva a cabo para ello se muestran en la fig. 3.8. En los
cronogramas presentaremos las señales lógicas con cierta inclinación, indicando
así los tiempos de subida (bajada), es decir, el tiempo que le cuesta a la señal
alcanzar el estado ‘1’ (‘0’) (nanosegundos). Los buses los representaremos con
dos líneas paralelas que cambian de estado (se cruzan) cuando aparece un nuevo
dato o configuración en el bus. Una señal es interpretada como un ‘0’ lógico
hasta una determinada tensión VILMAX (Input Low Maximum Voltage), y se
interpreta como ‘1’ cuando supera una tensión VIHMIN (Input High Minimum
82 Microprocesadores y microcontroladores

Voltage); los valores concretos para cada señal del sistema pueden consultarse en
las hojas de características del MC6800. Valores intermedios a estas dos
tensiones se consideran no válidos.

Comienzo de ciclo.
6800 pone dirección,
VMA y R/W PC←(PC)+1

Fin de ciclo
Ciclo de bus (tciclo)
VIHMIN
V
φ1 ILMAX CPU prepara
acceso bus
Lectura/escritura
φ2 dato

Escritura: 6800 pone dato


Lectura: memoria pone dato Lectura:
6800 toma dato

FIGURA 3.8. Acciones que emprende la CPU en cada punto de las fases del reloj.

Cuando φ1 empieza a subir, se inicia el ciclo de bus; una vez alcanza VIHMIN,
el 6800 establece el valor de las líneas de direcciones A0-A15, pone R/W a ‘1’ o
‘0’ (según vaya a realizar una lectura o una escritura), y coloca VMA a ‘1’,
indicando que ya existe una dirección válida de memoria en el bus de direcciones.
El tiempo que transcurre entre el inicio de este proceso y la estabilización de los
valores en el bus constituye el denominado tiempo de retraso de la dirección, tAD
(Address Delay) (véanse los cronogramas de las figs. 3.9 y 3.10). Cuando φ1
comienza a descender, concluye esta primera fase; si procede, en este instante se
incrementa el valor del contador de programa PC.
A partir de aquí hay que distinguir entre lectura y escritura. Si el acceso es de
lectura (fig. 3.9), cuando φ2 (E) comienza a ascender, la transición de φ2 de ‘0’ a
‘1’ marca el inicio de la solicitud a la pastilla de memoria (o puerto) de colocar el
dato en el bus, ya que esta señal se emplea en la decodificación de memorias y
puertos, y del cronograma observamos que es la última en activarse (previamente
lo han hecho A0-A15, VMA y R/W). El tiempo de establecimiento de la
dirección, tAS (Address Setup Time), es el tiempo mínimo que las líneas A0-A15,
6800 y 68HC11 83

VMA y R/W deben permanecer estables antes de este hecho, y se permite que la
pastilla tarde un tiempo tDDR , retraso permitido a los datos (Allowable Data Delay
(Read)), en poner el dato en el bus (350 ns como máximo). El tiempo total que
transcurre entre la solicitud y la colocación efectiva del dato por la pastilla de
memoria (junto a su estabilización) se denomina tiempo de acceso, tacc (Access
Time), tacc= tAS+tDDR, que a lo máximo es de 540 ns en un 6800 a 1 MHz (por lo
tanto, no se requieren memorias rápidas).
Concluyendo con el proceso de lectura, en el momento en que φ2 retorna a
cero la CPU retiene el dato presente en el bus; el tiempo que dicho dato debe
mantenerse previamente estable para una lectura correcta se denomina tiempo de
establecimiento de datos en lectura, tDSR (Data Setup Time (Read)) (los datos
tienen que permanecer estables por lo menos durante 100 ns, tabla 3.1). Con ello
se da por concluido el ciclo de bus.
Por otro lado, en una escritura (fig. 3.10), en la transición de φ2 a ‘1’ el 6800
inicia el proceso de colocar el dato en el bus de datos; el período que transcurre
entre este hecho y el establecimiento del dato válido en el bus se denomina tiempo
de retraso de datos en escritura, tDDW (Data Delay Time (Write)).
De entre el resto de los tiempos que pueden considerarse [Motorola 76],
concluiremos explicando los tiempos de mantenimiento (hold). El tiempo de
mantenimiento de datos de entrada, tH (Input Data Hold Time) es el tiempo
mínimo que deben mantenerse los datos en el bus tras acabar la fase de lectura (φ2
retorna a ‘0’) para que sean leídos correctamente. Por otro lado, el tiempo de
mantenimiento de datos de salida, tH (Output Data Hold Time), es el tiempo que
el dato permanece válido en el bus una vez concluye la fase de escritura (φ2
retorna a ‘0’). Por último, el tiempo de mantenimiento de la dirección, R/W y
VMA, tAH (Address Hold Time) es el tiempo durante el cual estas señales
permanecen válidas una vez concluye el ciclo de bus (lectura o escritura).
En las figuras indicadas se presentan los cronogramas de los ciclos de lectura
(fig. 3.9) y escritura (fig. 3.10) en un 6800, cuyos tiempos vienen expuestos en la
tabla 3.1. Recordemos que las señales sólo son válidas por debajo de VILMAX o por
encima de VIHMIN.
84 Microprocesadores y microcontroladores

tciclo

φ1
tr

φ2

tAD
R/W
tAH

A0-A15

tAS tDDR
VMA
tDSR tH
tAD tacc
D0-D7

Datos
Válidos

FIGURA 3.9. Ciclo de lectura (1.000 ns de tiempo de ciclo). Notas: tr es el tiempo de subida (rise
time); normalmente E (φ2) se emplea en la decodificación de memorias y puertos, por lo que incluimos
los tiempos tAS y tDDR (tacc=tAS+tDDR) referidos al comienzo de E=‘1’.

tciclo

φ1
tr

φ2

tAD
R/W
tAH

A0-A15

VMA tDDW

tAD tH
D0-D7
(DBE=φ2)
Datos
Válidos

FIGURA 3.10. Ciclo de escritura en memoria o puerto (1.000 ns de tiempo de ciclo).


6800 y 68HC11 85

Tiempos Min (ns) Típico Max (ns)


(ns)

Retraso de la dirección (Address Delay) tAD - 220 300


Tiempo de establecimiento de la tAS 190 - -
dirección (Address Setup Time)
Retraso permitido a los datos en lectura tDDR - 200 350
(Allowable Data Delay (Read))
Tiempo de acceso (Access Time) tacc= - - 540
tAS+tDDR
Tiempo de establecimiento de los datos tDSR 100 - -
en lectura (Data Setup Time (Read))
Tiempo de mantenimiento de datos de tH 10 - -
entrada (Input Data Hold Time)
Tiempo de mantenimiento de datos de tH 10 25 -
salida (Output Data Hold Time)
Tiempo de mantenimiento de dirección, tAH 50 75 -
R/W y VMA (Address Hold Time)
Retraso de los datos en escritura tDDW - 165 225
(Data Delay Time (Write))

TABLA 3.1. Tiempos en las operaciones de lectura y escritura (en nanosegundos), operando a una
frecuencia de 1 MHz (solamente se muestran los más característicos [Motorola 76]).

3.3.3. Circuitos de reset


Tras conectar la alimentación y esperar unos instantes a que ésta se estabilice,
el 6800 debe iniciar una secuencia de arranque o reset, que establezca cierto
estado inicial (siempre el mismo) desde el que comenzar su operación (registros
internos a cero, carga en el PC de la dirección de la primera instrucción del
programa, etc.). Dicha señal de /RESET, activa a nivel bajo, debe mantenerse a
cero mientras la alimentación se estabiliza para evitar que la CPU comience a
ejecutar las instrucciones del programa con una tensión de alimentación
demasiado baja, ya que en esta situación la CPU puede comportarse de manera
impredecible. Posteriormente, la señal de /RESET sirve también para arrancar de
nuevo el sistema en cualquier momento, para lo cual suele estar conectada
también a un pulsador que el usuario puede accionar.
86 Microprocesadores y microcontroladores

+5 v. +5 v.

10 K 10 K

100

/RESET
/RESET

1 µF 1 µF
74HC14

FIGURA 3.11. Ejemplos de circuitos de reset típicos.

En ocasiones se emplea como circuito de arranque (reset) una simple red RC


(fig. 3.11, izda.), que proporciona y mantiene durante un tiempo (del orden de
R×C) un estado inicial ‘0’ al conectar la alimentación (power-on reset), y también
genera una señal ‘0’ cuando el usuario acciona el pulsador. En el caso del 6800,
es necesario que se mantenga el nivel ‘0’ durante el tiempo suficiente para que la
alimentación alcance por lo menos +4,75 V, más 8 ciclos de reloj adicionales (los
que el 6800 emplea en fijar su estado interno inicial).
Un circuito más completo es el de la fig. 3.11 (dcha.). En él, nada más
conectar la alimentación la tensión en el condensador es de cero voltios, con lo
que se inicia el arranque del 6800. El condensador se carga a través de la
resistencia de 10 K, por lo que en un determinado tiempo (del orden de R×C) se
alcanza el umbral que causa una salida ‘0’ en el primer inversor Schmitt (con
histéresis) y un ‘1’ en el segundo (colocamos dos para que globalmente no
inviertan); en definitiva, unos instantes después de alimentar el sistema, el circuito
Schmitt proporciona una señal ‘1’ al 6800, dando por concluida la secuencia de
reset e iniciando su operación normal. Tanto el circuito Schmitt como el
condensador filtran los rebotes que pueden generarse en los contactos del
pulsador, proporcionando una señal lógica «pura». El diodo se introduce para
facilitar la descarga del condensador cuando se retira la alimentación.
En este último circuito, la resistencia de 100 Ω se introduce como medida de
protección del 74HC14, ya que al desconectar la alimentación el condensador
tiende a alimentar el circuito CMOS a través de su diodo interno de protección.
Hablando en términos generales (no solo para el caso del 6800 sino para cualquier
microprocesador), suele ser recomendable colocar una resistencia de 100 Ω entre
el circuito de reset y la patilla de reset del microprocesador o microcontrolador,
6800 y 68HC11 87

por un lado para proteger al propio microprocesador del citado problema. Por
otro lado, en algunos microcontroladores, como es el caso del 68HC11, la patilla
de RESET es bidireccional y, si accidentalmente queda configurada como salida,
podría dañarse al ser conectada a una tensión fija.

3.4. Otros microprocesadores de la familia 68XX


El 6800 fue el primer microprocesador comercializado por Motorola (1975).
A lo largo de la segunda mitad de los años setenta Motorola introdujo diversos
microprocesadores basados en el 6800 original, que trataban de mejorar distintos
aspectos; por ejemplo, el MC68A00 es idéntico al 6800, sólo que puede operar
hasta a 1,5 MHz, y el MC68B00 hasta 2 MHz.
Otros derivados incorporan algunas novedades más importantes. Así, el 6808
es prácticamente idéntico al 6800, sólo que integra el circuito generador de reloj,
por lo que únicamente precisa del cristal de cuarzo externo. El 6802 es un 6800
con circuito de reloj y RAM de 128 bytes integrados en un encapsulado DIP-40,
facilitando enormemente el desarrollo de sistemas.
Por último, el 6809, de finales de los años setenta, se considera en ocasiones
el microprocesador de 8 bits más potente nunca construido (incluso se contempló
su empleo en el primer PC de IBM, en vez del 8088 de Intel). Basado en el 6800,
se completa con registros adicionales, nuevas instrucciones (p.e., multiplicación),
nuevos modos de direccionamiento y más velocidad. Poco después Motorola
introdujo el 68000 (el utilizado en los primeros ordenadores MacIntosh de Apple),
de 16 bits, rompiendo la compatibilidad con la familia 68, e inaugurando una
nueva familia de microprocesadores de 16 y 32 bits denominada 68K, cuyas
prestaciones eran incomparablemente superiores a los «clásicos» 68.
A pesar del tiempo transcurrido, la familia 68 pervive todavía en el corazón
de los microcontroladores de la familia 68XX de Motorola, en los que no se
necesitan prestaciones desmesuradas y sí muchos periféricos integrados y un
precio reducido. Éstos serán los que estudiemos a continuación.

3.5. El microcontrolador M68HC11


Recordemos que un microcontrolador (µC) es un dispositivo electrónico que
incluye en una única pastilla los elementos esenciales de todo un sistema
microprocesador (por ello, en ocasiones son denominados microcomputadores
monopastilla, o simplemente microcomputadores). Así, un µC contiene en su
interior la CPU o núcleo procesador, memoria (RAM, ROM, EPROM, EEPROM
88 Microprocesadores y microcontroladores

y/o flash, en diversas cantidades y combinaciones), puertos de entrada/salida


(paralelo y serie) y diversos bloques de periféricos, como contadores,
temporizadores, circuitos de vigilancia, conversores A/D, etc. En definitiva,
mientras que los µP desarrollados para computación se optimizan en cuanto a
velocidad de procesamiento, los microcontroladores sacrifican potencia de cálculo
en beneficio del número de periféricos integrados en el mismo chip.
El tipo de µC a emplear en una determinada aplicación debe ser elegido
cuidadosamente según los requisitos concretos: idealmente, el µC elegido debe
contener los módulos justos y necesarios para la aplicación, ya que, si integra
bloques que no serán empleados, estaremos pagando un precio más elevado por
algo que no se utiliza.
Cada tipo de µC incluye un núcleo procesador o CPU diferente. Los
procesadores de los distintos microcontroladores pertenecientes a la gran familia
de Motorola 68XX de 8 bit son derivados del M6800 original, que acabamos de
estudiar, de modo que podemos ver en primera aproximación un µC de esta
familia como un sistema microprocesador mínimo basado en el 6800, integrado
al completo en un único chip de silicio. Dentro del grupo de microcontroladores
68XX existen diversas familias, siendo la 6805 y 68HC11 las más conocidas
(http://www.mcu.motsps.com). Gary Daniels, ingeniero de Motorola que ha
participado en el desarrollo de sus microcontroladores desde los años setenta,
narra en [Daniels 96] toda su historia y evolución.
La familia 6805 es de gama baja y media, es decir, de prestaciones limitadas,
resultando el precio de sus miembros en general reducido (inferior a las mil
pesetas). Esta familia incluye µC sencillos, de pocos pines (desde tan sólo 16),
contando con múltiples versiones diferentes (más de cien) y posibilidad de diseño
a medida (para grandes series, claro está). En realidad, muchas de las versiones
del 05 son diseños que grandes compañías solicitan a Motorola para alguna
aplicación particular, y que Motorola luego incluye en sus catálogos. El 6805, en
sus diferentes versiones, es sin duda alguna el µC más vendido de toda la historia.
A modo de ilustración, el modelo MC68HC05K1, uno de los más pequeños,
posee 16 pines en formato DIP, con 0,5 KB de ROM, 32 bytes de RAM, 10 líneas
de E/S (4 de ellas de alta corriente) y un temporizador; se alimenta con tensiones
entre 3 y 5,5 V. Si se adquiere en grandes cantidades, su precio es de tan solo 0,9
dólares (unas 100 pesetas).
6800 y 68HC11 89

1990 1991 1992 1993 1994 1995 1996 1997


1 Motorola Motorola Motorola Motorola Motorola Motorola Motorola Motorola

2 Mitsubishi Mitsubishi Mitsubishi Mitsubishi Mitsubishi Mitsubishi Mitsubishi Microchip

3 NEC NEC Intel NEC NEC NEC Thomson NEC

4 Intel Intel NEC Hitachi Philips Philips NEC Mitsubishi

5 Hitachi Hitachi Philips Philips Intel Microchip Microchip Philips

6 Philips Philips Hitachi Intel Microchip Thomson Philips Toshiba

7 Matsushita Matsushita Matsushita Thomson Zilog Intel Zilog Hitachi

8 National Thomson Thomson Microchip Thomson Hitachi Hitachi Fujitsu

9 Siemens Siemens National Matsushita Matsushita Toshiba Fujitsu Thomson

10 Texas Texas Texas Toshiba Hitachi Fujitsu Intel Zilog

TABLA 3.2. Mercado mundial de microcontroladores de 8 bits durante los años noventa en unidades
vendidas (fuente: Dataquest). Motorola domina claramente el mercado con su familia 68xx; resulta
también destacable la espectacular evolución de los PIC Microchip y el descenso de Intel.

A diferencia de la familia 05, la 68HC11 está compuesta por µC de 8 bits de


gama media y alta (equiparable a la 8051 de Intel). El 68HC11 se introdujo en el
año 1985 como actualización de un µC más antiguo, el 6801, siendo su
orientación inicial las aplicaciones de automoción (encendido electrónico, control
electrónico del motor, frenos ABS, etc.); grandes compañías como General
Motors, Chrysler, Volkswagen o Toyota lo incorporan en sus automóviles. No
obstante, el HC11 se viene empleando desde hace mucho tiempo en campos
diversos, como aplicaciones de consumo (p.e., las cámaras fotográficas Canon
EOS), telecomunicaciones (p.e., teléfonos móviles de Motorola) e industriales
(detectores de incendios, instrumentación biomédica, y muchas más). El 68HC11
es, por lo tanto, otro de los µC más populares en todo el mundo (en 1996 se
llevaban vendidos ya 400 millones de ejemplares) y ampliamente utilizado en la
enseñanza, debido a sus características sumamente pedagógicas.
Existen muchas otras familias de microcontroladores de Motorola
(http://www.mcu.motsps.com), de ellas se hablará brevemente en el capítulo 7.
Así como Intel lidera el mercado de microprocesadores, Motorola es claramente
la compañía líder en el de microcontroladores (en 1995 el 19% del mercado total
de µC era suyo, llegando al 30% en el caso del de los de 8 bits). En [Khan 96] se
habla sobre el estado actual del mercado de microcontroladores, y en la tabla 3.2
puede apreciarse la evolución de las unidades de µC de 8 bits vendidas a lo largo
de los últimos años por los grandes fabricantes (puede apreciarse que Motorola es
90 Microprocesadores y microcontroladores

siempre el líder y que Intel ha ido perdiendo posiciones hasta desaparecer del top
10).

3.5.1. Arquitectura del 68HC11


El HC11 se construyó en torno a una CPU basada en la arquitectura del 6800,
pero reforzada con registros adicionales y nuevas instrucciones. El resultado es
un núcleo procesador capaz de ejecutar las mismas instrucciones que el 6800
(algunas en menos ciclos de reloj), además de otras nuevas que se echan de menos
en el 6800, como las de producto y división, manejo de bits individuales o
instrucciones para el trabajo en doble precisión. Los modos de direccionamiento
que implementa son los mismos que los del M6800.
Las siglas HC en la denominación de los miembros de esta familia de
microcomputadores hace mención al proceso HCMOS (High CMOS) empleado
en su integración, lo que conlleva reducido consumo, alta inmunidad al ruido y
elevada velocidad de operación. Una versión típica de este microcontrolador,
como el MC68HC11A8, incluye en un dado de silicio de 6,5×7,4 mm más de
100.000 transistores [Millman 91] (un microprocesador potente como el
MC68020 contiene unos 200.000).
La frecuencia típica de trabajo de estos µC es de 2 MHz, empleando para ello
un cristal de cuarzo de 8 MHz (internamente dividen la frecuencia por cuatro); el
resto del circuito de reloj está integrado. Algunas versiones operan también a 3 y
4 MHz. Como se ha comentado con anterioridad, esta frecuencia no debe llevar a
engaño, pues, aunque existen µC que operan a frecuencias mucho más altas, los
de Motorola realizan un ciclo de bus en un único ciclo de reloj, mientras que otros
(como los de Intel) precisan tres o cuatro, de modo que deben operar a frecuencias
tres o cuatro veces superiores para obtener un rendimiento equiparable.
Por otra parte, y a diferencia del 6800, el HC11 es un diseño estático, de
modo que no necesita refrescar los valores de sus registros internos, no
presentando por ello límite inferior en su frecuencia de reloj. De esta manera, en
los diseños cuyo requisito fundamental es el bajo consumo puede reducirse su
frecuencia todo lo que sea preciso (recordemos que en los dispositivos CMOS el
consumo se incrementa con la frecuencia de operación).
Como el 6800, su bus de direcciones es de 16 líneas; por lo tanto, puede
direccionar hasta 64 KB (aunque algunos de sus miembros pueden direccionar
más de un megabyte), y el bus de datos es de 8 bits, si bien incorpora algunas
características que le permiten operar fácilmente con datos de 16 bits. El conjunto
6800 y 68HC11 91

de registros del HC11 incluye los del 6800, con las siguientes salvedades (fig.
3.12):
a) Puede trabajar con los acumuladores A y B independiente, o como si de un
único registro de 16 bits se tratase (denominado D).
b) Se incluye un nuevo registro índice, el Y, de similares características al X.
c) Algunos opcodes son de 8 bits y otros de 16, por lo que el IR es de 16 bits.
d) El CCR incluye dos nuevos indicadores (flags), el S y el X

A B
D

SP

PC

CCR SXHINZVC

FIGURA 3.12. Modelo del programador del microcontrolador MC68HC11.

MODB MODA Modo seleccionado


1 0 Sencillo (single-chip)
1 1 Expandido
0 1 Especial: test
0 0 Especial: arranque externo (bootstrap)

TABLA 3.3. Modos de operación del MC68HC11.


92 Microprocesadores y microcontroladores

Los µC de la familia del 68HC11 pueden funcionar en cuatro modos de


operación diferentes, dos normales y dos especiales, denominados sencillo
(single-chip), expandido (expanded), especial de test (special test) y especial de
arranque externo (bootstrap). Estos modos se establecen mediante dos líneas
destinadas al efecto, MODA y MODB: tras la señal de reset el HC11 mira el
estado de estos pines y establece su modo de operación según los valores
presentes en ellos (tabla 3.3). Este estado no es modificable posteriormente por
software.

3.5.2. Patillaje del 68HC11A8


El 68HC11 posee numerosas versiones y tipos de encapsulado, por lo que las
patillas presentes varían de un tipo a otro; no obstante, existe un conjunto de pines
más o menos comunes o habituales en todos ellos. En concreto describiremos las
características del 68HC11A8 (fig. 3.13a), por ser el miembro base de la familia.
El también habitual 68HC11E9 (fig. 3.13b), versión que aparece en las tarjetas de
evaluación EVBU, es similar; tanto el A8 como el E9 suelen utilizarse en los
libros de texto como ejemplos básicos de la familia y serán a los que nosotros
hagamos referencia a lo largo del texto, mientras no se indique lo contrario. Debe
tenerse en cuenta que en el caso del HC11 el papel de algunas de las patillas varía
según opere en modo simple o expandido.

Pines del 68HC11A8 en modo simple


• VDD y VSS. Terminales de alimentación (+5V) y tierra (0V).
• XTAL y EXTAL. Conectores del cristal de reloj (8 MHz).
• MODA y MODB. Modo actual de operación del µC (entradas).
• RESET. Línea de reset (entrada).
• IRQ y XIRQ. Entradas de interrupción.
• VrH y VrL. Tensiones de referencia alta (High, VrH) y baja (Low, VrL) para
el conversor A/D interno.
• E. Reloj E (salida) o reloj del sistema. Es el utilizado en la sincronización del
HC11 con los dispositivos externos, asegurando que se habilitan solamente en
el momento adecuado (por lo tanto, su papel es similar a la fase φ2 de reloj del
6800). E=‘0’ indica que se está llevando a cabo una operación interna, y
E=‘1’ que se accede a los buses.
• Puerto A (PA0-PA7). Puerto de propósito general, y conexión al sistema de
temporizadores y contadores, con líneas de entrada, salida y programables.
6800 y 68HC11 93

• Puerto D (PD0-PD6). Puerto de propósito general programable como entrada


o salida, conectado a las líneas de los canales serie asíncrono y síncrono (SCI y
SPI).
• Puerto E (PE0-PE8). Puerto de entradas tanto digitales como analógicas, para
el acceso al conversor A/D. En el encapsulado DIP-48 solamente hay 4 líneas
disponibles externamente, PE0-PE3.
• Puerto B (PB0-PB7). Puerto de salida (propósito general).
• Puerto C (PC0-PC7). Puerto programable como entrada o salida (propósito
general).
• STRA y STRB (strobe A y strobe B). Líneas de entrada y salida,
respectivamente, empleadas en el diálogo (handshaking) con periféricos
externos.

68HC11A8 (DIP-48) 68HC11A8 y 68HC11E9 (PLCC-52)

FIGURA 3.13. Patillaje de dos de las versiones más usuales del M68HC11. En las versiones PLCC-
52 el puerto E tiene 8 pines, y en las DIP-48 tan sólo 4 (se pierden cuatro líneas).
94 Microprocesadores y microcontroladores

Pines del 68HC11A8 en modo expandido


En este caso las líneas descritas en los tres últimos puntos cambian de papel,
el resto no varían:
• PB0-PB7/A8-A15. Las líneas del puerto B se convierten en las líneas altas del
bus de direcciones, A8 a A15.
• PC0-PC7/AD0-AD7. Las líneas del puerto C se convierten en las líneas del
bus de direcciones (parte baja) y del bus de datos multiplexadas, AD0 a AD7.
• STRA/AS (address strobe). La línea STRA se convierte en salida AS de
habilitación de direcciones (Address Strobe), la cual indica cuándo en las
líneas AD0 a AD7 hay colocada una dirección, AS=‘1’, y cuándo un dato,
AS=‘0’.
• STRB/ R/W. La salida STRB se convierte en la línea de lectura/escritura R/W.

3.5.3. Bloques internos del 68HC11A8


Los bloques internos presentes en el 68HC11A8 ilustran perfectamente los
que podemos encontrar en las demás de las versiones del HC11. Distinguiremos
los siguientes (fig. 3.14):
• CPU (núcleo microprocesador). Arquitectura basada en el 6800, mejorada y
con un juego de instrucciones ampliado a 307 opcodes, con fácil manejo de
números de 16 bits.
• ROM. 8 KB (situado en la parte alta de la memoria), se emplea para el
almacenamiento del programa. En algunas versiones de la familia, como la
MC68HC11E9, el bloque de ROM puede ser sustituido por memoria EPROM,
añadiéndose a la denominación la cifra 7, p.e., el MC68HC711E9, es idéntico
al MC68HC11E9, pero incluye EPROM en vez de ROM.
• RAM. 256 bytes (por defecto en la parte baja de la memoria $0000, aunque es
relocalizable). Se emplea para alojar la pila del sistema y datos (variables).
• EEPROM. 512 bytes (desde la dirección $B600, relocalizable en la versión
HC811E2). Puede emplearse como memoria de programa (sólo para
programas pequeños, pues su cantidad suele ser reducida), para guardar datos
de calibración que puedan ser actualizados con periodicidad, datos a mantener
en caso de pérdida de alimentación, etc.
• Oscilador interno. El chip necesita únicamente un cristal (o un resonador
cerámico, más barato), y dos condensadores externos.
6800 y 68HC11 95

FIGURA 3.14. Bloques internos del 68HC11A8. Se muestra el papel de cada uno de sus patillas, en
modo normal y expandido (líneas entre corchetes).

• SCI (Serial Communications Interface). Bloque de comunicación serie


asíncrona, de tipo UART. Pensado para comunicaciones con dispositivos
remotos, como un ordenador PC.
• SPI (Serial Peripheral Interface). Canal de comunicaciones serie síncrono.
Pensado para comunicación serie de alta velocidad con dispositivos cercanos,
dentro de la misma tarjeta o en tarjetas próximas.
• Puertos de salida.
• Puertos programables de entrada/salida.
• Sistema de temporizadores programables. Permite la medida de intervalos
temporales y frecuencias (por ejemplo, para medir r.p.m.), y el control de
salidas temporizadas (por ejemplo, para generar PWM).
• Acumulador de pulsos. Empleado en el contaje de eventos externos.
• RTI (Real Time Clock). Reloj en tiempo real que permite ejecutar
interrupciones periódicas, cada cierto tiempo.
96 Microprocesadores y microcontroladores

• Sistema de conversión A/D. Incluye un conversor A/D de 8 bits (por


aproximaciones sucesivas), conectado a 8 líneas analógicas de entrada por
medio de un multiplexor analógico.
• COP (Computer Operating Properly) o dispositivo de vigilancia, monitores
del reloj y de instrucciones ilegales. Son bloques que previenen fallos del
software y del hardware, lo que garantiza fiabilidad en el sistema en
aplicaciones potencialmente peligrosas. El COP (en inglés coloquial cop
significa «poli») es lo que otras compañías llaman un temporizador de perro
guardián o watch-dog timmer.
• Bloque de registros de configuración (por defecto, de las direcciones $1000 a
$103F, aunque relocalizables). Se trata de 64 registros de 8 bits que se
emplean para programar o configurar las diversas opciones del hardware,
puertos, etc.

El acceso a los bloques internos se realiza a través de líneas de puertos. Éstas


pueden emplearse como líneas digitales de propósito general de entrada, salida o
programables como E/S, o bien pueden utilizarse para el acceso a dichos módulos.
Por ejemplo, el puerto E (entrada) puede utilizarse como puerto de entrada de
señales digitales, o para dirigir señales analógicas procedentes de sensores al
sistema de conversión A/D integrado.
En la fig. 3.15 aparece el mapa de memoria del 68HC11A8 operando en sus
modos normales (en los especiales algunas de las direcciones indicadas cambian
[Motorola 91]). La dirección de la RAM y los registros de configuración puede
ser alterada cambiando el contenido del registro denominado INIT ($1030, fig.
3.16). Por motivos de seguridad, el contenido de este registro solamente puede
ser alterado durante los 64 primeros ciclos de reloj tras arrancar el sistema. Si la
configuración establecida en este registro crea un conflicto de posiciones en el
mapa de memoria (varios bloques comparten determinadas posiciones), no se
ocasiona ningún daño físico al hardware simplemente entran en juego las
prioridades existentes entre ellos (el orden de mayor a menor prioridad es:
registros de configuración, memoria RAM y memoria ROM). En modo
expandido, en caso de conflicto entre las direcciones de los bloques de memoria
internos y las pastillas de memoria externas, los bloques internos tienen máxima
prioridad (cuando en modo expandido el HC11 direcciona memoria interna,
mantiene el bus de datos externo en alta impedancia, pero A0-A15, AS y R/W sí
son significativos, de modo que, si externamente se realiza una decodificación
total, no hay posibilidad de escribir «basura» en memoria RAM).
6800 y 68HC11 97

Por otra parte, el registro CONFIG ($103F), que es de tipo EEPROM (por lo
que se graba de igual forma que la memoria EEPROM, y mantiene los datos al
retirar la alimentación), establece la configuración de partida del chip tras un
reset, según se indica en la fig. 3.17. Éste se comporta de igual modo para el A8 y
el E9, aunque difiere en el caso de la versión E2 (ver más adelante).

FFFF (Zona del vector de interrupción)


FFC0
ROM
ROM de 8 KB
E000 (puede ser deshabilitada
desabilitada
medianteun
mediante unbit
bitde
deCONFIG)
CONFIG)

B7FF EEPROM de 512 bytes


EEPROM (puedeser
(puede serdeshabilitada
desabilitada
B600 medianteununbitbitdedeCONFIG)
CONFIG)
mediante

103F
1000 Reg. Conf. Bloque de 64 registros
de configuración (64 bytes)
(puede ser recolocado a partir de
cualquier posición múltiplo de 4K)
00FF
0000 RAM RAM de 256 bytes
(puede ser recolocada a partir de
cualquier posición múltiplo de 4K)

FIGURA 3.15. Mapa de memoria del MC68HC11A8 (en modos normales de operación).

Posición de la RAM. Posición de los Reg. de conf.


Indican el valor de los primeros 4 Indican el valor de los primeros
bits de su dirección (normalmente 4 bits de su dirección
%0000) (normalmente %0001)

$103D RAM3 RAM2 RAM1 RAM0 REG3 REG2 REG1 REG0 INIT

7 6 5 4 3 2 1 0

FIGURA 3.16. Registro INIT ($103D), de tipo EEPROM, cuyo contenido es solamente alterable en los
primeros 64 ciclos de reloj que siguen al reset.
98 Microprocesadores y microcontroladores

ROM/EPROM
COP ‘0’ no habilitada
Seguridad (opción ‘0’ habilitado ‘1’ habilitada
sólo de máscara) ‘1’ no habilitado
EEPROM
‘0’ habilitada
‘0’ no habilitada
‘1’ no habilitada
‘1’ habilitada

- - - - NO NO ROM EEON CONFIG


$103F SEC COP ON
7 6 5 4 3 2 1 0

COP
Seguridad (opción ‘0’ habilitado
sólo de máscara) ‘1’ no habilitado
EEPROM
‘0’ habilitada
‘0’ no habilitada
‘1’ no habilitada
‘1’ habilitada

EE3 EE2 EE1 EE0 NO NO - EEON CONFIG


$103F SEC COP
(68HC811E2)
7 6 5 4 3 2 1 0

Colocan los 2 K EEPROM en cualquier


bloque de 4 K de memoria
Estos 4 establecen los bits más significativos de
la dirección (normalmente a ‘1’, $F800-FFFF)

FIGURA 3.17. Registro CONFIG ($103F) de tipo EEPROM. El superior es el incluido en los HC11
convencionales (A8 y E9); el inferior es el del 68HC811E2, sin ROM y con 2 K EEPROM.

Por último, adelantaremos que el 68HC11 posee un sistema de interrupciones


más extenso y completo que el 6800. En principio, se distingue entre fuentes de
interrupción externas y internas. Como externas se tiene el RESET, la
enmascarable IRQ (similar a la IRQ del 6800) y la no enmascarable XIRQ
(similar a la NMI del 6800, aunque de comportamiento más sofisticado). Fuentes
internas de interrupción son la software SWI, el COP, monitor de reloj, RTI,
temporizadores, acumulador de pulsos, SCI y SPI. Condiciones como la
presencia de un código de instrucción ilegal pueden desencadenar también una
interrupción. El sistema de interrupciones se estudiará más ampliamente en el
capítulo 5.
6800 y 68HC11 99

Versión RAM EPROM ROM EEPROM

MC68HC11A8 256 - 8K 512 Base de la familia HC11


MC68HC11A1 256 - - 512 A8 con ROM deshabilitada
MC68HC11A0 256 - - - Ídem ROM y EEPROM desh.
MC68HC11E9 512 - 12 K 512 Mayor capacidad de ROM
MC68HC711E9 512 12 K - 512 Versión EPROM del E9
MC68HC11E1 512 - - 512 E9 con la ROM deshabilitada
MC68HC11E0 512 - - - Ídem ROM y EEPROM desh.
MC68HC811E2 256 - - 2K Sin ROM y más EEPROM
MC68HC11F1 1K - - 512 Para grandes sistemas

TABLA 3.4. Algunas versiones del MC68HC11. Todas incluyen los mismos bloques internos
(puertos, conversor...), aunque sus características concretas pueden variar en detalles.

3.5.4. Versiones del 68HC11


Se dispone en la actualidad de unas 60 versiones del 68HC11, aunque todas
poseen el mismo núcleo procesador CPU-11, y todas se asientan sobre las mismas
bases. Las principales diferencias proceden del tipo y cantidad de memoria
integrada, periféricos, buses externos multiplexados o no, etc.
El MC68HC11A8, base de la familia, se presenta en formato PLCC-52 o
DIP-48; en este último caso cuatro de las líneas del conversor A/D no se conectan
a los pines. El MC68HC11A1 y MC68HC11A0 se basan en el mismo dado de
silicio que el A8, pero en el A1 se ha deshabilitado la ROM interna, y en el A0 la
ROM y la EEPROM. Los pines son idénticos en los tres casos.
El MC68HC11E9 y el MC68HC711E9, de encapsulado PLCC-52 (no existen
en formato DIP), con 12 K de ROM y EPROM, respectivamente, es una versión
mejorada del A8, con más memoria y con una de las líneas OC reconfigurable
como IC; por lo demás, son prácticamente idénticos. El patillaje del E9 es
idéntico al del A8 en PLCC-52. La versión con EPROM, MC68HC711E9, se
comercializa con ventana, para la realización de prototipos, y sin ventana, para
pequeñas series; en este último caso, la EPROM del microcontrolador no puede
borrarse, por lo que se suele denominar «programable una sola vez» u OTP (One
Time Programmable). Por otro lado, la versión E1 es un E9 con la ROM/EPROM
deshabilitada, y la E0 es un E9 con ROM/EPROM y EEPROM deshabilitadas.
100 Microprocesadores y microcontroladores

FIGURA 3.18. Algunas versiones del MC68HC11. Los pines de la A1 y A0 coinciden con la A8
mostrada; la E9 no existe en versión DIP; finalmente, la versión PLCC de la E2 coincide con la E9.
6800 y 68HC11 101

FIGURA 3.19 MC68HC11A8 configurado en modo simple [Motorola 91].

El MC68HC811E2 es muy similar al E9. Resulta ideal para el desarrollo de


prototipos, puesto que en vez de ROM o EPROM incluye 2KB EEPROM (de ahí
el ‘8’ que aparece en su denominación), la cual resulta fácilmente grabable por el
usuario desde un ordenador PC. Disponible en DIP-48 y PLCC-52.
El MC68HC11D3 y el MC68HC711D3 se disponen tanto en PLCC-44 como
DIP-40. El HC11D3 incluye 4 K ROM y el HC711D3 4 K EPROM, en
encapsulados con ventana o sin ella. Sin conversor A/D, son las versiones más
baratas del HC11.
102 Microprocesadores y microcontroladores

El MC68HC11F1, PLCC-68, sin ROM ni EPROM, 1 K RAM, buses no


multiplexados y líneas para la selección directa de chips. Se orienta claramente a
la confección de sistemas grandes, con mucha memoria externa (el resto es similar
al E9).
Emplazamos al lector interesado en el resto de las versiones disponibles (C,
K, G, L, etc.) a los catálogos de Motorola, muchos de ellos disponibles en formato
pdf en http://www.mcu.motsps.com.

3.6. Sistemas basados en el M68HC11


El 68HC11 puede trabajar en dos modos normales de operación, simple y
expandido. En modo simple (fig. 3.19) el HC11 no expone sus buses al exterior,
de forma que conserva todos sus puertos y solamente opera con la memoria
incluida dentro del propio chip. Un sistema basado en un HC11 en modo simple
es de tamaño muy reducido y perfectamente válido para numerosas aplicaciones.
En este caso, solamente deben incluirse externamente una serie de componentes
electrónicos en torno al chip, que aseguran su correcta operación (fig. 3.19), como
son un cristal de cuarzo o resonador cerámico (para la generación del reloj), un
circuito adecuado de reset y un conjunto de resistencias y condensadores (para
polarizar o terminar ciertas patillas, filtrar la alimentación, proporcionar los
niveles de referencia del conversor A/D y establecer el modo de operación). Se
recomienda consultar las hojas de características de Motorola para profundizar en
los detalles [Motorola 91].
En una aplicación real, siempre que se pueda se tratará de encontrar un
ejemplar de microcontrolador que integre todos los recursos requeridos. No
obstante, en ocasiones no queda otra alternativa que configurar el 68HC11 en
modo expandido (fig. 3.20), de modo que se precisa el acceso desde el exterior a
los buses internos para, por ejemplo, incorporar más memoria o nuevos
periféricos (a costa de un importante incremento en el precio final del sistema y
mayor probabilidad de fallos). En modo expandido el HC11 pierde los puertos B
y C, cuyos pines se transforman en las líneas de los buses: el puerto B se
convierte en las líneas altas del bus de direcciones (A8 a A15), mientras que el C
contiene las líneas bajas multiplexadas con las líneas de datos (AD0 a AD8). La
línea AS (Address Strobe) indica con un ‘1’ que en ellas hay presente una
dirección y con un ‘0’ que se trata de un dato. Para demultiplexar los buses del
sistema se debe incluir un registro de retención como el 74HC373, que mantenga
el valor bajo del bus de direcciones antes de que aparezca un rato más tarde por
las mismas líneas el dato de 8 bits del bus de datos (fig. 3.21; el 373 permanece
6800 y 68HC11 103

habilitado cuando AS=‘1’, con lo que toma el valor bajo del bus de direcciones, y,
cuando AS retorna a ‘0’, este valor queda retenido).
Tras la demultiplexación, la única diferencia aparente entre los buses del
68HC11 y los del 6800 son las líneas de validación y de reloj, VMA, φ1 y φ2 en
el caso del 6800, y tan sólo el reloj E en el HC11. En el microcontrolador
68HC11 las fases φ1 y φ2 son internas, por lo que solamente presenta al exterior
la φ2 en la forma de reloj E, para sincronizar las operaciones del sistema de buses;
VMA no aparece en el HC11.

FIGURA 3.20. MC68HC11A8 configurado en modo expandido [Motorola 91]. Las ocho resistencias
de la parte superior mantienen las líneas de datos a ‘1’ para evitar que «floten» cuando el bus de
datos queda en alta impedancia.
104 Microprocesadores y microcontroladores

E=‘1’, acceso a
Incicio de ciclo memoria o periféricos
de bus tciclo=500 ns

Fin de ciclo
de bus
Reloj E

R/W
A8-A15

AD0-AD7
(Lectura) Dirección Dato

AD0-AD7
(Escritura) Dirección Dato

AS

El registro externo 74HC373 retiene


la parte baja de la dirección

FIGURA 3.21. Cronograma de lectura y escritura de los buses externos de un 68HC11 en modo
expandido a 2 MHz (500 ns de tiempo de ciclo).

En modo expandido el microcontrolador se comporta esencialmente como un


microprocesador, con la particularidad de que incluye parte del sistema en su
interior. Los buses obtenidos son totalmente compatibles con los del M6800, de
modo que comparten todos los periféricos, por lo que se habla de la familia 68XX
de microprocesadores, microcomputadores y periféricos. Se debe tener en cuenta,
además, que el sistema está diseñado de manera tal que el multiplexado de
direcciones y datos no reduce la velocidad de su operación respecto del modo
simple (se emplea un solo ciclo de reloj tanto en el acceso a memoria interna
como externa).
Por lo tanto, el diseño de un sistema basado en un 68HC11 operando en
modo expandido se lleva a cabo de modo similar a lo comentado para el 6800:
habrá que plantear el mapa de memoria del sistema y construir a partir de él el
decodificador de direcciones. De la misma manera, la generación de las señales
de habilitación de lectura y escritura, /OE y /WE, que muchas pastillas de
memoria incorporan, se realiza mediante E y R/W de la forma indicada en la fig.
3.22, de modo que /WE=NAND(E, /R/W) y /OE=NAND(E, R/W).
6800 y 68HC11 105

FIGURA 3.22. Generación de señales de habilitación de lectura y escritura en el HC11.

E y R/W son señales válidas en todos los ciclos de bus, incluidos los accesos
a memoria interna. R/W indica el sentido de los datos (lectura o escritura) y E
habilita los dispositivos externos para recibir un dato o para que envíen un dato
(es E quien porta la información de sincronismo).
Por otro lado, cuando en modo expandido el HC11 direcciona memoria
interna, mantiene el bus de datos externo en alta impedancia, pero A0-A15, AS y
R/W sí son siempre significativos (puede apreciarse que en el cronograma nunca
aparecen en alta impedancia, excepto A0-A7, pero éstas, a su vez, son mantenidas
en valores correctos por el 74HC373). Por tal circunstancia, no es recomendable
el empleo de la técnica de decodificación parcial cuando se coloca memoria RAM
externa, pues al escribir en memoria interna podría producirse también la escritura
de datos erróneos en la RAM externa [Peatman 88]. Obsérvese que en la fig. 3.20
se lleva a cabo una decodificación parcial, pero en este caso tan sólo se ha
colocado externamente memoria EPROM, por lo que no puede darse una escritura
errónea sobre ella. En resumen, cuando se debe colocar RAM externa se
recomienda realizar el mapa de memoria completo del sistema, teniendo en cuenta
tanto los bloques de memoria internos como externos, y realizar externamente una
decodificación total sobre las líneas de direccioness.

3.6.1. Circuitos de reset para el 68HC11


En principio, podrían emplearse como circuitos de reset los descritos para el
6800 (fig. 3.11); sin embargo, Motorola recomienda en el caso del HC11 utilizar
otro tipo de circuitos. La razón fundamental es que, cuando la alimentación de un
microprocesador cae por debajo de cierta tensión, y antes de que deje de operar
por completo, existe un rango de tensiones intermedias en las que su operación no
está garantizada, pudiendo llevarse a cabo operaciones indeseadas. Si una de
estas operaciones no esperadas es una lectura o escritura en RAM, no sucede
nada, pues al desvanecerse totalmente la alimentación se perderán estos datos. El
problema reside en la EEPROM interna del HC11, que en estas circunstancias
podría ser erróneamente escrita o incluso borrada.
106 Microprocesadores y microcontroladores

Para evitar este efecto, Motorola recomienda utilizar siempre circuitos de


reset que actúen como detectores de nivel, y no los sencillos RC estudiados, que
simplemente mantienen la línea de /RESET a cero durante un tiempo. Tales
circuitos detectores de nivel (fig. 3.23) deben forzar un nivel ‘0’ en la línea de
/RESET siempre que observen una tensión de alimentación demasiado baja (p.e.,
inferior a +4,5 V), paralizando completamente la operación del microcontrolador
y evitando los problemas relacionados con un operación descontrolada.
Un ejemplo de tales circuitos es el MC34064, denominado inhibidor de bajas
tensiones de alimentación o LVI (Low Voltage Inhibit), que mantiene a ‘0’ la línea
de /RESET cuando observa que la alimentación ha descendido peligrosamente por
debajo de cierto valor (esta tensión umbral viene ajustada de fábrica, de modo que
el LVI se adquiere ajustado a una determinada tensión, p.e., 4.65 voltios). Otro
circuito de este tipo es el MAX690, de la casa Maxim (http:/www.maxim.com),
que, además de generar la señal de /RESET, permite en situaciones de caída de
tensión por debajo de cierto umbral alimentar el sistema mediante una pequeña
batería de respaldo, evitando la pérdida de datos de las memorias RAM. En la fig.
3.24 se muestra un circuito de reset sugerido por Motorola para el 68HC11.

V /RESET

5 v.
4.65 v.

Alimentación

FIGURA 3.23. Señal de /RESET generada por niveles; ésta se mantiene en bajo hasta que la tensión
de alimentación supera un umbral de 4,65 voltios.
6800 y 68HC11 107

FIGURA 3.24. Circuito de reset propuesto por Motorola para el HC11 [Motorola 91].

Se genere de una u otra manera, la señal de /RESET en el 68HC11 debe


permanecer en bajo durante el tiempo que tarda la alimentación en estabilizarse,
más los 4064 ciclos de reloj adicionales que le cuesta llevar a cabo todas sus
operaciones internas de inicialización. Otra cuestión a tener presente es la
peculiaridad de la señal de /RESET del 68HC11, que es tanto de entrada como de
salida, es decir, puede recibir una señal de reset del exterior, pero también puede
enviar hacia los periféricos una señal de reset generada por alguno de sus bloques
internos que tienen capacidad de ordenar la reinicialización del sistema.

3.6.2. Terminación de pines


El 68HC11 es un dispositivo CMOS; en la fig. 3.25 aparece un modelo que
nos permite interpretar cómo se comporta un pin de entrada. Al contar las
entradas con una muy elevada impedancia, si no se conectan (entradas «al aire»),
la entrada puede oscilar o flotar a un nivel intermedio entre 0 y Vdd. El resultado
es un aumento del consumo de la pastilla (recordemos que el mayor consumo en
una puerta CMOS se da cuando los dos transistores se encuentran en una zona
intermedia entre saturación y corte). La oscilación puede causar además la
introducción de ruido en la fuente Vdd. En los viejos diseños CMOS el problema
era más grave aún, pues las grandes intensidades asociadas a una entrada flotante
(a unos Vdd/2) podían provocar también el fenómeno denominado latch-up,
llevando a la destrucción del circuito; en los diseños actuales las entradas poseen
protecciones para minimizar la probabilidad de que se produzca este hecho.
La conclusión importante es que, hablando en términos generales, no es
recomendable dejar entradas no utilizadas sin conectar, sino que hay que
«terminarlas» a Vdd o tierra. No obstante, las variadas características eléctricas
108 Microprocesadores y microcontroladores

de los diferentes pines del HC11 hacen que cada tipo de entrada requiera una
terminación diferente (como siempre, remitimos al manual de referencia del HC11
[Motorola 91] a los interesados en aclarar o profundizar en detalles):
• Las entradas de /RESET, XTAL, MODA y MODB siempre deben conectarse
apropiadamente; no tiene ningún sentido dejarlas al aire.
• Las tensiones de referencia del conversor A/D, VrH y VrL, no necesitan ser
terminadas, pues estos pines no están conectados a ninguna puerta CMOS,
sino a un bloque analógico interno. No obstante, se recomienda su
polarización y estabilización mediante redes RC, tal y como sugiere el
fabricante (fig. 3.19).
• Los pines sólo de entrada no utilizados deben ser conectados a Vdd o a 0 V a
través de una resistencia de 4K7. Aunque una resistencia común para todos
puede ser suficiente, se recomienda el empleo de resistencias individuales para
facilitar posibles futuros cambios en el circuito.
• Los pines de E/S no utilizados, o bien se configuran en la rutina de arranque
como salidas o, mejor aún, pueden polarizarse de la misma forma que se indicó
para los pines sólo de entrada (aunque los configuremos como salidas en la
rutina de reset, durante breves instantes pueden ser entradas al aire).
• El puerto E es especial, al conectarse a un sistema analógico y, en general, no
requiere ser terminado (salvo en casos muy concretos).

Pin de E/S
Vdd Vdd
Vdd Vdd

Entrada Interior del


Salida
68HC11
Interior del Buffer de
68HC11 salida
Buffer de
entrada

FIGURA 3.25. Esquemas simplificados de los pines de entrada, salida y E/S del HC11 [Motorola 91].
Capítulo 4
Instrucciones y modos de direccionamiento

4.1. Introducción: el software del sistema


El desarrollo de sistemas basados en microprocesadores incluye una vertiente
de diseño electrónico (hardware) y otra no menos importante de programación
(software). En este capítulo abordaremos los aspectos relativos al software,
empleando como ilustración los µP de 8 bits 6800 y 68HC11, de la familia 68XX
de Motorola. Estudiaremos en primer lugar los modos de direccionamiento y
juegos de instrucciones de estos microprocesadores, para exponer a continuación
diversas cuestiones prácticas relativas a la programación de µP y µC, así como
algunos aspectos de metodología de confección de programas.
Recordemos que una instrucción como LDAA (carga en el acumulador A),
ADDA (suma) o STAA (guarda el contenido del acumulador A en memoria),
introducidas ya en capítulos anteriores, se compone de un código de operación u
opcode y, si lo requiere, unos operandos (o la dirección de tales operandos). La
forma de obtener los operandos (datos) sobre los que se aplica una instrucción se
conoce como modo de direccionamiento (es decir, si vienen justo a continuación
del opcode, si están en determinada casilla de memoria, etc.).
Cada microprocesador se caracteriza por su juego de instrucciones y sus
modos de direccionamiento. En el M6800 el código de operación es un número
binario de 8 bits (posee cerca de 200 opcodes en total), cuyos bits individuales
indican tanto la instrucción a ejecutar (si hay que cargar un dato, realizar una
suma, etc.), como el modo de direccionamiento en el que se va a trabajar. En la
memoria, justo a continuación del opcode y dependiendo del modo de
direccionamiento concreto empleado, pueden encontrarse uno o dos bytes
adicionales que contienen, bien el dato propiamente dicho, bien la dirección
donde éste se encuentra. En ambos casos se trata de un número de 8 o 16 bits, por
lo que en el 6800 una instrucción ocupará entre 1 y 3 bytes (fig. 4.1).
El juego de instrucciones del M68HC11 se diseñó a partir del del 6800,
introduciéndose instrucciones nuevas hasta llegar a una cifra de 307 opcodes.
Como mediante 8 bits solamente pueden codificarse 256 diferentes, en el HC11
los códigos de operación de algunas de las nuevas instrucciones van precedidos de
un grupo de 8 bits adicional que Motorola denomina pre-byte. De este modo, los
110 Microprocesadores y microcontroladores

códigos de operación pueden tener uno o dos bytes, por lo que las instrucciones
del HC11 estarán formadas por un número de bytes comprendido entre 1 y 4 (fig.
4.1).

opcode operando/dirección
M6800

prebyte opcode operando/dirección


M68HC11

FIGURA 4.1. Tamaño y composición de las instrucciones en el 6800 (arriba) y 68HC11 (abajo).

4.2. Modos de direccionamiento


Cuando se tiene una instrucción como LDAA, que toma un dato y lo lleva al
acumulador A, debe indicarse al microprocesador el lugar donde se encuentra
dicho dato. Se denominan modos de direccionamiento a las diferentes formas que
contempla la máquina para obtener la dirección donde la información (los
operandos) debe ser tomada o almacenada al ejecutar una instrucción (en el caso
de las instrucciones de salto, la dirección del punto al que se debe saltar). La
dirección calculada por la CPU para obtener el lugar donde realmente se sitúan los
datos se denomina dirección efectiva, que en el caso del 6800 y 68HC11 es un
número de 16 bits, capaz de apuntar a cualquiera de los 64 KB de memoria.
No es difícil imaginar diversas posibilidades para proporcionar los operandos
a la instrucción; por ejemplo, éstos podrían colocarse justo a continuación del
opcode. Otra posibilidad es que justo tras el opcode no se sitúe el dato, sino la
dirección de memoria donde éste se encuentra; también podría darse el caso de
que una instrucción siempre opere implícitamente sobre cierto registro (p.e., el
acumulador A). Estas y otras posibilidades son manifestaciones de los diferentes
modos de direccionamiento presentes en la máquina, que pasamos a estudiar.
Cuando la CPU carga de memoria una nueva instrucción, tres de los bits del
opcode indican en qué modo de direccionamiento concreto debe ser ejecutada; a
partir de esta información el microprocesador calcula la dirección efectiva de
donde tomar los operandos (o bien donde dejar el resultado). Tanto el 6800 como
el 68HC11 contemplan siete modos de direccionamiento, a saber, directo,
Instrucciones y modos de direccionamiento 111

extendido, indexado, inmediato, implícito, relativo y acumulador. Pasamos a


continuación a describirlos.
a) Modo extendido. En este caso se proporciona explícitamente una dirección
efectiva de 16 bits. Así, en memoria aparecen justo a continuación del opcode
dos bytes adicionales que indican la dirección donde se encuentra el dato sobre
el que hay que operar (o bien la dirección a la que hay que saltar). Mediante
este modo se puede direccionar cualquier posición del espacio de memoria (64
K), y permite el manejo de variables de programa. En otros
microprocesadores este modo es conocido como direccionamiento directo.

opcode dirección (alta) dirección (baja)

Por ejemplo, la instrucción de carga en el acumulador A en modo extendido,


LDAA $1032, toma el dato contenido en la dirección $1032, y lo lleva a A,
A←($1032).
b) Modo directo. En los µP de 8 bits de Motorola este modo es un caso particular
del extendido, con la restricción de que solamente se indica una dirección de 8
bits, la cual apuntará a una de las primeras 256 casillas de memoria (de la $00
a la $FF). En este modo el µP sólo puede acceder a la primera página de
memoria o «página 0» (la memoria se considera dividida en páginas de 256
bytes). Las ventajas de este modo de direccionamiento son que la instrucción
ocupa menos espacio en memoria, pues se compone del opcode más un único
byte adicional, por lo que además la ejecución de la instrucción dura un ciclo
de reloj menos (pues se ahorra un acceso a memoria). La desventaja es que
solamente puede accederse a los primeros 256 bytes del espacio de memoria.

opcode dirección

Por ejemplo, la instrucción de carga en el acumulador A en modo directo,


LDAA <$18, toma el dato contenido en la dirección de memoria $0018, y lo
lleva a A, A←($0018).
c) Modo indexado. Es el modo empleado en el tratamiento de tablas y matrices
de datos. Para el cálculo de la dirección efectiva la CPU se apoya en un
registro índice (el X en el 6800, el X o el Y en el HC11), que almacena una
dirección de memoria de 16 bits, cantidad a la que se suma un desplazamiento
(offset) de 1 byte, el cual se aloja a continuación del opcode. Esta operación es
112 Microprocesadores y microcontroladores

realizada en ciertos µP (6800, 68HC11) por la ALU de la UP, pero en otros


(8086) la ejecuta una ALU específica para el cálculo de direcciones. El
desplazamiento a añadir a la dirección almacenada por el registro índice se
interpreta como un número sin signo, entre 0 y 255. Comparándolo con el
extendido, el direccionamiento indexado ahorra espacio de memoria, pero es
mucho más lento debido a la necesidad de calcular la dirección efectiva.
opcode desplazamiento

Por ejemplo, la instrucción LDAA $20,X carga en el acumulador A en modo


indexado, interpretando el dato contenido en el registro X como una dirección
de memoria, a la cual le suma el desplazamiento $20, construyendo así una
dirección efectiva (por ejemplo, si X contenía el valor $1012, se tendrá la
dirección efectiva $1032); por último, toma el dato colocado en esta dirección
y lo lleva a A, en resumen, A←( (X)+$20 ).
Cuando no se conoce directamente la dirección del dato, sino la dirección de
memoria donde está almacenada la dirección efectiva del dato, se dice que se
está trabajando en modo indirecto, y la primera dirección citada, que
representa una variable que almacena una dirección de memoria, se denomina
puntero. Éste es un tipo de direccionamiento común en diferentes CPU, pero
la familia 68XX no lo incorpora explícitamente, si bien puede ser
implementado ejecutando los siguientes dos pasos: a) cargar en el registro
índice el valor del puntero, b) hacer uso a continuación de una instrucción en
modo indexado con desplazamiento cero. Por ejemplo
LDX $390F X←($390F)
LDAA 0, X A←((X)+0)
d) Modo inmediato. Consiste en colocar el dato justo a continuación del opcode.
Es decir, en memoria aparece el opcode seguido por el propio dato, un número
de 8 o de 16 bits. Este modo se emplea para almacenar constantes del
programa; es rápido y ocupa poco espacio.
opcode # dato

opcode # dato (alto) dato (bajo)

Por ejemplo, la instrucción de carga en el acumulador A en modo inmediato


LDAA #$A3, simplemente toma el dato $A3 y lo lleva a A, A←$A3.
Instrucciones y modos de direccionamiento 113

e) Modo inherente o implícito. En este caso la dirección de los datos va implícita


en el código de operación, por lo que no es preciso proporcionar ninguna
dirección o dato adicional.

opcode

Por ejemplo, la instrucción CLC (CLear Carry) pone a cero el bit indicador de
acarreo C, C←0.
f) Modo acumulador. Es el empleado por aquellas instrucciones que pueden
operar con el acumulador A o con el B, indicando simplemente con cuál de los
dos se trabaja.
opcode

Por ejemplo, INCA e INCB (INCrement A e INCrement B), instrucciones que


incrementan el registro A o el B, respectivamente, A←00, B←00.
g) Modo relativo. Este modo es únicamente empleado en ciertas instrucciones de
salto. En él a continuación del opcode aparece un byte adicional que
representa un desplazamiento (offset) relativo al actual valor del contador de
programa PC, el cual se interpreta en complemento a dos (de −128 a +127).
La dirección efectiva de salto se calcula sumando al actual valor del PC el
desplazamiento indicado, de modo que pueden ejecutarse saltos entre
(PC)−128 y (PC)+127. Sin embargo, debe tenerse en cuenta que cuando la
CPU calcule esta suma el PC no apuntará a la instrucción de salto, sino que
habrá sido actualizado ya, apuntando a la siguiente instrucción dos bytes más
adelante. Por ello, el salto puede realizarse a cualquiera de las 126 casillas
anteriores a la instrucción de salto o a una de las 129 posteriores. La
utilización de saltos relativos permite la confección de rutinas reubicables.

opcode desplazamiento

Por ejemplo, la instrucción de salto relativo BRA $03 (BRAnch) salta tres
casillas más allá de la posición actualmente indicada por el PC,
PC←(PC)+$03.
114 Microprocesadores y microcontroladores

Si se examina en el apéndice A las tablas de los juegos de instrucciones del


6800 o del 68HC11, se observará que cada instrucción soporta únicamente
algunos de los siete modos de direccionamiento posibles. Asimismo, el lector
atento habrá ya observado que para distinguir entre ellos se utilizan una serie de
símbolos (tabla 4.1). Así, en las instrucciones que soportan los modos extendido,
directo, indexado e inmediato, como la LDAA (LoaD Accumulator A), si a
continuación del mnemónico aparece una dirección de 16 bits sin ningún símbolo,
se considera que actúa en modo extendido. Por otra parte, si va seguida de una
dirección inferior a $FF (255 en decimal), muchos compiladores asumen que
actúa en modo directo, aunque otros para indicar este modo requieren el empleo
del símbolo ‘<’ precediendo al operando. Por otra parte, si entre el mnemónico y
el operando aparece el símbolo ‘#’, la instrucción actuará en modo inmediato, y si
tras el mnemónico aparece un byte seguido por los símbolos ‘,X’ (o también ‘,Y’
en el HC11), el modo será el indexado referido al registro índice correspondiente.
Por otra parte, cuando en una instrucción no existe ambigüedad en el modo
de direccionamiento a emplear, pues sólo operan con uno, no se utiliza símbolo
adicional alguno; ello sucede, por ejemplo, en las instrucciones que únicamente
operan en modo inherente o las de salto relativo. En las de modo acumulador, el
propio mnemónico incluye ya el símbolo A o B, según el acumulador del que se
trate.
Por último, hay que indicar que, si bien los modos de direccionamiento
descritos son los empleados en la familia 68XX de Motorola, resultan comunes a
muchas familias de µP de otras casas comerciales, aunque cada cual puede
emplear denominaciones algo diferentes. En cada caso se deberá recurrir a la
documentación técnica para determinar la nomenclatura concreta empleada.

FA00
1000 BRA
FA01 +3
FA02 LDAA PC (nueva posición
FA03 10 del PC)
FA04 32 +3
FA05 INCA

FIGURA 4.2. Ejecución de un salto relativo respecto de la nueva posición del PC.
Instrucciones y modos de direccionamiento 115

Modo Ejemplo RTL


Extendido LDAA $1032 A←($1032)
Directo LDAA $18 (LDAA <$18) A←($0018)
Indexado LDAA $20, X A←( (X)+$20 )
Inmediato LDAA #$A3 A←$A3
Inherente CLC C←0
Acumulador CLRA A←00
CLRB B←00
Relativo BRA $3 PC←(PC)+$3

TABLA 4.1. Ejemplos de los distintos modos de direccionamiento.

Modo Utilidad Ventajas Inconvenientes


Extendido Variables de programa Direcciona 64 K Precisa 2 bytes (y 2
ciclos)
Directo Variables de programa Precisa un solo byte (y Direcciona tan sólo
un solo ciclo). 256 bytes
Indexado Tablas Precisa un solo byte Desplazamiento
Matrices de datos Direcciona 64 K limitado a 256 bytes
Cadenas de caracteres Punteros y estructuras Lento (la ALU debe
dinámicas de datos calcular la dirección
Manejo de la pila
efectiva)
Inmediato Constantes de Tiempo ejecución Limitado a constantes
programa Ocupación de memoria
Inherente Tiempo ejecución Sólo instrucciones
Ocupación de memoria muy concretas
Acumulador Tiempo ejecución Cantidad limitada de
Ocupación de memoria datos
Relativo Rutinas reubicables Precisa un solo byte Salto limitado a 256
Tiempo ejecución bytes

TABLA 4.2. Características de los distintos modos de direccionamiento.


116 Microprocesadores y microcontroladores

Direccionamiento: Modo Extendido

Ejemplo: LDAA $1032 A←($1032)

0000
PC 01 00
1
:
(PC ini)→ B6 LDAA IR AR
10 $1032 B6 10 32
2
32 (reg. instrucciones) (reg. direcciones)
(PC fin)→ :

A 54
4
B
: 3
1032 54 X
:

FFFF

Direccionamiento: Modo Directo

Ejemplo: LDAA $18 A←($18)

0000
PC 00 04
1
:
(PC ini)→ 96 LDAA IR AR
18 $18 96 00 18
2
(PC fin)→ : (reg. instrucciones) (reg. direcciones)
:

A 54
4
B
: 3
0018 54 X
:

FFFF

FIGURA 4.3. Ilustración de la operación de los modos de direccionamiento extendido y directo.


Instrucciones y modos de direccionamiento 117

Direccionamiento: Modo Indexado


Ejemplo: LDAA $20, X A←( (X) $20)

0000
PC 01 00
1
:
(PC ini)→ A6 LDAA IR AR
20 $20,X A6 10 32
2
(PC fin)→ : (reg. instrucciones) (reg. direcciones)
:

A 54
4
B
: 3
1032 54 X 10 12
:

FFFF

Direccionamiento: Modo Inmediato


Ejemplo: LDAA #$A3 A←$A3

0000
PC 01 00
1
:
(PC ini)→ 86 LDAA IR AR
A3 #$A3 86 ... ...
(PC fin)→ : 2 (reg. instrucciones) (reg. direcciones)
:

A A3

B
:
: X
:

FFFF

FIGURA 4.3 (Cont.). Ilustración de la operación de los modos de indexado e inmediato .


118 Microprocesadores y microcontroladores

4.3. Tipos de datos


Tanto las instrucciones (opcodes) como los datos deben estar situados en
memoria codificados mediante ceros y unos. En este sentido, debe tenerse en
cuenta que dato y código de operación, por sí solos, no pueden distinguirse, sino
que un dato binario almacenado en un registro de memoria se interpreta en un
sentido u otro en función de cómo se utilice; p.e., la cantidad $C6 guardada en
memoria, si es apuntada por el PC, indicará instrucción LDAB (en modo
inmediato), pero, si es cargada en el acumulador B, se interpretará como un
simple dato (198 en decimal).
Estudiado el formato de la instrucción, en esta sección, repasaremos diversas
formas de codificar los datos en un sistema digital. A lo largo de este texto se está
dando por supuesto siempre que el lector ha seguido previamente un curso de
electrónica digital (o de sistemas lógicos), por lo que ahora solamente revisaremos
los aspectos más importantes referentes a la codificación de datos ([Pollán 94,
Tanenbaum 92] son referencias interesantes para fijar conceptos o ampliar
conocimientos). Asimismo, expondremos cómo quedan actualizados los
señalizadores o flags del registro de estado cuando la CPU opera con datos.

0
-1 0 +1
15 1
-2 0000 +2
14 1111 0001 2
-3 1110 0010 +3
13 3
1101 0011

-4 12 1100 0100 4 +4

1011 0101
11 5
-5 1010 0110 +5
1001 0111
10 6
-6 1000 +6
9 7
-7 8 +7
-8

Decimal → 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
Hexadecimal → 0 1 2 3 4 5 6 7 8 9 A B C D E F

FIGURA 4.4. Números binarios de 4 bits y sus equivalentes decimales y complemento a dos (un
mismo código binario puede interpretarse de ambas formas, dependiendo del propósito).
Instrucciones y modos de direccionamiento 119

A partir de un sencillo ejemplo podemos comprender la necesidad de hacer


uso de diversas formas de codificación de datos, según el propósito o aplicación.
Si en una empresa de embotellado se desea almacenar en una casilla de memoria
de un sistema microprocesador el número de botellas que han pasado por
determinada cinta transportadora, basta codificar con ceros y unos dicho dato
como un número entero sin signo (pues está claro que pueden haber pasado 273
botellas, pero ni 2,73 ni −273); sin embargo, si se deben almacenar temperaturas,
en general se precisará codificar con ceros y unos números tanto positivos como
negativos. Es decir, pueden considerarse distintos tipos de datos en función del
objetivo requerido (enteros sin signo, enteros con signo, decimales codificados en
binario o BCD, números en punto fijo, flotante, caracteres, cadenas de caracteres,
etc.), los cuales pueden codificarse de diferentes formas mediante unos y ceros.

4.3.1. Enteros sin signo y enteros con signo (complemento a dos)


En el 6800 los datos con los que la ALU opera son de 8 bits. Mediante 8 bits
pueden codificarse enteros sin signo en el rango de 0 a 255 (2n−1), que se puede
representar alternativamente en hexadecimal como $00 a $FF o, en binario,
%0000 0000 a %1111 1111 (en el lenguaje de alto nivel C, de uso extendido,
estos enteros sin signo de 8 bit coinciden con el tipo de dato denominado
unsigned char). Por otra parte, si se precisa trabajar con números positivos y
negativos (enteros con signo), se suele emplear la codificación complemento a dos
(tipo char en lenguaje C), que consiste en construir el opuesto −X de un cierto
número X, mediante la siguiente operación indicada en decimal
− X = 2n − X
siendo n el número de bits de resolución. En el 6800 n es 8, por lo que, p.e., el
opuesto de 3 es 256−3=253 o, en binario, 3 es %0000 0011 y −3 es %1111 1101.
En esta codificación el bit más significativo (el 8.º, en nuestro caso) indica el
signo del número, ‘0’ para los números positivos y ‘1’ para los negativos. Si se
calcula el opuesto del número obtenido, se retornará al original, ya que
− ( − X ) = 2 n − ( − X ) = 2 n − (2 n − X ) = X
Por último, una sencilla regla para calcular el complemento a dos de un número
binario consiste en invertir uno a uno sus bits individuales y sumar 1 al resultado.
Por ejemplo, en el caso del número decimal 3 (%0000 0011) se tiene:

%0000 0011 ⎯inversion


⎯⎯⎯→ %1111 1100 ⎯sumar
⎯⎯⎯1→ %1111 1101
obteniéndose el mismo valor calculado antes.
120 Microprocesadores y microcontroladores

Haciendo uso de complemento a dos de n bits se abarca un rango de −2n-1 a


+2n-1−1; para n=8, de −128 ($80 o %1000 0000) a +127 ($7F o %0111 1111). En
este caso el hexadecimal $00 (%0000 0000) representa el 0, el $FF (%1111 1111)
es el decimal −1.
Debe recordarse que las reglas aritméticas tal y como se definen en binario
sirven tanto para números sin signo como con signo (complemento a dos). Así, la
ALU del 6800 y del 68HC11 al sumar dos números binarios no precisa saber si
éstos son de un tipo u otro; tan sólo «ve» ceros y unos, y opera con ellos; la
interpretación de su significado (con signo o sin él) la realizaremos nosotros.

4.3.2. Actualización y significado de los bits de estado (flags)


Los bits de estado (flags), indicadores o, en traducción literal, «banderas»,
son actualizados por la ALU en función del resultado de una operación (aplica las
expresiones lógicas de la tabla 4.3). De nuevo somos nosotros los que tenemos
que interpretar su significado, según estemos trabajando con números con o sin
signo (supondremos en adelante números de 8 bits):
• Bit de acarreo C (Carry). Solamente es significativo en el caso de los
números sin signo. Indica tanto la presencia de acarreo («me llevo una») en
una suma, como el necesidad de «tomar prestado uno» (borrow) en una resta.
Suma de enteros sin signo. En una suma C se activa cuando el resultado no
cabe en los ocho bits destinados al efecto, es decir, cuando supera el valor 255
($FF). En este caso, el valor de C puede interpretarse como un noveno bit, y el
resultado completo de nueve bits es perfectamente correcto. El 6800
solamente suma números de 8 bits, pero el bit de acarreo puede emplearse en
la ejecución de sumas de dos, tres o más bytes, o para sumar más de dos
números (por supuesto, todos ellos interpretados como números sin signo).
Para ello, el bit C de acarreo se deberá propagar a las cifras más significativas,
haciendo uso de la instrucción ADCA, que suma dos operandos (como
ADDA) y además el bit C, implementando así el «me llevo una».
Resta de enteros sin signo. En el caso de la resta el bit C se activa cuando se
requiere un préstamo (borrow, p.e., 153-27, ejecutando la resta cifra a cifra
desde las unidades: «de 7 a 3 no cabe, tomo prestado 1 de las decenas»). Es
decir, C en una resta se activará cuando el minuendo sea menor que el
sustraendo, y no se activará en caso contrario. Esta propiedad se empleará más
adelante en los saltos condicionales, pues al ejecutar una comparación entre
dos números (con una instrucción de resta o una de comparación CMP), C=1
indicará «menor que» y C=0 indicará «mayor o igual que».
Instrucciones y modos de direccionamiento 121

Suma: X+M=R Resta: X-M=R


N =R7 N =R7
Z =/R7./R6./R5./R4./R3./R2./R1./R0 Z =/R7./R6./R5./R4./R3./R2./R1./R0
V =X7.M7./R7+/X7./M7.R7 V =X7./M7./R7+/X7.M7.R7
C =X7.M7+M7./R7+/R7.X7 C =/X7.M7+M7.R7+R7./X7
H =X3.M3+M3./R3+/R3.X3

TABLA 4.3. Expresiones booleanas que emplea la CPU para actualizar los señalizadores tras una
suma y una resta de dos números X y M (el número presente tras cada letra indica el bit que
involucra; el símbolo ‘/’ indica negación lógica; ‘+’ y ‘.’ las operaciones OR y AND).

• Bit de desbordamiento V (oVerflow). Solamente es significativo para números


en complemento a dos. En este caso, el octavo bit indica el signo, pero cuando
el valor absoluto del resultado es grande, resulta desbordado o sobre-escrito
(pues no cabe en los siete bits restantes). El bit V indica precisamente este
desbordamiento, poniéndose a uno cuando el resultado de una operación
aritmética supera el valor +127 o resulta inferior a −128. Este bit es
importante desde la óptica de los números en complemento a dos, pues indica
que el resultado global no tiene ningún sentido y debe ser desechado, pero no
será tenido en cuenta al trabajar con números sin signo.
Otra forma de determinar un posible desbordamiento consiste en comprobar si
al sumar dos números se da alguna de las siguientes circunstancias:
(+a) + (+b) = −R (sumando dos positivos da negativo) (+a) − (−b) = −R

(−a) + (−b) = +R (sumando dos negativos da positivo) (−a) − (+b) = +R


También puede determinarse V como la operación o-exclusivo (XOR) entre el
acarreo que entra al bit más significativo y el que sale de él (el global C):
V = C 7in ⊕ C 7 out = C 7in ⊕ C

• Bit de resultado negativo N. No es otra cosa que el octavo bit del resultado,
que indica el signo del número (N=‘0’ si resultado positivo, N=‘1’ si
negativo). En general, será ignorado cuando se opere con números sin signo.
• Bit de resultado cero Z. Se activa o marca (Z=‘1’) cuando el resultado de una
operación es cero; Z=‘0’, cuando el resultado es diferente a ‘0’.
122 Microprocesadores y microcontroladores

• Bit de acarreo a la mitad H (Half carry). Si consideramos un número de 8 bits


dividido en dos grupos de 4 (nibble), el bit H indica la existencia de acarreo
entre ambos. Este bit H, que en el 6800 solamente es actualizado por las
instrucciones de suma, se emplea en el trabajo con números BCD, como
veremos a continuación (solamente la instrucción DAA, que explicaremos más
adelante, se apoya en el valor de H).
Es importante tener en cuenta que cada instrucción afecta de una forma
particular a los bit de estado, y que a veces podemos encontrarnos con situaciones
que pueden causar sorpresa (por ejemplo, la instrucción de incremento INC afecta
a los bit N y Z, ¡pero no al C!). Para evitar los graves errores de programación
que estas situaciones atípicas pueden conllevar, conviene siempre consultar
detenidamente las hojas del repertorio de instrucciones, especialmente cuando se
deben elaborar condiciones para la ejecución de saltos condicionales.

Ejemplo: actualización de los bits de estado


Realiza las siguientes operaciones en decimal, hexadecimal y binario, y deduce
el estado de los flag en cada caso.
a) 205+118 b) (+89)+(+49) c) 2−64

Resolución:
a) Realizamos la primera suma en decimal (números sin signo), en hexadecimal,
en binario y en decimal (números con signo); obviamente, el resultado debe
ser el mismo en todos los casos. Hay que observar que en la suma en decimal
(números sin signo) es fácil apreciar si se ha producido acarreo comprobando
si el resultado supera 255; en la suma en decimal (números con signo) se
comprueba fácilmente si se ha producido desbordamiento observando si el
resultado es superior a +127 o inferior a −128. En la suma en binario ambos,
junto al acarreo a la mitad (H), son fácilmente deducibles: el acarreo C es
claramente el «me llevo una» del último bit (el 7); el desbordamiento se puede
calcular como la operación o-exclusivo (XOR) del acarreo que entra al último
bit con el acarreo que sale (el global, C); finalmente, y por definición, el flag H
es el acarreo entre los bits 3 y 4.
En la siguiente figura realizamos la operación correspondiente al apartado a)
del ejemplo, señalando todas las posibilidades. Se obtiene C=1, V=0, N=0 y
H=1; se tendrá Z=0, puesto que el resultado final es distinto a $00.
Instrucciones y modos de direccionamiento 123

El bit de signo Cin=Cout⇒V=0


es ‘0’⇒N=0
1 1 1⇒H=1

204 $CC 1100 1100


+118 +$76 + 0111 0110
322 $142 C= 1 0100 0010
1 4 2 (66 en decimal)
>255⇒acarreo C=1
Re-interpretado en Condiderando 9 bits el resultado
complemento a 2 como número sin signo ($142)
es significativo
-52 sin desborda-
+118 miento V=0
+66

b) De manera similar, en la segunda suma (números con signo) se tendrían los


siguientes bits de estado: C=0, V=1, N=1, H=1 (y Z=0, claro).

El bit de signo Cin≠Cout⇒V=1


es ‘1’⇒N=1
0 1 1⇒H=1

+89 $59 0101 1001


+46 +$2E + 0010 1110
135 $87 C= 0 1000 0111
8 7 (135 en decimal)
>+128⇒desborda-
miento V=1

c) En el caso de la resta, el bit C indica «tomo prestado» (borrow): como 2 es


inferior a 64, debe tomarse prestado, por lo que el bit C se pondrá a ‘1’, C=1.

Como $2 es menor que H solo se actualiza


$40, «tomo prestado en las sumas
1»⇒borrow C=1
H=0

2 $1 0 2 10000 0010
-64 -$ 4 0 - 0100 0000
-62 $C 2 01100 0010
C 2 (-62 en decimal)
El bit de signo
No hay desbordamiento V=0 es ‘1’⇒N=1
124 Microprocesadores y microcontroladores

Debe tenerse en cuenta que si bien nosotros empleamos diversas técnicas para
calcular el estado de los indicadores, en realidad el 6800 realiza las
operaciones lógicas indicadas en la tabla 4.3.

En resumen...
• Dato y opcode por sí solos no pueden distinguirse, sino que un dato binario
almacenado en un registro de memoria se interpreta en un sentido u otro en
función de cómo se utilice.
• El µP no entiende de números con signo o sin signo, solamente ve números
binarios y opera con ellos, actualizando C y V en función de determinadas
expresiones booleanas (tabla 4.3). La interpretación «con signo», «sin signo»,
«desbordamiento», etc., la realizamos nosotros.
• El bit de acarreo C solamente es significativo en el caso de números sin signo,
pudiéndose considerar un noveno bit del resultado.
• El bit de desbordamiento V solamente debe ser tenido en cuenta en el caso de
operaciones con números complemento a dos, indicando en este caso que
desde este punto de vista el resultado carece de sentido.
• El bit H (acarreo a la mitad) sólo es actualizado por las instrucciones de suma.

4.3.3. Números decimales codificados en binario (BCD)


Aunque la máquina opera en binario, los seres humanos empleamos la
codificación decimal. Para facilitar las tareas de entrada y salida de datos
(decimales), se suele emplear la denominada codificación BCD, o decimal
codificado en binario, consistente en representar cada dígito decimal del 0 al 9
mediante cuatro bits. Como la CPU opera con unidades de 8 bits (byte), si se
dividen en dos grupos de cuatro con un byte, pueden representarse números
decimales desde el 00 al 99, los cuatro bits más significativos representarían la
cifra decimal más significativa, y los otros cuatro la menos significativa. Por
ejemplo, el número 74 se construiría en BCD de la siguiente manera: 7 es %0111
y 4 es %0100; por lo tanto, 74 es, concatenando ambos, %0111 0100. Debe
tenerse en cuenta que en BCD habrá valores no permitidos, ya que de los 256
valores posibles exclusivamente se emplean 100 (p.e., %1100 1111).
Los microprocesadores de la familia 68XX solamente operan en binario, por
lo que las instrucciones de suma, resta, etc., aplicadas sobre números BCD pueden
proporcionar un resultado BCD no válido. Para facilitar la realización de
operaciones aritméticas con números BCD, Motorola introduce la instrucción de
Instrucciones y modos de direccionamiento 125

ajuste a decimal DAA (Decimal Adjust Accumulator), que opera de la siguiente


manera: si se suman con la instrucción ADDA dos números BCD, el resultado
almacenado en A puede no ser significativo como BCD; pero, si tras ADDA
colocamos la instrucción DAA, ésta ajusta el contenido de A al correcto BCD que
representa el resultado. DAA solamente puede ir colocada tras las instrucciones
ABA, ADD y ADC, las únicas que modifican el estado del bit H. A continuación
mostramos un ejemplo del empleo de la instrucción DAA (el símbolo ‘*’ en el
lenguaje ensamblador indica que lo que viene a continuación es un comentario del
programador, que no debe compilarse):
LDAA #$37 * A vale $37 (BCD)
ADDA #$25 * suma $37 y $25 (BCD) como binarios: A=$5C (no BCD)
DAA * DAA ajusta A a BCD, por lo que A=$62 (BCD correcto)

4.3.4. Datos alfanuméricos: caracteres y cadenas


Los códigos alfanuméricos, entre los que se incluyen los caracteres (‘A’, ‘B’,
etc.) se representan también mediante unos y ceros. Existen distintas formas de
realizar esta codificación, siendo la más extendida la denominada ASCII
(American Standard Code for Information Interchange), en la que, en la versión
original, cada código viene representado mediante un conjunto de 7 bits (128
códigos). Como el microprocesador maneja información en grupos de 8 bits, cada
byte entre $00 y $7F representará un código ASCII. De esta manera pueden
codificarse las letras mayúsculas, minúsculas, los caracteres que representan
dígitos, signos de puntuación, etc. (tabla 4.4). Por ejemplo, la letra ‘A’ tiene por
ASCII $41, la ‘B’ es $42, etc. (se sigue el orden alfabético); la ‘a’ es $61, la ‘b’ es
$62, etc.; el ‘0’ es $30, ‘1’ es $31, ‘2’ es $32, etc. Algunos valores ASCII
representan códigos de control o no imprimibles, como el de nueva línea (LF, line
feed, $0A), retorno de carro (CR, carriage return, $0D) o fin de transmisión
(EOT, end of transmission, $04). El ASCII original (7 bits) ha sido ampliado a 8
bits, donde los códigos que van del $80 a $FF se han reservado a diversos
caracteres internacionales y gráficos.
Por otro lado, las cadenas de caracteres o strings consisten en concatenar los
códigos ASCII de los caracteres que la componen. En un sistema µP suelen
emplearse para enviar mensajes al usuario (p.e., en el caso de las máquinas
expendedoras, «Introduzca importe exacto», «Crédito 200 ptas.», o «Su tabaco,
gracias»). Las cadenas pueden visualizarse en displays (como un LCD o una
pantalla), o pueden ser traducidas a sonidos y emitidas a través de un altavoz.
Las cadenas de caracteres se almacenan en memoria colocando los valores
ASCII (bytes) de cada uno de los caracteres que las componen en posiciones
126 Microprocesadores y microcontroladores

consecutivas (fig. 4.5). La cadena finaliza normalmente con un código que se


establece por convenio, denominado carácter terminador o de fin de cadena,
como, por ejemplo, el valor $04 (‘EOT’, tabla 4.4). Por lo tanto, una cadena
queda definida por su dirección de comienzo y el carácter de fin empleado.

$0100 48 ‘H’
4F ‘O’
4C ‘L’
41 ‘A’
04 EOT

FIGURA 4.5. Almacenamiento en memoria de una cadena de caracteres.

Dec Hex Ascii Dec Hex Ascii D. H. Ascii De. H. Ascii De. H. Ascii De. H. Ascii Dec Hex Ascii
0 00H NUL 20 14H DC4 40 28H ( 60 3CH < 80 50H P 100 64H d 120 78H x
1 01H SOH 21 15H NAK 41 29H ) 61 3DH = 81 51H Q 101 65H e 121 79H y
2 02H STX 22 16H SYN 42 2AH * 62 3EH > 82 52H R 102 66H f 122 7AH z
3 03H ETX 23 17H ETB 43 2BH + 63 3FH ? 83 53H S 103 67H g 123 7BH {
4 04H EOT 24 18H CAN 44 2CH ' 64 40H @ 84 54H T 104 68H h 124 7CH |
5 05H ENQ 25 19H EM 45 2DH - 65 41H A 85 56H U 105 69H i 125 7DH }
6 06H ACK 26 1AH SUB 46 2EH . 66 42H B 86 57H V 106 6AH j 126 7EH ~
7 07H BEL 27 1BH ESC 47 2FH / 67 43H C 87 58H W 107 6BH k 127 7FH DEL
8 08H BS 28 1CH FS 48 30H 0 68 44H D 88 58H X 108 6CH l
9 09H HT 29 1DH GS 49 31H 1 69 45H E 89 59H Y 109 6DH m
10 0AH LF 30 1EH RS 50 32H 2 70 46H F 90 5AH Z 110 6EH n
11 0BH VT 31 1FH US 51 33H 3 71 47H G 91 5BH [ 111 6FH o
12 0CH FF 32 20H SP 52 34H 4 72 48H H 92 5CH \ 112 70H p
13 0DH CR 33 21H ! 53 35H 5 73 49H I 93 5DH ] 113 71H q
14 0EH SO 34 22H " 54 36H 6 74 4AH J 94 5EH ^ 114 72H r
15 OFH SI 35 23H # 55 37H 7 75 4BH K 95 5FH _ 115 73H s
16 10H DLE 36 24H $ 56 38H 8 76 4CH L 96 60H ` 116 74H t
17 11H DC1 37 25H % 57 39H 9 77 4DH M 97 61H a 117 75H u
18 12H DC2 38 26H & 58 3AH : 78 4EH N 98 62H b 118 76H v
19 13H DC3 39 27H ' 59 3BH ; 79 4FH O 99 63H c 119 77H w

TABLA 4.4. Equivalencia decimal-hexadecimal-valor ASCII.


Instrucciones y modos de direccionamiento 127

4.4. Juego de instrucciones


En esta sección describiremos con brevedad algunas de las instrucciones más
habituales que conforman el juego de instrucciones (instruction set) del 6800; el
resto de las instrucciones, entre las que están las que conciernen al control de la
secuencia de programa, así como las nuevas instrucciones que incorpora el
68HC11, se expondrán al final del capítulo. Recordemos aquí que el juego de
instrucciones del 68HC11 es un superconjunto de las del 6800.
Las instrucciones que expondremos en esta sección (de movimiento de
información, lógicas, aritméticas y de manipulación del CCR) no son difíciles de
comprender, por lo que serán descritas con brevedad, incidiendo en los aspectos
básicos exclusivamente. Para profundizar en detalles, como puedan ser los modos
de direccionamiento concretos que cada instrucción soporta, o los bit de estado a
los que afecta, deberán consultarse las hojas de características de los citados
microprocesadores (en particular, en el manual de referencia del 68HC11
[Motorola 91] se explican con todo lujo de detalles). Por otra parte, recordemos
que no pretendemos aquí impartir un curso de programación en lenguaje
ensamblador, sino solamente proporcionar unas bases mínimas que permitan
programar los µP de 8 bits de la familia de Motorola. Por último, indicaremos
que la mejor manera de estudiar las instrucciones y modos de direccionamiento de
un microprocesador es realizando pequeños programas, que pueden ser simulados
o ejecutados en una tarjeta basada en el microprocesador a estudio.

4.4.1. Introducción
En el 6800 el código de operación se compone de un byte, que define tanto el
tipo de instrucción como el modo de direccionamiento que emplea. Con 8 bits
podrían definirse hasta 256 opcodes diferentes, de los cuales el 6800 sólo
implementa 195. La instrucción puede completarse con uno o dos bytes
adicionales, que, como hemos visto, o bien proporcionan el propio operando, o
bien permiten calcular su dirección. Algunas instrucciones se componen
solamente del opcode, al actuar implícitamente sobre algún bit de estado o
registro. De esta manera, en el 6800 las instrucciones pueden ocupar de 1 a 3
bytes, y su ejecución emplea de 1 a 8 ciclos de reloj.
A modo de ejemplo ilustrativo de la forma de codificar las instrucciones en
memoria, en las hojas de características del 6800 podemos encontrar que el
opcode de la instrucción LDAA en modo inmediato es 86, por lo que, si la
instrucción LDAA #$3F se sitúa en la posición $FB00 de memoria, aparecerá
codificada como se muestra en la fig. 4.6, con la secuencia de bytes 86 3F. Por
128 Microprocesadores y microcontroladores

otra parte, la instrucción LDAA $10A6 opera en modo extendido, por lo que
tendrá B6 por opcode, y aparecerá codificada en memoria como la secuencia B6
10 A6 (fig. 4.6).

FB00
1000 86 LDAA #$3F
FB01 3F
FB02 B6 LDAA $10A6
FB03 10
FB04 A6

FIGURA 4.6. Almacenamiento de las instrucciones en memoria.

4.4.2. Instrucciones de movimiento de la información


Desplazan información de un punto a otro del sistema: de memoria a
registro, de registro a memoria o de registro a registro. Algunas de ellas ya han
aparecido, como son la de carga en el acumulador A, LDAA, o guarda su
contenido en memoria STAA. Con ‘arg’ denotaremos el argumento, dato o
dirección que precisa la instrucción para operar.

LDAA arg LoaD Accumulator A (B), carga en el acumulador A (B) el


LDAB arg contenido de una casilla de memoria, o un dato inmediato

STAA arg STore Accumulator A (B), almacena el valor del


STAB arg acumulador A (B) en una casilla de memoria

TAB Transfer A to B, transfiere el contenido de A a B


TBA Transfer B to A, transfiere el contenido de B a A
LDX arg LoaD indeX (Stack pointer), carga en el registro X (S) el
LDS arg contenido de una casilla de memoria, o un dato inmediato

STX arg STore indeX (STore Stack pointer), almacena el valor del
STS arg registro X (S) en una casilla de memoria
Instrucciones y modos de direccionamiento 129

FB00
1000 CE LDX #$1234
FB01 12
FB02 34
FB03

FIGURA 4.7. Almacenamiento en memoria de una instrucción que opera con un número de 16 bits.

Las instrucciones que mueven información apoyándose en uno de los dos


acumuladores, A o B, ambos de un byte, lo hacen de ocho en ocho bits, mientras
que aquellas que trabajan con X o S, registros de dos bytes, mueven 16 bits. En
este sentido, Motorola utiliza un convenio contrario al de Intel: guarda en
memoria el byte más significativo y a continuación el menor. Por ejemplo, en la
fig. 4.7 se tiene la instrucción LDX #$1234, el byte más significativo ($12) se
almacena en $FB01 y el menos ($34) en $FB02; al ejecutarse la instrucción el
valor $12 se transferirá a la parte alta de X (XH) y $34 a la parte baja (XL).

4.4.3. Instrucciones aritmético/lógicas


Realizan operaciones aritméticas y lógicas sobre memoria o registros, algunas
de ellas ya han sido comentadas, como las de suma ADD y la de ajuste decimal
DAA. Las instrucciones más peculiares son la de rotación y desplazamiento,
cuya operación se interpreta con facilidad si se imagina un registro de
desplazamiento de ocho bits, más el acarreo C, que hace de noveno bit; p.e., al
ejecutar un desplazamiento a la izquierda, el contenido del bit 0 pasa al 1, el del 1
al 2, etc., y el del 7 al C. En el caso de los bits de los extremos, que traspasan su
contenido a un bit contiguo, pero en principio no reciben nada de ninguno de los
vecinos, su contenido se puede rellenar con ‘0’, con el valor de C o mantener su
valor actual, dependiendo de la instrucción. En el caso de las instrucciones de
rotación, el proceso es realimentado (en forma de «anillo»). Si esta explicación
no aclara lo suficiente el funcionamiento de estas instrucciones, se recomienda al
lector la consulta de los juegos de instrucciones de Motorola que se incluyen en el
apéndice.

CLRA CLeaR accumulator A (B), borra el contenido del


CLRB acumulador A (B)
CLR arg CLeaR, borra el contenido de una casilla de memoria
130 Microprocesadores y microcontroladores

DECA DECrement accumulator A (B), decrementa el contenido de


DECB A (B)
DEC arg DECrement, decrementa contenido de casilla de memoria
DEX DECrement indeX (Stack pointer), decrementa el contenido
DES del índice X (S)
INCA INCrement accumulator A (B), incrementa el contenido de
INCB A (B)
INC arg INCrement, incrementa contenido de una casilla de memoria
INX INCrement indeX (Stack pointer), incrementa el contenido
INS del índice X (S)
ADDA arg ADD accumulator A (B), suma A (B) con un dato o
ADDB arg contenido de memoria, el resultado se guarda en A (B)
ADCA arg ADd with Carry A (B), suma A (B) con dato o contenido de
ADCB arg memoria, más el acarreo C, guarda resultado en A (B)
ABA Add A to B, suma A y B, deja el resultado en A
SUBA arg SUBtract accumulator A (B), resta de A (B) un dato o
SUBB arg contenido de memoria, el resultado se guarda en A (B)
SBCA arg SUBtract with Carry A (B), resta de A (B) dato o contenido
SBCB arg de memoria y el valor de C, guarda el resultado en A (B)
SBA Subtract A minus B, resta A−B, deja el resultado en A

DAA Decimal Adjust A, ajusta A a BCD; A debe contener el


resultado de una suma ejecutada con ADDA, ADCA o ABA
ROLA ROtate Left A (B), rota hacia la izda. los bits del registro A
ROLB (B), con apoyo en el bit C (registro desplaz. realimentado)
ROL arg ROtate Left, ídem sobre contenido casilla de memoria
RORA ROtate Right A (B), rota hacia la dcha. los bits del registro A
RORB (B), apoyo en el bit C (registro desplaz. realimentado)
ROR arg ROtate Right, ídem sobre el contenido casilla de memoria
ASLA Arithmetic Shift Left A (B), desplazam. aritmético a la izda.
Instrucciones y modos de direccionamiento 131

ASLB del contenido de A (B) (el bit 7 va al C, entra ‘0’ por dcha.)
ASL arg Arithmetic Shift Left, ídem sobre contenido casilla memoria
ASRA Arithmetic Shift Right A (B), despl. aritm. de A (B) a dcha.
ASRB (bit 7 se propaga a dcha., el 0 va a C; conserva signo dato)
ASR arg Arithmetic Shift Left, ídem sobre el contenido de una casilla
LSRA Logic Shift Right A (B), despl. lógico a la decha. de A (B)
LSRB (entra ‘0’ por el bit 7, el bit 0 va a C; no conserva el signo)
LSR arg Logic Shift Left, idem sobre el contenido de una casilla
ANDA arg AND A (B), AND lógica entre los bits individuales de A (B)
ANDB arg y dato o contenido de memoria, el resultado queda en A (B)
ORAA arg OR Accumulator A (B), OR entre los bits individuales de A
ORAB arg (B) y un dato o contenido de memoria, resultado en A (B)
EOAA arg Exclusive OR Accumulator A (B), XOR entre bits de A (B) y
EOAB arg
dato o contenido de memoria, el resultado queda en A (B)

NEGA
NEGate A (B), complemento a dos de A (B), −A (−B)
NEGB
NEG arg NEGate, complemento a dos del contenido casilla memoria
COMA COMplement A (B), invierte los bits individuales de A (B)
COMB (complemento a uno)
COM arg COMplement, ídem del contenido de una casilla de memoria

El lector interesado en los detalles de cada instrucción debe consultar las


hojas de datos de Motorola. En particular, en el manual de referencia del 68HC11
[Motorola 91] cada instrucción se explica con elevado nivel de detalle.

4.4.4. Instrucciones de manipulación de los bits de estado


Este conjunto de instrucciones permiten cambiar el contenido de los bits
individuales que componen el registro de estado o CCR.
132 Microprocesadores y microcontroladores

CLC CLear Carry, pone a cero el bit C de acarreo


CLI CLear Interrupt mask, pone a cero el bit I (máscara de IRQ)
CLV CLear oVerflow, pone a cero el bit V de desbordamiento
SEC SEt Carry, pone a uno el bit C de acarreo
SEI SEt Interrupt mask, pone a uno el bit I (máscara de las IRQ)
SEV SEt oVerflow, pone a uno el bit V de desbordamiento
TAP Transfer A to P, transfiere el contenido de A al registro CCR
TPA Transfer P to A, transfiere el contenido del registro CCR a A

4.5. Control de la secuencia de programa


La secuencia normal de ejecución de un programa consiste en procesar
instrucción tras instrucción, siguiendo el orden en el que éstas están dispuestas en
memoria. No obstante, para construir estructuras algorítmicas (si/entonces,
bucles, etc.) se requieren algunas instrucciones que permitan romper esta
secuencia normal de ejecución; son las denominadas instrucciones de control de
la secuencia, que estudiaremos agrupadas del siguiente modo:
a) Instrucciones de salto incondicional, que ejecutan un salto a otra zona del
programa, desde la cual se prosigue la ejecución.
b) Instrucciones de salto condicional, que ejecutan el salto solamente cuando se
cumplen determinadas condiciones; mediante ellas se crean estructuras
algorítmicas.
c) Instrucciones de comparación y test, que apoyan la realización de estructuras
algorítmicas, elaborando la condición que posteriormente se comprobará con
una instrucción de salto condicional.
d) Instrucciones de manejo de subprogramas, que posibilitan la creación de
programas modulares.
e) Instrucciones de manejo de interrupciones, que se estudiarán detenidamente
cuando se aborde el importante capítulo de las interrupciones del µP.
De todas ellas, en esta sección estudiaremos las tres primeras, dejando los
subprogramas y las interrupciones para más adelante. Aunque incidiremos en ello
más adelante, debemos ya apuntar que mediante el manejo eficiente de estas
instrucciones conseguiremos desarrollar programas estructurados, compuestos por
Instrucciones y modos de direccionamiento 133

módulos que incluyen o llaman a otros módulos, siguiendo para ello una
metodología de diseño descendente.
Para el desarrollo de esta sección nos hemos inspirado en el texto de [Silva
82]. A dicho texto, y a otros como [Spasov 96, Peatman 88, Huang 96, Miller
93], remitimos al lector interesado en profundizar en estas cuestiones relativas a la
programación de microprocesadores.

4.5.1. Instrucciones de salto incondicional: JMP y BRA


Estas instrucciones ejecutan directamente un salto a cierta posición de
memoria. Se dispone para ello de dos instrucciones, JMP (JuMP) y BRA
(BRAnch). La instrucción JMP se denomina de salto absoluto, y en modo de
direccionamiento extendido su opcode va seguido de una dirección absoluta de 16
bits que expresa la casilla a la que se debe saltar. También puede operar en modo
indexado; en este caso, el opcode irá seguido de un desplazamiento de un byte a
añadir a la dirección almacenada en el registro X.
La instrucción BRA es de salto relativo; en ella, en vez de indicarse el
número concreto de la dirección a la que hay que saltar, se proporciona el número
de posiciones de memoria que deben saltarse. Tras el opcode correspondiente a
BRA se coloca un número de un byte, el desplazamiento o número de casillas que
deben saltarse a partir del valor actual del contador de programa; este
desplazamiento se interpreta en complemento a dos, por lo que permite saltos de
entre −128 y +127 bytes (hacia atrás o hacia adelante, respectivamente). Como ya
se ha comentado con anterioridad, a la hora de ejecutar efectivamente el salto el
PC se encuentra apuntando ya a la siguiente instrucción, dos bytes más allá en la
memoria (los que ocupa la propia instrucción de salto), por lo que los mayores
saltos posibles contados desde la posición que ocupa el opcode de la instrucción
BRA son, en realidad, de 126 bytes hacia atrás o 129 hacia adelante.
Podemos deducir, por lo tanto, que la instrucción JMP cuenta con la
desventaja de ocupar más espacio en memoria si la empleamos en modo
extendido (3 bytes, frente a los 2 de BRA), pero BRA como contrapartida
solamente permite acceder a posiciones relativamente próximas a la actual; por
tanto, siempre que sea posible, se prefiere el empleo de BRA. Además, las rutinas
basadas en instrucciones de salto relativo, como la BRA, son reubicables, es
decir, pueden ser colocadas libremente dentro del mapa de memoria del sistema
microprocesador (dentro de las restricciones del hardware disponible), al no
apuntar a posiciones fijas y concretas de memoria, como hace la JMP.
134 Microprocesadores y microcontroladores

Por último, se debe tener presente que el lenguaje ensamblador permite


trabajar con etiquetas que pueden representar datos o direcciones de memoria, a
las que el propio compilador asignará el valor adecuado, por lo que, en el caso de
los saltos relativos, nos ahorrarán el trabajo de tener que calcular «a mano» el
número de casillas de memoria que deben saltarse para acceder a la posición
deseada. Por ejemplo, en vez de escribir BRA 3, puede escribirse BRA AQUI, y
el compilador de ensamblador se ocupará de establecer qué valor numérico
concreto debe asignarse a la etiqueta ‘AQUI’. Por ejemplo, en el caso que
mostramos a continuación, en la rutina de la izquierda se realiza un salto de tres
posiciones hacia adelante (BRA 3), mientras que en la de la derecha se realiza el
mismo salto, pero haciendo uso de una etiqueta que apunta a la instrucción donde
se debe saltar; al compilar (ensamblar) la rutina de la derecha, el compilador
contará el número de casillas que debe saltar y automáticamente sustituirá la
etiqueta ‘AQUI’ por el valor 3.
LDAA #34 LDAA #34
BRA 3 * Salto BRA AQUI * Salto
STAA $A301 STAA $A301
LDAB $1000 AQUI LDAB $1000

Debe tenerse en cuenta que las etiquetas no pueden coincidir con ninguna
palabra reservada del lenguaje (ni instrucciones ni directivas). Recordemos
además que el símbolo ‘*’ indica que se va a incluir un comentario; cuando el
compilador encuentra un símbolo de este tipo ignora todo lo que viene a
continuación, pues sabe que no se trata de instrucciones de ensamblador. Es
importante incluir abundantes comentarios en los programas para mejorar su
legibilidad, lo que facilitará la introducción de modificaciones o su futura
adaptación. Si no se incluyen comentarios, un programa ensamblador leído unos
pocos días más tarde resulta absolutamente críptico e indescifrable.

4.5.2. Instrucciones de comparación y test


A diferencia de los lenguajes de alto nivel, el ensamblador no contiene
instrucciones que directamente implementen estructuras algorítmicas como las
condicionales SI/ENTONCES (if/then) y HAZ/MIENTRAS (do/while), o los
habituales bucles DESDE/HASTA (for/to), sino que el programador deberá
realizarlas «a mano» combinando varias instrucciones del ensamblador. Para
ello, la estructura debe dividirse en dos partes:
Instrucciones y modos de direccionamiento 135

1. Elaboración de la condición. Si la condición es sencilla, como por ejemplo


«actuar en caso de desbordamiento», esta etapa puede ser obviada, pues el
estado del indicador (en este caso, el V) surgirá directamente del programa
(por ejemplo, de una instrucción ADDA). Si se trata de otro tipo de
condiciones, como las habituales «mayor que», «menor o igual», etc., sí se
debe previamente elaborar la condición. Para ello se introducen las
denominadas instrucciones de comparación y test, que mediante una resta
comparan dos números, estableciendo en función del resultado el estado de los
indicadores (C, V, N y Z).
2. Saltar condicionalmente. Una vez la condición ya se ha elaborado por el
propio curso del programa, o explícitamente empleando instrucciones de
comparación, mediante instrucciones de salto condicional se saltará o no,
dependiendo de si se cumple la condición. Estas instrucciones se basan en el
valor de los indicadores de estado, que normalmente habrán sido establecidos
por una instrucción de comparación.
Por ejemplo, si se trata de implementar la siguiente estructura condicional:
SI (condición cierta) ENTONCES [bloque 1]
[bloque 2]
donde [bloque 1] y [bloque 2] son dos secuencias de instrucciones diferentes, se
puede hacer uso de la siguiente estructura de programa ensamblador:
Elaborar la condición (con instrucción de comparación)
Saltar a SIGUE si condición falsa (instrucción de salto condicional)
[bloque 1]
SIGUE [bloque 2]
donde la elaboración de la condición consiste en establecer una comparación entre
dos valores, haciendo uso de instrucciones de comparación, para a continuación
comprobar el resultado de dicha comparación mediante una instrucción de salto
condicional (obsérvese que se comprueba justo lo contrario, es decir, si la
condición es falsa). En esta sección nos centraremos en la parte relativa a la
elaboración de la condición, mientras que en la siguiente estudiaremos las
instrucciones de salto que se apoyan en ella.
Las instrucciones encargadas de elaborar la condición simplemente comparan
dos números, para que la instrucción de salto condicional posterior opere en
consecuencia (saltando si ambos números son iguales, o solamente si el primero
es mayor que el segundo, etc.). Para comparar dos datos estas instrucciones
136 Microprocesadores y microcontroladores

realizan, bien su resta, bien operaciones lógicas AND bit a bit, en función de las
cuales quedan actualizados los indicadores del registro de estado, mientras que el
resultado en sí no queda almacenado en parte alguna. P.e., si se desea saber si
X=Y, se realizaría la resta X−Y, y si queda activado Z querrá decir que,
efectivamente, dicha condición es cierta. Las instrucciones de elaboración de la
condición son las siguientes:
• Comparación. CMPA (CoMPare A), CMPB (CoMPare B) y CBA (Compare
B y A), la última de direccionamiento implícito (no requiere operandos
adicionales). Estas instrucciones comparan dos números realizando la resta del
contenido de uno de los acumuladores menos otro dato, actualizando el estado
de los señalizadores sin almacenar el resultado. Por ejemplo, CMPA $1000
lleva a cabo la operación (A)−($1000), y actualiza C, V, Z y N según el
resultado. Por su parte, la instrucción CBA compara los acumuladores A y B,
realizando la operación (A)−(B).
• Comparación de números de 16 bits. La instrucción CPX (ComPare X)
permite comparar dos números de 16 bits, el primero de los cuales es el
almacenado en el registro X. Por ejemplo, CPX $1000 realiza las operaciones
(XH)−($1000) y (XL)−($1001), actualizando Z y alterando N y V de una
forma particular (consúltense las tablas del juego de instrucciones en el
apéndice A). Recordemos que XL indica parte baja (Low) de X, o menos
significativa, y XH parte alta (High), o más significativa.
• Test. Realizan la comparación de un dato dado con el valor $00 (es decir, son
un caso particular de las anteriores). Se tiene TSTA (TeST A), TSTB (TeST B)
y TST (TeST), las dos primeras implícitas. Estas instrucciones actualizan Z y
N, y ponen siempre V y C a cero.
• Comparación de bits. Comprueban el estado de bits individuales, para lo cual
realizan la operación AND lógica entre los bits individuales de un acumulador
con un determinado dato. Se tiene BITA y BITB. BITA $1000, por ejemplo,
realiza la operación (A)⋅($1000), que se interpreta como la operación AND
lógica realizada entre sus 8 bits individuales. Estas instrucciones actualizan Z
y N, y ponen V a cero.

4.5.3. Instrucciones de salto condicional


Las instrucciones de salto condicional operan de forma similar a la de salto
relativo BRA, sólo que previamente comprueban el estado de alguno (o varios) de
los señalizadores C, V, N y/o Z, y únicamente ejecutan el salto cuando éstos
Instrucciones y modos de direccionamiento 137

poseen determinado valor. Estas instrucciones en combinación con las de


comparación permiten crear estructuras como bucles, «si/entonces», etc.
De entre las instrucciones que se emplean en la ejecución de saltos
condicionales, distinguiremos entre las de salto condicional simple, y las
instrucciones de salto que requieren elaboración previa de la condición.

4.5.3.1. Instrucciones de salto condicional simples (un señalizador)


Denominaremos de esta manera a aquellas instrucciones que comprueban el
valor de un solo bit de estado, para deducir si en una operación previa se ha dado
acarreo (C=1), desbordamiento (V=1), resultado negativo (N=1) o cero (Z=1), y
actuar en consecuencia.
Para su estudio distinguiremos entre aquellas instrucciones que suelen
emplearse con números sin signo, con signo, o en cualquiera de los dos casos.
Las instrucciones de salto condicional que se fijan en el estado del señalizador C
se suelen emplear para números sin signo, puesto que, en general, éste será
significativo solamente para ellos. Para el caso de los números con signo se
comprobará el estado de los señalizadores V y N (desbordamiento y negativo). El
indicador Z podrá emplearse en ambos casos. Con estas consideraciones, se tiene
la clasificación de la tabla 4.5. Por ejemplo, la instrucción BCC 7 saltaría 7
casillas de memoria en el caso de que el indicador de acarreo estuviese a cero.

Tipo numérico Instr. Significado Condición


Sin signo BCC Branch if Carry Clear C=0
BCS Branch if Carry Set C=1
Con signo BMI Branch if MInus N=1
BPL Branch if PLus N=0
BVC Branch if oVerflow Clear V=0
BVS Branch if oVerflow Set V=1
Con o sin signo BEQ Branch if EQual to zero Z=1
BNE Branch if Not Equal to zero Z=0

TABLA 4.5. Instrucciones simples de salto condicional.


138 Microprocesadores y microcontroladores

Una función típica de la instrucción BCS es saltar a una rutina de error


cuando se produce acarreo en una operación con dos números sin signo, y BVS
suele emplearse para saltar a una rutina de error de desbordamiento. En cuanto a
las instrucciones BMI y BPL, por una parte se debe tener en cuenta que, si se ha
producido un desbordamiento, el estado del señalizador N no tiene sentido; por
otra, el cero ($00) se considera un número positivo (N=0).

Conviene tener presente que...


En las hojas de características no aparece explícitamente si determinada
instrucción de salto condicional se emplea con números con o sin signo,
aunque puede deducirse fácilmente:
• Si una instrucción de salto condicional dada tiene en cuenta el señalizador C,
se utilizará para números sin signo.
• Si observa el estado de los bit V o N, se aplicará a números con signo
(complemento a dos).
• Si solamente tiene en cuenta el bit de cero Z, puede aplicarse en ambos casos.

4.5.3.2. Instrucciones de salto con comparación previa


Denominaremos de esta manera a aquellas instrucciones de salto condicional
que suelen emplearse tras realizar una previa comparación entre dos valores; para
ello se hace uso con frecuencia de instrucciones de comparación y test, aunque
puede realizarse también mediante una instrucción de resta u operaciones lógicas.
Cuando se realiza la comparación de dos números (instrucciones de
comparación), para luego tomar la decisión de saltar o no saltar (instrucción de
salto condicional), se dice que se elabora la condición que se desea comprobar.
La mayor parte de las instrucciones de salto condicional que presentamos a
continuación comprueban el estado de varios bits indicadores; son excepciones las
instrucciones, BNE y BEQ, que solamente comprueban el señalizador Z, y las
BCC y BCS, que solamente comprueban el C, las cuales fueron ya introducidas
con anterioridad. De nuevo, consideraremos por separado las instrucciones que
suelen emplearse con números sin signo, con signo, o en ambos casos; en la tabla
4.6 proporcionamos un resumen de todas ellas. En la columna «Bits de estado» se
muestra la condición que deben cumplir los señalizadores para producirse el salto,
mientras que en la columna «Condición» aparece su traducción a lenguaje
algorítmico, la cual es válida solamente si la instrucción de salto se emplea tras
una elaboración de condición basada en la resta de dos datos (como las de
comparación y test).
Instrucciones y modos de direccionamiento 139

Instr. Significado Bits estado Condición


Sin signo BCC Branch if Carry Clear C=0 mayor o igual
(BHS) (Branch if Higher of Same)

BCS Branch if Carry Set C=1 menor


(BLO) (Branch if LOwer)

BHI Branch if HIgher C+Z=0 mayor


BLS Branch if Lower or Same C+Z=1 menor o igual
Con signo BGE Branch if Greater or Equal N⊕V=0 mayor o igual
BGT Branch if Greater Than Z+(N⊕V)=0 mayor
BLE Branch if Less than or Equal Z+(N⊕V)=1 menor o igual
BLT Branch if Less Than N⊕V=1 menor
Con BEQ Branch if EQual to zero Z=1 igual
o sin signo BNE Branch if Not Equal to zero Z=0 distinto

TABLA 4.6. Instrucciones de salto condicional con elaboración previa de la condición en el 6800.
Estas instrucciones requieren de una instrucción previa que elabore la condición.

En la tabla 4.6 podemos observar que la comparación de dos números sin


signo se basa en el valor del acarreo C. P.e., para deducir si X es menor que Y, se
realiza X−Y, y, como hemos visto, si X<Y la ALU debe «tomar prestado», por lo
que activará C (C=1); por lo tanto, comprobar si X<Y (sin signo) equivale a
comprobar si C=1, es decir, se debe emplear la instrucción BCS. Por lo tanto, la
condición contraria, X mayor o igual que Y, se comprueba observando si C=0
mediante BCC. Por lo tanto, BCC y BCS se emplean para dos asuntos diferentes,
para comprobar acarreo y para comparar dos números sin signo; para distinguir
ambas situaciones en el 68HC11 se introducen dos nuevos mnemónicos, BHS y
BLO, de igual opcode que BCC y BCS, es decir, operan de idéntica forma, pero
denotan explícitamente su empleo en la comparación de números sin signo.

4.5.4. Ejemplos de estructuras algorítmicas


En general, las estructuras que definen la secuencia de ejecución de las
instrucciones por una máquina pueden clasificarse en tres grupos:
140 Microprocesadores y microcontroladores

1. Estructura secuencial. Es el orden habitual de ejecución de instrucciones, una


tras otra.
2. Estructura de alternativa. Un grupo de instrucciones que se ejecuta cuando se
cumple cierta condición (SI/ENTONCES, SI/ENTONCES/SINO).
3. Estructuras repetitivas. Grupo de instrucciones que se ejecuta determinado
número de veces (HAZ/MIENTRAS/, PARA/HASTA, MIENTRAS QUE).
En esta Sección mostraremos algunas formas de codificar en ensamblador
distintas estructuras algorítmicas habituales; no pretende ser un estudio formal
completo sino simplemente ilustrativo.

SI/ENTONCES (if/then).
La estructura SI/ENTONCES (if/then) presenta la siguiente forma, ya
mostrada previamente:

SI (condición cierta) ENTONCES [1] Verdadera


Falsa
¿condición? [1]
[2]

[2]

donde [1] y [2] son dos secuencias de instrucciones diferentes. Esta estructura se
realizaría en ensamblador de la siguiente manera:
Elaborar la condición (instrucción de comparación)
Saltar a SIGUE si condición falsa (salto condicional)
[1]
SIGUE [2]
En los siguientes ejemplos ilustraremos la codificación en ensamblador de la
estructura SI/ENTONCES. En el ejemplo 1 no se precisará de la elaboración
previa de la condición con instrucciones de comparación, pero sí en el ejemplo 2.

Ejemplo 1
En una planta embotelladora se controlará el número de botellas envasadas
mediante un 6800. Construye un contador software de 16 bits que permita
contabilizar hasta 65.535 botellas, haciendo uso de dos casillas de memoria
Instrucciones y modos de direccionamiento 141

consecutivas etiquetadas como DATO1 y DATO2, siendo DATO1 la más


significativa.

Resolución:
Una posible codificación en ensamblador consiste en incrementar DATO2
(INC DATO2) y cuando DATO2 pase de $FF a $00 (se sobrepasa su capacidad
de contabilizar hasta 255) incrementar entonces DATO1; para ello habrá que
comprobar cuándo se cumple Z=1.
Como norma, a la hora de confeccionar un programa, siempre en primer lugar
debe proponerse el algoritmo que resuelve el problema, bien en diagrama de flujo,
bien en pseudocódigo (se denomina así a una manera esquemática de representar
un algoritmo mediante instrucciones que recuerdan las de los lenguajes de alto
nivel). En el caso que se plantea, p.e., se tiene el siguiente diagrama de flujo:

DATO1 DATO2

DATO2:=DATO2+1
Contador de 16 bits

No Si
¿Z=1? DATO1:=DATO1+1

O bien, haciendo uso de pseudocódigo quedará:


Incrementar DATO2
SI Z=1 ENTONCES DATO1:=DATO1+1
Estamos haciendo uso de la condicional SI/ENTONCES, que no tiene
contrapartida en ensamblador, por lo que habría que detallarlo así:
Incrementar DATO2
Saltar a SIGUE cuando Z≠1 (instrucción salto condicional)
DATO1:=DATO1+1
SIGUE ....
142 Microprocesadores y microcontroladores

que, codificado en ensamblador, quedaría


INC DATO2
BNE SEGUIR * sólo salta si Z=0
INC DATO1
SEGUIR .....
Normalmente, tras incrementar DATO2 el indicador Z valdrá cero, por lo que
BNE ejecutará el salto y no se incrementará DATO1. Cuando Z=1 (lo que indica
que el byte menos significativo pasa de $FF a 0), BNE no saltará, por lo que se
incrementará DATO1.
Es importante observar que en una condicional SI/ENTONCES
comprobaremos con instrucciones de salto condicional justo si se ha dado la
condición contraria a la que nos interesa, para en ese caso saltar y no ejecutar las
instrucciones asociadas al ‘ENTONCES’.
Por último, hay que hacer notar que aunque podría pensarse que también es
posible realizar este programa basándose en el bit de acarreo C en vez de en el Z,
resulta que la instrucción INC no modifica el estado de C (lo cual puede
comprobarse consultando el juego de instrucciones del 6800 en el apéndice A).

En el siguiente ejemplo ilustraremos la realización en ensamblador de la


estructura SI/ENTONCES haciendo uso de instrucciones de comparación, y
mostraremos la diferencia de tratamiento de los números con signo y sin signo.

Ejemplo 2
Escribir un programa que guarde en la dirección etiquetada por MAXTEM la
mayor de 3 temperaturas almacenadas en las direcciones TEM1, TEM2,
TEM3, considerando que se trata de binarios de 8 bits sin signo (temperaturas
entre 0 y 255 ºC). A continuación, resolver el mismo problema suponiendo
que se trata de números en complemento a dos (de −128 a +127 ºC).

Resolución:
Una solución al problema es la siguiente (haremos uso de pseudocódigo-
RTL):
Instrucciones y modos de direccionamiento 143

MAXIMA ←(TEM1)
SI (MAXIMA)<(TEM2) ENTONCES MAXIMA ←(TEM2)
SI (MAXIMA)<(TEM3) ENTONCES MAXIMA ←(TEM3)
MAXTEM ←(MAXIMA)
El siguiente paso consiste en codificar el algoritmo en ensamblador. Una
posible codificación para los dos casos solicitados (con y sin signo) es la
siguiente, donde codificamos la estructura SI/ENTONCES de la manera indicada:

* Temperaturas solo + (sin signo) * Temperaturas + y − (con signo)


LDAA TEM1 LDAA TEM1
CMPA TEM2 CMPA TEM2
BCC fin1 * BHS BGE fin1
LDAA TEM2 LDAA TEM2
fin1 CMPA TEM3 fin1 CMPA TEM3
BCC fin2 * BHS BGE fin2
LDAA TEM3 LDAA TEM3
fin2 STAA MAXTEM fin2 STAA MAXTEM

De nuevo puede observarse que, si se desea implementar ‘Si X menor que Y’,
se hará uso de la instrucción que salta justo cuando se da lo contrario BCC (BHS),
o BGE para el caso de números complemento a dos, las cuales equivalen a
«mayor o igual».
En los programas se señalan las instrucciones que implementan la estructura
algorítmica SI/ENTONCES haciendo uso de una instrucción de elaboración de
condición, más un salto condicional. Conviene observar que en cada caso, con
signo o sin signo, se aplican las instrucciones de salto adecuadas. Por otra parte,
debe siempre tenerse en cuenta que la solución de un problema nunca es única,
sino que a cada cual se le pueden ocurrir diferentes soluciones, mejores o peores,
pero quizás perfectamente válidas.
144 Microprocesadores y microcontroladores

SI/ENTONCES/SINO (if/then/else)
La estructura SI/ENTONCES/SINO (if/then/else) presenta la siguiente forma
conocida:

SI (condición cierta) ENTONCES [1] Falsa Verdadera


¿condición?
SINO [2]
[2] [1]
[3]

[3]

que se realizaría de la siguiente manera en ensamblador:


Elaborar la condición (instrucción de comparación)
Saltar a FALSO si condición falsa (salto condicional)
VERDAD [1]
Saltar a FIN
FALSO [2]
FIN [3]

HAZ/MIENTRAS (do/while)
La estructura HAZ/MIENTRAS es una condicional que permite realizar
iteraciones, en las que el conjunto de instrucciones que incluyen se ejecutan por lo
menos una vez, pues la condición se comprueba al final. Presenta la siguiente
forma:

HAZ [1]

[1]
MIENTRAS (condición cierta) Verdadera
¿condición?
[2]
Falsa

[2]
Instrucciones y modos de direccionamiento 145

Esta estructura se puede realizar de la siguiente manera en ensamblador:


OTRA [1]
Elaborar condición (instrucción de comparación)
Saltar a OTRA si condición verdad (salto condicional)
[2]

Bucles DESDE/HASTA (for/to)


Realizando bucles con HAZ/MIENTRAS, primero se ejecuta el cuerpo del
bucle y luego se comprueba la condición, de modo que sus instrucciones por lo
menos se ejecutan una vez. Pero en ocasiones resulta más conveniente realizar
primero la comprobación, de forma que su interior no se ejecute nunca si de
entrada la condición es falsa; éste es el caso de los bucles DESDE/HASTA, que
presentan la siguiente forma:

contador +1
PARA contador=M HASTA N
[1]
Falso
FIN PARA ¿contador=fin? [1]
[2]
Verdadero

[2]

Suponiendo M<N, esta estructura se realizaría de la siguiente manera en


ensamblador:
contador← M
OTRA Elaborar la condición (contador=N)
Saltar a FIN si condición verdad
contador← contador+1
[1]
Saltar a OTRA
FIN [2]
146 Microprocesadores y microcontroladores

Ejemplo 3
Realizar una rutina para el 68HC11 que copie un bloque de 10 bytes que
comienza en la dirección $3000 a la $4000 (recordar que el 68HC11 incluye,
además del X, un segundo registro índice Y, por lo que, además de las
instrucciones LDX, STX, etc., se tendrán las LDY, STY, etc.).

Resolución:
El algoritmo sería:
FOR I=0 TO 9
$4000←($3000+I)
END FOR
y en RTL detallado tendríamos:
X←$3000 * dirección origen (puntero de datos de origen)
Y←$4000 * dirección destino (puntero de destino)
B←10 * número de casillas a copiar; B hace de contador
MIENTRAS (B>=0)
(Y)←((X))
X←(X) +1
Y←(Y) +1
B←(B)−1
FIN_MIENTRAS
(la estructura FOR habitual es un caso particular de la MIENTRAS QUE).
Codificamos en ensamblador:
LDX #$3000 * X es el puntero origen
LDY #$4000 * Y es el puntero destino
LDAB #10 * B es el contador
OTRA TSTB * (B)−0, compara contenido de B con 0...
BLO FIN * ... y si es menor (LOwer), se acabó
LDAA $00, X
STAA $00, Y
INX
INY
Instrucciones y modos de direccionamiento 147

DECB * aquí la condición la elabora DECB


BNE OTRA * y aquí se comprueba el contenido de B
FIN ....... * continuaría el resto del programa

También podíamos haber resuelto este problema con la estructura


anterior HAZ/MIENTRAS:
X←$3000
Y←$4000
B←10
HAZ
(Y)←((X))
X←(X) +1
Y←(Y) +1
B←(B)−1
MIENTRAS (B≠0)
que en ensamblador quedaría:
LDX #$3000
LDY #$4000
LDAB #10
OTRA LDAA $00, X
STAA $00, Y
INX
INY
DECB
BNE OTRA
pero ésta cuenta con el inconveniente de actuar primero y comprobar después, de
modo que, si por error se coloca inicialmente en el contador B un valor negativo
(¡número de veces negativo!), no sería detectado y el bucle se ejecutaría
erróneamente.
148 Microprocesadores y microcontroladores

4.6. Programación de microprocesadores


Antes de presentar el resto de las instrucciones pertenecientes al repertorio
del 6800, estudiaremos algunas cuestiones sobre la programación de µP.
Queremos de nuevo advertir que no es nuestra intención impartir un curso de
programación en ensamblador, sino solamente proporcionar una base suficiente
que permita programar los µP de 8 bits de la familia 68XX de Motorola.

4.6.1. Código máquina, ensamblador y lenguajes de alto nivel


En primer lugar, clarificaremos una serie de conceptos que pueden
permanecer todavía un tanto obscuros o confusos: código máquina, lenguaje
ensamblador y lenguajes de alto nivel. El código máquina no es otra cosa que el
código binario que realmente entiende el µP, es decir, series de unos y ceros;
debido a que al ser humano le resultan difíciles de manejar y memorizar, suelen
representarse codificados en hexadecimal (el hexadecimal no es otra cosa que
código binario en notación compacta, en la cual 4 bits se representan por un
código entre 0 y F). A modo de ejemplo, resulta más fácil memorizar B6 como
opcode de la instrucción LDAA (modo extendido) que su binario 1011 0110.
Con todo, la notación hexadecimal del código máquina sigue pareciendo
sumamente críptica a los ojos del ser humano, por lo que ya en los años cincuenta
se introdujo el lenguaje ensamblador para facilitar la programación de las
máquinas computadoras. El lenguaje ensamblador consiste en representar cada
código de operación (un número binario) por una cadena de caracteres
denominada mnemónico, que posee cierto sentido para el ser humano, lo que
permite una mucho más fácil memorización y manejo. Los mnemónicos no son
otra cosa que una abreviatura de la operación que representan (en inglés). Así, en
vez de escribir B6, podemos escribir LDAA (LoaD Accumulator A), más
fácilmente reconocible y memorizable.
En el lenguaje ensamblador se introducen más elementos que facilitan la
programación, como la utilización de etiquetas que representan datos o
direcciones de memoria, y las directivas o pseudoinstrucciones (pues poseen
apariencia de instrucciones), órdenes directas al compilador, sin traducción a
código máquina. Las siguientes son algunos ejemplos de las directivas de los
ensambladores de Motorola (AS0, AS11, Apéndice B): ORG (origen), que
establece el lugar de la memoria donde se guardará el programa; END, que indica
el final del fichero; FCB (Form Constant Byte), que permite guardar datos en una
determinada posición de memoria; EQU, que asigna valores a etiquetas, etc. A
modo de ejemplo, presentamos a continuación un programa de suma BCD en el
que se hace uso de instrucciones (LDAA, ADDA, DAA, STAA), directivas
Instrucciones y modos de direccionamiento 149

(ORG, EQU, FCB, END), etiquetas que representan direcciones (dato1, dato2,
resul) y comentarios (seguidos por el símbolo ‘*’). Obsérvese el formateo del
texto, con las etiquetas pegadas al margen izquierdo y las instrucciones separadas
del margen mediante un tabulador.
* Programa de suma BCD. Marzo 1999.
resul EQU $0003 * definición de la etiqueta resul

ORG $0000 * los datos del programa se colocan a partir de $00


dato1 FCB $37 * en $0000 (etiqueta dato1) se guarda el primer dato
dato2 FCB $25 * en $0001 (etiqueta dato2) se guarda el segundo dato
ORG $100 * el programa se guarda a partir de $100
LDAA dato1 * A←($0000), es decir, A vale $37
ADDA dato2 * A←($0001)+(A), es decir, suma $37 y $25
DAA * DAA ajusta A a BCD, por lo que A=$62
STAA resul * guardamos el resultado en la dirección resul ($0003)
END * fin de programa

Una vez que se transcribe en un fichero un programa en lenguaje


ensamblador, se hace necesaria su traducción a código máquina, que, en
definitiva, es el único lenguaje que la CPU reconoce y ejecuta. Para ello se utiliza
un programa traductor o compilador, que se encarga de leer el fichero con los
mnemónicos y las pseudoinstrucciones (código fuente) y construir un nuevo
fichero con los códigos hexadecimales (código objeto). Este programa recibe el
nombre de programa ensamblador (assembler); y, cuando el programa
ensamblador se ejecuta sobre una máquina diferente a aquella para la que está
generando código máquina, se denomina ensamblador cruzado (cross-assembler).
Por ejemplo, los programas AS0.EXE y AS11.EXE de Motorola (dominio
público, http://www.motorola.com/pub/SPS/MCU/ibm) son ensambladores
cruzados, ya que se ejecutan en un PC, pero generan código máquina para los µP
6800 y 68HC11, respectivamente. Mediante estos programas ensambladores
podría compilarse el programa anterior.
Con todo, la programación en ensamblador seguía siendo tarea ardua y
tediosa, por lo que no muchos años más tarde (finales de los años cincuenta) se
introdujeron los denominados lenguajes de alto nivel, que hacían uso de
instrucciones más próximas a la forma de pensar del ser humano y más fáciles de
usar, como las conocidas if/then/else, while, do/until, etc. Cada una de las
instrucciones de un lenguaje de alto nivel representa, en realidad, una serie de
150 Microprocesadores y microcontroladores

instrucciones del ensamblador, que a su vez equivalen a ciertos códigos


hexadecimales. El programa que traduce un fichero con un programa escrito en
lenguaje de alto nivel a código máquina se denomina compilador. Haciendo uso
de un lenguaje de alto nivel, como C, Fortran o Pascal, al ser humano le resulta
más fácil programar una CPU. Como contrapartida, en términos generales se
tiene que el código generado será menos óptimo que el que un buen programador
puede obtener codificando directamente en ensamblador, pues resultará más
extenso y además más lento. Por ello, a la hora de programar microprocesadores
incorporados en sistemas específicos, en los que la cantidad de memoria está muy
limitada, a menudo se sigue empleando el lenguaje ensamblador.
A continuación expondremos la diferencia entre ensambladores absolutos y
reubicables. Un compilador como AS0 o AS11, en el que el programa está
incluido en un único fichero, y donde la dirección de cada bloque queda definida
de forma precisa mediante la directiva ORG (p.e., ORG $F000), se denomina
ensamblador absoluto, ya que genera código absoluto, es decir, directamente
ejecutable, pues cada instrucción tiene ya asignada una dirección concreta.

Lenguaje ensamblador Lenguaje ensamblador Lenguaje de alto nivel

Ensamblador absoluto Ensamblador reubicable Compilador

Código objeto absoluto Código objeto Código objeto


(ejecutable)
Linker Linker

Código ejecutable Código ejecutable

FIGURA 4.8. Proceso de compilación del código fuente (en ensamblador y alto nivel).

Lenguaje de alto nivel

Lenguaje ensamblador

Código máquina

FIGURA 4.9. Distintos niveles de los lenguajes de programación.


Instrucciones y modos de direccionamiento 151

Sin embargo, cuando se desarrolla un programa de gran longitud, puede


resultar más práctico dividirlo en varios ficheros, cada uno conteniendo un
módulo de programa. En este caso se desconoce la dirección final donde irá cada
módulo (sólo puede saberse cuando se pongan todos juntos, uno a continuación de
otro), por lo que el compilador no asigna aún direcciones definitivas: se dice que
se tiene un ensamblador reubicable. Para construir el código ejecutable
(absoluto) deben reunirse los distintos módulos en un programa único, en el que
cada uno tendrá asignadas ya sus posiciones definitivas dentro del mapa de
memoria del sistema. Éste es el proceso denominado linkado (del inglés link) o
ensamblado de módulos, que se realiza mediante un programa denominado
montador o linker. En el caso de los lenguajes de alto nivel, es siempre necesario
realizar este último paso antes de disponer de un programa directamente
ejecutable por la máquina.
Un ejemplo concreto de ensamblador reubicable y proceso de linkado puede
consultarse en [Cahill 93]. En el ensamblador reubicable que aparece en dicha
referencia, en los ficheros fuente se indican las zonas de programa con la directiva
‘.pset _text’, y las de datos con ‘.pset _data’, el programa principal se indica con
‘.public main’, y las etiquetas que pueden ser referenciadas por otros ficheros se
declaran externas, por ejemplo ‘.external hola’. Al compilar se generan diversos
ficheros de extensión ‘*.o’, por ejemplo, ‘main.o’, ‘vector.o’, etc., y el linkador
debe reunirlos y asignar la dirección final de la zona de datos y del programa, por
ejemplo, de la forma ‘link -db 0x000 -tb0xe000 main.o -tb vector.o -o
ejemplo.exe’; todo el programa ejecutable queda así contenido en el fichero
‘ejemplo.exe’. Los detalles concretos pueden variar de un compilador a otro, pero
la filosofía es la misma.

4.6.2. Metodología de la programación. Programación metódica


A continuación proporcionaremos una serie de consejos relacionados con la
forma recomendable de realizar programas. Los malos programadores
directamente se sientan ante el teclado a codificar el programa (sea ensamblador
o alto nivel); el resultado habitual es el denominado «código espagueti» (código
enrevesado, sin orden ni estructura, con saltos de un lado para otro). Por contra,
los buenos programadores trabajan con método; los pasos recomendables a
seguir en el desarrollo de un programa metódicamente serían los siguientes:
1. Definición precisa del problema. Se debe comprender bien el problema a
resolver y plantearlo en sus justos términos.
2. Planteamiento y partición del problema. Se debe tender hacia una
metodología descendente o modular, dividiendo el programa en módulos o
152 Microprocesadores y microcontroladores

subprogramas, que a su vez llaman a módulos más simples. De este modo, el


problema inicial queda dividido en problemas más sencillos y más fáciles de
resolver (divide y vencerás).
3. Desarrollo y verificación de los algoritmos. Previamente a su plasmación
concreta como rutinas, cada algoritmo debe ser planteado sobre el papel,
haciendo uso del denominado pseudocódigo, o mediante diagramas de flujo
(fig. 4.10).
4. Codificación. Es la transformación de los algoritmos en el código del lenguaje
de programación seleccionado (ensamblador, C, Pascal, etc.). En una
aplicación real el lenguaje a utilizar no suele venir impuesto, sino que puede
ser seleccionado en función de diversos factores, como la aplicación concreta,
el sistema donde se implantará, facilidades de desarrollo, etc. No obstante, los
microprocesadores de aplicación industrial suelen programarse en ensamblador
o en lenguaje C (relativamente próximo al ensamblador). El código debe
resultar claro y legible, y se deben incluir abundantes comentarios.
5. Depuración y optimización. Una vez desarrollado el programa, debe
comprobarse exhaustivamente. Pueden también plantearse mejoras para lograr
una menor ocupación de memoria o reducción del tiempo de ejecución
(optimizaciones), según las exigencias del problema.
6. Documentación. Se trata de un aspecto importante, pues de una buena
documentación dependerá, entre otras cosas, la posibilidad de introducir
mejoras en el futuro o de adaptar el programa a otras aplicaciones, ahorrando,
por lo tanto, tiempo de desarrollo. Contempla tanto el incluir comentarios en
los programas como explicar su operación y adjuntar diagramas de flujo,
especificar qué datos de entrada precisa junto a su formato y qué tipo de
salidas proporciona.
Normalmente, la calidad de un programa se mide por el tiempo de ejecución
y la memoria que precisa. No obstante, existen otras cuestiones importantes que
muchas veces no son tan tenidas en cuenta, como la legibilidad del código final
desarrollado, algo que resulta fundamental en el frecuente caso de precisar
introducir futuras modificaciones (mantenimiento del programa), o de trabajar en
equipo (donde diversos programadores deben ser capaces de entender con
facilidad programas desarrollados por otros).
Instrucciones y modos de direccionamiento 153

Principio Fin Entrada/Salida

No
¿condición?

Bloque de Si
instrucciones (proceso)
No
¿condición? A B

Si Llamada a subrutina Conector a la Conector a


misma página diferente página

FIGURA 4.10. Algunos símbolos convencionales empleados en diagramas de flujo.

* ENCABEZAMIENTO
* Título del programa
* Nombre del autor, fecha, versión
* Microprocesador, mapa de memoria...
* DEFINICIÓN DE ETIQUETAS
EQU
* CONSTANTES
ORG $NN
FCB
* VARIABLES
ORG $MM
FCB
* PROGRAMA DE INICIALIZACIÓN (RESET)
ORG $XX
* PROGRAMA PRINCIPAL
ORG $YY
* SUBRUTINAS
ORG $ZZ
*FIN
END

FIGURA 4.11. Estructura/formato del fichero que contiene un programa.

Por lo tanto, los objetivos ideales consistirían en la confección de programas


cortos, rápidos, fácilmente comprensibles (legibles), verificables y modificables.
No obstante, estos cinco puntos son objetivos contrapuestos, pues muchas veces
la mejora en uno de estos aspectos conlleva el empeoramiento en otros, por lo que
se debe alcanzar un compromiso. Con frecuencia resulta conveniente sacrificar
154 Microprocesadores y microcontroladores

velocidad y memoria ocupada (a no ser que se trate de una aplicación muy


especial) para mejorar la legibilidad. Es también fundamental que el programa
quede bien comentado y estructurado siguiendo algún tipo de norma (fig. 4.11),
pues con ello aumentará notablemente su legibilidad.
Finalmente, en el desarrollo de grandes aplicaciones se tiende hacia la
programación estructurada, término que hace referencia a la práctica del diseño
descendente (de lo general a lo particular), al uso de las estructuras algorítmicas
señaladas en la sección 4.5.4, y de recursos abstractos en el tratamiento de datos y
módulos de programas (cuyo objetivo es que se comporten como una nueva
instrucción, caja negra que implementa cierta función sin que necesitemos
conocer los detalles). Así, la aplicación final suele constar de un pequeño
programa principal y de numerosas subrutinas que son llamadas.

Conviene recordar que...


Se recomienda una metodología descendente o modular, en la que debe
procurarse:
• Separar la zona de datos de la zona de programa.
• Plantear un (pequeño) programa principal...
• ... y subrutinas, que son llamadas (problema dividido en partes sencillas).
• Debe evitarse el código «espagueti», utilizando estructuras algorítmicas como
‘mientras’ o ‘si/entonces/sino’, en vez de saltos directos (equivalentes a los
famosos ‘go to’).
• Se deben incluir abundantes comentarios.
• ... y el programa debe quedar bien documentado, con diagramas de flujo o
pseudocódigo.
• La legibilidad final es importante; simplificar u optimizar «excesivamente» un
programa puede conllevar una menor legibilidad del código y aparición de
errores difícilmente detectables.

4.7. Subprogramas
En el punto anterior hemos hablado de programar haciendo uso de una
metodología descendente, en la que se reduce la complejidad de un problema
descomponiéndolo en partes más fáciles de resolver. Ello nos conduce
directamente a dividir el programa en desarrollo en módulos o subprogramas más
simples. Existen diferentes tipos de subprogramas, como las subrutinas, las
interrupciones y las macros, que trataremos a continuación. Para el manejo de
Instrucciones y modos de direccionamiento 155

estos distintos tipos de subprogramas se introducen instrucciones de salto a


subprograma, y retorno de subprograma, que también estudiaremos.

4.7.1. Subrutinas. La pila del sistema


Dividir el programa en módulos es importante como método de facilitar el
desarrollo del software, pero también sucede en ocasiones que un mismo conjunto
de instrucciones debe ser repetido en diversas partes del programa (por ejemplo, si
en distintos puntos de la aplicación debemos medir el tamaño de una cadena de
caracteres). Una alternativa a teclear un mismo conjunto de instrucciones una y
mil veces por todo el programa consiste en hacer uso de subrutinas. Una
subrutina es un grupo de instrucciones que pueden ser llamadas desde cualquier
punto del programa para ser ejecutadas. Cuando una subrutina es llamada, para lo
cual se emplea una instrucción del microprocesador al efecto, el denominado
programa principal transfiere su ejecución a la subrutina, procediéndose a
continuación a la ejecución de las instrucciones que la componen. Otra
instrucción diferente se encargará de indicar al microprocesador el final de la
subrutina, devolviéndose entonces el control al programa principal, el cual
prosigue con la secuencia normal de ejecución allá donde se dejó.
En el 6800 existen dos instrucciones de llamada a subrutina, JSR (Jump to
SubRoutine) y BSR (Branch to SubRoutine). JSR tiene las mismas características
que la instrucción JMP de salto absoluto, mientras que BSR hereda las
características de la de salto relativo BRA. Por otra parte, la instrucción RTS
(ReTurn from Subroutine) sirve en ambos casos para indicar el fin de la subrutina
y devolver el control al programa principal.
Por ejemplo, la instrucción JSR $FB00 salta a la dirección $FB00 y prosigue
a partir de allí la ejecución del programa; para ello, el microprocesador sustituye
el actual valor del PC por la nueva dirección $FB00. Pero, cuando el µP
encuentre una instrucción RTS, deberá retornar al punto de origen (desde el cual
se pasó el control del programa a la subrutina), por lo que se necesita guardar el
valor original del PC en algún lugar, para recuperarlo luego. Una opción
consistiría en destinar algún registro de la CPU para este fin, pero, si la subrutina
llama a otra subrutina (lo que se denomina anidamiento), la dirección original
sería sobreescrita y se perdería. En el 6800, y en la mayoría de los
microprocesadores, esta situación se resuelve haciendo uso de una zona de la
memoria denominada pila (stack), cuya gestión resulta algo peculiar, y que se
suele emplear en almacenamiento temporal o intercambio de datos entre módulos.
156 Microprocesadores y microcontroladores

La pila es una estructura de almacenamiento dinámico de datos de tipo LIFO


(Last In, First Out), es decir, el último dato colocado es el primero que saldrá.
Para entender cómo opera una pila, imaginemos un conjunto de libros apilados
sobre una mesa (una pila de libros). Si sobre la cima de la pila colocamos un
libro, y otro, y otro, cuando debamos tomar uno de ellos el último colocado será
precisamente el primero en ser extraído. En el caso de los µP, en el mapa de
memoria existe una zona de RAM con un tratamiento especial, denominada pila,
y cuya gestión responde a este esquema. En ella pueden depositarse datos sin
tener que indicar dirección alguna de almacenamiento, pero a la hora de tomar un
dato se extraerá el último colocado. Se denomina base de la pila a la dirección
donde ésta comienza, que se corresponde con la dirección que ocupa el primer
dato guardado en ella; por otra parte, se llama cima a la dirección de la primera
casilla libre, justo encima de la que ocupa el último dato depositado.
En términos de hardware, la pila no es otra cosa que una zona de la memoria
RAM convencional, pero cuya gestión lleva a cabo el microprocesador de esta
forma peculiar. Para ello hace uso de un registro especial de 16 bits denominado
puntero de pila o SP (stack pointer), el cual almacena (apunta a) la posición de
memoria dentro del mapa en la que se encuentra la primera posición libre de la
pila, y lugar donde se almacenará el próximo dato.
Una serie de instrucciones permiten depositar y recoger datos de la pila.
PSHA (PuSH A) y PSHB (PuSH B) (direccionamiento de tipo acumulador)
colocan el dato contenido en el acumulador A y B, respectivamente, en lo alto de
la pila. En RTL se tiene, p.e., para PSHA:
PSHA (SP)←(A) , SP←(SP)−1
es decir, primero se coloca el contenido de A en la dirección apuntada por SP (la
primera casilla libre de la pila), decrementando a continuación el valor del
puntero de pila, de manera que apunte a la nueva primera posición vacía de la
pila. Podemos observar, por lo tanto, que el tamaño de la pila «crece» de las
direcciones altas a las bajas.
Por otra parte, las instrucciones PULA (PULl A) y PULB (PULl B) extraen el
último dato almacenado en la pila, depositándolo en el registro A y B,
respectivamente. En RTL se tiene para, p.e., PULA:
PULA SP←(SP)+1 , A←((SP))
se incrementa SP para que apunte al primer dato almacenado en lo alto de la pila,
el cual es cargado en el registro A. En el caso del 68HC11, además de las
indicadas, existen las equivalentes que actúan con los registros índice, X e Y
(PSHX, PSHY, PULX, PULY).
Instrucciones y modos de direccionamiento 157

Dentro del repertorio, tanto del 6800 como del 68HC11, hay un conjunto de
instrucciones específicas para el manejo del registro SP. Así, LDS (LoaD SP) y
STS (Store SP) sirven respectivamente para cargar el contenido de dos casillas de
memoria consecutivas en SP (pues es de 16 bits) y para almacenar el valor de SP
en memoria. INS (Increment SP) y DES (Decrement SP) incrementan y
decrementan SP, respectivamente. Por último, TSX (Transfer SP to X) transfiere
el contenido de SP más uno al registro X, y TXS (Transfer X to SP) transfiere el
contenido de X menos uno a SP. Estas instrucciones permiten tanto el control del
tamaño y situación actual de la pila como el manejo de los datos almacenados.
De todas las anteriores LDS resulta particularmente importante, ya que carga
un determinado valor en SP, o, en definitiva, LDS establece el lugar de memoria
donde debe situarse la pila. Veremos que una de las primeras cosas que el
microprocesador debe realizar al conectar la alimentación del sistema es
precisamente asignar a la pila un lugar dentro del mapa de memoria que
corresponda a memoria RAM (lo suele hacer la rutina de reset). Por ejemplo,
LDS #$7F colocaría la cima de la pila (comienzo) en la dirección $7F.

0000 0000

(SP)→ CIMA (libre) (viejo SP)-2


PC High (viejo SP)-1
CIMA (libre) PC Low (viejo SP)
(SP)→
: :
: :
BASE BASE

FFFF FFFF

FIGURA 4.12. Estructura de la pila en el 6800, antes y después de un salto a subrutina.


158 Microprocesadores y microcontroladores

0000

...
EC00 JSR ←(viejo PC) (SP)→ CIMA (libre) (viejo SP)-2
EC01 FB $EC (PC High) (viejo SP)-1
EC02 00 (viejo SP)
$03 (PC Low)
EC03 ... ←(PC) :
:
Instrucción en memoria BASE

FFFF

FIGURA 4.13. Detalles de una llamada a subrutina y colocación del viejo PC en la pila.

Estudiado el funcionamiento de la pila, describiremos con detalle cómo


operan JSR, BSR y RTS. La instrucción de salto a subrutina JSR en primer lugar
coloca el contenido del PC en lo alto de la pila, y a continuación carga en el PC el
valor de la dirección donde debe saltar. En RTL, si suponemos que la instrucción
de salto está en la dirección $EC00, y que JSR actúa en modo extendido, se tiene:
$EC00: JSR $FB00 (SP)←(PCL) , SP←(SP)−1 , (SP)←(PCH) ,
SP←(SP)−1, PCH←($EC01) , PCL←($EC02)
donde PCL representa el byte menos significativo del PC (Low) y PCH el más
significativo (High). JSR puede actuar en modo directo, extendido e indexado.
Por último, BSR actúa como JSR pero en modo de direccionamiento relativo.
Por otra parte, la instrucción de retorno de subrutina RTS (sin argumentos)
únicamente recoge de lo alto de la pila el valor original del PC, para que la
ejecución siga su curso en el programa principal. Viendo la disposición del PC
(H y L) en la pila (fig. 4.11), es fácil determinar que RTS debe llevar a cabo la
siguiente secuencia de acciones:
RTS SP←(SP)+1 , PCH←((SP)) , SP←(SP)+1 , PCL←((SP))
Finalmente, las subrutinas deben operar sobre datos que en ocasiones deberán
ser proporcionados o «traspasados» por el programa principal; a su vez, la
subrutina quizás deba devolver algún resultado. Este importante asunto lo
trataremos un poco más adelante.
Instrucciones y modos de direccionamiento 159

4.7.2. Otros tipos de subprogramas: macros e interrupciones


Un tipo de subprograma que aparece con cierta frecuencia en el ensamblador
son las denominadas macros. Una macro no es otra cosa que un conjunto de
instrucciones de ensamblador a las que se asigna cierta etiqueta. Cada vez que en
el proceso de compilado el programa ensamblador se encuentra con dicha
etiqueta, la sustituye por el conjunto de instrucciones que simboliza, que son
insertadas así repetidas veces en el código. No todos los programas
ensambladores tienen la capacidad de trabajar con macros; los que sí contemplan
tal posibilidad se denominan macro-ensambladores. Un ejemplo de programa
macroensamblador es el famoso MASM de Microsoft, para los microprocesadores
de la familia 80x86.
Presentamos a continuación la estructura de la definición de una macro, junto
a un ejemplo:
etiqueta MACRO condi5 MACRO
{instrucciones} CMPA #$05
ENDM BEQ $4
ENDM
Cuando en el programa principal aparezca la etiqueta ‘condi5’, el compilador
la sustituirá por las dos instrucciones presentes en el interior de la definición de la
macro. Obsérvese que tanto MACRO como ENDM no son instrucciones del
juego del 6800, sino directivas o pseudo-instrucciones, que debe ejecutar el
propio programa ensamblador, no el microprocesador.
El inconveniente de las macros es que los programas tienden a ser más largos,
pues una misma sección de código es repetida e insertada cada vez que se precisa,
a diferencia de lo que sucede con las subrutinas, que, cuando son ejecutadas, se
hace uso siempre de un mismo conjunto de instrucciones. Por otra parte, la
utilización de macros hace que el programa sea más rápido, pues se ahorra el
tiempo que en el caso de las subrutinas se dedica a preservar en la pila el valor del
PC, así como el empleado en traspasar los argumentos.
Cambiando de tema, las interrupciones son un tipo de subprograma que nos
va a resultar más interesante. En ocasiones el programa que gestiona el sistema
microprocesador debe responder ante ciertos eventos, externos o internos al µP,
que suceden en un instante temporal muy preciso, lo que se denomina control en
tiempo real. Imaginemos, p.e., un sistema µP que controla una habitación y que
ante la presencia de un intruso debe disparar una alarma, o bien el caso de un
brazo robot, que al alcanzar el objetivo envía una señal al µP que lo controla, y
160 Microprocesadores y microcontroladores

éste inmediatamente debe responder, enviando una orden de «parada» o de «coger


objeto».
En estos casos se emplean las denominadas interrupciones del sistema.
Como ya sabemos, el 6800 dispone de unas líneas de interrupción (/IRQ, /NMI);
cuando aparece un evento activo en una de ellas (interrupción hardware) el µP
suspende la ejecución del programa actual y salta automáticamente a la rutina de
servicio de la interrupción. Estas rutinas de servicio de interrupciones son otro de
los tipos de subprogramas más empleados, que debido a su enorme importancia
trataremos con gran extensión en el Capítulo 5.
Por otra parte, el 6800 posee además una interrupción software, que es
producida mediante la inserción de la instrucción SWI (SoftWare Interrupt), cuya
acción detallada también se estudiará. El final de una interrupción, sea hardware
o software, debe venir marcada siempre por una instrucción RTI (ReTurn from
Interrupt). Finalmente, adelantaremos que el 68HC11, además de las descritas,
dispone de otras muchas fuentes de interrupción (una veintena).

4.7.3. Rutinas reubicables y reentrantes


Una rutina se dice independiente de la posición o reubicable cuando puede
ser alojada en cualquier zona del mapa de memoria del sistema sin tener que
modificar su código máquina. Para que una rutina sea reubicable no debe hacer
uso de los modos de direccionamiento directo y extendido, pues éstos se aplican
sobre casillas de memoria perfectamente definidas, de modo que, si cambiamos la
posición del código, deberían ser modificadas también estas instrucciones.
En el caso particular de los saltos, la condición de rutina independiente de la
posición se traduce en el empleo de saltos relativos en vez de absolutos. Para
comprenderlo, pensemos en un sector de programa que empieza en la dirección
$EC00, al cual saltamos desde otro punto con la instrucción JMP $EC00; si
movemos toda la rutina a otra zona, la instrucción seguirá siendo JMP $EC00,
pero en la dirección $EC00 ya no estará la instrucción que nos interesaba, sino
que puede estar vacía, contener datos, etc. Sin embargo, si en el programa se
emplea un salto relativo como BRA 62, siempre saltaremos 62 casillas hacia
adelante con independencia de la posición concreta que ocupe el código, por lo
que, si movemos todo el módulo, no habrá problemas de este tipo, ya que se
mantienen las distancias relativas. Este mismo razonamiento se aplica también a
las instrucciones de llamada a subrutina. En resumen, las instrucciones de salto
relativo (‘BRANCH’) permiten el desarrollo de código reubicable, no así las de
salto absoluto (‘JUMP’).
Instrucciones y modos de direccionamiento 161

Por otra parte, en el caso del acceso a datos almacenados en memoria, la no


utilización de los modos directo y extendido lleva en ocasiones a emplear la pila
para el intercambio de información o para su almacenamiento temporal, lo cual se
denomina almacenamiento dinámico de datos.
En los programas de computador es importante que los programas sean
reubicables, pues para su ejecución son cargados por el sistema operativo en
cualquier lugar de la RAM, dependiendo del espacio libre actualmente disponible.
En los sistemas microprocesadores para aplicaciones específicas, los que más
nos interesan en este curso, el programa final residirá en un lugar concreto de la
ROM (en general, de memoria no volátil), por lo que en principio la propiedad de
reubicabilidad no resulta indispensable.
No obstante, en ciertos casos esta propiedad podría ser importante o
recomendable, como en un tipo especial de subrutina reubicable denominada
reentrante. Un rutina se dice reentrante cuando puede ser llamada antes de que
acabe de ejecutarse [Miller 93]; las rutinas reentrantes son importantes en el caso
de las interrupciones. Imaginemos que una subrutina de visualización de cadenas
de caracteres ha sido llamada por el programa principal, pero antes de llegar a la
instrucción de final de subrutina, RTS, se genera una interrupción cuya rutina de
servicio emplea esa misma subrutina de visualización (p.e., para mostrar un
mensaje de atención al usuario): en este caso se habrá entrado en la subrutina de
visualización más de una vez sin que se haya concluido su ejecución en ninguna.
Para que una rutina sea reentrante tampoco puede emplearse
direccionamiento directo o extendido para los datos, pues si no en una segunda
llamada se sobre-escribirían los datos parciales de la anterior. Por ello, resulta en
tal caso inevitable el empleo de la pila para almacenar estos datos temporales de la
rutina, lo cual se corresponden con las denominadas variables locales (por
ejemplo, en el lenguaje C se emplea esta técnica). Siempre se debe tener un
especial cuidado con el empleo de este tipo de subrutinas, ya que pueden aparecer
errores difícilmente detectables, como, por ejemplo, que al ser llamadas muchas
veces se cause un desbordamiento de la pila del sistema.
En conclusión, aunque en el caso de los sistemas específicos muchas veces
no es necesario que las rutinas sean reubicables, suele considerarse una buena
costumbre su empleo [Miller 93], si bien ello resultará más tedioso y el programa
final puede tener mayor longitud. En estas condiciones puede ser más interesante
programar directamente en lenguaje C.
162 Microprocesadores y microcontroladores

4.8. Transmisión de argumentos entre módulos


En ocasiones el programa principal debe transmitir datos a la subrutina a la
que llama para que ésta los procese y devuelva al principal unos resultados. Para
llevar a la práctica este intercambio de información pueden emplearse diversas (y
muy diferentes) técnicas, de las cuales describiremos a continuación algunas de
las más comunes.
En primer lugar, en el intercambio de argumentos (o parámetros) entre
subrutina y programa principal podemos distinguir dos grandes modalidades, la
transmisión por valor y la transmisión por referencia. En la transmisión por valor
lo que se envía es el propio dato (su valor), operando o resultado, mientras que en
el caso de la transmisión por referencia lo que se envía no es su valor, sino la
dirección donde se encuentra. En el caso de los lenguajes de alto nivel se
emplean ambas técnicas, dependiendo del tipo de dato y también del lenguaje
particular (cada uno, C, Fortran, Pascal, utiliza sus propios convenios).
Se intercambien los parámetros por referencia o por valor, existen diferentes
maneras de hacerlo efectivo, dependiendo del lugar de la memoria donde se
coloquen los argumentos a traspasar. Comentaremos brevemente las técnicas más
habituales, remitiendo al lector interesado en profundizar en estas cuestiones a la
literatura especializada [Silva 82, Spasov 96].
a) Usando los registros de la CPU (variables tipo registro en lenguaje C). Los
datos que el programa principal envía a la subrutina (por valor o por
referencia) se colocan en este caso en los propios registros del µP; lo mismo
sucede con los argumentos que devuelve. La ventaja de esta técnica es su
rapidez y simplicidad, así como el ahorro de memoria; su inconveniente es que
el número de registros del µP es limitado, con lo que solamente puede
emplearse para intercambiar un número de argumentos reducido. También
debe tenerse en cuenta que los registros pueden contener información valiosa
que no puede perderse al llamar a la subrutina, por lo que habrá que preservar
antes su valor, p.e., colocándolo en la pila (instrucciones PSH). Esta sencilla
técnica permite la confección de subrutinas reentrantes y recursivas, siempre y
cuando al llamar a una subrutina se salvaguarde en la pila el contenido de los
registros de forma sistemática.
b) Usando una zona de memoria RAM reservada (variables globales,
almacenamiento estático). Consiste en depositar los parámetros de
intercambio en cierta zona de memoria, cuya dirección es fija y conocida tanto
por la rutina que llama como por la que es llamada (fig. 4.14); por lo tanto,
esta técnica representa una extensión de la anterior, mediante la que se
Instrucciones y modos de direccionamiento 163

pretende resolver el problema del número limitado de argumentos a traspasar.


El precio que hay que pagar por poder transmitir muchos más argumentos es la
mayor lentitud y ocupación de memoria (se emplee o no se emplee,
permanecerá reservada). Esta técnica no permite realizar rutinas reentrantes.
c) Usando la pila del sistema (variables locales, almacenamiento dinámico).
Consiste en depositar los parámetros a enviar a la subrutina en la pila del
sistema. Es una técnica completamente general, pues posibilita la realización
de subrutinas recursivas y reentrantes, y realiza un eficiente uso de la memoria.
Como contrapartida resulta compleja de programar, es lenta y puede resultar
peligrosa si se realiza de forma incorrecta (pues puede dañar la estructura de la
pila y bloquear el sistema). Por todo ello, mientras que lenguajes de alto nivel
como el C hacen amplio uso de esta técnica (de forma completamente
transparente), programando en ensamblador solamente se empleará cuando
resulte imprescindible (ver p.e., [Spasov 96], pp. 127 y 543). En particular, en
las referencias [Lipovski 88, Silva 82] se muestra una forma general de
implementar el paso de argumentos a través de la pila, que permite construir
subrutinas recursivas y reentrantes (procedimiento que por su complejidad no
expondremos aquí). Uno de los motivos por los que los programas en C
necesitan mucha más memoria RAM que los ensamblador, y emplean más
instrucciones, es precisamente el manejo de la pila.
d) Existen también otras técnicas, como la utilización de la secuencia de llamada
(colocando los argumentos a enviar inmediatamente detrás de la instrucción de
salto a subrutina, de un modo similar al empleado en algunos lenguajes de alto
nivel), o el uso de punteros a estructuras de datos de memoria.
Como cuestiones a tener presentes destacaremos la conveniencia de que las
subrutinas salvaguarden el estado de los registros del microprocesador,
normalmente en la pila del sistema. Por otra parte, aquellas subrutinas que deben
trabajar sobre la pila han de ser analizadas muy cuidadosamente, pues un manejo
incorrecto de ésta puede llevar a que el sistema quede bloqueado («se cuelgue»).
Ello puede suceder si colocamos demasiados datos en la pila (sobre todo cuando
existen niveles elevados de anidamiento), llevando al desbordamiento de la pila,
de modo que su tamaño crezca y alcance un área de datos o incluso colisione con
el propio programa, o bien que alcance una zona de memoria ROM. Por ello, el
tamaño de la pila debe ser mantenido dentro de límites aceptables, y debe
procurarse recoger el mismo número de datos que se depositaron (equilibrio entre
el número de instrucciones PSH y PUL).
164 Microprocesadores y microcontroladores

Datos

Zona reservada
RAM
Datos (datos y pila)

Pila

Libre
Puertos Zona de
Coloca entradas/salidas
Accede datos Libre
a datos
Programa
Llamada Principal
ROM (programa,
Subrutina rutinas, vector interr.)
Subrutina
FFFF Vector interrupc.

FIGURA 4.14. Traspaso de datos mediante una zona de memoria RAM reservada.

El tema del intercambio de argumentos entre módulos es de suma


importancia e interés; el lector interesado en profundizar en este asunto puede
consultar las referencias [Silva 82, Short 85, Lipovski 88, Miller 93, Spasov 96].

4.9. Otras instrucciones del 6800 y 68HC11


Para estudiar los aspectos relativos a la programación nos hemos basado
hasta el momento en el juego de instrucciones del 6800. Concluiremos este
capítulo presentando las instrucciones que restan para completar el juego del
6800, así como las nuevas instrucciones que se introducen en el 68HC11.

4.9.1. Instrucciones del 6800


Del 6800 solamente nos resta por estudiar dos instrucciones particulares. La
primera es la instrucción NOP (No OPeration), que ocupa un byte (su opcode, el
$01) y tarda dos ciclos en ejecutarse. Como su propio nombre indica, esta
instrucción no realiza ninguna operación, simplemente sirve para perder tiempo
(dos ciclos de reloj). Se emplea, por ejemplo, en la temporización de rutinas,
bucles de espera o para reservar espacio en áreas de memoria.
Instrucciones y modos de direccionamiento 165

Finalmente, la instrucción WAI (WAit for Interrupt) sirve para detener la


operación del µP hasta que se produzca alguna interrupción. WAI almacena el
estado de los registros en la pila y coloca las líneas de direcciones, datos y R/W
en alta impedancia, así como VMA a cero, entonces el µP detiene la ejecución del
programa y queda en espera de la generación de alguna interrupción.

4.9.2. Instrucciones del 68HC11


El juego de instrucciones del 68HC11 incluye el del 6800 como subconjunto
(307 instrucciones frente a 195), de modo que aquel código desarrollado para el
6800 puede ejecutarse directamente sobre un 68HC11 (son compatibles hacia
arriba). No obstante, el 68HC11, más moderno y potente, completa de una
manera importante las carencias que presenta el conjunto de instrucciones del
6800 en los siguientes términos:
• Nuevas instrucciones de manejo del registro X. Se incluyen las siguientes
nuevas instrucciones: PSHX y PULX, permiten colocar y extraer X de la pila,
muy echadas en falta en el repertorio del 6800; ABX (Add B to X), suma el
contenido de B a X; y XGDX (eXchanGe D and X), que intercambia el
contenido del acumulador doble D y el del índice X.
• Instrucciones de manejo del nuevo registro índice Y. Se tienen las
instrucciones ABY, LDY, CPY, DEY, INY, PSHY, PULY, STY, TSY, TYS,
XGDY, cuya operación es similar a las ya conocidas de manejo del registro X
(basta sustituir en las anteriores Y por X para identificarlas).
• Instrucciones de manejo del acumulador doble D. Aparecen las nuevas
instrucciones ADDD, ASLD, CPD, LDD, LSLD, LSRD y STD, instrucciones de
suma, desplazamientos aritméticos y lógicos, y carga y comparación, similares
a las de los acumuladores A y B, pero aplicadas sobre el D (16 bits).
• Instrucciones de producto y división. Se introducen una de producto y dos de
división, a saber, MUL (MULtiply unsigned), IDIV (Integer DIVide) y FDIV
(Fractional DIVide), que operan implícitamente. MUL multiplica dos
números de 8 bits sin signo guardados en los acumuladores A y B para obtener
un número de 16 bits sin signo, que deja en D. IDIV divide dos números de 16
bits sin signo almacenados en D y X, cuyo cociente se guarda en X y el resto
en D. FDIV es similar, sólo que supone que el numerador (D) es menor que el
denominador (X), y que los datos de D y X contienen números fraccionarios
(únicamente con parte decimal).
• Instrucciones que operan sobre bits individuales. Sirven para comprobar o
actuar sobre el estado de bits individuales; todas ellas trabajan sólo en los
166 Microprocesadores y microcontroladores

modos de direccionamiento directo e indexado (no operan en extendido, por


ejemplo). Así, BCLR (Bits CLeaR) y BSET (Bits SET) permiten borrar y
activar, respectivamente, los bits individuales pertenecientes a una
determinada posición de memoria, haciendo uso para ello de una máscara de 8
bits; p.e., BSET $10 %11000000, activa los dos bits más significativos de la
casilla $10, y BCLR $10 %11000000 los borraría. Estas instrucciones
permiten, p.e., enviar señales por una línea individual de un puerto de salida.
BRCLR (BRanch if bits CLeaR) y BRSET (BRanch if bits SET) saltan a
determinada casilla de memoria si los bits marcados por una máscara de 8 bits
están activados o desactivados, respectivamente; por ejemplo, BRSET $10
%11000000 $08 saltaría 8 casillas si los dos bits más significativos de la
dirección 10 estuvieran a ‘1’, y BRCLR si estuvieran a ‘0’.
• Nuevas instrucciones de salto. Además de las ya citadas BRCLR y BRSET
(que saltan en función del estado de ciertos bits individuales), se introducen
BLO (Branch if LOwer) y BHS (Branch if Higher or Same), que poseen el
mismo opcode que BCS y BCC, respectivamente; por lo tanto, actúan de
idéntica forma. Por último, BRN (BRanch Never) posee un papel similar a la
instrucción NOP, pero emplea tres ciclos de reloj («pierde» más tiempo).
• Otras instrucciones. LSL (Logical Shift Left), es la misma que la ya conocida
ASL; STOP (STOp Processing) detiene los relojes y coloca al sistema en un
estado de espera de mínimo consumo de energía, una interrupción puede
«despertar» al microprocesador (ver hojas de características para más detalles);
TEST (TEST operation) opera solamente en el modo especial de test del
68HC11, siendo una instrucción ilegal en el resto de los modos.
Por último, completaremos la comparación entre ambos juegos de
instrucciones citando algunas novedades que no involucran nuevos mnemónicos
en el repertorio. Así, en el 68HC11 la instrucción JSR ya conocida también puede
ser empleada en modo de direccionamiento directo. Por otra parte, CPX actúa de
una forma algo diferente sobre los señalizadores N y V. Finalmente, debe tenerse
en cuenta que muchas instrucciones en el 68HC11 ven reducido su tiempo de
ejecución (ciclos de reloj). Recordemos para concluir que para poder trabajar con
más de 256 instrucciones, algunas de las nuevas incluidas en el juego del 68HC11
incorporan un pre-byte precediendo al opcode. Remitimos al lector a las hojas de
características de Motorola para profundizar en los detalles [Motorola 91].
Capítulo 5
Entradas y salidas (I): aspectos básicos

5.1. Introducción al subsistema de entradas/salidas


El microprocesador, además de constituir la base de los actuales
computadores, es un dispositivo muy útil para la construcción de sistemas
electrónicos de relativa complejidad, que de otra manera habría que realizar
mediante electrónica convencional; gracias al uso de microprocesadores se gana
en sencillez de realización, tiempo de desarrollo, precio y fiabilidad. Desde este
punto de vista, comprenderemos que su conexión a los denominados dispositivos
periféricos resulta absolutamente esencial, pues gracias a ellos el microprocesador
se comunicará con el exterior. Algunos periféricos envían a la CPU información
procedente del entorno (sensores, pulsadores, teclados...), otros son empleados
por el microprocesador para presentar información (LEDs, visualizadores,
pantallas...), mientras que otra clase de periféricos sirven para ejecutar acciones
sobre el exterior (relés, motores, electroválvulas...). Se deduce además que los
distintos periféricos presentarán muy diferentes características en relación al tipo
de control, tiempo de respuesta, etc.
En los próximos dos capítulos trataremos todos los aspectos relacionados con
la comunicación del microprocesador con el exterior, es decir, el denominado
subsistema de entradas/salidas (E/S). Estos aspectos relacionados con el
interconexionado (interfacing) implican un desarrollo de hardware (la conexión
física µP-periférico), pero el control se realizará en buena medida mediante un
programa (software).
Hay que tener presente desde el principio que conceptualmente la
comunicación de un microprocesador con un periférico constituye un proceso de
transferencia de información similar al ya estudiado de lectura o escritura en
memoria, y que, como en él, se manejarán dos tipos diferentes de información:
a) Datos, de entrada o de salida, suministrados por (o enviados al) periférico.
b) Señales de control, que permiten enviar órdenes al periférico e informan a la
CPU sobre su estado.
168 Microprocesadores y microcontroladores

No obstante, en el caso de las entradas y salidas aparecen nuevos aspectos


que introducen una mayor complejidad en el proceso de transferencia de
información que en el acceso a memoria, como son:
a) La gran variedad de los periféricos disponibles (LED, pulsadores, teclados,
impresoras, pantallas, motores, sensores, electroválvulas, modems, etc.).
b) El enorme rango de velocidades de comunicación (algunos periféricos actúan
en microsegundos, otros en milisegundos y otros en segundos o más).
c) La necesidad de ejercer algún tipo de control sobre el periférico.
Debido a todo ello, para conectar un periférico a un microprocesador deberá
hacerse uso de circuitos que harán el papel de interfaces o adaptadores de
periféricos, se tendrá que manejar determinadas señales de control, y establecer
cierta secuencia de instrucciones y señales de actuación (protocolo).
En este capítulo estudiaremos distintos tipos de interfaces básicos de
periféricos (de entrada, de salida y programables), y trataremos las diferentes
técnicas de entrada/salida que pueden establecerse (por programa, por
interrupciones y por acceso directo a memoria). Asimismo, realizaremos también
el estudio en profundidad de los sistemas de interrupciones del 6800 y 68HC11.
Dejaremos para el capítulo siguiente algunos aspectos más avanzados
relacionados con las E/S, así como el estudio de los propios dispositivos
periféricos y sistemas de almacenamiento masivo de la información.

5.2. Adaptadores básicos de periféricos (interfaces)


Denominaremos adaptador de periféricos o interfaz al circuito que
desempeña el papel de enlace entre el microprocesador y el periférico (fig. 5.1),
llevando a cabo la transferencia efectiva de información entre ambos. Las
funciones de un adaptador de periféricos son las siguientes:
a) Adaptación de señales.
b) Almacenamiento temporal de los datos a transferir.
c) Realización de tareas de control sobre el periférico, liberando de trabajo a la
CPU.
Debido a la gran variedad de tipos de periféricos disponibles, los circuitos de
adaptación deben diseñarse específicamente para cada caso particular, teniendo en
cuenta las características concretas del periférico en cuestión, las señales de
control necesarias y el protocolo que requiere. La tarea del diseño de la conexión
Entradas y salidas (I): aspectos básicos 169

microprocesador-periférico es, sin duda, la más creativa desde el punto de vista


del hardware en el desarrollo de sistemas microprocesadores.
En el estudio de los circuitos integrados adaptadores distinguiremos entre los
específicos y los no específicos. Los adaptadores específicos son diseñados por
los fabricantes para el control de una determinada clase de periféricos, por
ejemplo, los controladores de pantallas de rayos catódicos o CRT (Catode Ray
Tube), como el 6854, o los controladores de unidad de disquete, como el 6843,
ambos pertenecientes a la familia 68XX de Motorola.
Por su parte, los adaptadores genéricos (no específicos) son circuitos más o
menos estándar, que no han sido diseñados pensando en ningún periférico en
particular, sino que pueden emplearse para diversos de ellos. Algunos hacen uso
de circuitos digitales convencionales ya conocidos, como buffers y registros,
mientras que otros son circuitos programables, de mucha mayor complejidad y
versatilidad, como los puertos programables paralelos (PIA, VIA, PIO, PPI) y los
serie (ACIA, UART, USART).

SISTEMA MICROPROCESADOR EXTERIOR

Bus Datos

Adaptador 1 Periférico 1
Decodif.
Direcciones EN

Microprocesador
(CPU) Adaptador 2 Periférico 2

EN
EN

Adaptador 3 Periférico 3

Bus Datos

Bus Direcciones

FIGURA 5.1. Esquema de la conexión del subsistema de E/S al sistema microprocesador. Por
simplicidad, no se incluyen señales de control, excepto las de habilitación ‘EN’ (ENable).
170 Microprocesadores y microcontroladores

Estos circuitos de adaptación o de interfaz, que permiten la comunicación


entre el microprocesador y un periférico, incorporan los puertos de E/S (ports).
Al igual que sucede con los registros que conforman la memoria, cada puerto
constituye un registro que tiene asignada una dirección dentro del mapa de
memoria del sistema µP. En algunas familias, como la Intel, existen dos espacios
de direcciones separados, el correspondiente a las direcciones de memoria (mapa
de memoria), y el de las direcciones de los puertos de entrada y salida (mapa de
E/S). En este caso, incluso las instrucciones que acceden a registros de memoria
son diferentes a las que operan sobre los puertos de entrada/salida (MOVE en el
primer caso, IN y OUT para las entradas/salidas).
En otras familias de microprocesadores, como la de Motorola, los puertos de
E/S están mapeados en memoria, es decir, existe un único espacio de direcciones,
y en él se sitúan tanto las correspondientes a casillas de memoria, como a puertos.
En este caso, las instrucciones que acceden a ambos son las mismas (por ejemplo,
LDAA y STAA, en la familia 68XX).
Finalmente, hasta el momento hemos hablado de circuitos integrados que
hacen el papel de adaptadores de periféricos o interfaces; sin embargo, para el
caso de los periféricos complejos los fabricantes comercializan tarjetas completas
denominadas tarjetas controladoras, cuyo empleo facilita enormemente la
conexión de un periférico complejo al sistema. Ello sucede, sobre todo, en los
periféricos de computador, como es el caso de la controladora de vídeo, CD-
ROM, disco duro, etc.

5.2.1. Adaptadores de entradas


Introduciremos a continuación los circuitos de interfaz básicos, comenzando
por los de entradas. Supongamos que disponemos de un sistema microprocesador
mínimo, compuesto por el circuito µP, cierta cantidad de memoria y los buses de
direcciones, datos y control (fig. 5.2). Cuando el microprocesador trata de leer el
contenido de un registro de memoria, por ejemplo, en el caso del 6800 mediante
una instrucción del tipo LDAA dir, coloca su dirección en el bus de direcciones y
activa la línea que indica dirección válida (VMA en el 6800); el registro (casilla)
de memoria direccionado, en respuesta, coloca su contenido en el bus de datos y
el microprocesador finalmente lo toma.
Supongamos que en vez de leer el dato almacenado en una casilla de
memoria se trata de leer el dato proporcionado por un periférico, por ejemplo, el
estado de un conjunto de ocho microinterruptores. En principio, podríamos
pensar en conectar directamente los interruptores a las líneas de datos, pero esta
conexión directa no es factible: el bus de datos es compartido por todo el sistema,
Entradas y salidas (I): aspectos básicos 171

en particular es empleado en la transferencia de datos entre el microprocesador y


memoria, y, si conectáramos los pulsadores directamente al bus, cada una de sus
líneas permanecerían siempre en el estado marcado por los interruptores,
impidiendo el intercambio normal de datos entre la CPU y las diferentes pastillas
de memoria.
Una regla de oro en este sentido es que, en general, nunca debe conectarse
ningún periférico directamente al bus de datos de un sistema microprocesador,
sino que ésta debe realizarse mediante el empleo de un circuito adaptador de
periféricos (interfaz o puerto), que en el caso de los periféricos de entrada siempre
poseerá capacidad triestado.

FIGURA 5.2. Diagrama de bloques de un sistema basado en un 6800, incluyendo periféricos


conectados por medio de adaptadores (interfaces). La fase φ2 del reloj se amplifica pasándose a
denominar E (nombre que retoma el 68HC11 y el 68000), pudiéndose interpretar como una línea de
validación de datos;VMA es la línea de validación de direcciones.
172 Microprocesadores y microcontroladores

FIGURA 5.3. Esquema genérico de un interfaz o adaptador de entradas (AE), y construcción por
medio de un buffer triestado.

En un sistema de buses el diseñador debe garantizar que existe siempre un


único dispositivo que coloca datos en el bus en un instante dado. Para ello deberá
confeccionar el mapa de memoria del sistema (en el que se incluyen tanto los
registros de memoria como los puertos de E/S), y construir a partir de él los
circuitos de decodificación, encargados de seleccionar los distintos dispositivos
(chips de memoria, puertos), de tal manera que solamente uno a la vez pueda estar
conectado al bus de datos en cada instante (cuando aparezca su dirección en el
bus). Los dispositivos conectados al bus deberán poseer capacidad triestado,
permaneciendo deshabilitados cuando no son seleccionados por el decodificador.
Esta circunstancia puede apreciarse en el sistema de la fig. 5.2, en el que en cada
momento solamente estarán conectados al bus de datos el µP y una pastilla del
sistema, la correspondiente a la RAM, la ROM, el adaptador de entradas o el de
salidas. En todo momento uno de ellos envía datos (por ejemplo, la RAM) y otro
los recibe (por ejemplo, el microprocesador).
Entradas y salidas (I): aspectos básicos 173

74LS244

FIGURA 5.4. Buffers triestado: 74241, 244, 367 y 541 (arriba), y diagrama del 74LS244 (abajo).

En la fig. 5.3 se muestra el esquema de un adaptador de entradas (AE)


genérico, que conectará un periférico de entrada (por ejemplo, un conjunto de
interruptores o un teclado) al bus de datos cuando su dirección sea colocada en el
bus de direcciones, y lo desconectará en el resto de los casos. La manera más
común de realizarlo es mediante el empleo de buffers triestado, que normalmente
estarán en situación de alta impedancia, /EN=‘1’ (ENable, habilitación), de
manera que el periférico normalmente se mantendría desconectado del bus. El
AE solamente permitirá el paso de datos del periférico al bus de datos cuando el
µP haya colocado la dirección correspondiente al AE (situación que determinará
el decodificador de direcciones activando la línea que hemos denominado DIR en
la fig. 3), y cuando además las líneas VMA, R/W y φ2 también estén activas, es
decir, cuando se cumpla la condición lógica /EN=NAND(φ2, VMA, R/W, DIR).
El buffer se comporta, por lo tanto, como una compuerta que deja o no deja pasar
al bus los datos procedentes de un periférico. La lectura de los datos de los
interruptores se realizará mediante una instrucción de tipo LDAA dir, siendo ‘dir’
la dirección del puerto de entrada en el mapa de memoria. En este sentido, leer
un puerto o leer una casilla de memoria resulta ser exactamente lo mismo.
Hasta el momento hemos visto el adaptador de entradas como una caja negra,
que permite o no permite el paso de datos en función del valor presente en su
entrada de habilitación /EN (normalmente activa en bajo). El AE se construye en
174 Microprocesadores y microcontroladores

la práctica haciendo uso de buffers triestado convencionales (fig. 5.4), con las
entradas de habilitación cableadas de forma adecuada. Por ejemplo, el 74LS367
es un buffer triestado de seis líneas, con dos entradas de habilitación que actúan
sobre dos grupos de dos y cuatro buffers individuales, respectivamente. Los
integrados 74LS241 y 74LS244 son buffer triestado de 8 líneas de amplio uso
(ambos se diferencian levemente en sus líneas de habilitación). El 74LS541 es
una versión del 241, cuyas entradas y salidas están dispuestas «ordenadamente» a
ambos lados del encapsulado para facilitar la realización de montajes. Se suelen
emplear integrados pertenecientes a las familias lógicas LS y ALS, por su bajo
consumo y rapidez (la ALS, Advanced Low-Schottky, es una familia lógica más
moderna, de consumo inferior a la LS tradicional).
Debido a la elevada capacidad de manejo corriente que presentan estos
buffers, son también denominados drivers de bus, empleándose asimismo para
aumentar la capacidad de carga del bus de direcciones (para el caso del bus de
datos deberá emplearse un transceiver, buffer de tipo bidireccional).

Ejemplo
Conecta un grupo de 8 interruptores al bus de un sistema basado en un 6800.

Resolución:
La conexión se realiza por medio de un adaptador de entradas siguiendo el
esquema de la figura mostrada a continuación Este adaptador se construiría con
buffer triestado; la conexión concreta depende del modelo de buffer elegido. La
habilitación se produce cuando VMA, R/W y φ2 estén a ‘1’ y la dirección DIR
sea la correcta (línea que procede de un bloque decodificador). La salida de los
interruptores se mantiene a ‘1’ por medio de resistencias de polarización.
Entradas y salidas (I): aspectos básicos 175

FIGURA 5.5. Esquema genérico de un adaptador de salidas (AS), y realización mediante biestables
D síncronos.

5.2.2. Adaptadores de salidas


Explicada la manera de confeccionar un adaptador de entradas, vamos a
estudiar los adaptadores de salidas (AS). En este caso se precisa de un circuito
que permita al µP enviar datos al exterior (por ejemplo, a un conjunto de diodos
LED, una impresora, etc.), haciendo uso para ello de instrucciones del tipo STAA.
En principio, uno podría pensar en buffers triestado como los utilizados en la
realización de un AE, de modo que, cuando se direccione el adaptador y se
cumplan el resto de las condiciones ya conocidas, es decir, /EN=NAND(φ2,
VMA, /R/W, DIR), los datos pasen del bus al periférico. Sin embargo, surge
entonces el siguiente problema: si nos fijamos en la fig. 5.2, si AS fuese
simplemente un conjunto de buffers, los datos pasarían al conjunto de ocho LED
solamente cuando AS se encontrase habilitado, de modo que, en el momento en
que la CPU retire la dirección de AS para proceder a direccionar una casilla de
memoria u otro puerto, AS volverá a situarse en alta impedancia y los LED
quedarán de nuevo apagados. En resumen, con un montaje de este tipo los LED
permanecerían encendidos solamente durante un período del orden de un
microsegundo, con lo que no apreciaríamos nada.
176 Microprocesadores y microcontroladores

FIGURA 5.6. Patillaje de los integrados 74175 (4 biestables D síncronos, con reset) y 377 (8 D
síncronos, con habilitación), empleados para realizar adaptadores de salida.

Ello nos sugiere que en el caso de los puertos de salida debe emplearse un
registro que retenga los datos cuando el µP prosiga con otras tareas (fig. 5.5), y
los mantenga ante las entradas del periférico (por ejemplo, el conjunto de LED).
Habitualmente para ello se hace uso de registros síncronos tipo D, por ejemplo, un
74LS175, que consta de 4 biestables D, o un 73LS377, que incluye 8 (fig. 5.6).
En este caso /EN no es una línea de habilitación propiamente dicha, sino una
entrada de reloj (activa por flanco) que se encarga de actualizar el estado del
registro cuando se dan las condiciones expuestas. También pueden emplearse
registros de retención (latch), con las líneas de habilitación convenientemente
conectadas (dejamos los detalles como ejercicio para el lector).

Ejemplo
Conecta un conjunto de 8 LED al bus de un sistema basado en un 6800.

Resolución:
La conexión se realiza por medio de un adaptador de salidas siguiendo el
esquema de la figura que sigue. Este adaptador se construiría con biestables; la
conexión concreta depende del modelo elegido. En la figura se ha supuesto que
se emplean biestables síncronos que actualizan sus salidas con una transición ‘0’ a
‘1’ en la línea de reloj (p.e., un 74175), que nosotros hemos denominado /EN para
que la notación coincida con los adaptadores de entrada; dicha transición se
producirá cuando VMA=1, R/W=‘0’, la dirección sea la correcta, y φ2 conmute
de ‘1’ a ‘0’ (lo que sucede al finalizar un proceso de escritura), momento en el que
el contenido del bus de datos pasa a las salidas. Los LED se han conectado de
modo que se iluminen cuando aparezca un ‘0’ en la salida del interface (los
circuitos TTL pueden absorber más intensidad que la que pueden proporcionar,
por lo que esta disposición permite que presenten mayor luminosidad).
Entradas y salidas (I): aspectos básicos 177

5.3. Adaptadores programables paralelos


Los adaptadores vistos hasta el momento son circuitos sencillos, que
solamente pueden emplearse en ciertas situaciones (sólo con entradas o sólo con
salidas). A continuación estudiaremos los adaptadores programables, de uso más
complejo pero más versátiles. Distinguiremos dos grandes grupos: los
adaptadores programables serie, que transmiten los datos secuencialmente, y los
paralelos, con diversas líneas de E/S que permiten comunicar datos en paralelo.
En este punto trataremos los aspectos más básicos de los adaptadores
programables paralelos, dejando para el capítulo siguiente los aspectos más
avanzados y los puertos serie.

5.3.1. La PIA 6821 de Motorola


El adaptador paralelo PIA 6820 (Peripheral Interface Adapter), introducido
en 1975 por Motorola para la familia 68XX, fue uno de los primeros interfaces
programables comercializados. El 6821, algo más moderno, es funcionalmente
equivalente al 6820 (solamente difiere en la mejora de algunas de sus
características eléctricas), por lo que en adelante hablaremos indistintamente de la
PIA 6820 o la 6821 (prácticamente da lo mismo). La PIA sigue la filosofía de
conexionado típica de Motorola, y no resulta fácil conectarlo con un sistema µP
basado en el estilo Intel (en este caso es usual emplear el PPI 8255 de Intel).
La PIA 6820 se introdujo para facilitar el diseño de sistemas basados en el
M6800, padre de la familia 68XX. Recordemos que el M6800 fue el primer
microprocesador comercializado por Motorola, respuesta al Intel 8080. Junto al
6800 se comercializaron diferentes circuitos de apoyo, que facilitaban el
desarrollo de sistemas, como circuitos de reloj, memorias o adaptadores de
178 Microprocesadores y microcontroladores

periféricos, como la PIA y el ACIA (adaptador serie que estudiaremos en el


siguiente Capítulo). El 6820 o el 6821 proporcionan al 6800 la posibilidad de
trabajar con periféricos, de modo que casi siempre un sistema basado en un 6800
(o en cualquiera de sus descendientes, como el famoso 6809) incluía una o más
circuitos PIA. La PIA se sigue empleando en la actualidad con µP más potentes,
como los de la familia 68000, o también con microcontroladores, como el
68HC11.
Se trata el 6821 de un adaptador programable, capaz de comunicar una CPU
con varios periféricos a la vez a través de 16 líneas de entrada/salida
(programables individualmente como entradas o como salidas), agrupadas en dos
puertos de 8 bits. Contiene además cuatro líneas de control o diálogo con
periféricos (handshaking), que serán estudiadas en detalle en el capítulo 6. La
PIA se considera dividida en dos secciones, A y B, incluyendo cada una un puerto
y dos líneas de diálogo; cada sección de la PIA incluye además los siguientes tres
registros (que permiten programar su funcionamiento):
a) Registro de datos ORA(B) o Output Register A(B) (indicaremos con A(B) que
lo explicado afecta tanto a la sección A como la B de la PIA; así, ORA(B)
indica tanto el registro ORA como el ORB). Contiene la información enviada
al exterior o recibida del periférico. Cada uno de sus ocho bits se conecta a
una línea exterior.
b) Registro de dirección de los datos DDRA(B) (Data Direction Register A(B)).
Registro de 8 bits que sirve para programar como entradas o como salidas cada
una de las 8 líneas de datos de ORA(B). Un ‘0’ en uno de sus bits indica que
la línea de ORA(B) correspondiente actúa como entrada de datos, un ‘1’ indica
que actúa como salida. Así, cada una de las líneas que compone un puerto
puede programarse individualmente como entrada o como salida.
c) Registro de control CRA(B) (Control Register A(B)), registro de 8 bits que
permite programar con gran detalle el modo de funcionamiento de la PIA.
Cada uno de sus bits posee un cometido especial, que estudiaremos con detalle
en el capítulo siguiente.
Por lo tanto, la PIA incluye 6 registros en total, repartidos entre sus dos
secciones. Aunque por esta razón pudiera pensarse que la PIA ocupa seis
direcciones dentro del mapa de memoria (una por registro), tan sólo ocupa cuatro,
pues los registros de direcciones DDRA(B) y datos ORA(B) comparten una
misma dirección. A continuación estudiemos la manera de direccionar los seis
registros con únicamente cuatro direcciones.
Entradas y salidas (I): aspectos básicos 179

FIGURA 5.7. Esquema de la PIA 6821.

Si observamos la fig. 5.7, la PIA dispone de tres líneas de selección de chip,


CS0, CS1, y /CS2, por lo que las tres deben permanecer activadas para que el chip
quede seleccionado, y poder así acceder a sus registros. Al igual que cualquier
circuito integrado de memoria, debe accederse a los registros cuando VMA esté
activa, por lo que esta línea suele conectarse directamente a una de las líneas de
selección activas en alto, por ejemplo, a la CS1. CS0 y /CS2 se reservan entonces
para la decodificación de direcciones, pudiéndose conectar a la salida de un
bloque decodificador, que establece el valor alto de la dirección de la PIA.
Habilitada la PIA, debe seleccionarse el registro que se va a leer o sobre el
que se va a escribir, lo cual se lleva a cabo con los dos pines RS (Register Select).
La línea RS1 discrimina entre la sección A (‘0’) y la B (‘1’); dentro de cada
sección, si RS0=‘0’ se selecciona ORA(B) o DDRA(B) (recordemos que
comparten la misma dirección), mientras que si RS0=‘1’ se selecciona el registro
de control CRA(B). En definitiva, RS0 y RS1 en realidad hacen el papel de líneas
de direcciones, conectándose normalmente a A0 y A1.
Si RS0=‘0’, o el registro ORA(B) o el DDRA(B) quedará seleccionado; para
distinguir entre uno y otro hay que actuar sobre el bit 2 del registro de control
CRA(B) (fig. 5.8). Si CRA(B)2=‘0’, es el registro de direcciones DDRA(B) el
que queda seleccionado, y si CRA(B)2=‘1’, es el de datos ORA(B). Dejaremos el
estudio del resto de los bits del registro de control para el capítulo siguiente.
180 Microprocesadores y microcontroladores

Selección de
ORA(B) (=1) o DDRA(B) (=0)
Señalizadores
de C1 y C2 Control de C2 Control de C1

7 6 5 4 3 2 1 0

CRA(B)

FIGURA 5.8. Registro de control de la PIA CRA(B) (por el momento sólo nos interesa el bit 2).

Resumen de la inicialización de la PIA


Siempre que se vaya a emplear la PIA, debe previamente inicializarse
mediante una pequeña rutina, que debe llevar a cabo los siguientes pasos:
a) Se selecciona primero DDRA(B), poniendo a cero el bit 2 de CRA(B).
b) Se escriben unos o ceros en los bits que componen DDRA(B), según cada una
de las líneas del puerto correspondiente sean salidas (‘1’) o entradas (‘0’).
c) Se pone a ‘1’ el bit 2 de CRA(B); de ese modo queda seleccionado
definitivamente ORA(B). Normalmente, ya no actuaremos más sobre el bit 2
de CRA(B), pues durante la operación del programa principal rara vez
cambiaremos la condición de entradas o salidas de las líneas que componen los
puertos, por lo que no habrá que modificar ya DDRA(B).
d) Si es necesario, se programan las líneas de diálogo C1 y C2, actuando sobre
los bits adecuados de CRA(B) (lo explicaremos en detalle más adelante).

Evidentemente, si se van a emplear ambos puertos de la PIA, deberán


inicializarse los dos, con lo que las acciones anteriores habrá que ejecutarlas por
duplicado, para cada uno de ellos.

Ejemplo
Realiza una rutina que inicialice como entrada el puerto A de una PIA,
supuesto que está colocada a partir de la dirección $A000 del mapa de
memoria del sistema.
Entradas y salidas (I): aspectos básicos 181

Resolución:
Si la PIA está colocada a partir de la dirección $A000, ORA/DDRA ocupará
la dirección $A000, CRA la $A001, ORB/DDRB la $A002 y CRB la $A003.
Aplicando lo explicado:
* definición de etiquetas
ORA EQU $A000
DDRA EQU $A000
CRA EQU $A001
* rutina de inicialización
ORG $0100
* selección de DDRA (‘0’ en el bit 2 de CRA)
LDAA #$00
STAA CRA
* programa líneas como entradas cargando $00 en DDRA
STAA DDRA
* seleccionar ORA para trabajar con él: CRA<--0000 0100
LDAA #$04
STAA CRA
* fin inicialización puerto A PIA
......

El resto de las líneas de la PIA deben conectarse a los buses del sistema de la
siguiente manera (fig. 5.9): las líneas D0-D7 se conectan al bus de datos,
mediante ellas µP y adaptador intercambian datos. La patilla E (Enable) es la
entrada de habilitación de la PIA, que se conecta a la fase φ2 del reloj del sistema
(en el caso del 68HC11 y del 68000, esta línea se uniría directamente al reloj E
proporcionado por ellos). La línea de lectura/escritura R/W (en el caso de la PIA,
hace de entrada/salida de datos) se conecta obviamente a la línea R/W del sistema
microprocesador.
Aunque más adelante estudiaremos las interrupciones del 6800, indicaremos
que las dos líneas de interrupción /IRQA e /IRQB de la PIA son salidas drenaje
abierto, pudiéndose cablear entre sí y a la entrada IRQ del 6800 (fig. 5.10); para
mantenerlas desactivadas hay que conectarlas a +5 V mediante una resistencia de
4,7 KΩ. Finalmente, la entrada /RESET se conecta al reset general del sistema.
182 Microprocesadores y microcontroladores

FIGURA 5.9. Conexión de la PIA a los buses del 6800.

FIGURA 5.10. Conexión de las dos salidas de interrupción de la PIA, /IRQA y /IRQB, a la línea de
interrupción no enmascarable /IRQ del 6800 .

La operación de las dos secciones A y B de la PIA es en esencia similar; no


obstante, se diferencian en algunas características funcionales y eléctricas. Las
funcionales tienen que ver con la actuación de las líneas de diálogo, que
estudiaremos en el capítulo siguiente. En cuanto a sus características eléctricas,
comentaremos que el puerto A es capaz de manejar mucha menos corriente que el
B, merced al buffer que éste último incluye. Gracias a este buffer, si se ha
programado B como salida y se ejecuta posteriormente una operación de lectura
Entradas y salidas (I): aspectos básicos 183

con una instrucción como LDAA (es decir, leemos un puerto de salida), se
obtendrá el dato correcto que anteriormente se colocó en el puerto B, con
independencia de la carga externa que se haya conectado. Como A no incluye
buffer, si se programa el puerto A como salida y posteriormente se lee, no queda
garantizado que obtengamos el dato que inicialmente se grabó.
El buffer integrado en el puerto B resulta suficiente para excitar una carga
TTL estándar; como está capacitado para proporcionar 1mA de intensidad a 1,5
voltios, también permite excitar directamente la base de un par Darlington
operando como interruptor. No obstante, esta corriente resulta insuficiente para
excitar periféricos convencionales como diodos LED, visualizadores de siete
segmentos, etc., con lo que frecuentemente se deben conectar buffers externos
(como un 74LS241 o un 74LS541), o bien hacer uso de pares Darlington para
excitar periféricos (como veremos en el capítulo 6, el circuito ULN2803, pensado
para aplicaciones de este tipo, integra 8 transistores Darlington).
Como el puerto B permite manejar más corriente que el A, y debido al
comportamiento de las líneas de diálogo en ambas secciones (que se estudiará en
el capítulo 6), se tiene que habitualmente el puerto A se emplea para entrada de
datos y el B para salida. No obstante, recordemos que en todo caso la capacidad
de suministro de corriente es muy limitada, por lo que casi siempre habrá que
utilizar buffers externos para la excitación de periféricos mediante la PIA.
La PIA es un circuito adaptador muy versátil, cuya programación básica no
reviste demasiada complicación, no así la programación en detalle de sus cuatro
salidas de control, cuyo estudio dejamos pendiente para más adelante.

5.3.2. Puertos de entrada/salida paralelos en el 68HC11


El aumento de la capacidad de integración electrónica a mediados y finales de
los años setenta permitió construir los primeros microcontroladores [Daniels 96],
pues, al poder incorporar más elementos dentro de un único chip, se integró en
una misma pastilla junto a la CPU, memoria, puertos de E/S, así como otros
periféricos. Por ejemplo, en el caso del 68HC11, µC comenzado a comercializar
en el segundo lustro de la década de los ochenta, se incluye un núcleo procesador
(versión mejorada del 6800), memoria y multitud de periféricos.
El HC11 contiene cinco puertos de E/S (A, B, C, D y E), programables en
mayor o menor grado. Nos vamos a centrar en este momento en los puertos B y
C, por su similitud con los de la PIA; el resto los estudiaremos más adelante
(capítulo 6). El puerto B del 68HC11 es un puerto de 8 líneas de salida, y el
puerto C presenta 8 líneas, programables individualmente como entradas o
184 Microprocesadores y microcontroladores

salidas, cuya operación recuerda mucho la de PIA (Motorola debió aprovechar el


diseño de la vieja PIA a la hora de integrar puertos paralelos en sus µC).
En la tabla 5.1 aparecen las direcciones de ambos puertos, PORTB y PORTC.
La escritura sobre el registro de memoria $1004 mediante STAA $1004, por
ejemplo, hace que el valor contenido en el acumulador A aparezca en las líneas
del puerto B, saliendo al exterior por las correspondientes patillas del HC11, por
lo que, si conectamos a éstas unos LED (con un buffer intermedio que amplifique
la pequeña intensidad que es capaz de suministrar el puerto), quedará en ellos
representado el dato contenido en A.
Las líneas de PORTC (dirección $1003) son programables como entradas o
como salidas, para lo cual hay que actuar sobre su registro de dirección de datos
DDRC, que ocupa la dirección $1007. El papel de DDRC es idéntico al DDRA o
DDRB de la PIA, excepto que en este caso es más fácil de emplear, ya que no
comparte dirección con ningún otro registro, por lo que no es necesario
seleccionarlo previamente sino que se puede escribir en él de forma directa. Si el
contenido de DDRC es $00 (valor por defecto), el puerto C se comporta como
entradas, de modo que, si ejecutamos a continuación la instrucción LDAA $1003,
en A quedará almacenado el valor actualmente presente en las líneas del puerto C,
que podría quedar establecido, por ejemplo, por un conjunto de interruptores.

Registros Dirección Descripción


PORTB $1004 8 líneas, siempre de salida
PORTC $1003 8 líneas, programables individualmente de entrada/salida
mediante DDRC (inicialmente DDRC=$00, por lo que
por defecto son de entrada)
DDRC $1007 Registro de dirección de datos en PORTC (Data
Direction Register C). Cada bit determina si el
correspondiente pin de PORTC actúa como entradas (‘0’)
o salidas (‘1’). DDRC=$00 por defecto.
PIOC $1002 Bits de control del puerto C (Parallel Input/Output
Control). Controla las líneas de diálogo STRA y STRB.

TABLA 5.1. Puertos de propósito general B y C del 68HC11.


Entradas y salidas (I): aspectos básicos 185

Como hemos dicho, tras alimentar el HC11 el DDRC queda a cero, por lo
que, si no se modifica el puerto C, se comporta como entrada; cargando $FF en
$1007 el puerto C se comporta como salida (como en la PIA, cada línea puede
programarse individualmente de una forma o de otra).
Existen además dos líneas de diálogo, STRA (entrada) y STRB (salida), cuyo
papel es similar al de las C1 y C2 de la PIA, y cuya acción se controla
programando adecuadamente los bits del registro de control del puerto C,
colocado en la dirección $1002 (denominado PIOC, Parallel Input/Output
Control), que equivaldría al registro CRA o CRB de la PIA. En el capítulo
siguiente estudiaremos más profundamente los puertos del 68HC11.

Ejercicio
Conecta 8 LED y un conjunto de 8 microinterruptores (incorporados en un
encapsulado DIP-16) a los puertos B y C del 68HC11.

Resolución:
El puerto B es de salida, el C es programable de E/; por lo tanto,
conectaremos los LED al puerto B y los interruptores al C. Por defecto el puerto
C es ya de entrada, por lo que, en general, no será necesario programarlo.
Como la capacidad del 68HC11 de suministrar corriente es muy pequeña
(algo más de 20 mA en total, según hojas de características [Motorola 91b]), y
como cada LED precisa de 10 a 20 mA para que se ilumine apreciablemente,
colocaremos a la salida del puerto B un buffer para aumentar la capacidad del
68HC11 para manejar corriente; en la figura se muestra el empleo de un 74LS541
permanentemente habilitado (también es usual el empleo de un driver ULN2803).
Por su parte, el conjunto de 8 interruptores incorporados en un encapsulado DIP-
16 puede conectarse directamente al puerto C.
186 Microprocesadores y microcontroladores

5.3.3. Otros adaptadores paralelos


Uno de los adaptadores paralelos más conocidos es el PPI 8255
(Programmable Peripheral Interface) de Intel, que consta de tres registros PA, PB
y PC, asociados a 3 puertos paralelos de 8 bits, programables como entradas o
como salidas, más un registro de modo, PD. Posee menos versatilidad que otros
puertos programables, como la PIA, pero su empleo es relativamente sencillo. La
forma de conectar este adaptador sigue la filosofía Intel, aunque su conexión a
otros microprocesadores, como los de Motorola, no plantea graves problemas.
Otro famoso interfaz paralelo es la VIA 6522 (Versatile Input/Output
Adapter), cuyas características básicas resultan extraordinariamente similares a las
de la PIA 6821, en cuanto a arquitectura, operación e incluso patillaje del
integrado. A las funcionalidades ya conocidas de la PIA añade un sistema de
contadores y temporizadores, más un registro de desplazamiento (útil para la
conversión de datos serie a paralelo, y viceversa). La VIA es al famoso
microprocesador 6502 de MOS Technology (incorporado en los clásicos
ordenadores Commodore, y en los entrenadores KIM-1 y AIM65 de Rockwell) lo
que la PIA al 6800, pudiéndose conectar ambos fácilmente a cualquiera de los dos
microprocesadores, o de los miembros de sus familias (podemos considerar las
familias 65XX y 68XX primas, ya que parte del equipo de ingenieros que
desarrollaron el 6800 poco después abandonaron Motorola y diseñaron el 6502).

5.4. Técnicas básicas de entrada/salida (E/S)


Estudiados los tipos de interfaces de periféricos, pasaremos a continuación a
tratar las diversas técnicas de entrada/salida disponibles (métodos de gestionar
periféricos). Debido a la gran diversidad de periféricos deberá emplearse el tipo
de E/S más indicada a cada caso.
Un grupo importante de técnicas son las controladas por programa.
Supongamos que se dispone de un visualizador de siete segmentos conectado a un
puerto de salida; como este dispositivo periférico siempre está dispuesto a recibir
algún dato, el programa en el momento que lo precise puede enviarle un valor a
visualizar mediante una instrucción tipo STAA. En este caso se tiene un tipo de
E/S denominada directa por programa.
Sin embargo, si se tiene un conversor analógico a digital conectado a un
puerto de entrada, la CPU deberá solicitar el inicio de conversión por programa
(por ejemplo, mediante un instrucción STAA); pero en este caso la respuesta del
periférico no es inmediata, ya que el conversor puede tardar decenas de
microsegundos en traducir la señal analógica presente en su entrada al valor
Entradas y salidas (I): aspectos básicos 187

digital que deberá leer el µP. Por lo tanto, la CPU, tras solicitar la conversión,
deberá consultar el estado en el que se encuentra el periférico (leyendo el estado
de alguna línea o bit de control), hasta que éste le haga saber que ha concluido su
operación; en este caso se tiene una E/S por programa con diálogo.
No obstante, en ocasiones un periférico necesita urgente atención por parte
del µP (por ejemplo, puede ser el caso de un sensor de alarma), o simplemente la
CPU deja operar autónomamente (asíncronamente) a un periférico, y cuando éste
lo requiera él mismo tomará la iniciativa de la comunicación y solicitará atención
a la CPU (por ejemplo, una impresora que está imprimiendo y se queda sin papel).
En este caso se utiliza un tipo especial de E/S denominada por interrupciones.
Para ello, el µP dispone de unas líneas especiales, denominadas de interrupción, a
las cuales pueden estar conectados diversos periféricos; si uno de ellos activa una
línea de interrupción, la CPU deja de hacer la tarea que en ese momento estaba
realizando, y atiende al periférico que lo ha solicitado. Ésta es la manera más
eficiente de gestionar eventos asíncronos con la CPU, que resulta sumamente útil
sobre todo en el caso del control en tiempo real.
Por último, si se precisa el intercambio de cantidades masivas de datos entre
un periférico (p.e., un disco duro o un CD-ROM) y la memoria, si la CPU lo lleva
a cabo dato a dato (como hemos hecho hasta ahora), resultará extremadamente
lento. En este caso se suele hacer uso del acceso directo a memoria o DMA
(Direct Memory Access), consistente en abrir una vía directa de comunicación
entre periférico y memoria, llevándose a cabo el intercambio de datos sin
intervención de la CPU, gestionado por un chip controlador de DMA.
En lo que queda de capítulo estudiaremos todas estas técnicas de E/S.

Técnicas básicas de E/S:


• Directa

(1) Por programa ⇒ • Bucle de espera


• Con diálogo
• Consulta periódica
(2) Por interrupciones
(3) Por acceso directo a memoria (DMA)

TABLA 5.2. Técnicas básicas de entrada/salida.


188 Microprocesadores y microcontroladores

5.5. Entrada/salida controlada por programa


En las E/S por programa es el microprocesador quien toma la iniciativa de
establecer la comunicación con un determinado periférico. En esta sección
estudiaremos las dos formas de llevar a cabo la E/S de control por programa: de
forma directa y mediante diálogo con el periférico.

5.5.1. E/S directa por programa


La técnica de entrada/salida directa por programa es la más sencilla de todas,
tanto en cuanto a programa de control, como en hardware necesario, pero
solamente puede aplicarse a periféricos que estén siempre dispuestos a recibir un
dato (por ejemplo, un visualizador de siete segmentos) o a enviar un dato (por
ejemplo, un conjunto de 8 interruptores). Por lo tanto, esta técnica podrá
emplearse solamente con periféricos sencillos, como interruptores, LEDs,
visualizadores simples, conversores digital a analógico, etc., que no conllevan el
empleo de líneas de control.
En este caso la iniciativa es de la CPU, que en el transcurso de la ejecución
de un programa, en un momento dado precisa enviar un dato o recibirlo del
exterior. Esta técnica se lleva a cabo mediante el empleo de instrucciones de
transferencia de datos entre memoria y registro, como son las de carga y
almacenamiento. Por ejemplo, si un conjunto de 8 interruptores están conectados
a un adaptador de entradas como los estudiados antes, el cual se sitúa en la
dirección $1000 del mapa de memoria, la CPU podrá leer su estado mediante la
instrucción LDAA $1000. El estado abierto o cerrado de cada interruptor quedará
codificado en este caso como un ‘1’ o un ‘0’ en cada uno de los bits que
componen el acumulador A.
Por otro lado, si el sistema dispone de dos visualizadores de siete segmentos
conectados a un adaptador de salidas como se aprecia en la fig. 5.11, el cual se
sitúa en la dirección $2000 del mapa de memoria, la CPU puede presentar al
exterior un dato BCD de dos dígitos almacenado en el acumulador A mediante
una instrucción del tipo STAA $2000.

5.5.2. E/S con diálogo


Es la que se establece con aquellos periféricos que no están dispuestos
inmediatamente a recibir un dato o a enviarlo. Este tipo de periférico debe
disponer de alguna línea que indique su estado actual; la CPU antes de leer o
recibir el dato deberá comunicarse con el periférico, comprobar su estado (si está
dispuesto o no para comunicar). En definitiva, la CPU, que de nuevo es la que
Entradas y salidas (I): aspectos básicos 189

toma la iniciativa, no actúa directamente como en el caso anterior, sino que


establece un diálogo previo con el periférico.

FIGURA 5.11. Ejemplos de periféricos que admiten la técnica de E/S directa por programa.

FIGURA 5.12. E/S con diálogo: ejemplo de gestión de un conversor A/D. La CPU solicita inicio de
conversión con una lectura muda sobre la dirección que activa la salida del decodificador conectada a
INI; la CPU lee entonces el estado de FIN (conectada a BDat por un AE), y solamente procederá a
leer la salida de datos del conversor (D0-D7) cuando FIN=‘1’.
190 Microprocesadores y microcontroladores

Este diálogo, que consiste en consultar el estado del periférico, puede llevarse
a cabo en bucle de espera o por consulta periódica. En bucle de espera o modo
bloqueado la CPU comprueba continuamente el estado de algún tipo de línea que
indique «periférico preparado», y no prosigue con otras tareas hasta que logra
definitivamente la comunicación con el periférico (por ello, en ocasiones se
denomina también modo bloqueado). En el caso de la técnica de consulta
periódica, el µP sigue con sus tareas, y de vez en cuando consulta el estado de
disponibilidad del periférico.
Es fácil comprender que cada una de las dos técnicas descritas posee ventajas
e inconvenientes: el bucle de espera es un método sencillo y rápido, ya que, al
monitorizar permanentemente el estado del periférico, se podrá actuar en cuanto
esté listo, por contra, la CPU pierde mucho tiempo al tener que observar
continuamente el estado de un periférico (que puede ser extremadamente lento).
La técnica de consulta periódica, en cambio, es más eficiente, puesto que, al
consultar el estado del periférico solo de vez en cuando, la CPU puede dedicarse a
otras tareas mientras tanto; sin embargo, la implementación de esta técnica es algo
más compleja, y el periférico tardará en general más tiempo en ser atendido.
Este tipo de E/S con diálogo se emplea, por ejemplo, en las impresoras.
Cuando la CPU envía el texto a imprimir, la impresora lo recibe y almacena en su
buffer (memoria FIFO de almacenamiento temporal), y cuando dicho buffer se
llena, la impresora envía a la CPU una determinada señal de advertencia. Si la
CPU enviase datos a imprimir sin consultar el estado del buffer, se perderían
caracteres cuando éste se llenase, de modo que antes de enviar un dato la CPU
deberá consultar el estado de la impresora para comprobar si dispone de espacio
en el buffer, y cuando ya no disponga, deberá suspender el envío de datos hasta
que haya espacio.
En la fig. 5.12 desarrollamos un ejemplo de la aplicación de la técnica de
diálogo al caso de un conversor analógico a digital (A/D). Este tipo de circuito,
como es sabido, convierte la tensión analógica presente en su entrada a un valor
digital. La señal analógica de entrada debe situarse dentro del rango de tensiones
marcado por las dos patillas de referencia del conversor, VrL y VrH, que
adecuadamente conectadas a dos voltajes de referencia determinan las tensiones
mínima y máxima, respectivamente, que pueden ser convertidas.
Un conversor A/D se caracteriza, entre otras cosas, por el número de bits de
resolución que proporciona; así, un conversor A/D de 8 bits dará un valor binario
%0000 0000 cuando en su entrada analógica observe una tensión igual al valor
establecido para VrL, el valor %1111 1111 cuando sea igual a VrH, e intermedio
para tensiones dentro de este rango. Por ejemplo, si las tensiones de referencia
Entradas y salidas (I): aspectos básicos 191

son 0 y 5 voltios, se tendría que 255 es el valor binario correspondiente a +5 V, y


128 el correspondiente a aproximadamente +2,5 V (mitad de rango).
Los conversores A/D disponen de una línea que indica solicitud de comienzo
de conversión, que denominaremos INI, y otra de final de conversión, que
denotaremos por FIN. Supondremos que un flanco ascendente en INI hará que el
conversor comience a convertir, poniendo a su vez FIN a ‘0’; el conversor pondrá
FIN a ‘1’ solamente cuando haya concluido la conversión y disponga del valor
digital equivalente en sus líneas de datos (el tiempo que puede tardar depende del
tipo de conversor concreto, nosotros supondremos un tiempo de conversión del
orden de decenas de microsegundos).
Si se conecta un conversor A/D a un µP según el esquema de la fig. 5.12, éste
solicitará la conversión activando INI; el conversor empleará un rato en obtener el
valor digital correspondiente. El µP, en bucle de espera, leerá de forma continua
el estado de la línea FIN, y solamente tomará el dato cuando observe que FIN se
activa. En la fig. 5.12 la línea INI se conecta directamente a una salida del
decodificador de direcciones del sistema, que supondremos se corresponde con la
dirección $1000 del mapa de memoria; la activación de INI se llevará a cabo al
realizar una lectura o escritura sobre $1000, lo que se denomina una lectura muda
(o escritura muda, si se escribe), pues con ella no se pretende leer un dato, sino
simplemente que cierto valor aparezca en el bus de direcciones para que provoque
determinada acción. La línea FIN se conecta a D7 (bit más significativo del bus
de datos) por medio de un adaptador situado en la dirección $1001; por último, el
dato de 8 bits proporcionado por el conversor A/D se conecta a un puerto de
entrada de dirección $1002 (téngase en cuenta que la salida de los conversores
comerciales suele ser triestado, en cuyo caso este segundo adaptador de entradas
ya no sería necesario). La siguiente rutina realizaría el proceso descrito:
* Rutina conversión A/D
LDAA $1000 * lectura muda que solicita conversión
* bucle de espera
AUN_NO LDAA $1001 * lectura de línea FIN
BPL AUN_NO * cuando el bit 7 de $1001 sea 0, (A)>0
* entonces, conversión no concluida
* conversión concluida
LDAA $1002 * lectura del valor convertido
......
192 Microprocesadores y microcontroladores

5.6. E/S por interrupciones

5.6.1. Motivación e interés de las interrupciones


Hasta ahora hemos estudiado diversas técnicas de E/S; todas ellas se basan en
que la CPU atiende al periférico continuamente o de vez en cuando, pero siempre
desde su propia iniciativa. Sin embargo, en ocasiones resulta mucho más
eficiente que sea el propio periférico el que solicite la atención del
microprocesador cuando lo precise; en este caso se hace uso de las denominadas
interrupciones del microprocesador.
Ejemplo 1. Pensemos en una aplicación del campo de la domótica.
Supongamos que un sistema microprocesador controla toda una planta de un
edificio de oficinas y que los µP de todas las plantas se conectan por medio de
una red local al ordenador central del servicio de seguridad. Supongamos que
cada sistema µP debe tomar y almacenar los datos procedentes de un conjunto
de sensores de temperatura distribuidos por la planta, de un grupo de sensores
que indican el estado abierto o cerrado de las puertas y ventanas, y de un tercer
conjunto de sensores que señalan el estado encendido o apagado de las luces de
las dependencias. El µP va leyendo uno tras otro los datos proporcionados por
todos estos sensores, los almacena en su memoria y los envía al ordenador
central desde el que se monitoriza todo el edificio; si el número de sensores es
relativamente elevado este proceso podría tomarle varios minutos.
El sistema de seguridad sería mucho más útil si pudiese además controlar
diversos sensores de presencia que indiquen el posible acceso de intrusos a
determinadas zonas restringidas, o leer el estado de un conjunto de detectores
de incendio. Sin embargo, si estos importantes sensores se deben introducir
junto con el resto (temperatura, puertas, luces) en la secuencia completa de
lectura, el sistema resultaría ineficaz, ya que de esta manera el µP podría tardar
varios minutos en emitir una alarma de incendio o de intruso.
En el ejemplo anterior, y en otras muchas situaciones reales, se precisa de un
método de interconexión de periféricos que permita una rápida respuesta por parte
del µP a iniciativa del propio periférico. Para ello se introduce el concepto de
interrupción, consistente en una demanda de atención solicitada por un periférico
al microprocesador o CPU.
El µP posee para ello una serie de líneas específicas denominadas líneas de
interrupción, que en principio denotaremos por IRQ (Interrupt ReQuest), por
medio de las cuales un dispositivo externo puede solicitar que la CPU le atienda
durante unos instantes. Si el microprocesador admite la interrupción, suspenderá
la ejecución del programa actual y atenderá la solicitud del periférico ejecutando
Entradas y salidas (I): aspectos básicos 193

la denominada rutina de servicio de la interrupción, un subprograma (similar a


una subrutina) en el que están codificadas las acciones que deberá realizarse sobre
el periférico. En el ejemplo anterior tomado de la domótica, esta rutina de
servicio debería, entre otras cosas, disparar una alarma y enviar señales de
atención al ordenador central del edificio.
En definitiva, las técnicas de E/S controladas por programa resultan
relativamente simples, pero no permiten gestionar eficientemente sucesos
asíncronos, al ser éstos de carácter impredecible (como suelen ser los procedentes
del mundo real, por ejemplo, la activación de un sensor de presencia o de
incendio, una impresora que se queda sin papel, un teclado que puede ser pulsado
en cualquier momento, etc.), resultando estas técnicas difícilmente aplicables en
control en tiempo real, cuando el µP deba responder instantáneamente ante cierto
evento externo. Las interrupciones permiten al µP gestionar eficientemente y de
una forma relativamente sencilla estos sucesos asíncronos y ocasionales, y
atender a la iniciativa de cierto dispositivo periférico «instantáneamente».
Además, de este modo se logra cierta descentralización en el funcionamiento de
los componentes del sistema, ya que cada periférico puede operar autónomamente
y sólo demanda la atención de la CPU cuando sea preciso.
Como inconveniente del empleo de interrupciones cabe citar la necesidad de
incluir hardware adicional. Asimismo, la asincronía de las interrupciones
dificulta la verificación y puesta a punto del sistema microprocesador (pueden
producirse fallos esporádicos, difícilmente detectables), y también puede llegar a
desbordarse la capacidad del sistema si se produce un excesivo número de
interrupciones. Estos hechos habrá que tenerlos presentes.

5.6.2. Sistema de interrupciones del microprocesador


De manera que un microprocesador, que habitualmente ejecuta cierto
programa instrucción a instrucción, en un determinado momento puede verse
interrumpido por un dispositivo externo (periférico) al activar éste una línea de
interrupción (fig. 5.13, arriba). Si la CPU acepta dicha interrupción, suspenderá
por unos instantes la ejecución del programa en curso y atenderá al periférico, lo
que significa ejecutar la rutina de servicio asociada a dicha interrupción (fig. 5.13,
abajo). Posteriormente, servida la petición del periférico, el microprocesador
deberá retornar al programa original, justo en el mismo punto donde lo dejó y con
los registros conteniendo exactamente los mismos datos.
Ejemplo 2. Un sencillo ejemplo que ilustra el proceso descrito es la gestión de
un teclado. En principio, la CPU se encuentra ejecutando determinado
programa, por ejemplo, el que controla un osciloscopio digital; cuando alguien
194 Microprocesadores y microcontroladores

pulsa una tecla del panel de mandos, el circuito que controla el teclado envía
una señal de interrupción al microprocesador, el cual pasa a ejecutar la rutina
de servicio del teclado cuyo objetivo es explorar el teclado y obtener el valor
ASCII de la tecla pulsada, actuando en consecuencia. Finalmente, la CPU
proseguirá con la ejecución del programa de control del osciloscopio.

5.6.2.1. Proceso de interrupción


A continuación explicaremos con detalle los pasos que comprende el proceso
que sigue un µP genérico en el servicio de una interrupción (los detalles concretos
varían de un µP a otro, aunque en líneas generales casi todos responden a este
esquema):

/IRQ Periférico
Adaptador
Microprocesador
(CPU)

/INTA

Bus Datos

Programa Principal
Principal Rutina Servicio
: Interrupción
:
: Rutina Serv.
:
Interrupción
:
: :
: Retorno
:

FIGURA 5.13. Arriba, solicitud de interrupción a través de la línea IRQ y reconocimiento (aceptación)
de la misma por medio de INTA. Abajo, ejecución de la rutina de servicio.
Entradas y salidas (I): aspectos básicos 195

1. Concluir la ejecución de la instrucción en curso. No suele dejarse a medias la


ejecución de una instrucción, sino que se espera a que concluya antes de
atender una interrupción.
2. Decidir si acepta la interrupción. En determinadas circunstancias puede no
resultar oportuno que el µP sea interrumpido, por lo que algunas
interrupciones son de tipo enmascarable, es decir, pueden no ser atendidas
(«enmascaradas»). En algunos casos se tiene un sistema de prioridades, de
modo que, si la prioridad de la interrupción solicitada es inferior a cierto nivel,
ésta no se atiende; en otros casos, una interrupción enmascarable simplemente
tiene asociado un biestable denominado máscara, que dependiendo de si está a
‘0’ o a ‘1’ impide o no impide el servicio de la interrupción (en el 6800 se
denomina I, y en el 8086 es IF, Interrupt enable Flag).
3. Reconocimiento o aceptación. Si la interrupción es aceptada, lo habitual es
que el µP de alguna manera se lo indique al periférico. En algunos µP dicha
aceptación se realiza automáticamente; por ejemplo, el 8086 envía una señal al
periférico por la línea INTA (INTerrupt Acknowledge, fig. 5.13). En otros,
como el 6800, este proceso no es automático, y, cuando se requiera enviar una
señal de reconocimiento, habrá que programar en la rutina de servicio una
instrucción específica al efecto (una lectura o escritura).
4. Preservar el estado de la CPU. Tras atender la interrupción, el µP debe
proseguir su tarea justo en el mismo punto y estado en el que se encontraba,
por lo que antes de servir la interrupción debe salvaguardar el valor de sus
registros, normalmente en la pila del sistema. Algunos µP, como el 8086,
solamente guardan de forma automática en ella la dirección de retorno (el
valor del PC) y el registro de estado (los flag), mientras que otros, como el
6800 y el 68HC11, guardan automáticamente todos los registros.
5. Obtener la dirección de la rutina de servicio de la interrupción. La rutina de
servicio asociada a cada interrupción se encuentra alojada en una zona distinta
de la memoria; existen distintos esquemas para que la CPU obtenga tal
dirección para saltar a ella y servir la interrupción solicitada.
Un esquema usual es el de las interrupciones vectorizadas (p.e., 8086, 68000):
en este caso, el µP en una zona reservada de la memoria (siempre la misma)
denominada tabla de vectores de interrupción guarda las direcciones donde
comienzan las rutinas de servicio asociadas a las distintas interrupciones; el
periférico solicitante de interrupción colocará en el bus de datos un código o
número de vector, el cual viene a indicar la posición de la tabla donde se
encuentra la dirección (vector), que apunta a la rutina de servicio
correspondiente. Un caso particular de las interrupciones vectorizadas es el de
196 Microprocesadores y microcontroladores

las auto-vectorizadas, en las que cada línea de interrupción tiene asociada ya


una posición dentro de la tabla de vectores, por lo que el periférico no tiene
por qué colocar código alguno en el bus de datos (p.e., 6800, 68000).
En algunos µP antiguos (8080A, 8085 y Z80) se tenían interrupciones no
vectorizadas: en caso de interrupción, la CPU quedaba en espera de que el
periférico colocase en el bus de datos una instrucción de salto (de RESTAR en
los µP citados), que, al ser ejecutada por la CPU, la llevase directamente a la
casilla de memoria donde comenzaba la rutina de servicio.
6. Ejecución de la rutina de servicio. Recordemos que se trata simplemente de
un conjunto de instrucciones, a modo de subrutina (fig. 5.13); el fin de la
rutina de servicio viene indicada por una instrucción especial que indica «fin
de interrupción» o «retorno de interrupción» (RTI en el 6800, RFI en el 8086).
7. Restaurar el estado inicial de la CPU. Finalmente, la CPU debe retomar de la
pila los antiguos valores de los registros, en particular el del PC y el registro de
estado, para así retornar al punto del programa original donde se interrumpió la
ejecución, con la CPU colocada exactamente en el mismo estado.
8. Continuar con la ejecución del programa.

5.6.2.2. Tipos de interrupciones


Los tipos de interrupciones que soporta un µP pueden clasificarse de diversas
maneras. En primer lugar, distinguiremos entre interrupciones enmascarables y
no enmascarables:
a) Interrupciones enmascarables, que denominaremos IRQ (Interrupt ReQuest).
Son aquellas que pueden no ser atendidas por la CPU (en ocasiones pueden
quedar pendientes para más adelante). Recordemos que este tipo de
interrupciones suelen tener asociadas un biestable denominado máscara de la
interrupción, manipulable desde el programa, que en función de su estado hace
que la interrupción quede «enmascarada», y no se atienda.
b) Interrupciones no enmascarables, que denominaremos NMI (Non-Maskable
Interrupt). Son aquellas que la CPU siempre debe atender, no pudiéndose
deshabilitar por programa. Suelen asociarse a situaciones extremas que
precisan de una acción urgente, por ejemplo, un inminente fallo de
alimentación, una alarma de incendio, un error de memoria, etc.

Por otro lado, hasta ahora pensamos en las interrupciones como un proceso
desencadenado por un periférico que activa determinada línea del µP; sin
embargo, en los microprocesadores se da también la posibilidad de desencadenar
Entradas y salidas (I): aspectos básicos 197

una interrupción desde el propio programa: son las interrupciones software. Por
lo tanto, también podemos considerar la siguiente clasificación alternativa:
a) Interrupciones hardware. Debidas a la activación de una línea de interrupción
del µP por parte de un periférico. Algunas líneas se activan por flanco (con
frecuencia descendentes) y otras por nivel lógico (a menudo, nivel bajo ‘0’).
b) Interrupciones software (en algunos µP, como el 68000, denominadas traps).
Suelen generarse mediante instrucciones software específicas, asemejándose
así a una subrutina; en otros casos pueden desencadenarse por situaciones
especiales, como una división por cero.

5.6.3. Sistema de interrupciones del 6800


Describiremos a continuación los detalles del sistema de interrupciones del
6800. Los pasos que este µP sigue son muy similares a los generales expuestos,
con las precisiones que estableceremos a continuación. En el caso de toda la
familia 68XX de Motorola, la preservación del estado de la CPU consiste en
guardar el contenido de todos los registros de la CPU en la pila, siempre en un
mismo orden (fig. 5.14): PC (bajo y alto, es decir, PCL y PCH), X (bajo y alto,
XL y XH), A, B y CCR. Como en el caso de las subrutinas, el puntero de pila SP
queda apuntando a la primera casilla vacía de la pila.
Por otro lado, la búsqueda de la dirección de la rutina de servicio se basa en
la utilización de una tabla de vectores de interrupción, conjunto de casillas de
memoria colocadas en la familia 68XX en la parte más alta del mapa, y en el caso
concreto del 6800 desde la dirección $FFF8 a la $FFFF. La tabla de vectores
contiene las direcciones correspondientes al lugar donde comienzan las rutinas de
servicio de las distintas interrupciones del sistema; por ejemplo, el 6800 posee
cuatro interrupciones, por lo que habrá cuatro vectores, que ocupan ocho casillas
de memoria (fig. 5.15). Cuando se produce una solicitud de interrupción, el µP
acude a las dos casillas de la tabla de vectores donde está almacenada la dirección
de la rutina asociada a la interrupción concreta solicitada, dirección que será
cargada en el PC, ejecutando inmediatamente el µP un salto a dicha dirección. En
un sistema µP para control, como los que estudiamos, los vectores de interrupción
deben guardarse en una zona de memoria no volátil (ROM, EPROM, etc.), puesto
que al desconectar el sistema deben mantenerse sus valores.
198 Microprocesadores y microcontroladores

0000 0000

(SP)→ (SP)
CCR (SP)-1
B (SP)-2
A (SP)-3
XH (SP)-4
XL (SP)-5
PCH (SP)-6
(SP)→ PCL (SP)-7

FFFF FFFF

FIGURA 5.14. Estructura de la pila en el 6800, antes y después de servir una interrupción.

0000 0000

FFF8 IRQ (High) FFF8 FC


FFF9 IRQ (Low) FFF9 10
FFFA SWI (High) FFFA FA
FFFB SWI (Low) FFFB 00
FFFC NMI (High) FFFC FD
FFFD NMI (Low) FFFD C0
FFFE RESET (High) FFFE F8
FFFF RESET (Low) FFFF 00

FIGURA 5.15. Estructura de la tabla de vectores de interrupción del 6800. En el ejemplo de la


derecha, si se recibe una solicitud de interrupción IRQ y ésta es aceptada, el programa saltará
directamente a ejecutar las instrucciones colocadas a partir de la casilla $FC10.

Como ya sabemos, la rutina de servicio de una interrupción no es otra cosa


que una secuencia de instrucciones que codifican las acciones que deben llevarse
a cabo tras la aceptación de determinada solicitud de interrupción. La única
particularidad de las rutinas de servicio frente a las subrutinas convencionales es
que deben concluir con una instrucción específica de retorno de interrupción. En
el caso del 6800 se trata de la instrucción RTI (ReTurn from Interrupt), que indica
que la rutina ha concluido, procediendo entonces la CPU a desapilar y recuperar
Entradas y salidas (I): aspectos básicos 199

los viejos valores de los registros. Por lo tanto, en el 6800 la instrucción RTI
opera de forma similar a RTS (retorno de subrutina), pero ésta última solamente
recupera de la pila el viejo valor del PC, mientras que RTI recobra los valores de
todos los registros.
Obsérvese que al restaurar el contexto tras la instrucción RTI también se
recupera el antiguo valor del PC, con lo cual se obtiene de forma automática la
dirección del lugar desde el que el µP debe proseguir la ejecución del programa
anterior a la interrupción.
El M6800 dispone de cuatro tipos de interrupciones, tres hardware (IRQ,
NMI y RESET) y una software (SWI), que pasamos a describir:
1. Interrupción enmascarable IRQ (Interrupt ReQuest). Es la de menor prioridad
del sistema. Para su activación debe colocarse un nivel correspondiente a un
cero lógico en la línea /IRQ del 6800; pero, si el bit de estado I, máscara de la
interrupción IRQ (incluido en el registro de estado CCR) se encuentra a ‘1’,
esta interrupción se hallará en situación de enmascaramiento y no será atendida
(fig. 5.16). Es una línea de interrupción de propósito general, que suele ser
empleada por varios periféricos a la vez. Normalmente, la CPU enviará una
señal de aceptación al periférico indicando que su solicitud va a ser atendida
(reconocimiento), aunque el 6800 no lleva a cabo este proceso
automáticamente, sino que habrá que hacerlo por programa.

I CCR
M6800
/IRQ IRQ (interna)
(nivel)

‘1’ D Q NMI (interna)


/NMI clk
(flanco) clr

clear

FIGURA 5.16. Tratamiento interno de las interrupciones IRQ (por nivel) y NMI (por flanco) por el 6800
[Cahill 93].
200 Microprocesadores y microcontroladores

El bit de estado I (máscara de IRQ) puede ser manipulado por programa


haciendo uso de las instrucciones de puesta a ‘1’, SEI (SEt Interrupt flag), y
borrado con CLI (CLear Interrupt flag). Así, en los lugares críticos de un
programa donde no sea conveniente que se produzca una interrupción puede
colocarse una instrucción SEI que las deshabilita; posteriormente, las IRQ
pueden habilitarse de nuevo mediante una instrucción CLI.
Los pasos que el 6800 sigue si se solicita una interrupción IRQ pueden verse
en la fig. 5.17: en primer lugar, se espera a concluir la instrucción en curso, a
continuación se comprueba si las IRQ están enmascaradas o no; si no lo están
(I=0), se guardan los registros en la pila, se activa el bit I para evitar que el
servicio de la IRQ actual pueda ser interrumpido por una nueva IRQ, se carga
en el PC la dirección de la rutina de servicio (almacenada en las casillas $FFF8
y $FFF9) y, finalmente, se ejecuta la rutina de servicio. Hay que hacer notar
que, al retornar al programa principal tras la instrucción RTI, las IRQ quedarán
de nuevo habilitadas (el contenido del CCR se preservó en la pila, y si acaba
de servirse una IRQ quiere decirse que inicialmente I estaba a 0, por lo que al
desapilar el CCR se colocará de nuevo a este valor).
2. Interrupción no enmascarable NMI (Non-Maskable Interrupt). Se activa ante
la presencia de un flanco descendente en la línea /NMI del 6800 (fig. 5.16).
Suele reservarse para aquellos casos especiales en los que se deba producir una
respuesta rápida, como pueda ser un fallo inminente de alimentación o error en
un acceso a memoria. Se sirve en cuanto aparece, cuenta con mayor prioridad
que la IRQ y no requiere señal de aceptación o reconocimiento. Suele
dedicarse en exclusiva a un solo dispositivo externo.
Los pasos concretos que el 6800 sigue para el servicio de una NMI pueden
verse en la fig. 5.17: en primer lugar, se espera a concluir la instrucción en
curso, a continuación se guardan los registros en la pila, se activa el bit I para
evitar que durante el servicio de la interrupción NMI pueda ser interrumpido
por una IRQ (menos prioritaria), se carga en el PC la dirección de la rutina
NMI (guardada en $FFFC y $FFFD) y, finalmente, se ejecuta dicha rutina.
En la fig. 5.16 se muestra la diferencia del tratamiento interno en el 6800 de
las señales /IRQ y /NMI. Mientras que la interrupción IRQ se activa por nivel,
de modo que el periférico externo debe mantener la señal IRQ en estado bajo
hasta que sea atendido, la NMI lo hace por flanco: una transición descendente
en /NMI activa un biestable interno (transparente para el usuario) cuyo estado
es comprobado por el 6800, por lo que el periférico simplemente debe
provocar un flanco descendente y esperar que su solicitud sea servida.
Entradas y salidas (I): aspectos básicos 201

/IRQ

¿Instrucción No /NMI
Concluida?

Si

IRQ enmascarada. ¿Instrucción No


Si Continuar ejecutando Concluida?
¿I=1?
programa actual
No Si

Guardar registros en la pila ←(SP) Guardar registros en la pila ←(SP)


CCR CCR
B B
A A
Hacer I=1 Hacer I=1
XH XH
XL XL
PCH PCH
Actualizar PC Actualizar PC
PCL PCL
PCH←($FFF8) PCH←($FFFC)
PCL←($FFF9) PCL←($FFFD)

Saltar a la rutina de servicio de Saltar a la rutina de servicio de


IRQ (dada por el PC) NMI (dada por el PC)

FIGURA 5.17. Ejecución de las interrupciones IRQ y NMI en el 6800.

SWI

/RESET

Guardar registros en la pila ←(SP)


CCR
B Hacer I=1
A
Hacer I=1
XH
XL Cargar valor PC inicial
PCH PCH←($FFFE)
Actualizar PC PCL←($FFFF)
PCL
PCH←($FFFA)
PCL←($FFFB)
Saltar a la dirección
apuntada por el PC.
Saltar a la rutina de servicio de Comenzar la ejecución del
SWI (dada por el PC) programa de aplicación

FIGURA 5.18. Ejecución de la interrupción SWI y RESET en el 6800.


202 Microprocesadores y microcontroladores

3. Interrupción software SWI (SoftWare Interrupt). Se ejecuta mediante la


inserción en algún punto del programa de la instrucción SWI (SoftWare
Interrupt), comportándose de una manera parecida a una subrutina
convencional, sólo que en este caso se guardan en la pila automáticamente
todos los registros de la CPU. Suele emplearse en el depurado de programas
(por ejemplo, para implementar puntos de ruptura, en cuyo caso la rutina de
servicio se encargaría de visualizar el estado de los registros y detener la
ejecución), o para devolver el control del sistema a un programa monitor o
sistema operativo.
Los pasos concretos que se siguen para el servicio de una SWI son los
siguientes (fig. 5.18): se guardan los registros en la pila, se activa el bit I para
evitar que durante el servicio de SWI pueda ser interrumpido por una IRQ
(menos prioritaria), se carga en el PC la dirección de la rutina SWI (guardada
en $FFFA y $FFFB) y se ejecuta dicha rutina.
4. RESET o arranque. Se activa cuando se coloca un nivel correspondiente a un
cero lógico en la línea /RESET del 6800. Esta señal sirve para re-iniciar o
arrancar el µP (fig. 5.18), estableciendo los valores iniciales de los registros de
la CPU (coloca todos a cero, excepto el PC, que lo carga con los contenidos de
las direcciones $FFFE y $FFFF, y el bit I que lo activa), y comenzando la
ejecución del programa de aplicación o principal. Aunque el estado de RESET
puede considerarse también como una interrupción, en realidad es algo más
importante, pues determina el estado inicial de la operación del sistema µP.
Profundizaremos en esta cuestión en el siguiente punto.

• IRQ (Enmascarable, por nivel)


• Hardware • NMI (No enmascarable, por flanco)
Interrupciones • RESET (No enmascarable, por nivel)
del 6800

• Software • SWI (No enmascarable)

TABLA 5.3. Cuadro-resumen del sistema de interrupciones del 6800.


Entradas y salidas (I): aspectos básicos 203

/RESET

Secuencia de
comienzo
FFFE, FFFF

Si
/HALT

Máquina
detenida (HALT) No

Si Si
/HALT /NMI

No No

Si
/IRQ

No
Si No
¿I=1?

Carga Ejecuta rutina


instrucción servicio interrupción

Ejecuta NMI IRQ


instrucción FFFC, FFFD FFF8, FFF9

FIGURA 5.19. Diagrama de flujo del ciclo de trabajo del 6800.

5.6.3.1. Ciclo trabajo del 6800


Aprovecharemos el estudio en detalle del sistema de interrupciones del 6800
para describir el proceso exacto que realiza el 6800 para la ejecución de una
instrucción (fig. 5.19). Las dos fases básicas de la ejecución de una instrucción
son las bien conocidas de carga y ejecuta, pero previamente la máquina debe
comprobar una serie de condiciones, relacionadas con el estado de sus líneas de
interrupción /IRQ o /NMI, de /RESET y /HALT.
El funcionamiento de la máquina parte siempre de un estado inicial o de
reset. Para que se dé un estado de reset válido, tras la conexión de la alimentación
del µP y una vez que su patilla Vcc alcanza los 4,75 V, la línea de /RESET debe
204 Microprocesadores y microcontroladores

permanecer en estado bajo durante por lo menos 8 ciclos de reloj. Tras una señal
de RESET válida, todos los registros se ponen a cero, excepto el PC, que se carga
con los contenidos de las direcciones $FFFE y $FFFF. Es decir, en un sistema
basado en un 68XX, en las casillas más altas del mapa de memoria debe colocarse
la dirección donde se situará la primera instrucción del programa. Por ejemplo, si
el programa de aplicación comienza en la dirección $E000, la casilla $FFFE
contendrá el valor $E0, y la $FFFF el $00.
Tras ello, la CPU comprueba el estado de la patilla /HALT (fig. 5.19), que de
encontrarse activa fuerza la parada de la máquina. En situación normal se tiene
/HALT=‘1’, con lo que la CPU a continuación comprueba si se ha solicitado una
interrupción NMI o una IRQ, por este orden de prioridad, para servirlas (fig.
5.19). Si es la IRQ la que se ha solicitado, además comprueba el estado del bit I
máscara de IRQ. Solamente si /HALT está inactiva y no se debe servir ninguna
interrupción, el 6800 proseguirá con la ejecución de la instrucción actualmente
apuntada por el PC, cargándola y ejecutándola.
El ciclo de trabajo del 68HC11 se basa en principios similares, aunque debido
a la cantidad de periféricos y fuentes de interrupción que integra resulta más
complejo; el lector interesado puede consultar los detalles concretos en su manual
de referencia [Motorola 91].

5.6.3.2. La rutina de reset


La rutina de reset o arranque sirve para establecer el estado inicial del µP (por
ejemplo, tras conectar la alimentación), de modo que éste comience siempre su
operación a partir de unas condiciones iniciales pre-establecidas perfectamente
conocidas. La acción de reset también puede emplearse para sacarlo de un estado
de fuera de control (cuando vulgarmente se dice que el µP «se ha colgado»). La
secuencia de acciones llevadas a cabo por la máquina en estado de reset
establecen los valores iniciales por defecto de los registros del µP. Así, en el
6800, por un lado se ponen a cero los registros A, B, X y SP, por otro se coloca en
el PC el contenido de las posiciones de memoria $FFFE y $FFFF del vector de
interrupciones, que apuntan a la casilla de memoria donde se encuentra la primera
instrucción a ejecutar. El reset además pone a ‘1’ el bit de estado I para evitar la
aparición de interrupciones enmascarables prematuras (por ejemplo, antes de que
la pila esté colocada ya en el lugar adecuado).
En ocasiones se considera que las instrucciones que la CPU ejecuta tras la
señal de reset constituyen una rutina de reset, aunque pueden ser simplemente las
primeras instrucciones que componen el programa de aplicación (p.e., el control
de una máquina expendedora de latas de refrescos). En esta «rutina de reset», que
Entradas y salidas (I): aspectos básicos 205

el desarrollador de sistemas microprocesadores debe programar, pueden


encontrarse una serie de instrucciones que ejecuten las siguientes acciones:
1. Establecimiento del lugar donde se coloca la pila del sistema, para lo cual el
µP debe colocar la dirección de la base de la pila en el puntero SP mediante
una instrucción LDS. El microprocesador debe realizar esta acción lo antes
posible (LDS #dir_pila suele ser la primera instrucción del programa de
aplicación o rutina de reset).
2. Configurar los dispositivos de entrada/salida, almacenando los datos
adecuados en los registros de configuración (p.e., los de puertos programables,
como la PIA).
3. Ejecutar programas de diagnóstico del estado de la memoria, periféricos, etc.
4. Borrado de la memoria.
5. Inicialización de variables del sistema.
6. Habilitar interrupciones IRQ, si procede (instrucción CLI)
7. La última acción de la rutina de reset será el salto al lugar de comienzo del
programa principal (a veces, el programa principal es simplemente la
continuación de la rutina de reset, por lo que no resulta necesario saltar).
Por último, en el reset del 68HC11, además de los registros de la CPU,
también se inicializan a ciertos valores por defecto los numerosos registros de
configuración y periféricos integrados en la pastilla, con lo que los detalles de las
condiciones de partida son mucho más numerosas. De nuevo, remitimos al lector
interesado a su manual de referencia [Motorola 91].

5.6.3.3. Cuestiones avanzadas sobre las interrupciones en el 6800


En este punto comentaremos una serie de detalles adicionales relativos a las
líneas de interrupción del M6800. Buena parte de estas cuestiones han sido
extraídas del Apéndice del M6800 Microprocessor Applications Manual
[Motorola 75]. La lectura de estas cuestiones puede ser obviada en un primer
estudio del tema de las interrupciones.
Requisitos de tiempos para la activación de /IRQ y /NMI. Las señales internas de
IRQ y NMI (fig. 5.16) son muestreadas por la CPU durante la fase φ2 del reloj.
Para que al 6800 detecte una señal por /IRQ, ésta debe mantenerse a ‘0’ durante
por lo menos dos ciclos de reloj. Por su parte, si se desea que una NMI solicitada
mientras se ejecuta una instrucción sea atendida antes de empezar a ejecutar la
siguiente, la señal /NMI debe estar presente unos 200 ns antes de la conclusión de
la ejecución de la actual instrucción (antes del fin del último φ2 activo) [Motorola
206 Microprocesadores y microcontroladores

75]. Por otro lado, el biestable interno de /NMI es borrado tres ciclos de reloj
antes de ejecutarse la primera instrucción de la rutina de servicio; como ésta no es
enmascarada, si entonces ocurre un nuevo flanco descendente será interpretado
como una nueva solicitud de interrupción NMI (anidamiento).
Tiempo de respuesta (latencia). Se denomina latencia al tiempo que una
interrupción tarda en ser atendida. El M6800 tarda entre 13 y 23 ciclos de reloj en
empezar a ejecutar la primera instrucción de la rutina de servicio (depende de la
instrucción actualmente en curso y del ciclo en el que ésta se encuentra cuando
llega la señal de solicitud). La instrucción WAI (WAit for Interrupt), que
almacena los registros en la pila y detiene el funcionamiento de la CPU hasta que
se produzca una interrupción, puede ser empleada en ciertas situaciones para
disminuir la latencia, ya que tras la ejecución de esta instrucción la CPU precisa
únicamente de 4 ciclos de reloj para comenzar a ejecutar la rutina de servicio.
Subrutinas reentrantes. Según se estudió en el capítulo 4, aquellas subrutinas
susceptibles de ser utilizadas por una rutina de servicio de interrupción deberían
ser reentrantes, ya que pueden ser llamadas de nuevo antes de que acabe su
ejecución; por ejemplo, el programa principal llama a una subrutina de
visualización de dato en pantalla, y cuando la está ejecutando el µP acepta y sirve
una interrupción que hace uso de esta misma subrutina. Para que una subrutina
sea reentrante no puede hacer uso de direccionamiento directo ni extendido, ya
que en una segunda llamada se sobre-escribirían los datos parciales de la anterior;
por ello, en el almacenamiento de datos temporales debería emplear la pila.

5.6.4. Gestión de interrupciones múltiples


La gestión de múltiples interrupciones puede llevarse a cabo dedicando una
línea de interrupción a cada periférico o conectando varios periféricos a una
misma línea (fig. 5.20). Aunque el primer caso es el más sencillo, debido a que el
número de periféricos que pueden solicitar interrupción suele ser superior al de las
líneas de interrupción disponibles, casi siempre deben conectarse varios
periféricos a una misma línea de interrupción.
Ya se ha comentado que en muchos microprocesadores el sistema de
interrupciones es de tipo vectorizado, ya que el periférico solicitante debe indicar
el tipo concreto de interrupción colocando en el bus de datos un código o número
de vector; con dicho número la CPU calculará el lugar de la tabla de vectores de
interrupción donde se encuentra el correspondiente a la interrupción solicitada.
Entradas y salidas (I): aspectos básicos 207

Periférico 1 Periférico 1 Periférico N

Microprocesador
(CPU)
Adaptador 1 Adaptador 2 Adaptador N

/IRQ1
/IRQ2

/IRQ N

Periférico 1 Periférico 1 Periférico N

Microprocesador
(CPU)
Adaptador 1 Adaptador 2 Adaptador N

/IRQ1
/IRQ /IRQ2

/IRQ N

FIGURA 5.20. Gestión de múltiples interrupciones, por medio de varias líneas (arriba) o de una sola
(abajo).

No obstante, recordemos que el sistema de interrupciones del M6800 no es


vectorizado puro, sino más bien autovectorizado, pues cada tipo de interrupción
tiene ya asignado un lugar concreto dentro de la tabla de vectores, por lo que, en
principio, el periférico no tiene que proporcionar número de vector alguno.
El 6800 solamente dispone de dos líneas de interrupción reales, la /IRQ y la
/NMI. La interrupción IRQ, que actúa por niveles, es de propósito general; a ella
suelen conectarse a la vez periféricos como teclados, impresoras, sensores de
presencia, detectores de fin de carrera, etc.; para ello, habría que conectar las
líneas de interrupción correspondientes a las diversas fuentes a la entrada de
interrupción /IRQ del µP, realizando la operación AND de todas ellas (fig. 5.20),
de modo que en cuanto uno de los periféricos conectados solicita interrupción
poniendo su línea de solicitud a ‘0’, llegue ese ‘0’ lógico a la entrada /IRQ de la
CPU. En este caso se requiere algún mecanismo adicional mediante el cual la
CPU pueda determinar de entre todos los periféricos conectados a una misma
208 Microprocesadores y microcontroladores

línea de interrupción quién es el solicitante; éste va a ser uno de los aspectos que
estudiaremos en la presente sección.
Por otro lado, la interrupción no enmascarable NMI del 6800 actúa por
flancos, por lo que suele dedicarse en exclusiva a una sola fuente de interrupción,
como circuitos indicadores de fallo de alimentación, alarmas o cualquier otra
circunstancia grave [Lipovski 88, Motorola 91]. Ello no quiere decir que no
pueda emplearse con varias fuentes, sino que su gestión resultará mucho más
compleja y problemática que si actuase por niveles. Por ejemplo, si varios
periféricos han solicitado NMI por medio de un flanco descendente, al concluir la
rutina de servicio (instrucción RTI) los periféricos pendientes seguirán
manteniendo la línea /NMI a ‘0’, lo cual no sólo no desencadena una nueva NMI
(se precisa de un flanco), sino que además bloquea la posibilidad de que en el
futuro se genere otra. Este y otros problemas asociados a la gestión de múltiples
interrupciones a través de /NMI se describe en [Lipovski 88, Motorola 91].
Las interrupciones por flanco se dedican a situaciones extremas, por lo que en
principio debería actuar de forma instantánea, por lo que no resulta en general
conveniente que el µP pierda tiempo averiguando por alguna de las técnicas que
estudiaremos a continuación qué tipo de circunstancia concreta la ha producido.

5.6.4.1. Salidas colector/drenaje abierto


Para facilitar la conexión de múltiples periféricos a una misma línea de
interrupción de un microprocesador, las salidas de solicitud de interrupción suelen
ser de tipo colector o drenaje abierto, ya que permiten realizar dicha operación
lógica AND de forma cableada.
Recordemos que en un dispositivo colector abierto, de los dos transistores de
la típica salida TTL el superior no se integra (fig. 5.21), de modo que la salida de
la puerta debe mantenerse polarizada a una tensión Vcc mediante una resistencia
externa Rc. Como Vcc no tiene por qué ser +5 V, una puerta de salida colector
abierto permite la interconexión entre familias lógicas con niveles lógicos
diferentes, sin más que seleccionar la Vcc apropiada. Por otra parte, al no
integrarse el transistor superior, se puede proporcionar al inferior una mayor
capacidad en tensión y corriente, por lo que una puerta de este tipo permite
alimentar directamente periféricos con mayores requisitos en este sentido (p.e.,
una pequeña lámpara de 12 V). Además, las puertas de salida colector abierto (o
drenaje abierto, en tecnologías MOS) permiten el cableado directo de las salidas
de diversas puertas; manteniendo la salida global a Vcc con una resistencia
externa Rc, cuando la salida de todas las puertas esté en alto (transistor en corte)
la salida global valdrá Vcc, pero cuando una de las salidas (o más) esté en estado
Entradas y salidas (I): aspectos básicos 209

bajo (transistor en saturación) forzará una salida global de 0 V. Por lo tanto,


mediante la conexión directa de múltiples salidas colector abierto se está
realizando la operación lógica AND de todas ellas, por lo que se denomina
operación AND cableada.

Vcc Vcc

Rc (exterior)
exterior exterior

Salida TTL

Salida colector
abierto

FIGURA 5.21. Salidas TTL estándar y colector abierto. La salida se mantiene polarizada a Vcc (no
necesariamente de +5 V) por medio de una resistencia externa Rc. Varias salidas colector abierto
pueden unirse entre sí sobre la misma Rc, realizándose la operación AND cableada.

Operación AND
Salidas colector/
cableada
drenaje abierto

Vcc

3K3 M6800
/IRQ1

/IRQ2
/IRQ
/IRQ3

FIGURA 5.22. Varios dispositivos cuya salida de solicitud de interrupción sea colector abierto (o
drenaje abierto) pueden interrumpir al M6800 a través de la misma línea /IRQ.
210 Microprocesadores y microcontroladores

Esta propiedad se emplea para conectar múltiples fuentes de interrupción a


una única línea de solicitud sin necesidad de introducir puertas lógicas adicionales
(en el caso del 6800 se recomienda una Rc externa de unos 3,3 KΩ para Vcc=+5
V). De esta manera (fig. 5.22), en cuanto uno de los periféricos conectados a
/IRQ ponga su línea de solicitud de interrupción de tipo colector/drenaje abierto
en estado de cero lógico, la línea /IRQ se situará a ‘0’ y el 6800 detectará una
solicitud de interrupción.

5.6.4.2. Flag de interrupción pendiente y reconocimiento de IRQ


Supongamos que varios periféricos pueden interrumpir a la CPU a través de
la misma línea de solicitud de interrupción, que genéricamente denominamos
/IRQ (la cual supondremos que actúa por niveles, como la /IRQ del 6800 y
68HC11, o la INTR del 8086). Un periférico deberá colocar su salida /IRQ en
estado bajo, pero una vez su solicitud sea servida es obligatorio que el periférico
devuelva su salida /IRQ a ‘1’: si después de haberse ejecutado la rutina de
servicio y retornado al programa principal el periférico sigue manteniendo la línea
/IRQ a ‘0’ la CPU seguirá observando su entrada /IRQ en estado bajo, lo que
accidentalmente ocasionará una nueva interrupción (y así una vez tras otra). Es
decir, cuando se procede a servir una interrupción hay que indicárselo al
periférico (reconocimiento de interrupción) para que éste devuelva a reposo (‘1’)
su línea de petición [Cahill 93].
En muchos µP, como es el caso del 8086, la CPU realiza automáticamente
dicho reconocimiento activando una salida específica denominada de
reconocimiento de interrupción o INTA (INTerrupt Acknowledge, fig. 5.13). Sin
embargo, cuando no se dispone de una línea similar a INTA, como sucede en el
6800, este problema puede resolverse de la forma presentada en la fig. 5.23. En
primer lugar, la solicitud de interrupción se realiza utilizando como intermediario
un biestable D (síncrono) que hará el papel de flag señalizador de solicitud de
interrupción, el cual puede ser puesto a ‘0’ (solicitud de interrupción) por la línea
/IRQ del periférico, y devuelto a ‘1’ por la acción de una de las salidas del
decodificador de direcciones del sistema. Por lo tanto, cuando el periférico
solicita interrupción activa la entrada de reloj del biestable (CLK), por lo que
aparecerá un nivel bajo en su salida Q (fig. 5.23), que está conectada a la entrada
/IRQ del 6800; el µP responderá ejecutando la rutina de servicio. Una de las
primeras instrucciones de la rutina de servicio de IRQ deberá indicar al periférico
que la interrupción ha sido detectada y que se está sirviendo (reconocimiento);
para ello basta incluir en la rutina de servicio una instrucción que realice una
lectura o escritura sobre la dirección asignada al biestable D, lo que causará la
activación de su entrada asíncrona SET (fig. 5.23), devolviendo su salida Q a ‘1’,
Entradas y salidas (I): aspectos básicos 211

y, por ende, la entrada /IRQ del 6800 a su estado inactivo ‘1’. Dicha lectura o
escritura puede ser la misma que se ejecuta para tomar el dato que suministra el
periférico (entrada) o la correspondiente al dato que le enviamos (salida), o bien
puede tratarse de una lectura o escritura muda (de no importa qué dato).

Periférico 1 Periférico 2 Periférico n


borra

activa
D Adapt. D D
/INTA1 /INTA2 /INTAn
CPU EN EN EN
(M6800) /IRQ
/IRQ1 /IRQ2 /IRQn

DIR1
Decod. DIR2
Direcc.

DIRn

Bus Datos

Bus Direcciones

Flag de solicitud de IRQ

D Q
/IRQ
‘0’
Interrupción procedente
de un periférico
D M6800
clk
set
Reconocimiento
Interrupción

Habilitación /INTA Decodif.


puerto periférico Direcc. A0-A15

16 BDir

FIGURA 5.23. Arriba, esquema de reconocimiento de interrupción en un 6800 implementado con un


biestable D, que hace de flag (que es borrado por el periférico cuando solicita interrupción y es puesto
a ‘1’ por el decodificador de direcciones cuando se accede al adaptador). Abajo, detalle de su
implementación mediante un biestable D típico (7474). Se debe tener presente que, si el periférico se
gestiona mediante una PIA, ésta integra ya dicha lógica en los flag de los registros de control.
212 Microprocesadores y microcontroladores

Por lo tanto, cada periférico conectado a /IRQ deberá poseer su propio


biestable indicador, cada uno con su propia dirección; cuando un periférico desee
interrumpir a la CPU pondrá su biestable a ‘0’, lo que se interpretará como una
indicación de interrupción pendiente de respuesta.
Algunos periféricos y adaptadores incorporan ya un biestable indicador de
interrupción, con el mismo mecanismo de reconocimiento descrito. Por ejemplo,
como veremos en la siguiente Unidad, la PIA 6821 integra cuatro biestables que
cumplen precisamente este papel, implementando el reconocimiento de
interrupción, por lo que no es necesario incluir biestables externos, facilitando así
el trabajo con periféricos. Los puertos y periféricos integrados del 68HC11
también incorporan este mismo tipo de indicadores de interrupción pendiente.

5.6.4.3. Gestión de múltiples interrupciones sobre una misma línea


Supongamos que varias líneas de solicitud de interrupción procedentes de
diversos periféricos están conectadas a la entrada /IRQ del µP. Cuando uno o más
periféricos soliciten interrupción, el µP deberá determinar qué periférico o
periféricos son los solicitantes y establecer a cuál de ellos va a atender primero,
dependiendo de la prioridad de cada cual. Para la determinación del periférico o
periféricos solicitantes distinguiremos las siguientes tres técnicas [Aleksandridis
84, Peñalver 88, Rico 96]:
1. Encuesta o muestreo (polling). En este caso, cada periférico (o su adaptador)
incluye un biestable que indica la solicitud de una interrupción (o la existencia
de una interrupción pendiente de respuesta), el cual puede ser leído por la
CPU. Cuando un periférico precisa de la atención de la CPU, pondrá su
correspondiente biestable indicador de interrupción a ‘0’ (o a ‘1’, según el
convenio que se adopte), lo cual genera una señal activa en /IRQ. La situación
es la mostrada ya en la fig. 5.23. Cuando la CPU recibe por su línea /IRQ una
solicitud de interrupción debe leer uno a uno el estado del bit indicador de
cada periférico, siguiendo un orden determinado por la importancia concedida
a cada uno, es decir, la prioridad se establece por software. Cuando encuentra
uno de estos biestables activados (o desactivados, depende del convenio)
considera que ese periférico ha sido el causante de la interrupción, y sirve su
petición. De esta manera, al comienzo de la rutina de servicio de IRQ deberá
programarse dicha encuesta o muestreo, y saltar a un subprograma u otro en
función de quién sea el solicitante.
Entradas y salidas (I): aspectos básicos 213

Periférico 1 Periférico 2 Periférico n

/INTA /INTA /INTA


D Adapt. D Adapt. D Adapt.

CPU /IRQ1 EN /IRQ2 EN /IRQn EN


/IRQ

DIR1
Decod. DIR2
Direcc.

DIRn

Bus Datos

Bus Direcciones

Periférico i
/INTA Periférico i+1
(entrada) /INTA
(salida)
(Consideramos que /INTA se
mantiene a ‘0’ tan solo un instante.)

Set D

CPU /IRQ

FIGURA 5.24. Arriba, gestión de múltiples interrupciones por encadenamiento (daisy chain). Abajo,
un posible esquema de la lógica del encadenamiento de interrupciones (D=‘0’ indica solicitada /IRQ).

2. Estructura encadenada (daisy chain). De nuevo todos los periféricos conectan


su salida /IRQ particular a la /IRQ del microprocesador, del cual parte una
única señal de reconocimiento /INTA que llega en primer lugar al periférico de
más alta prioridad (fig. 5.24); si él no ha sido el solicitante de la interrupción
traspasa la señal de reconocimiento al vecino inmediato, y así sucesivamente
hasta que el periférico solicitante reciba por fin la señal de reconocimiento
(que habrá atravesado todos los periféricos de la cadena que le precedían);
dicho periférico desactiva entonces su propio biestable (y, por lo tanto, su
salida /IRQ), y coloca un código de identificación en el bus de datos, para que
la CPU pueda saber finalmente el periférico al que debe atender. En este
214 Microprocesadores y microcontroladores

esquema la prioridad se establece por la posición del periférico en la cadena.


En la fig. 5.24 puede apreciarse la lógica de este esquema: si la línea /INTA
de entrada al periférico i es 0 (reconocimiento) y él ha sido el solicitante
(D=‘0’), envía entonces una señal /INTA=‘1’ (no reconocimiento) al periférico
i+1, colocará su código particular en el bus de datos y así será atendido por la
CPU (tan pronto la CPU devuelva /INTA a ‘1’, el biestable D volverá a reposo
‘1’); si D=‘1’, él no habrá sido el solicitante, con lo que traspasa /INTA=‘0’ al
siguiente periférico.
3. Vectorización. Se hace uso en este caso de un circuito auxiliar denominado
controlador de interrupciones, que puede estar constituido por varios
integrados estándar, o bien puede tratarse de un único circuito integrado
específico, como el PIC (Programmable Interrupt Controller) 8259A de los
sistemas 80x86 de Intel. Las líneas de solicitud de interrupción de los distintos
periféricos se conectan al controlador, quien posee una única línea de salida de
interrupción que se conecta a la entrada /IRQ del µP. De nuevo, cada
periférico tiene asignado un determinado código que le identifica, usualmente
una palabra de 8 bits. Cuando un periférico i activa su línea /IRQi conectada
al controlador, éste avisa a la CPU a través de /IRQ. Si la CPU acepta la
interrupción, envía al controlador una señal de reconocimiento /INTA, quien
en respuesta retorna /IRQ al estado de reposo y pone en el bus de datos el
código del periférico solicitante. Finalmente, la CPU lee dicho código,
saltando a la rutina de servicio apropiada. Cada entrada de interrupción tiene
asignada una prioridad, de modo que si hay varias solicitudes pendientes el
controlador suministra a la CPU el código del periférico de mayor prioridad.
Aunque las prioridades se establecen por hardware, en muchos controladores
de interrupciones (como el 8259A) éstas pueden programarse en alguna
medida actuando sobre registros internos.
La ventaja de la técnica de encuesta es su relativa sencillez, pues no precisa
hardware adicional, aunque su gestión es lenta al tener que interrogar uno a uno a
todos los periféricos. La priorización por encadenamiento es algo más rápida,
pero aun así, si se trata de gestionar un elevado número de periféricos, el retraso
acumulado puede ser importante. La vectorización es, sin duda, el método más
rápido de todos, pero también resulta más complejo de implementar. Por lo tanto,
el esquema a emplear en cada ocasión dependerá de la aplicación concreta.
Finalmente, recordemos que en el caso del 6800 no se dispone de una línea
específica de reconocimiento, por lo que una de las salidas del decodificador de
direcciones podría adquirir el papel de línea de reconocimiento /INTA.
Entradas y salidas (I): aspectos básicos 215

Periférico 1 Periférico 2 Periférico n


borra habilita

/INTA D Set D Adapt. D Adapt.

EN EN EN
/IRQ PIC /IRQ1
/IRQ2

CPU
/IRQn

DIR1
Decod. DIR2
Direcc.

DIRn

Bus Datos

Bus Direcciones

FIGURA 5.25. Gestión de múltiples interrupciones por vectorización; hemos denominado PIC al
controlador de interrupciones. Cuando el PIC suministra el código del periférico y activa /INTA, la
CPU accede al periférico en cuestión colocando su dirección en el bus, activándose la
correspondiente línea DIR salida del decodificador de direcciones, la cual, además de habilitar la
conexión del periférico al bus, pondrá a ‘1’ (reposo) el biestable indicador de interrupción.

5.6.5. Sistema de interrupciones del 68HC11


Presentamos a continuación las características generales del sistema de
interrupciones del 68HC11; para un estudio de los detalles se sugiere al alumno la
consulta de [Motorola 91].
El sistema de interrupciones del 68HC11 hereda las características básicas del
del 6800, aunque presenta algunas diferencias significativas, entre las cuales cabe
destacar la incorporación de numerosas fuentes de interrupción adicionales. Así,
mientras que el 6800 dispone de cuatro interrupciones, con dos patillas del chip
dedicadas a las externas (/NMI e /IRQ), el 68HC11 dispone de más de veinte
posibles fuentes de interrupción (tabla 5.4), y dedica diversas patillas a las
interrupciones externas (por ejemplo, en la versión 68HC11A8 siete líneas pueden
generar interrupciones: XIRQ, IRQ, PA0/IC3, PA1/IC2, PA2/IC1, PA7/PAI/OC1
y AS/STRA).
216 Microprocesadores y microcontroladores

Vector Dispositivo Máscara Máscara


interrupción en CCR específica
FFC0 a FFD5 Direcciones reservadas ninguno ninguno
FFD6, FFD7 SCI: Registro receptor de datos lleno I RIE
SCI: Receptor sobre-escrito I RIE
SCI: Detección de línea inactiva I ILIE
SCI: Registro transmisor de datos vacío I TIE
SCI: Transmisión completa I TCIE
FFD8, FFD9 SPI: Transmisión serie completa I SPIE
FFDA, FFDB Flanco entrada acumulador de pulsos I PAII
FFDC, FFDD Acumulador de pulsos lleno I PAOVI
FFDE, FFDF Temporizador desbordado I TOI
FFE0, FFE1 Temporizador OC5 I OC5I
FFE2, FFE3 Temporizador OC4 I OC4I
FFE4, FFE5 Temporizador OC3 I OC3I
FFE6, FFE7 Temporizador OC2 I OC2I
FFE8, FFE9 Temporizador OC1 I OC1I
FFEA, FFEB Temporizador IC3 I IC3I
FFEC, FFED Temporizador IC2 I IC2I
FFEE, FFEF Temporizador IC1 I IC1I
FFF0, FFF1 Interrupción en tiempo real (RTI) I RTII
FFF2, FFF3 IRQ (pin externo o E/S paralelo) I ninguno
IRQ: Puerto E/S paralelo I STAF
FFF4, FFF5 Pin XIRQ X ninguno
FFF6, FFF7 SWI ninguno ninguno
FFF8, FFF9 Opcode ilegal ninguno ninguno
FFFA, FFFB COP desbordado ninguno NOCOP
FFFC, FFFD Monitor de reloj ninguno CME
FFFE, FFFF RESET ninguno ninguno

TABLA 5.4. tabla de vectores de interrupción del 68HC11. El orden en la tabla indica prioridad
creciente (la de mayor prioridad es RESET). Para cada interrupción se indica el bit del CCR que
puede enmascararla y el bit propio que permite enmascararla individualmente.
Entradas y salidas (I): aspectos básicos 217

Para facilitar el estudio de las numerosas interrupciones del 68HC11


trataremos, por un lado, las no enmascarables y, por otro, las enmascarables. El
sistema es, como en el 6800, de tipo autovectorizado, situándose el vector de
interrupciones entre las direcciones $FFC0 y $FFFF (de ellas las que van de la
$FFC0 a la $FFD5 están reservadas, mientras que las que van de la $FFD6 a la
$FFFF se corresponden con las distintas interrupciones del sistema).

5.6.5.1. Interrupciones no enmascarables en el 68HC11


El 68HC11 incluye las siguientes interrupciones de tipo no enmascarable:
• XIRQ. Interrupción hardware externa que hace uso de la línea /XIRQ, versión
mejorada de la NMI del 6800. Recordemos que en el 6800 durante el estado
de reset la interrupción IRQ permanecía inhabilitada, pero no así la NMI, por
lo que podría aparecer una interrupción de este tipo antes incluso de que la
rutina de reset hubiese colocado la pila en el lugar adecuado, lo que puede
ocasionar una catástrofe. Otro problema de NMI es que si la señal que la
activa presenta rebotes ocasionaría múltiples interrupciones anidadas. En el
HC11 se resuelven ambos problemas mediante un flag X asociado a /XIRQ,
situado en el CCR, y cuyo papel es inhibir en situaciones muy concretas la
interrupción no enmascarable XIRQ. Cuando el µP está en estado de reset X
permanece activado, con lo que no se admite la aparición de XIRQ, lo que
resuelve el primero de los problemas citados; en la rutina de reset una
instrucción TAP podrá poner X a cero, habilitando así las interrupciones
XIRQ. Por otra parte, siempre que se produce una interrupción XIRQ el
68HC11 pone X a ‘1’, con lo que se evita el problema descrito de los rebotes.
Se debe tener en cuenta que X es una máscara muy particular, cuyo valor no
puede ser modificado por software fuera de la rutina de reset, por lo que XIRQ
se comporta como una verdadera interrupción no enmascarable. A diferencia
de la NMI, XIRQ responde a niveles, por lo que no resulta tan compleja la
gestión de interrupciones múltiples, como señales de fallo de alimentación,
alarmas, etc. (las salidas drenaje abierto se conectarían directamente a /XIRQ,
que se mantiene a +5V mediante una resistencia de polarización de 4,7 KΩ).
• Código de operación ilegal (illegal opcode fetch). Cuando el 68HC11 carga el
opcode de una nueva instrucción, si éste no se corresponde con ninguno de los
correspondientes al juego del HC11 considera que se ha producido algún error
en el sistema, ejecutando entonces una interrupción de código ilegal. Una
carga de un opcode falso puede ser debido a un fallo del software (error de
programación) o del hardware (por ejemplo, ruido).
218 Microprocesadores y microcontroladores

• SWI. Es la interrupción software equivalente a la del 6800. La instrucción


SWI no se cargará si existe alguna interrupción pendiente de respuesta. Por
otra parte, si se está ejecutando una interrupción SWI no se sirve ninguna otra
interrupción, ya que pone a uno tanto el bit X como el I. Como en el 6800,
esta interrupción se emplea en el depurado de programas (devolución del
control a un programa monitor, puntos de ruptura, etc.).
• COP (Computer Operating Properly) y monitor del reloj. Se activan en
situaciones de mal funcionamiento, garantizando la correcta operación del µC.
• Estado de RESET (si lo consideramos un tipo de interrupción).

5.6.5.2. Interrupciones enmascarables en el 68HC11


Las restantes interrupciones del 68HC11 son enmascarables, unas activables
por eventos externos y otras por internos; el bit de estado I permite enmascarar
globalmente todas a la vez (fig. 5.26). Excepto la IRQ (externa similar a la del
6800), cada una de las demás pueden ser además deshabilitadas individualmente
haciendo uso de un bit de máscara específico a cada una (similar al I), que se
sitúan en los registros de configuración internos del HC11 (a partir de la dirección
$1000). También cada interrupción tiene asignado un bit específico cuyo papel es
el de flag de solicitud de interrupción (como el biestable D de los apartados
anteriores, fig. 5.26), el cual indica que la interrupción correspondiente está
pendiente de respuesta.

68HC11

I CCR
Máscara global
Interrupción Interrupción
(externa) (interna)

Máscara particular
Flag indicador
solicitud
interrupción

FIGURA 5.26. Máscaras global y específicas en las interrupciones enmascarables del 68HC11.
Entradas y salidas (I): aspectos básicos 219

• IRQ. Es la equivalente a la IRQ del 6800. Por defecto, se trata de una


interrupción que actúa por nivel, aunque puede ser configurada para que actúe
por flanco.
• Temporizadores IC (Input Capture) y OC (Output Compare) (puerto A).
Permiten generar interrupciones en función de eventos provocados por señales
externas sobre las líneas IC (capturas de entradas), o por señales internas del
temporizador en las OC (salidas por comparación).
• El bloque de interrupciones en tiempo real o RTI (Real Time Interrupt)
permite generar interrupciones periódicas cada cierto tiempo (programables).
• Acumulador de pulsos, SCI y SPI. Son otros de los bloques internos del HC11
que generan interrupciones cuando se dan ciertos eventos en la comunicación
en serie con periféricos (recepción de un byte, errores de transmisión, etc.).
Recordemos que los pines del 68HC11 que permiten la generación de
interrupciones enmascarables son: IRQ, PA0/IC3, PA1/IC2, PA2/IC1,
PA7/PAI/OC1 y AS/STRA. Algunos de ellos dependen de cómo hayamos
configurado los puertos/periféricos en los que se enmarcan; por otro lado, tanto
IRQ como PA0/IC3, PA1/IC2 y PA2/IC1 son configurables para que puedan
responder tanto a nivel como a flanco (ascendente o descendente), mientras que
PA7/PAI/OC1 y AS/STRA responden a flancos (ascendentes o descendentes
según se programen).

5.7. E/S por acceso directo a memoria (DMA)


Cuando se trata de transmitir una voluminosa cantidad de información las
técnicas descritas hasta el momento resultan ineficientes. Por ejemplo, en el caso
de los computadores esto sucede cuando debe cargarse un programa de disco duro
a memoria, al leer ficheros de un CD-ROM, cuando se accede a archivos
almacenados en cinta, etc.
En una transferencia como las estudiadas hasta ahora la CPU en todo
momento gobierna el movimiento de datos; por ejemplo, en el caso del 6800, para
la lectura de un dato de un periférico de entrada y su almacenamiento en memoria,
en primer lugar la CPU debe llevar el dato del puerto de entrada a uno de sus
registros internos, como el A (LDAA puerto), y a continuación transferir el dato
del registro interno A a una casilla de memoria (STAA memoria).
220 Microprocesadores y microcontroladores

Canales de DMA
adicionales

DACK
Reconocimiento DMA Controlador de DMA Periférico con
Petición de dato capacidad DMA
BA/HOLDA Dir origen
DRQ
Dir destino Aceptación
HALT/HOLD
Tamaño bloque Al bus de
Solicitud DMA datos

Al bus de
direcciones

FIGURA 5.27. Esquema básico de un ontrolador de DMA.

En resumidas cuentas, en el caso de transferencia masiva de información la


CPU se verá monopolizada durante un buen rato por una rutinaria tarea de
movimiento de datos, en detrimento de las más propias de procesamiento. Es
más, si se tiene que mover un gran bloque de datos se necesita un programa
considerable, perdiéndose más tiempo en ejecutar las instrucciones asociadas
(para cada dato, primero ‘LDAA origen’, a continuación ‘STAA destino’) que en
el movimiento de los propios datos. En estos casos sería preferible algún
mecanismo que proporcione una mayor velocidad, evitando que la CPU deba
comandar todo el proceso (pudiendo en ciertos casos quedar libre para realizar
otras tareas mientras tanto), y procurando que los datos no tengan que pasar
obligatoriamente por la CPU. Para ello se emplea la técnica conocida como
acceso directo a memoria o DMA (Direct Memory Access). Mediante DMA se
establece una comunicación directa entre un periférico con capacidad DMA (por
ejemplo, un disco duro, un CD-ROM, etc.) y la memoria, empleando los propios
buses del sistema, y ello de una manera completamente transparente para la CPU,
pues el proceso es gobernado por un circuito integrado especial denominado
controlador de DMA (fig. 5.27).
Cuando se va a realizar un acceso a memoria, el controlador de DMA solicita
permiso a la CPU, que es quien habitualmente cumple el papel de maestro
(master) del bus del sistema. Si ésta acepta la petición, indicará al controlador de
DMA la dirección de memoria a partir de la cual se van a tomar los datos y dónde
se deben alojar, así como el número de bytes que se transmitirán, información que
el controlador de DMA almacena en sus registros internos (fig. 5.27). La CPU
Entradas y salidas (I): aspectos básicos 221

entonces pone sus líneas de datos y direcciones en alta impedancia, e indica al


controlador de DMA que le cede el control de los buses del sistema durante el
proceso. El chip controlador de DMA se erige entonces en maestro del bus y
emprende la transferencia de datos entre periférico y memoria. Cuando ésta
concluye, se lo hace saber a la CPU, normalmente por medio de alguna
interrupción; entonces la CPU vuelve a retomar el control de los buses y prosigue
con su actividad normal.
El proceso de DMA descrito en el párrafo anterior se denomina DMA por
transferencia de bloques; es el tipo de DMA más sencillo y rápido, pues permite
la transferencia de todo un bloque completo de datos, pero a un elevado coste,
puesto que durante todo el proceso la CPU detiene su actividad. Una alternativa
es la DMA por robo de ciclo; en esta variante el controlador de DMA se mantiene
atento a la actividad de la CPU y realiza poco a poco la transferencia directa de
datos a memoria aprovechando aquellos ciclos en los que la CPU no emplea los
buses. La ventaja de este segundo caso reside en que la CPU no detiene su
actividad, por lo que en paralelo se lleva a cabo procesamiento y transferencia de
datos, pero cuenta con el inconveniente de resultar un proceso más lento y
complejo.
En la fig. 5.28 se muestra un ejemplo de sistema con capacidad de DMA;
obsérvese que un controlador de DMA puede gestionar varios periféricos a través
de los distintos canales de DMA que incorpora. En el caso del 6800, las líneas
que se emplean para realizar DMA son /HALT, BA, TSC y DBE. Para llevar a
cabo DMA por bloques, /HALT («alto») hace el papel de línea de solicitud de
DMA que el controlador debe activar, en cuyo caso el 6800 concluye la ejecución
de la instrucción actualmente en curso, pone en alta impedancia VMA, R/W y sus
buses de direcciones y datos, y activa BA (Bus Available), que es la línea de
reconocimiento de DMA, indicando al controlador que puede tomar el control del
bus. Para llevar a cabo una DMA por robo de ciclo, el controlador de DMA debe
hacer uso también de las líneas TSC (Tri-State Control) y DBE (Data Bus
Enable), las cuales, respectivamente, ponen en alta impedancia las líneas de
direcciones, R/W y el bus de datos. El M6844 es el circuito integrado controlador
de DMA de la familia 68XX de Motorola [Lipovski 88].
En el caso de los sistemas 80x86 clásicos el controlador de DMA es el 8237;
las líneas HOLD y HOLDA (petición y reconocimiento) establecen el diálogo del
controlador 8237 con el 80x86, y DRQ (DMA ReQuest) y DACK (DMA
ACKnowledge) establecen el diálogo controlador-periférico en cada uno de los
cuatro canales de DMA que soporta.
222 Microprocesadores y microcontroladores

Reconocimiento DMA Transferencia normal


BA/HOLDA
Canales de DMA
Microprocesador HALT/HOLD adicionales
(CPU) Control
Solicitud DMA DMA

DACK
Controlador de Periférico con
Registro Memoria
DMA DRQ capacidad DMA

Direcciones
Direcciones Dato de la CPU
a memoria
Dato del periférico a la CPU

Bus Datos

Bus Direcciones

Reconocimiento DMA Transferencia por DMA


BA/HOLDA
Canales de DMA
Microprocesador HALT/HOLD adicionales
(CPU) Control
Solicitud DMA DMA

DACK
Controlador de Periférico con
Registro Memoria
DMA DRQ capacidad DMA

Direcciones
Direcciones

Ruta de los datos en el acceso directo a memoria

Bus Datos

Bus Direcciones

FIGURA 5.28. Transferencia convencional de datos (arriba), apoyándose en un registro interno de la


CPU, y acceso directo a memoria o DMA (abajo). Los datos para ir del periférico con capacidad DMA
a memoria no necesitan pasar por la CPU.

El DMA es un proceso fundamental en los grandes sistemas


microprocesadores, especialmente en los computadores, pero no suele ser
necesario en los pequeños sistemas orientados a instrumentación y control, como
los microcontroladores de 8 bits (así, el 68HC11 no tiene capacidad de DMA);
por este motivo no profundizaremos más en el tema.
Capítulo 6
Entradas y salidas (II): control de periféricos

6.1. Introducción
Expuestos en el capítulo anterior los conceptos fundamentales sobre las
entradas/salidas (E/S), como son las técnicas disponibles y los aspectos más
básicos referentes a los circuitos adaptadores, en éste que comienza trataremos
de una forma amplia el tema de los periféricos y su control.
Así, hemos visto ya que un puerto de salida se construye en torno a un
registro que mantiene los datos enviados por la CPU hacia un periférico de
salida, mientras que un puerto de entrada se realiza a partir de buffers triestado
que en un instante dado se habilitan para permitir el paso de datos procedentes
de periféricos de entrada hacia bus interno. También hemos estudiado los
aspectos más básicos de los puertos programables de E/S, como la PIA 6821,
cuyas líneas pueden hacer el papel de entradas o salidas, dependiendo de cómo
sean programadas. Por motivos pedagógicos (para «dosificar» la información),
hemos dejado para el presente capítulo el estudio de los detalles más complejos
de la operación de un puerto paralelo como la PIA (los relacionados con sus
líneas de diálogo o control).
Por otro lado, en el capítulo anterior nos hemos centrado en el estudio de
los puertos paralelos, que envían o reciben varios bits a la vez (normalmente
ocho). Sin embargo, existe otra modalidad de intercambio de datos
denominada comunicación serie, consistente en enviar los bits que componen
un dato secuencialmente (uno tras otro) por una única línea. Para facilitar la
comunicación serie suele hacerse uso de circuitos adaptadores específicos,
como las UART (Universal Asynchronous Receiver Transmiter); en este
capítulo estudiaremos el ACIA 6850 de Motorola como ejemplo de UART.
Para concluir el estudio del subsistema de E/S, trataremos al final de este
capítulo los periféricos más habituales que suelen aparecer en los sistemas
microprocesadores, así como algunos de los sistemas de almacenamiento
masivo de la información más habituales. Asimismo, estudiaremos los bloques
(periféricos) que aparecen integrados en un microcontrolador típico como es el
68HC11; dada la complejidad del 68HC11, sería necesario dedicar varios
capítulos completos al estudio de los muchos periféricos que integra (conversor
224 Microprocesadores y microcontroladores

A/D, circuito temporizador, bloques de comunicación serie, etc.); aquí


trataremos solamente sus aspectos más genéricos, el lector interesado deberá
dirigirse al manual de referencia del M68HC11 [Motorola 91], o a los muchos
libros dedicados exclusivamente al estudio de este microcontrolador (por
ejemplo, [Driscoll 94, Huang 96, Lipovski 88, Spasov 96]). En este sentido,
recordemos que nuestro propósito es presentar los conceptos básicos relativos
al diseño de sistemas microprocesadores y microcontroladores, no realizar el
estudio en profundidad (que exigiría mucho tiempo) de los numerosos detalles
de funcionamiento que presenta un microcontrolador tan complejo como el
68HC11.

6.2. Adaptadores programables paralelos: E/S con diálogo


En el capítulo anterior realizamos una introducción a los puertos
programables paralelos y estudiamos los aspectos elementales de
funcionamiento de uno en particular, la PIA 6821 de Motorola, así como la
operación básica de los puertos de propósito general B y C del 68HC11. En
esta sección profundizaremos en los aspectos relacionados con la transferencia
de datos con diálogo mediante estos puertos.

6.2.1. Diálogo con periféricos


Recordemos que el modo más simple de comunicación es la entrada/salida
directa, consistente en escribir directamente sobre un puerto de salida, o bien
leer uno de entrada. La E/S directa se emplea en aquellos periféricos siempre
dispuestos a enviar o recibir datos, como un conjunto de interruptores o LED.
Sin embargo, cuando un periférico no siempre está disponible debe
establecerse una E/S con diálogo (handshaking), en cuyo caso se debe
consultar cuál es su estado antes de iniciar la comunicación; por lo tanto, este
tipo de comunicación permite trabajar con un periférico arbitrariamente lento.
Un ejemplo de ello sería la comunicación del microprocesador con una
impresora (suponiendo, para simplificar, que ésta no dispone de buffer FIFO de
almacenamiento temporal de datos): la impresión de un carácter en papel es un
proceso mecánico mucho más lento que el proceso electrónico de envío del
dato a la impresora (milisegundos frente a microsegundos), por lo que la CPU
no deberá enviar un nuevo dato hasta que no haya concluido la impresión del
anterior, pues si no se perderá. Otro ejemplo ya estudiado es la gestión de un
conversor A/D: la CPU solicita conversión activando determinada línea, el
conversor A/D requiere cierto tiempo (p.e., 100 µs) para realizar la conversión,
Entradas y salidas (II): control de periféricos 225

de modo que la CPU deberá consultar el estado del A/D y leer el dato
solamente cuando haya acabado de convertir.

Salida con diálogo completo

1 DATO

CPU+puerto Dato Válido Periférico


(envía dato y (STRB, CA2) (espera dato)
avisa)

2 DATO

CPU+puerto Dato Válido Periférico


(envía dato) (STRB, CA2) (recibe dato y
reconoce)

Dato Recibido
(STRA, CA1)

3
CPU+puerto Periférico
(retira señales) (espera)

Dato Recibido (STRA)

4
CPU+puerto Periférico
(fin (retira señal, fin)
transferencia)

FIGURA 6.1. Esquema de un proceso genérico de comunicación con diálogo (handshaking), con
iniciativa de la CPU (si la iniciativa fuese del periférico, en vez de ‘Dato recibido’, se tendría
‘Solicitud de dato’).
226 Microprocesadores y microcontroladores

La comunicación con diálogo completo entre CPU y periférico requiere de


un conjunto de líneas de datos y, por lo menos, dos de control, una que indique
«dato válido» o «dato listo» (data ready), y otra que señale «dato recibido»
(data acknowledge) o «solicitud de dato». El proceso genérico se lleva a cabo
siguiendo una serie de pasos bien definidos; a modo de ejemplo en la fig. 6.1 se
muestra el caso de una salida con diálogo: la CPU pone el dato en el puerto,
activando a la par la señal «dato listo»; el periférico, al observar la activación
de la línea de «dato listo», toma el dato presente en el puerto y activa a su vez
la señal de «dato recibido»; la CPU, al observar que el periférico ha activado la
señal «dato recibido», retira el dato del puerto y desactiva la señal «dato listo»;
por último, el periférico, al observar que «dato listo» retorna a reposo,
desactiva a su vez «dato recibido», completando de esta manera el ciclo de
diálogo y posibilitando un nuevo intercambio de datos.
Este tipo de protocolos pueden realizarse íntegramente por software: por
ejemplo, se envían los datos por las ocho líneas del puerto A de la PIA y se
emplean como líneas de «dato listo» y «dato recibido» dos líneas del puerto B,
cuyos estados podrían leerse y cambiarse mediante instrucciones LDAA y
STAA. No obstante, para facilitar este proceso y no tener que programarlo al
detalle, los puertos de E/S suelen incluir líneas específicas denominadas de
diálogo o de control de periféricos, que automatizan el diálogo. El empleo de
este hardware diseñado a propósito, que automáticamente implementa el
proceso descrito de salida con diálogo (y el complementario de entrada con
diálogo) es mucho más eficaz (rápido y sencillo de programar). En el caso de
la PIA cada una de las dos secciones (A y B) incluyen dos líneas de diálogo,
CA1 y CA2, CB1 y CB2 (las C1 son de entrada, las C2 son programables como
entrada o como salida), cuya acción se establece mediante los registros de
control CR (CRA y CRB). En el caso del 68HC11 se tienen dos líneas STRA
(entrada) y STRB (salida), programables mediante el registro PIOC. Éstos son
los aspectos que vamos a proceder a estudiar a continuación.

6.2.2. Transferencias con diálogo con la PIA 6821


Recordemos que la PIA incorpora dos puertos paralelos (A y B), cada uno
compuesto por 8 líneas de datos (PA0 a PA7, PB0 a PB7), que pueden hacer de
entradas o de salidas. Cada puerto tiene asociado un registro de datos, ORA y
ORB, que a su vez tienen asignadas determinadas direcciones dentro del mapa
de memoria del sistema. Cuando se trata de enviar un dato por uno de los
puertos, debe escribirse dicho dato con instrucciones como STAA en el registro
de datos correspondiente. En cambio, cuando se trata de recibir un dato,
obviamente deberá leerse mediante instrucciones como LDAA.
Entradas y salidas (II): control de periféricos 227

Para indicar si cada una de las líneas de cada puerto A y B trabajan como
entradas o como salidas se hace uso de los registros de dirección de los datos,
DDRA y DDRB, que tienen asignada también una dirección dentro del mapa de
memoria (recordemos que comparten la misma dirección que ORA y ORB,
respectivamente). Un ‘0’ en un bit i de DDRA hace que la línea i asociada
haga de entrada, mientras que un ‘1’ programa dicha línea como salida.
La PIA dispone de dos registros adicionales (uno por puerto), los registros
de control CRA y CRB; de sus 8 bits hasta ahora solamente hemos estudiado el
papel del bit 2 de CRA(B) (como todo lo que comentemos para el puerto A
sirve para el B, para simplificar las explicaciones escribiremos el nombre de un
puerto o registro particularizado para A, y añadiremos la letra B entre
paréntesis). Puesto que DDRA(B) y ORA(B) tienen asignada una misma
dirección, la manera de distinguir si se va a operar sobre uno u otro es el estado
actual de dicho bit 2, CRA(B)[2] (denotaremos un bit particular de un registro
escribiendo su número entre corchetes): así, si CRA(B)[2]=‘0’ (léase «el bit 2
de los registros de control A o B vale ‘0’»), se estará realizando una acción de
lectura/escritura sobre DDRA(B), y, si CRA(B)[2]=‘1’, será sobre ORA(B).

FIGURA 6.2. Diagrama del adaptador paralelo PIA 6821 de Motorola.


228 Microprocesadores y microcontroladores

6.2.2.1. Las líneas de diálogo o control


A continuación profundizaremos en las posibilidades que incorpora la PIA
para facilitar el diálogo de la CPU con dispositivos periféricos: las líneas de
diálogo (handshaking), CA1, CA2, CB1 y CB2 (fig. 6.2), y la programación de
todas sus posibilidades de funcionamiento mediante los bit de los registros de
control CRA(B) (fig. 6.3). Estas líneas de diálogo o control facilitan
(automatizan) la ejecución de determinadas acciones sobre los periféricos
conectados a la PIA, y también permiten que un periférico pueda interrumpir a
la CPU. Las líneas C1 (CA1 y CB1) son siempre de entrada, mientras que las
C2 (CA2 y CB2) son programables como entradas o como salidas.
El funcionamiento de estas líneas se programa por medio de los biestables
que componen el registro de control CRA(B). El papel del bit 2, CRA(B)[2],
es ya conocido: distingue entre DDRA(B) y ORA(B). Vamos a estudiar a
continuación el papel de los siete restantes (fig. 6.3): los dos primeros,
CRA(B)[0] y CRA(B)[1], definen la manera de operar de las líneas C1 (CA1 y
CB1); los tres siguientes, CRA(B)[3], [4], y [5], determinan el funcionamiento
de las líneas C2 (CA2 y CB2); por último, los bits más significativos del
registro de control, CRA(B)[6] y CRA(B)[7], hacen el papel de señalizadores
(flags), que se marcan a ‘1’ cuando se detecta un evento activo en las líneas
CA(B)1 o CA(B)2, respectivamente (fig. 6.3).
Estudiaremos en detalle el papel de cada uno de los bits. El modo de
operación de las líneas C1 (siempre de entrada) queda establecido por los bit 0
y 1 del registro de control. El bit 0 determina si al producirse un evento en C1
debe generarse una señal de interrupción por la salida /IRQA o /IRQB (que
denotaremos /IRQA(B)) de la PIA (CRA(B)[0]=‘1’), o bien no generarse señal
de interrupción (CRA(B)[0]=‘0’). Así, programando CRA(B)[0]=‘1’, un
periférico conectado a la PIA que envíe una señal activa por CA1 o CB1
directamente solicita una interrupción enmascarable a la CPU.
Por otro lado, el bit 1 determina si el flanco activo en las líneas C1 es el
alto a bajo (CRA(B)[1]=‘0’), o el bajo a alto (CRA(B)[1]=‘1’). Un flanco
activo en la línea C1 hace que el flag CRA(B)[7] se ponga a ‘1’; si además
hemos programado CRA(B)[0] a ‘1’, la PIA enviará una señal por la línea de
salida /IRQA(B), que si se ha conectado a la línea /IRQ del µP solicitará una
interrupción enmascarable. De este modo, la CPU puede saber si se ha
producido un evento en C1 de dos maneras alternativas, bien consultando el
señalizador CRA(B)[7], bien por la generación de una interrupción (si así lo
hemos programado). Estos señalizadores retornan automáticamente a cero al
realizar una operación de lectura sobre uno de los registros de la sección
Entradas y salidas (II): control de periféricos 229

apropiada de la PIA (A o B) (lo que implica el reconocimiento de evento o


interrupción), quedando así dispuestos a señalar un nuevo evento.
Por su parte, los bits 3, 4 y 5 programan la actuación de las líneas C2. Si
CRA(B)[5]=‘0’, la línea C2 correspondiente (A o B) actúa como una línea de
entrada, si CRA(B)[5]=‘1’, C2 actuará como salida. En el primer caso,
CRA(B)[5]=‘0’, al establecerse C2 como entrada resulta ser equivalente a C1,
con lo cual los bits CRA(B)[3] y CRA(B)[4] se comportan de igual manera
para C2 que los CRA(B)[0] y CRA(B)[1] para C1; así, CRA(B)[4] determina el
tipo de flanco activo de C2, y CRA(B)[3] define si debe solicitarse IRQ.

‘0’, C2 es entrada (los bits 3 y 4 actúan como los bits 0 y 1)


‘1’, C2 es salida (ver abajo operación de bits 3 y 4)

‘0’, Selección de DDRA(B)


‘1’, Selección de ORA(B)

Señalizadores Control Control


de C1 y C2 de C2 de C1
‘0’, no genera IRQ
‘1’, genera IRQ
7 6 5 4 3 2 1 0

‘0’, flanco activo de C1: ‘1’ a ’0’


‘1’, flanco activo de C1: ‘0’ a ’1’
‘1’ si evento en C1
Retorna a ‘0’ tras lectura Modo de diálogo manual
de ORA(B) o CRA(B)
Si CRA(B)[5]=‘1’ y CRA(B)[4]=‘1’ ⇒
El valor escrito en CRA(B)[3] sale por C2 (A o B)
‘1’ si evento en C2
Retorna a ‘0’ tras lectura Modos de diálogo automáticos (CRA(B)[5]=‘1’ y CRA(B)[4]=‘0’)
de ORA(B) o CRA(B) Modos lectura o escritura con diálogo:
(sólo si C2 es entrada)
Si CRA(B)[5]=‘1’, CRA(B)[4]=‘0’ y CRA(B)[3]=‘0’ ⇒
C2 (A o B) normalmente a ‘1’, pasa a ‘0’ si
Lectura de ORA (sólo para línea CA2)
Escritura en ORB (sólo para línea CB2)
C2 (A o B) retorna a ‘1’ cuando evento en C1 (A o B)

Modo pulso:
Si CRA(B)[5]=‘1’, CRA(B)[4]=‘0’ y CRA(B)[3]=‘1’ ⇒
Como antes, sólo que el retorno de C2 (A o B ) a ‘1’ se produce
cuando fin de R/W, en flanco ‘1’ a ‘0’ del siguiente pulso E

FIGURA 6.3. Programación de los bits de los registros de control CRA y CRB de la PIA 6821.
230 Microprocesadores y microcontroladores

Como hemos visto, si se ha producido un flanco activo en la línea CA1, se


activará el señalizador CRA[7], mientras que si se ha producido en CB1 el que
se pondrá a ‘1’ es CRB[7]. Lo mismo sucede para ambas señales C2 (CA2 y
CB2) respecto a los señalizadores CR[6] (CRA[6] y CRB[6]). Por lo tanto,
podría programarse la PIA de manera que, dada una señal activa en cualquiera
de estas cuatro líneas, se solicite a la CPU una interrupción IRQ (no
enmascarable): si la señal de interrupción procede de la sección A, se activará
la salida /IRQA de la PIA, y la /IRQB si procede de B; por lo tanto, ambas
líneas deberán conectarse a la entrada /IRQ del µP. Como las salidas /IRQA e
/IRQB son drenaje abierto, pueden ambas cablearse directamente a la línea
/IRQ haciendo uso de una resistencia de polarización (4,7 KΩ para el 6800),
realizándose de esta manera la operación lógica AND-cableada, de manera que
un nivel lógico bajo (cero voltios) en una cualquiera de estas líneas fuerza un
nivel de cero en /IRQ, provocando en cualquier caso una interrupción en el µP.
Así, si se ha programado la PIA de manera que una señal activa en CA1,
CB1, CA2 o CB2, genere una interrupción IRQ, éste podrá determinar cuál de
las cuatro líneas ha producido la interrupción sin más que comprobar el estado
de los cuatro señalizadores, CRA[7], CRA[6], CB[7] y CB[6], respectivamente.
Como cada una de las líneas de control podría estar conectada a un periférico
distinto, podrían así manejarse hasta cuatro interrupciones diferentes
procedentes de cuatro periféricos. La rutina de servicio de la interrupción IRQ
del µP tendría que incluir una serie de instrucciones que comprobaran uno a
uno los señalizadores indicados hasta encontrar el que se encuentra a ‘1’,
determinándose así el periférico concreto que ha solicitado la interrupción.
Ésta es una implementación con la PIA de la denominada encuesta (polling)
que describimos en el capítulo anterior.
Obsérvese también (fig. 6.3) que estos señalizadores retornan a cero al
realizar una operación de lectura sobre la sección adecuada de la PIA, es decir,
reconocida la interrupción, el señalizador vuelve a reposo para permitir en el
futuro poder repetir el proceso. El esquema propuesto en el capítulo anterior
(sección 5.6.3, donde se hablaba del «reconocimiento de interrupción»), en el
que debíamos introducir un biestable señalizador externo por hardware, no es
necesario en el caso de la PIA, pues podemos considerar que incorpora cuatro
de ellos. De este modo, podemos deducir que el empleo de circuitos tipo PIA
simplifica enormemente el diseño de sistemas microprocesadores en los
aspectos relativos a la gestión de periféricos.
Retornando al registro de control, si se establece CRA(B)[5]=‘1’, entonces
C2 no actúa como entrada sino como salida, con lo que el papel de CRA(B)[3]
Entradas y salidas (II): control de periféricos 231

y CRA(B)[4] resulta ser completamente diferente al caso descrito. Así, si se


programa CRA(B)[4] a ‘1’, se puede llevar a cabo un diálogo manual con el
periférico: el valor booleano que en un determinado instante coloquemos en
CRA(B)[3] mediante una instrucción de escritura sobre el registro CRA(B)
aparecerá inmediatamente en la correspondiente línea de salida C2 (A o B). De
esta manera puede enviarse al periférico por programa una señal de
confirmación de dato recibido, una señal de comienzo de operación, etc. Si,
por contra, se programa CRA(B)[4]=‘0’, se lleva a cabo un diálogo automático,
que describiremos en el siguiente punto.

6.2.2.2. Modos de diálogo automáticos de la PIA


Tan sólo nos resta por explicar el caso más complejo de la operación de
C2 como salida, cuando CRA(B)[5]=‘1’ y CRA(B)[4]=‘0’; en este caso se
dispone de diversas posibilidades o modos de diálogo automático. Para mayor
complicación, en este caso la operación de los dos puertos A y B es diferente.
Con el registro de control así programado, las líneas CA2 y CB2 se
mantienen normalmente a ‘1’ (reposo). CA2 pasa automáticamente a ‘0’
cuando se ejecuta una instrucción de lectura sobre el registro de datos del
puerto A (ORA), pudiendo indicar así a un periférico externo «solicitud de
dato» o «dato recibido» en una operación de entrada con diálogo. Por su parte,
CB2 se pone a ‘0’ con una de escritura sobre ORB, indicando a un periférico de
salida «dato válido» en una salida con diálogo.

FIGURA 6.4. Control de un conversor A/D haciendo uso de las líneas de diálogo de la PIA.
232 Microprocesadores y microcontroladores

El diálogo se completa con el retorno de las líneas CA2 o CB2 a reposo.


Si CRA(B)[3] se ha programado a ‘0’, las líneas CA2 o CB2 retornan a reposo
(‘1’) cuando sea activada la línea C1 correspondiente (CA1 indicaría «envío de
dato», y CB1 «dato recibido»). Si, por contra, CRA(B)[3]= ‘1’, CA2 o CB2
retornarán automáticamente a ‘1’ al finalizar la instrucción de lectura o
escritura, en el flanco ‘1’ a ‘0’ del siguiente ciclo del reloj E; este último modo
de operación se denomina modo de diálogo con pulso, puesto que se tiene una
respuesta en forma de pulso por las líneas C2 de un ciclo de reloj de anchura.
El esquema de todas estas posibilidades se muestra en la fig. 6.3.
Por lo tanto, la operación de las dos secciones A y B de la PIA es muy
similar, aunque existen algunas características funcionales y eléctricas que los
diferencian. La característica funcional diferente más importante es la señalada
en la programación de la operación de las líneas C2, que hacen que el puerto A
sea más indicado para entrada de datos y el B para salida.
En el caso de la PIA 6820, más antigua que la 6821, aparecen además
importantes diferencias en cuanto a las características eléctricas de ambos
puertos (p.e., el A posee menos capacidad de manejo de corriente que el B). El
buffer integrado en el puerto B de la PIA 6820 permite alimentar una carga
TTL estándar, y proporciona un 1mA a 1,5 V, corriente suficiente para excitar
la base de un par Darlington (que se emplearía como buffer externo). La PIA
6821, más moderna, mejora las características eléctricas de la 6820, y sus dos
puertos A y B poseen una capacidad equivalente a dos cargas TTL estándar.
En resumen, aunque muy similares, la sección A suele emplearse para
entrada de datos y la B para salida, debido a su capacidad de manejo de
corriente y funcionamiento de los registros de control. No obstante, debido a
la siempre limitada capacidad de manejo de corriente, a menudo habrá que
utilizar buffers externos para la excitación de periféricos, tal y como se
mostrará al final de este capítulo. La PIA es un circuito adaptador muy versátil,
cuya programación básica no reviste demasiada complicación, no así la
programación en detalle de sus cuatro salidas de control, como hemos visto.

6.2.3. Transferencias con diálogo con los puertos del 68HC11


Como vimos en la sección 5.3.2, el puerto B del 68HC11 (registro PORTB
de dirección $1004) siempre es de salida, mientras que las líneas del puerto C
(registro PORTC, $1003) son programables como entradas o como salidas
actuando sobre los bits del registro DDRC ($1007), similar al DDR de la PIA
(tras reset DDRC vale $00, por lo que el puerto C por defecto hace de entrada).
Entradas y salidas (II): control de periféricos 233

FIGURA 6.5. Puertos B y C del 68HC11, y registros y líneas involucradas en las E/S con diálogo.

Los puertos B y C del 68HC11, como los A y B de la PIA, pueden


emplearse en modo directo, por ejemplo, para leer unos interruptores o iluminar
unos LED, pero, de la misma manera que en el caso de la PIA, también se
tienen líneas específicas de diálogo con periféricos, STRA (STRobe A) y STRB
(STRobe B), cuyo papel es similar al de las C1 y C2 de la PIA.
STRA (fig. 6.5) es una entrada que detecta flancos, mientras que STRB es
una salida que indica al periférico que la CPU está preparada para efectuar una
nueva operación de E/S. La acción de ambas se controla programando
adecuadamente los bits del registro de control PIOC (Parallel Input/Output
Control register) situado en la dirección $1002, que equivale a los registros de
control CR de la PIA (aunque la programación de PIOC resulta mucho más
sencilla). Esta programación establece distintos modos de funcionamiento de
las entradas y salidas con diálogo utilizando los puertos B y C.
El puerto C (fig. 6.5), además de los registros de entrada PORTC y de
dirección DDRC, incluye un tercer registro, el PORTCL (PorT C Latched
data), que solamente se emplea en los modos de comunicación con diálogo,
bien para capturar y mantener el valor presente en un momento dado en las
líneas del puerto C (el cual se encuentra en el registro PORTC), bien el dato a
transferir a un periférico. En la tabla 6.1 se muestra un resumen de los registros
asociados al manejo de los puertos B y C, de propósito general.
234 Microprocesadores y microcontroladores

Registro Dir. Descripción


PIOC $1002 Control de las E/S con diálogo (Parallel Input/Output Control);
participan los puertos B, C, y las líneas de diálogo STRA y STRB.

PORTC $1003 Puerto C. 8 líneas programables individualmente como entrada o


salida mediante DDRC (por defecto son de entrada, pues tras reset
DDRC=00).

PORTB $1004 Puerto B. 8 líneas, siempre de salida

PORTCL $1005 Registro de retención del valor de PORTC (PORT C Latched data).

DDRC $1007 Registro de la dirección de los datos en PORTC (Data Direction


Register C). Cada bit determina si el correspondiente de PORTC
actúa como entradas (‘0’) o salidas (‘1’) (DDRC=00 por defecto).

TABLA 6.1. Registros relacionados con los puertos B y C del 68HC11.

STrobe A Interrupt Enable


Si se programa a ‘1’, cuando Output/Input handshaking
STAF se active se solicitará 0: Entrada con diálogo
interrupción IRQ 1: Salida con diálogo

Pulse/interlocked handshake operation


STrobe A Flag 0: diálogo manteniendo los niveles (STRB
Se pone a ‘1’ cuando permanece activo hasta que evento en STRA).
evento en STRA 1: diálogo con pulsos (cuando se activa STRB,
éste es un pulso de 2 E-clk de duración).

PIOC STAF STAI CWOM HNDS OIN PLS EGA INVB $1002

Port C Wire-Or Mode


0: Líneas de Port C salidas
CMOS normales Invert strobe B
1: Líneas de Port C salidas 0: nivel activo 0 para
drenaje abierto STRB

Handshake/Simple strobe mode Active Edge for STRA


0: Modo E/S con validación o 0: flanco descendente
aviso (simple strobe) 1: flanco ascendente
1: Modo diálogo (Handshake)

FIGURA 6.6. Diagrama detallado de PIOC. STAF es un indicador (flag), el resto son biestables
sobre los que pueden escribirse las distintas opciones.

Cada bit de PIOC tiene un papel determinado en las comunicaciones con


diálogo CPU-periférico; un resumen puede observarse en la fig. 6.6. De todos
los ellos, STAF (STrobe A Flag) es el único bit que hace de indicador o flag,
Entradas y salidas (II): control de periféricos 235

poniéndose a ‘1’ cuando se detecta un evento activo en la línea de entrada


STRA; si además el bit STAI (STrobe A Interrupt enable) se ha programado a
‘1’, se producirá una solicitud de interrupción IRQ.
Para su estudio, dividiremos los modos de transferencia con diálogo en dos
grupos: las E/S con señal de validación (simple strobed), algo así como un
diálogo parcial, que se programa poniendo el bit HNDS del registro PIOC a ‘0’
(ver diagrama adjunto); y las E/S con diálogo completo (handshake),
programando HNDS=‘1’. Hay que tener bien presente en todo momento que
las señales de diálogo microcontrolador-periférico, STRA (entrada) y STRB
(salida), no se activan directamente por programa, sino que se intercambian de
forma automática, para lo que deben programarse adecuadamente determinados
bits del registro PIOC (fig. 6.6). Para redactar esta sección nos hemos basado
en el libro de [Huang 96].

6.2.3.1. Modo E/S con validación (simple strobed), HNDS=‘0’


Cuando un periférico de entrada no siempre está dispuesto a proporcionar
un dato (por ejemplo, un conversor A/D), deberá indicar a la CPU que ya
dispone del mismo enviándole una señal de «dato disponible» o «dato válido».
Recíprocamente, en ciertas ocasiones puede resultar interesante que el
microcontrolador, además de enviar un dato, active a la vez una señal de «dato
válido» que advierta al periférico de salida que puede tomar un nuevo dato.
Estos dos son los modos de comunicación que denominaremos E/S con
validación, para los que el bit HNDS debe programarse a ‘0’. En este caso no
se tiene un diálogo completo, sino simplemente señales que acompañan a los
datos indicando cuándo el dato ya es válido y se puede leer.
El HC11 presenta dos posibilidades para el intercambio de datos con señal
de validación, entrada por el puerto C y salida por el B:
a) Entrada con validación por puerto C (strobed input port C). Cuando cierto
periférico de entrada no siempre está dispuesto a proporcionar un dato,
puede indicar al 68HC11 que ya dispone del mismo enviando una señal por
la línea STRA (entrada), para que el HC11 inmediatamente lo capture.
Como algunos periféricos enviarán una señal de validación activa en bajo (o
flanco descendente), y otros en alto (ascendente), habrá que programar
adecuadamente el bit EGA del registro PIOC (a ‘0’ si el flanco activo es el
descendente, a ‘1’ si es el ascendente). Un flanco activo en STRA indicará
«dato disponible», el HC11 al detectarlo automáticamente captura el valor
actualmente presente en los pines del puerto C, que es retenido en el registro
PORTCL, seguidamente coloca el bit STAF del registro PIOC a ‘1’,
236 Microprocesadores y microcontroladores

indicando así a la CPU «dato capturado». Si además el bit STAI se había


programado previamente a ‘1’, se solicitará automáticamente una
interrupción IRQ en el HC11. Por último, STAF retornará automáticamente
a ‘0’ cuando se lea PIOC y a continuación PORTCL, es decir, cuando se
compruebe la llegada de un nuevo dato y éste sea recogido.

El periférico pone
dato y STRA a ‘1’ 68HC11
toma dato

Puerto C (entrada)

STRA (entrada)

Dato listo

b) Salida con validación por puerto B (strobed input port B). En este caso, al
escribir un dato en el puerto B (por ejemplo, STAA $1004), el HC11
automáticamente envía una señal por STRB de dos ciclos E de duración
(indicando así «dato disponible» o «dato válido»). En este caso es el bit
INVB el que define el nivel activo de la señal STRB (‘0’ para bajo, ‘1’ para
alto), dependiendo del periférico con el que se deba comunicar. El
periférico debe vigilar el estado de la salida STRB y tomar el dato presente
en las líneas del puerto B tan pronto observe un nivel activo.

68HC11
escribe dato
CPU escribe dato

E-clk

Puerto B (salida) Dato anterior Dato actual

Dato disponible

STRB (salida)
En alto 2 clk
El periférico ya
puede tomar el dato
Entradas y salidas (II): control de periféricos 237

6.2.3.2. Modo E/S con diálogo completo (handshake), HNDS=‘1’


Estos modos se emplean cuando la temporización de las señales es crítica,
requiriéndose un diálogo completo entre µC y periférico (lo que permite la
comunicación con un periférico arbitrariamente lento). Un ejemplo es la salida
con diálogo expuesta al comienzo del capítulo (fig. 6.1): la CPU pone el dato
en el puerto a la par que activa una señal «dato válido» (STRB en el 68HC11),
el periférico al observar la activación de «dato válido» lee el dato del puerto y
activa la señal «dato recibido» (STRA); cuando la CPU observa la activación
de «dato recibido» retira el dato del puerto y desactiva «dato válido»; por
último, el periférico ve que «dato válido» retorna a reposo y desactiva «dato
recibido», completando así el ciclo de diálogo.
Expondremos a continuación las dos posibilidades que el HC11 presenta
para el intercambio de datos con diálogo completo (HNDS=‘1’), siempre por
medio del puerto C: entrada con diálogo (bit OIN de PIOC a ‘0’) y salida con
diálogo (OIN=‘1’); en ambos casos las señales de diálogo pueden ser por
niveles (bit PLS de PIOC a ‘0’) o por pulsos (PLS=‘1’).
a) Entrada por puerto C con diálogo (handshake input port C). Cuando el
HC11 está dispuesto a recibir un dato activa (o envía un pulso por) STRB
(«solicitud de dato»). El periférico, en respuesta, pone el dato en el puerto
C y activa (o envía un pulso por) STRA («dato enviado»). Un flanco activo
en STRA hace que el puerto C automáticamente capture el dato y lo guarde
en el registro PORTCL, activando a continuación el bit STAF («dato
recibido») y desactivando la línea STRB (indicando al periférico que ya no
debe enviar dato). Cuando el programa lea PORTCL, automáticamente se
activará STRB («solicitud de dato»), indicando de esta manera al periférico
que el 68HC11 se encuentra preparado para recibir un nuevo dato.

Lectura de PORTCL
‘Listo’
E-clk

‘Listo’ El HC11 dice


STRB (salida)
‘dato recibido’
(activo ⇒ el HC11 quiere dato)
El HC11, al observar STRA=‘1’,
guarda el dato en PORTCL
‘Dato disponible’
STRA
(entrada)
El periférico pone el
dato y avisa al HC11

Puerto C
(entrada)
238 Microprocesadores y microcontroladores

b) Salida por puerto C con diálogo (handshake output port B). En este modo,
cuando el programa que ejecuta el HC11 escribe un dato en PORTCL, éste
aparece en las líneas del puerto C y STRB es automáticamente activada
(«dato válido»); el periférico, al observar STRB activo, toma el dato y
activa (o envía un pulso por) STRA («dato recibido»); la activación de
STRA hace que STRB retorne automáticamente a reposo, poniéndose el
indicador STAF a ‘1’ («dato recibido»); el periférico, al observar que STRB
retorna a reposo, desactivará STRA (a no ser que operen con pulsos en vez
de niveles, en cuyo caso esto no es necesario), cerrando el ciclo. Por lo
tanto, el programa sobre el HC11 solamente deberá ocuparse de observar
STAF y escribir un nuevo dato en PORTCL cuando éste se active; el
protocolo de diálogo descrito se desarrolla automáticamente.

El 68HC11 escribe dato CPU escribe dato

E-clk

Puerto C (salida) Dato anterior Dato actual

Aparece el dato ‘Dato Listo’


en el puerto
STRB (salida)

68HC11 activa STRB ‘Dato Recibido’

STRA (entrada)

El periférico toma el dato


presente en el puerto C y
activa STRA 68HC11 desactiva STRB

El periférico desactiva STRA

6.3. Comunicación serie síncrona y asíncrona


En la comunicación en paralelo cada señal tiene asociada una línea física
de transmisión, mientras que en la transmisión en serie, que estudiaremos a
continuación, se emplea una sola línea por la cual la información circula
multiplexada en el tiempo (bit tras bit).
Cuando un microprocesador establece una comunicación con un periférico
próximo es habitual que lo haga por medio de puertos paralelos, pues el
intercambio de datos de 8 en 8 bits (o de 16 en 16, 32 en 32, etc.) es
obviamente más rápido que la transmisión en serie, bit a bit. Sin embargo,
Entradas y salidas (II): control de periféricos 239

cuando debe comunicarse con dispositivos alejados, la transmisión en serie


presenta la ventaja del ahorro en cables de conexión (imaginemos la
comunicación de un µP con un periférico situado a 200 metros de distancia
mediante un mazo de 16 cables, y la misma comunicación realizada con los dos
o tres cables que bastarían para una comunicación serie básica).
Un inconveniente de la comunicación serie es su mayor complejidad. Para
ello se requiere de nuevos circuitos adaptadores que, entre otros cometidos,
deben convertir a serie (ristras de unos y ceros) la información en paralelo de
las palabras digitales almacenadas en la memoria del sistema microprocesador,
para su transmisión por una única línea (o viceversa en el caso de la recepción
de datos). Otro inconveniente es el notable en la velocidad de comunicación
que la transmisión serie implica.

6.3.1. Principios básicos de comunicaciones


Antes de profundizar en los fundamentos de la comunicación serie y de sus
interfaces, introduciremos algunos términos relativos a la comunicación de
información en general. Cuando se establece una comunicación, siempre existe
un dispositivo emisor que envía los datos y un receptor que los recibe. El
canal es el medio físico por el que transita la información; puede tratarse de un
cable en el caso de señales eléctricas, fibra óptica en el caso de las
transmisiones ópticas, el vacío en las comunicaciones por ondas
electromagnéticas, o el aire para el sonido.
Existen diversas modalidades de comunicación (fig. 6.7). En la
comunicación simplex la información discurre siempre en un único sentido,
desde un dispositivo que siempre actúa como emisor a otro que siempre es
receptor (el cual no tiene posibilidad alguna de enviar mensajes). Una
comunicación de este tipo se realiza, por ejemplo, cuando una emisora de radio
o TV emite un programa que recibimos en nuestro hogar.
Por contra, en la comunicación denominada dúplex la información puede
circular en ambos sentidos, de modo que ambos dispositivos pueden ser
emisores y receptores. Existen dos variantes de este caso. En la semi-dúplex
(half-duplex), el sistema permite la comunicación en ambos sentidos, pero sólo
en uno cada vez, debido a que se utiliza un mismo canal de comunicación; por
lo tanto, ambos dispositivos pueden ser emisores o receptores, pero
alternativamente. Un ejemplo de comunicación semi-dúplex es la conexión por
medio del bus de datos entre un µP y una memoria RAM.
240 Microprocesadores y microcontroladores

FIGURA 6.7. Comunicación simplex (arriba), semi-dúplex (en medio) y dúplex completa (abajo).

Más costosa es la modalidad dúplex completa (full-duplex), o simplemente


dúplex, en la cual existe un canal para cada uno de los dos posibles sentidos.
Un ejemplo de comunicación dúplex completa es la que se establece entre una
terminal (pantalla y teclado) y el microprocesador, el cual puede a la vez recibir
datos del teclado de la terminal y enviar datos a la pantalla, puesto que existe
un canal físico diferente para cada uno.

6.3.2. Comunicación serie síncrona


La comunicación serie puede llevarse a cabo síncrona o asíncronamente:
a) Comunicación serie síncrona. En este caso se incluye una línea de reloj que
marca el sincronismo de los datos. Por lo tanto, emisor y receptor poseen
un reloj común que rige la comunicación, y los intervalos de duración de
cada bit se definen con precisión.
b) Comunicación asíncrona. En este caso no existe una señal de sincronismo
común a emisor y receptor, es decir, éstos no comparten un reloj común, por
lo que deben sincronizarse por otros medios.
Entradas y salidas (II): control de periféricos 241

La comunicación serie síncrona únicamente resulta factible para distancias


relativamente cortas, pues de otro modo los retrasos en las señales causados por
la longitud de los cables pueden hacer que emisor y receptor no observen las
transiciones del reloj en el mismo instante. La comunicación serie síncrona
suele utilizarse cuando se trata de enviar datos a dispositivos no muy lejanos
(normalmente contenidos en la misma tarjeta) a una velocidad relativamente
alta, sin emplear una transmisión de datos en paralelo para ahorrar cables,
espacio o patillas del chip, lo que puede conllevar un importante ahorro en el
coste final del producto.
Muchos microcontroladores integran un circuito adaptador para
comunicaciones serie síncronas, que emplean para el intercambio de
información entre dispositivos situados en la misma tarjeta. Se debe tener
presente que los µC más baratos (que son precisamente los más empleados en
la práctica) suelen disponer de muy pocos pines (una versión reciente del µC
PIC de Arizona Microchip posee tan sólo 8 pines), por lo que la comunicación
de datos en serie con periféricos próximos, como un conversor A/D de salida
serie, es una solución ampliamente utilizada. Este tipo de comunicación se
emplea también en el intercambio de datos entre µC cercanos.

Maestro (68HC11) Esclavo


MOSI MOSI
Data out

SPDR SPDR
(Reg. datos maestro) (Reg. datos esclavo)
MISO MISO
Data in

SCK SCK
Reloj de la CLK
transmisión /SS /SS

+5 V GND

FIGURA 6.8. Diagrama básico de dos dispositivos «maestro» (master) y «esclavo» (slave)
comunicándose mediante un esquema serie síncrono (SPI).
242 Microprocesadores y microcontroladores

Línea en reposo

0 1 1 0 0 1 0 1 0 0 1 1
Dato

Comienzo (start) Paro (stop)


Paridad

FIGURA 6.9. Formato de paquete de bits en la transmisión serie asíncrona.

Existen distintos protocolos que permiten comunicar en serie


síncronamente microprocesadores y periféricos. Los más famosos quizás sean
el denominado bus I2C (Inter Integrated Circuit bus) de Philips, de tan sólo
dos hilos y utilizado en microcontroladores como el 8051, y el SPI (Serial
Peripheral Interface), de tres hilos, que Motorola introdujo para su familia
68XX. Numerosos fabricantes han adoptado ambos buses serie síncronos.
El 68HC11 incluye un módulo SPI para comunicaciones serie síncronas,
cuyas cuatro líneas forman parte del puerto D. Su principio de funcionamiento
se basa en dos registros de desplazamiento unidos por dos líneas de datos (fig.
6.8), MOSI (Master Out Slave In) y MISO (Master In Slave Out), más una
línea de reloj SCK (Serial ClocK). Cada dispositivo con comunicación SPI
incluye además una entrada de selección /SS (Slave Select), que debe estar a ‘0’
en el dispositivo esclavo seleccionado y a ‘1’ en los demás (incluido el
maestro).
La velocidad de operación depende de la frecuencia de reloj, y puede
controlarse por la programación de dos bits del registro de control del SPI
denominado SPCR (Serial Peripheral interface Control Register); operando el
microprocesador a 2 MHz, la máxima velocidad de transmisión se cifra en un
millón de baudios (bits por segundo).

6.3.3. Comunicación serie asíncrona


Para comunicar datos a distancias medias y largas se hace uso de la
comunicación serie asíncrona. En este caso microprocesador y periférico no
poseen ninguna señal común de sincronismo o reloj, por lo que será necesaria
alguna forma de sincronización diferente. Además se requiere que emisor y
receptor asignen a cada unidad de información (bit) la misma duración, para lo
Entradas y salidas (II): control de periféricos 243

cual deben realizar las operaciones de transferencia de datos a una misma


velocidad, que suele darse en baudios (bits por segundo).
Por otra parte, los bits se envían en grupos conformando palabras o
paquetes (fig. 6.9); es necesario marcar de alguna manera el instante de
comienzo de la transmisión de cada paquete de bits. El formato de los paquetes
a transmitir en serie es el siguiente:
1. La línea de transmisión se sitúa en reposo a ‘1’ lógico (fig. 6.9).
2. El paquete a transmitir comienza con un ‘0’ lógico, denominado bit de
inicio (start). Por lo tanto, cuando el receptor observa un ‘0’ en la línea
sabe que comienza la transmisión de un paquete.
3. A continuación se transmiten secuencialmente los bits que componen el dato
a transferir (7 u 8 bits), comenzando por el primero de ellos (bit 0).
4. Opcionalmente puede añadirse un bit de paridad, para que el receptor pueda
comprobar un posible error de transmisión. La paridad de una palabra
binaria se refiere al número de unos que contiene: si tiene un número par,
poseerá paridad ‘0’, y paridad ‘1’ si contiene un número impar. Así, toda
palabra binaria completada con su bit de paridad resulta ser par (posee un
número par de unos), lo que permite una fácil comprobación de eventuales
recepciones erróneas de datos.
5. Se completa el paquete con uno o dos bits de finalización o paro (stop).
Por lo tanto, para la comunicación serie asíncrona el emisor debe construir
el paquete a partir de las palabras digitales a transmitir (habitualmente de 8
bits), completando la palabra con los bits de comienzo, paridad y paro. A
continuación deberá enviar en serie el paquete resultante a través de la línea de
transmisión de datos por desplazamiento secuencial de sus bits a la velocidad
de transmisión definida (fig. 6.10), común a emisor y receptor (por ejemplo,
9.600 baudios). Esta acción se llevará a cabo mediante un registro de
desplazamiento (de emisión de datos).
El receptor, por su parte, deberá reconocer el bit de comienzo y sincronizar
a partir de él la recepción del paquete. A continuación, irá recogiendo
secuencialmente los bits que recibe, almacenándolos en un registro de
desplazamiento (de recepción de datos, fig. 6.10), a la velocidad convenida.
Por último, deberá reconocer el bit de paridad y los bits de paro, y, si se
producen errores en la transmisión, indicárselo a la CPU.
244 Microprocesadores y microcontroladores

Adaptador 1 Adaptador 2 (o periférico)

TxD
(data out)

Registro 1 Registro 2

RxD
(data in)
CLK1 CLK2
Bus Datos Salida datos
GND
(del microprocesador) (al periférico)

FIGURA 6.10. Comunicación serie asíncrona entre dos adaptadores (ACIA, UART...). El primero
está conectado al bus del sistema, el segundo es el adaptador del periférico.

Para llevar a cabo las tareas descritas, así como el resto de las acciones
protocolarias que deben efectuarse en una transmisión de este tipo, existen
adaptadores específicos denominados adaptadores serie asíncronos, o circuitos
UART (Universal Asynchronous Receiver/Transmiter).
La comunicación serie asíncrona es habitual entre computadores,
computadores y pantallas de rayos catódicos (CRT), terminales de ordenador,
impresoras, teletipos, etc.; por ejemplo, el famoso estándar RS-232 es un caso
particular de esta modalidad de comunicación de datos serie (de él hablaremos
más adelante). La comunicación serie asíncrona también se emplea en la
comunicación de datos a larga distancia mediante redes de comunicación, a
través de la línea telefónica, etc. En este último caso se requiere de un circuito
adicional denominado módem (contracción de modulador-demodulador), el
cual codifica las señales serie tipo TTL (0-5 V) del sistema microprocesador
modulando una onda portadora, que es la que se envía por la línea telefónica.
La modulación puede realizarse en amplitud (ASK, Amplitude Shift Keying),
frecuencia (FSK, Frequency Shift Keying) o fase (PSK, Phase Shift Keying).
Al final de la presente sección concretaremos algunos de estos detalles.
En la comunicación serie asíncrona se definen dos tipos de dispositivos:
a) DTE (Data Terminal Equipment), o terminal de datos. Por ejemplo, un
ordenador PC, una terminal de computador (pantalla más teclado), etc.
b) DCE (Data Communications Equipment), o equipo de comunicaciones.
Normalmente se trata del módem, aunque podría ser cualquier otro equipo.
Entradas y salidas (II): control de periféricos 245

DTE DCE
TxD
TxD (out)
DCD (in) TxD (in)
DCD (out)
CPU Buses RxD (in) RxD (out)
RxD
Al 2.º sistema
Tierra de señal
microprocesador
Línea
telefónica
UART (ACIA) Módem

DTE DTE
TxD
DCD (in)
TxD (out) DCD(out)
TxD (out)
Buses
CPU (1) Buses RxD (in) RxD (in) CPU (2)
RxD

Tierra de señal

UART (1) UART (2)


larga distancia

FIGURA 6.11. Arriba, conexión directa DTE-DCE; abajo, conexión cruzada o de módem nulo
DTE-DTE (aunque no se muestran en la figura, también deben cruzarse las líneas de control).

Por ejemplo, en una conexión entre microprocesadores a través de la línea


telefónica (para comunicación a muy larga distancia), el conjunto CPU más
interfaz serie (UART) hace el papel de DTE (terminal de datos), y el módem es
el DCE. De este modo, una CPU1 por medio de su UART1 se comunicaría con
su módem, el cual enviaría las señales vía telefónica modulando una onda
portadora; el módem receptor recogería al otro lado de la línea la onda
modulada, extraerá de ella los bit, y la UART2 convertirá la serie de bits en
datos paralelos, que enviaría a la CPU2 a través del bus del sistema.
La conexión DTE-DCE (por ejemplo, UART-módem) se realiza de forma
directa, cableando directamente sus señales, tanto de datos como de control
(fig. 6.11). Sin embargo, cuando se trata de conectar directamente dos equipos
terminales (DTE), sin módem intermedio, se debe realizar una conexión
cruzada de las líneas de datos y de control, también denominada conexión de
módem nulo (ya que supone una conexión directa entre equipos, sin emplear
como intermediario módem alguno).
246 Microprocesadores y microcontroladores

Por ello, cuando se deben interconectar dos equipos empleando algún


protocolo serie (como la RS-232), se ha de averiguar previamente si ambos son
DTE, o bien uno es DTE y otro DCE, para saber si deben cruzarse los cables o
no. Por ejemplo, en el caso de la conexión de un equipo a un ordenador, éste
hará de DTE, y el fabricante del equipo a conectar deberá especificar en sus
hojas de características si ha sido configurado como DTE o como DCE.

Adaptadores programables serie: ACIA 6850


Para llevar a cabo una comunicación serie asíncrona se emplean
adaptadores integrados denominados UART (Universal Asynchronous Receiver
/Transmiter), o USART (Universal Synchronous/Asynchronous Receiver/
Transmiter) cuando un mismo adaptador puede emplearse tanto para
comunicaciones síncronas como asíncronas (p.e., el 8251 de Intel).
El ACIA 6850 (Asynchronous Communication Interface Adapter, fig. 6.12,
arriba) es el circuito tipo UART empleado en los microprocesadores y
microcontroladores de 8 bits de Motorola. El ACIA, construido en tecnología
NMOS (encapsulado DIP-24) y de señales compatibles TTL, incluye cuatro
registros: transmisión de datos, recepción, registro de estado (flags) y registro
de control (para programar su operación). Este circuito dispone de dos líneas
para la comunicación de datos, una de transmisión TxD y otra de recepción
RxD, además de las siguientes líneas de diálogo ACIA-periférico (módem):
a) /DCD (Data Carrier Detect), detección de portadora. Mediante esta entrada
el módem informa al ACIA que el canal de comunicación está abierto (es
decir, que recibe la señal portadora procedente de la línea telefónica). En
caso de pérdida de línea telefónica el módem hará /DCD=‘1’, y, si el bit 7
del registro de control se ha programado a ‘1’, se solicitará interrupción. Si
el ACIA no va a hacer uso de /DCD, ésta deberá conectarse a tierra.
b) /RTS (Request To Send), salida mediante la que el µP informa al periférico
(módem) de que se encuentra listo para realizar la comunicación. El estado
de la salida /RTS viene marcado por los valores de los bits 5 y 6 del registro
de control (fig. 6.14). Esta línea puede utilizarse también como señal de
«terminal preparada», o /DTR (Data Terminal Ready).
c) /CTS (Clear To Send, entrada), línea de entrada por la que el periférico
(módem) informa de que está listo para recibir y/o transmitir datos. Si el
ACIA no va a hacer uso de /CTS, se debe conectar a tierra.
Entradas y salidas (II): control de periféricos 247

+5V
74HC4024 300
Q7
2,4576 MHz 600
Q6
1200
Q5
HC14 HC14
CLK 2400
Q4
4800
Q3
24 pF 0,1 9600 TxC
µF Q2 RxC
Reset
2K2 2K2 Q1
Gnd puente

FIGURA 6.12. Esquema del ACIA 6850 (arriba) y generación de los relojes TxC y RxC (abajo).

TxD
DCD
TxD (out)
(in) TxD (in)
DCD (out)
RxD
CPU Buses RxD (in) RxD (out)

DTE DCE
DCD
DCD (in) DCD (out)
RTS
RTS (out) RTS (in)
ACIA CTS Periférico
CTS (in) CTS (out)
(UART) (Módem)

FIGURA 6.13. Conexión ACIA-periférico. Originalmente, este tipo de conexión se ideó para
módem, pero en la actualidad se emplea en aplicaciones diversas.
248 Microprocesadores y microcontroladores

Antes de emprender una comunicación de datos, ACIA y periférico


(módem) deben llevar a cabo el siguiente proceso de diálogo que asegure que
ambos se encuentran dispuestos para comunicar: cuando el módem ha logrado
conectarse a la línea telefónica y detecta señal portadora, se lo hace saber al
ACIA activando la línea /DCD; cuando la UART decide establecer la
comunicación (/DCD está activa), envía una señal /RTS al módem, y éste
indicará al ACIA que está listo activando la señal /CTS. La comunicación de
datos podrá entonces comenzar.
Pasamos a continuación a describir en detalle los cuatro registros que
incluye el ACIA (fig. 6.12, arriba):
a) Registro de transmisión de datos TDR (Transmit Data Register). Recibe de
la CPU en paralelo el dato de 8 bits para transmitirlo secuencialmente al
periférico a través de la línea TxD.
b) Registro de recepción de datos RDR (Receive Data Register), el cual recibe
secuencialmente el dato enviado por el periférico a través de la línea RxD.
c) Registro de control CR (Control Register), el cual programa la operación
del ACIA (fig. 6.14, arriba). Así, los bits 0 y 1 controlan la velocidad de
transferencia (dividen por 1, 16 o 64 la velocidad de los relojes conectados a
las líneas TxC y RxC del ACIA, fig. 6.12 abajo); ambos bits a ‘1’ realizan
un reset general del ACIA. Los bits 2, 3 y 4 determinan el formato de las
palabras a transmitir (transmisión de 7 u 8 bits; paridad par, impar o
ninguna; 1 o 2 bits de paro). Los bits 5 y 6 controlan el estado de la salida
/RTS y habilitan la solicitud de IRQ cuando se ha completado la transmisión
de un dato (TDR vacío). Finalmente, el bit 7 habilita la solicitud de IRQ
cuando se ha completado una recepción (RDR lleno).
d) Registro de estado SR (Status Register). Sus bits informan sobre el estado
de la transmisión, en diversos aspectos (fig. 6.14, abajo). Así, el bit 0 indica
que se ha recibido un nuevo dato (registro de recepción lleno); el bit 1
señala registro de transmisión vacío (es decir, transmisión concluida). Los
bits 2 y 3 indican el estado actual de las líneas /DCD y /CTS. Los bits 4 y 5
señalan errores de sincronización en la recepción de datos. El bit 6 señala
error de paridad y el bit 7 indica activación de la interrupción.
La conexión del ACIA 6850 a los buses del sistema resulta similar a la de
la PIA. El integrado 6850 (fig. 6.12, arriba) dispone de tres entradas de
selección generales, CS0, CS1 y /CS2; para que quede habilitado, las tres deben
estar activas (CS0 o CS1 suelen conectarse a la línea VMA, y /CS2 al
decodificador de direcciones del sistema).
Entradas y salidas (II): control de periféricos 249

Habilitación de IRQ en recepción Velocidad transferencia + RESET


(generación de IRQ al llenar RDR) 0 0: frecuencia oscilador externo
0: IRQ deshabilitada. 0 1: frecuencia reloj/16
1: se genera IRQ si registro recepción 1 0: frecuencia reloj/64
lleno o sobre-escrito, o si señal DCD a 1 1 1: RESET del ACIA
(pérdida portadora).

Control 7 6 5 4 3 2 1 0
Register

Formato de palabra
Control de transmisión (control de /RTS y 0 0 0: 7 bits, paridad par, 2 bit stop
generación de IRQ al vaciarse TDR) 0 0 1: 7 bits, impar, 2 bit stop
0 0: /RTS=‘0’ e IRQ transmi. deshabilitada 0 1 0: 7 bits, par, 1 bit stop
0 1: /RTS=‘0’ e IRQ transmisión habilitada 0 1 1: 7 bits, impar, 1 bit stop
1 0: /RTS=‘1’ e IRQ transmi. deshabilitada 1 0 0: 8 bits, sin paridad, 2 bit stop
1 1: /RTS=‘0’ y envía un break (0 continuo) 1 0 1: 8 bits, sin paridad, 1 bit stop
por salida TxD, IRQ transm. deshabilitada 1 1 0: 8 bits, par, 1 bit stop
1 1 1: 8 bits, impar, 1 bit stop

Parity Error
Detectado error de paridad Clear To Send
Indica estado de la línea /CTS
Interrupt Request (a ‘1’ si módem preparado)
Indica que se ha solicitado
interrupción (se borra al Data Carrier Detected
leer RDR o escribr TDR) Indica estado de la línea /DCD
A ‘1’ si portadora no presente
(si línea /DCD=‘1’)

Status IRQ PE OVRN FE CTS DCD TDRE RDRF


Register

Overun (dato sobre-escrito)


Indica que se ha recibido un Receive Data Register Full
nuevo dato en RDR antes de que Indica RDR lleno (recibido
el anterior haya sido leído. paquete completo).

Transmit Data Register Empty


Framing Error
Indica TDR vacío (envío de
Indica error de sincronización o
paquete concluido).
fallo de transmisión (a ‘1’ si se
recibe algún bit de STOP=‘0’)

FIGURA 6.14. Registro de control y registro de estado del ACIA 6850.

El ACIA posee tan sólo una línea de selección de registro RS (Register


Select, suele conectarse a la línea A0 del bus de direcciones). Los registros de
comunicación de datos, TDR y RDR, quedan seleccionados cuando RS=‘1’, de
250 Microprocesadores y microcontroladores

modo que ocupan la misma casilla de memoria; es el tipo de acceso el que los
discrimina: una lectura de datos sobre él supone que se trata de leer un dato
recibido, por lo que se toma el contenido de RDR; una escritura sobre esta
dirección supone que deseamos enviar un dato, por lo que se escribe sobre
TDR. Lo mismo sucede con los registros de control CR y estado SR (RS=‘0’).
Como en el caso de la PIA 6821, las líneas D0-D7 se conectan al bus de
datos, E al reloj del sistema y R/W indica lectura o escritura. La salida /IRQ
(drenaje abierto) se conectará a la entrada de interrupción /IRQ del µP.
En el ACIA 6850 la velocidad de comunicación se obtiene a partir de la
frecuencia base que proporciona un oscilador externo (que se conectará a las
líneas RxC y TxC, fig. 6.12), la cual puede ser dividida por 16 o 64 en función
de los bit 0 y 1 del registro de control (fig. 6.14). Dicho oscilador (que no se
debe confundir con el generador de reloj del sistema) suele construirse con un
cristal de cuarzo de 2,4576 MHz, cuya frecuencia se divide mediante un
contador [Huang 96, Motorola 88] (fig. 6.12, abajo). Para ello suele emplearse
un 74HC4024, contador de 7 bits por propagación que presenta al exterior el
estado Q de sus 7 biestables, dividiendo cada uno la frecuencia del anterior por
2; por ejemplo, Q2 proporcionará 2,4576 MHz dividido por 4, y si se programa
el ACIA para dividir por 64, se obtendrá una velocidad de comunicación de
2,4576 MHz/4/64=9.600 bits/seg. Tomando otras salidas, pueden obtenerse así
frecuencias entre 300 y 9.600 bits por segundo (fig. 6.12, abajo).
A la hora de utilizar el ACIA 6850 deben tenerse en cuenta las siguientes
cuestiones prácticas:
• Como habrá observado el lector atento, el ACIA no tiene patilla de RESET.
Su inicialización debe realizarse por programa, poniendo a uno los bits 0 y 1
del registro de control; la ejecución por programa del RESET del ACIA
tiene que ser la primera acción a ejecutar al proceder a su programación
(normalmente en la rutina de reset del sistema). La segunda acción
consistirá en programar el registro de control, para configurar la modalidad
de transmisión (paridad, velocidad, etc.); en particular, deberá establecerse
el valor de la señal /RST programando los bit 5 y 6.
• El ACIA puede solicitar interrupciones a la CPU. Si el bit 5 del registro de
control vale ‘1’ y el 6 ‘0’, se habilita la interrupción de transmisión, es
decir, se solicitará IRQ cuando el ACIA haya concluido de transmitir un
dato (indicando que el ACIA está preparada para transmitir un nuevo dato).
Por contra, la interrupción de recepción se habilita cuando el bit 7 del
registro de control está a ‘1’, solicitándose IRQ cuando el ACIA ha recibido
un nuevo dato (RDR lleno). Recordemos que el bit 7 del registro de estado
Entradas y salidas (II): control de periféricos 251

es un flag de interrupción, el cual retorna a ‘0’ cuando se lee RDR o se


escribe sobre TDR.
• Un proceso típico de transmisión de un paquete de bits consiste en lo
siguiente (supuesta el ACIA previamente inicializada): lectura del bit 1 del
registro de estado para comprobar si el registro de transmisión (TDR) está
vacío (esta lectura puede realizarse periódicamente dentro de una rutina que
gestiona varios periféricos, o bien tras una solicitud de IRQ); si
efectivamente el TDR está vacío, escribiremos en él el dato a transmitir
(STAA TDR); el ACIA inmediatamente construye el paquete y lo envía en
serie por TxD (cuando concluya el envío, activará el bit 1 del registro de
estado y solicitará IRQ, si así se ha programado); leyendo de nuevo el bit 1
del registro de estado sabremos cuándo podemos repetir el procedimiento
para transmitir un nuevo dato (repítase el proceso n veces).
• Un proceso típico de recepción de un paquete de bits consiste en lo
siguiente (supuesta el ACIA previamente inicializada): cuando el ACIA
detecte un ‘0’ en la línea RxD (bit de inicio), automáticamente (sin
intervención del microprocesador) capturará el paquete de bits que debe
llegar a continuación; cuando todo el paquete ha llegado activará el bit 0 del
registro de estado y solicitará IRQ (si así ha sido programado en el registro
de control); el programa que ejecuta la CPU simplemente debe leer el bit 0
del registro de estado para comprobar si el registro de recepción (RDR) está
lleno (esta lectura puede realizarse periódicamente dentro de una rutina que
gestiona varios periféricos, o bien tras una solicitud de IRQ); si
efectivamente el RDR está lleno, lo leeremos para obtener el dato recibido
(LDAA RDR); leyendo de nuevo el bit 0 del registro de estado sabremos
cuándo podemos repetir el proceso para recibir un nuevo dato (repítase el
proceso n veces). En la rutina de recepción de datos conviene comprobar
también el estado de los bit de error de paridad, dato sobre-escrito y error de
sincronía (fig. 6.14), para detectar posibles fallos en la comunicación.
• Para finalizar, debe tenerse en cuenta que, al realizarse en el ACIA la lectura
y escritura sobre registros diferentes que tienen asociada una misma
dirección, no podrán aplicarse sobre ellos instrucciones que toman un dato,
lo manipulan, y lo devuelven al mismo registro, como las de incremento y
desplazamiento (p.e., INC TDR). Por otro lado, nunca se podrá leer el
registro de control, por lo que, si se desea disponer de la posibilidad de
obtener su contenido actual, será necesario mantener una copia del mismo
en una casilla de memoria RAM convencional.
252 Microprocesadores y microcontroladores

FIGURA 6.15. Generación de niveles RS-232 mediante el MAX232, y conexión al puerto serie de
un PC (para poder trabajar tan sólo con las líneas TxD y RxD se requiere puentear las líneas de
diálogo, tal y como puede apreciarse en el conector DB-25 de la derecha). El MAX232 convierte
los niveles de hasta dos canales serie.

Remitimos a las hojas de características de Motorola a aquellos lectores


interesados en los detalles más concretos de la operación del ACIA. También
en [Cahill 93, Kheir 97] puede encontrarse información detallada; en [Kheir
97], además, se estudian aspectos genéricos sobre la comunicación de datos.

6.3.3.2. El bloque SCI del 68HC11


El 68HC11 integra un módulo de comunicaciones serie asíncronas
denominado SCI (Serial Communications Interface), cuyas características y
programación son similares al ACIA descrita. Gracias al SCI un 68HC11
puede comunicarse muy fácilmente vía RS-232 con un terminal u ordenador.
No obstante, dado que la RS-232 emplea lógica invertida y unas tensiones algo
particulares (una tensión entre +3 y +15 V representa el cero lógico, y entre −3
y −15 V es ‘1’), se requiere el empleo de un circuito adaptador de niveles TTL
a RS-232, como el MC145407 de Motorola, o el famoso MAX232 (fig. 6.15) de
la casa MAXIM (http://www.maxim-ic.com). Estos circuitos generan señales
compatibles RS-232 a partir de la alimentación convencional de +5 V.
El bloque SCI del 68HC11 presenta externamente tan sólo dos líneas, la de
transmisión TxD y la de recepción RxD (líneas 0 y 1 del puerto D), y no
Entradas y salidas (II): control de periféricos 253

incorpora líneas de diálogo, como las /DCD, /RTS y /CTS del ACIA. Estas
tres señales que se emplean en el diálogo ACIA-módem intervienen también en
protocolos de comunicación serie, como el conocido RS-232 (además de otras
líneas adicionales que no aparecen en el ACIA); de ahí que un conector típico
RS-232 esté compuesto de 9 o 25 pines (denominados DB-9 o DB-25). No
obstante, se debe tener en cuenta que cuando se trata de comunicar dos
dispositivos, por ejemplo, dos sistemas microprocesadores, para reducir el
número de cables necesarios a menudo se emplea únicamente TxD, RxD y la
tierra de la señal. Cuando haya que conectar un dispositivo que sólo trabaja
con estas tres señales (por ejemplo, el bloque SCI del 68HC11) a un equipo que
implementa la RS-232 completa (por ejemplo, un PC), entonces deben
puentearse algunas de estas señales, tal y como se muestra en la Figura 6.15 (de
esta manera, cuando el PC indica que está dispuesto a comunicarse le
engañamos devolviéndole su propia señal, deduciendo entonces el PC que
nosotros también estamos listos).
El SCI incorpora una serie de registros para programar y controlar su
funcionamiento, de cometido similar al de control y estado del ACIA. En
particular, permiten programar la velocidad de transmisión, teniendo en cuenta
que en este caso la frecuencia de transmisión se deriva del propio oscilador
interno del 68HC11. Con el SCI también resulta sencillo implementar una red
de área local, para que varios 68HC11 puedan intercambiar datos: a cada
68HC11 de la red puede asociarse una dirección, de forma que antes de enviar
un dato se envía en serie la dirección del microcontrolador al que el dato va
destinado, y aquel 68HC11 cuya dirección coincide con la enviada captura el
dato que llegará tras la dirección.
Como siempre, remitimos al lector interesado en el manejo del SCI al
manual de referencia del 68HC11 [Motorola 91], o a los libros sobre el
68HC11 que figuran en la bibliografía que aparece al final del libro.
Conociendo los principios de la comunicación serie descritos aquí, y ayudado
por los ejemplos que proporciona Motorola, no deberá tener el lector ningún
problema en comprender el funcionamiento detallado del SCI.

6.3.3.3. Estándares de comunicación


Cuando se debe enviar información más allá de unos 30 cm de distancia no
se recomienda el empleo de señales TTL convencionales, debido a la
degradación en los niveles lógicos causados por la impedancia de las líneas de
transmisión, tensiones en modo común, ruido electromagnético, etc. (no
obstante, a velocidades de comunicación muy bajas y en ausencia de
254 Microprocesadores y microcontroladores

perturbaciones electromagnéticas, podrían enviarse señales TTL hasta a


algunos metros de distancia).
Para enviar señales digitales a distancias medias (varios metros) o largas
(kilómetros) se emplean diversos estándares de comunicación serie
(asíncronos). Por ejemplo, el famoso RS-232 permite el envío de señales a
distancias de hasta 15 metros a unos 19.200 bits por segundo, haciendo uso de
unos rangos de tensión más amplios que los TTL (±12 V). El estándar RS-423
mejora algunas características del RS-232, permitiendo enviar señales a unos
1.000 bits por segundo a 1 km de distancia sin necesidad de ninguna estación
repetidora. Para alcanzar distancias más largas o mayores velocidades, se
introducen estándares que manejan señales diferenciales, como el RS-422, que
puede enviar señales a 100.000 baudios a 1 Km. Todos estos estándares hacen
uso de circuitos excitadores y receptores específicos (drivers y receivers), que
realizan la conversión de las señales TTL que generan las UART (como el
ACIA 6850) a los valores de tensión requeridos (por ejemplo, ±12 V); un
ejemplo de ello es el MAX232 ya citado. Fabricantes como Maxim y Texas
Instruments (http://www.maxim-ic.com, http://www.ti.com) comercializan este
tipo de circuitos; a sus hojas de características remitimos al lector interesado en
este tema (por ejemplo, en el libro de Data Transmision de Texas, se realiza
incluso una interesante introducción a estos estándares).
Cuando se deben enviar señales a distancias muy lejanas (decenas de
kilómetros) se hace uso de la línea telefónica. Las líneas telefónicas permiten
enviar señales dentro de la banda de 300 a 3.400 Hz, aproximadamente. Por
ello, los valores TTL de ‘0’ y ‘1’ generados por un circuito UART deben ser
convertidos en señales moduladas sobre una señal portadora, que será enviada a
través de la línea telefónica; esta tarea la realizan los circuitos módem. Por
ejemplo, en la técnica FSK (Frequency Shift Keying, o codificación por
variación en la frecuencias), se asigna una frecuencia al ‘0’ (por ejemplo, 1070
Hz), y otra al ‘1’ (por ejemplo, 1.270 Hz), enviándose en serie una señal
compuesta por una sucesión de tramos de ondas de ambas frecuencias. Otra
técnica diferente es la PSK (Phase Shift Keying), en la que en vez de
modificarse la frecuencia para enviar un ‘0’ o un ‘1’, se cambia la fase de la
señal portadora.
Entradas y salidas (II): control de periféricos 255

6.4. Periféricos
En esta sección estudiaremos algunos de los periféricos de uso más
habitual en los sistemas microprocesadores y microcontroladores, y
proporcionaremos diversos ejemplos de su control.

6.4.1. Tipos de periféricos


Los periféricos son los dispositivos o equipos que permiten que el
microprocesador pueda relacionarse con su entorno. La diversidad de
posibilidades y de casos (desde un sencillo diodo LED o un pulsador, hasta una
pantalla, pasando por teclados, motores paso a paso, etc.) hace que en cada caso
deban implementarse controles de muy diferente estilo.
Estos dispositivos son denominados así por situarse en la periferia del
sistema microprocesador. Hemos visto que los periféricos no se conectan
directamente a los buses del sistema, como lo puedan hacer los chip de
memoria, sino que lo hacen por medio de circuitos adaptadores o interfaces,
algunos de los cuales son genéricos, pudiéndose aplicar a distintas clases de
periféricos (por ejemplo, un puerto paralelo programable), mientras que otros
adaptadores son específicos para un tipo de periférico (por ejemplo, un chip
controlador de teclado). En cualquier caso, cada uno de estos adaptadores o
puertos se presenta ante el microprocesador como uno o varios registros de
memoria, que pueden ser leídos y escritos por la CPU.
Para su estudio distinguiremos entre periféricos básicos y periféricos
avanzados. Denominaremos periféricos básicos a los más sencillos, que
pueden ser controladores directamente por el microprocesador principal (LED,
interruptores, conversores A/D), los cuales son comúnmente empleados en los
pequeños sistemas de aplicación industrial o de consumo (serán los que más
ampliamente estudiemos en esta sección). En ocasiones, este tipo de
periféricos se incluyen dentro de un µC; en la sección 6.5 que sigue
estudiaremos algunos de los periféricos que integra el 68HC11 en su pastilla.
Por otro lado, denominaremos periféricos avanzados a aquellos
suficientemente complejos como para que incluyan su propio microprocesador
interno que los controla. Normalmente, se trata de periféricos de computador
(pantallas CRT, impresoras, etc.), los cuales serán estudiados con brevedad en
la sección 6.6. Para concluir este capítulo, consideraremos en la sección 6.7 los
denominados sistemas de almacenamiento masivo, que en ocasiones también se
consideran dispositivos periféricos.
256 Microprocesadores y microcontroladores

6.4.2. Periféricos básicos


Trataremos en este punto de proporcionar una relación de algunos de los
periféricos básicos más comúnmente empleados en los pequeños sistemas
microprocesadores. Podemos clasificar los periféricos en dos tipos, los de
entrada o sensores, y los de salida o actuadores. Los sensores permiten que el
microprocesador pueda recibir información del exterior, mientras que los
actuadores ejecutan sobre el mundo real acciones ordenadas por la CPU,
actuando físicamente o simplemente presentando visualmente información.
Distinguiremos también entre periféricos que suministran o reciben un bit
de información, los que suministran o reciben toda una palabra digital y los de
gestión matricial.

a) Periféricos de entrada que suministran un bit:


• Interruptores y pulsadores.
• Circuitos de comparación de una señal con una referencia.
• Detectores de presencia, circuitos de alarma, etc.

b) Periféricos de entrada que suministran un grupo de bits


• Conmutadores numéricos rotativos.
• Conjuntos de microinterruptores (4, 8...).
• Conversores A/D.
• Teclados ASCII, decimales y hexadecimales codificados (que proporcionan
al pulsar una tecla un carácter ASCII de 7 u 8 bits, un número BCD o un
hexadecimal de 4 bits).
• Contadores, registros, etc.

c) Actuadores que reciben del microprocesador un bit


• Diodos LED y lámparas.
• Activadores de relés.
• Habilitadores de disparo de tiristores y triacs.

d) Actuadores que reciben una palabra digital


• Conversores D/A.
• Visualizadores de 7 segmentos.
Entradas y salidas (II): control de periféricos 257

• Visualizadores LCD, etc.

e) Periféricos organizados matricialmente


En todos los casos anteriores se asignaba una línea de puerto a cada señal
de un sensor o actuador. Pero si, por ejemplo, en vez de disponer de uno o dos
pulsadores, tenemos un teclado con más de cien teclas, el asignar a cada tecla
una línea de E/S sería un verdadero derroche de hardware. En estos casos los
periféricos se organizan matricialmente, distribuyendo los periféricos
individuales (p.e., cada tecla) en una matriz fila-columna, gestionándose todos
por una exploración de filas o columnas. Ejemplos de este tipo de periféricos
serían los siguientes:
• Conjunto de visualizadores de siete segmentos multiplexados.
• Teclados matriciales.
• Impresoras por columnas de puntos.
• Pantallas CRT, etc.

6.4.3. Conexión de periféricos básicos


Vamos a presentar a continuación algunos periféricos habituales en los
sistemas microprocesadores para aplicaciones relacionadas con la electrónica
industrial o de consumo. A modo de ilustración mostraremos ejemplos de su
conexión a un 68HC11.

6.4.3.1. Diodos LED


De entre los periféricos que presentan información al exterior uno de los
más habituales (y sencillos) son los diodos LED; la conexión a un puerto de
salida (el B del 68HC11) de un grupo de ocho se muestra en la fig. 6.16.
Se debe tener presente que, según sus hojas de datos, el consumo total de
un M68HC11 típico está limitado a una corriente del orden de 25 mA
[Motorola 91b] (depende de la frecuencia de reloj, tensión de alimentación,
modo de operación, etc.). Un solo LED precisa ya entre 10 y 20 mA para que
se ilumine de forma apreciable; por lo tanto, un M68HC11 no podrá iluminar
directamente 8 LED, por lo que se deben introducir buffers externos que
suministren la corriente requerida. En la Figura 6.16 se ha empleado un típico
buffer triestado 74LS541 permanentemente habilitado (el 74LS541 es similar al
más antiguo 74LS241, sólo que sus líneas de entrada y de salida se encuentran
dispuestas de forma más «ordenada» a ambos lados del chip, facilitando su
montaje): si se carga en el acumulador A la palabra %11111111 y se ejecuta la
258 Microprocesadores y microcontroladores

instrucción STAA $1004 (dirección del puerto B), observaremos que los 8
LED se iluminan (ya que los integrados suelen ser capaces de absorber más
corriente que la que pueden proporcionar, no es raro encontrarse con los LED
conectados justo al revés que en la figura, con sus cátodos conectados a la
salida del puerto o del amplificador; en este caso, para iluminar un LED habría
que colocar un ‘0’ en la línea de puerto.)
Pensando en periféricos que requieren una corriente importante se fabrican
buffers específicos. Por ejemplo, el ULN2003 y ULN2803 son conjuntos de 7 y
8 transistores Darlington respectivamente (Darlington transistor arrays),
integrados en un único chip, junto a un número similar de diodos de protección
contra sobretensiones causadas por cargas inductivas. Estos buffers pueden
suministrar de forma continuada hasta 500 mA de corriente, soportar picos de
600 mA y operar con tensiones de entrada de hasta 30 V y de salida de hasta 50
V, de modo que permiten iluminar directamente no sólo conjuntos de diodos
LED sino también pequeñas lámparas incandescentes, activar relés, motores
paso a paso, etc. Además, pueden interconectarse directamente con la mayoría
de las familias lógicas. En el apartado dedicado al manejo de dispositivos de
potencia presentaremos sus esquemas y mostraremos ejemplos de su empleo.
Por último, conviene tener presente que algunos microcontroladores
integran buffers para dotar a algunas de sus líneas de puertos de una capacidad
de manejo de corriente importante, de modo que permiten la conexión directa
de diodos LED u otro tipo de dispositivos sin necesidad de buffers externos.
Por ello, antes de realizar ningún tipo de montaje con microcontrolador deberán
consultarse detenidamente sus hojas de datos para averiguar las características
eléctricas que garantiza el fabricante.

FIGURA 6.16. Conexión de diodos LED (izquierda) e interruptores (derecha) a un 68HC11.


Entradas y salidas (II): control de periféricos 259

FIGURA 6.17. Arriba: conexión de un pulsador a un 68HC11 y rebotes generados. Abajo: filtrado
de los mismos por hardware para un pulsador (izda.) y un conmutador (dcha.).

6.4.3.2. Interruptores
Otro de los periféricos habituales son los interruptores. Muy a menudo los
encontramos agrupados de 4 en 4 o de 8 en 8 en encapsulados DIP (de similar
tamaño a un circuito integrado). Se suelen emplear para indicar la
configuración actual del sistema (cantidad de memoria incluida, periféricos,
etc.) o el modo de funcionamiento de determinado equipo.
En la Figura 6.16 (dcha.) se muestra la conexión de un conjunto de 8
interruptores al puerto C del 68HC11 (configurado como puerto de entrada).
Cuando un interruptor se encuentra cerrado, la línea correspondiente queda
conectada a tierra, con lo que se leería ‘0’; si permanece abierto, la polarización
de su línea de salida mediante una resistencia de 10 K a +5 V hace que se lea
por la línea correspondiente un ‘1’. Con una instrucción LDAA $1003
(dirección del puerto C) el valor de los 8 interruptores quedaría guardado en el
acumulador A.
260 Microprocesadores y microcontroladores

6.4.3.3. Pulsadores
En la Figura 6.17 se muestra la conexión de un pulsador a la línea 7 del
puerto C del HC11. Si se mantiene pulsado, se apreciará un ‘0’ por dicha línea;
si no se pulsa, se tendrá un ‘1’. Es importante tener en cuenta que al accionar
un pulsador aparecen siempre rebotes, que pueden presentar el aspecto de la
fig. 6.17 (arriba). La duración de los rebotes será mayor o menor según la
calidad de los contactos del pulsador; para uno de calidad normal éstos pueden
manifestarse durante unos 10 ms al accionarlo y al soltarlo.
Por lo tanto, si un flanco del pulsador debe desencadenar cierta acción
sobre el microcontrolador (por ejemplo, incrementar un contador o ejecutar una
interrupción), se hace necesaria la eliminación o filtrado de dichos rebotes. En
ocasiones este filtrado puede hacerse por software, por ejemplo, esperando
unos 10 o 20 ms antes de responder a la acción del pulsador («dejando pasar»
todos los rebotes), o bien leyendo el estado del pulsador y no actuando hasta
que observemos que durante unas cinco veces consecutivas su valor no ha
cambiado. Combinando ambas acciones se tiene una solución muy robusta.
En ocasiones la solución software no es factible y hay que recurrir al
filtrado por hardware. Existen varias formas de filtrar estos rebotes, por
ejemplo, mediante una red RC más un inversor Schmitt (con histéresis), como
se muestra en la fig. 6.17. Existen circuitos comerciales, como el MC14490 de
Motorola, que integran esquemas de este tipo en una sola pastilla (en particular,
dicho circuito permite filtrar hasta 6 pulsadores).
Si en vez de un pulsador (dos terminales) se dispone de un conmutador
(tres terminales), se puede emplear para el filtrado un biestable RS, bien como
circuito integrado, bien configurado mediante dos puertas NAND o dos
inversores (fig. 6.17).

6.4.3.4. Conmutadores rotativos


Los conmutadores rotativos (fig. 6.18) contienen una rueda mecánica con
los dígitos del 0 al 9 rotulados en el lateral, los cuales se visualizan a través de
una pequeña ventana; dicho número puede cambiarse desplazando la rueda
paso a paso mediante dos pulsadores (hacia adelante y hacia atrás). Estos
conmutadores presentan en sus cuatro pines de salida el valor binario del
número que aparece en la ventana, de manera que se pueden emplear para
presentar uno o más dígitos BCD. En la fig. 6.18 se muestra su conexión al
puerto C del 68HC11.
Entradas y salidas (II): control de periféricos 261

FIGURA 6.18. Conexión de un conmutador rotativo a un 68HC11.

FIGURA 6.19. Conexión de un visualizador de siete segmentos al 68HC11.

6.4.3.5. Visualizadores de siete segmentos


Como es sabido, consisten en un conjunto de 7 diodos LED que
representan la imagen de un dígito base 10 o 16 (del 0 al 9 y de la A a la F),
incluyendo a veces un octavo LED, que representa el punto decimal. Estos
visualizadores pueden ser de cátodo común o de ánodo común, según el
terminal común a los diodos empleado en el visualizador. Para cada uno de los
dos tipos existen conversores BCD a siete segmentos, que traducen un dígito
binario del 0 al 9 al patrón de LED encendidos y apagados que representan a
ojos de un humano la imagen del número correspondiente; para un visualizador
de ánodo común se tiene el 74LS47, y el 74LS48 para cátodo común.
En la fig. 6.19 se representa la conexión de un visualizador de cátodo
común al puerto B del 68HC11. El integrado 74LS48 realiza la conversión
BCD a siete segmentos, de modo que, si se carga en el acumulador A el valor
$05 y se ejecuta STAA $1004, se observará el número ‘5’ en el visualizador.
262 Microprocesadores y microcontroladores

Una alternativa a emplear estos integrados consiste en realizar la codificación


BCD a siete segmentos por software (mediante una tabla guardada en memoria
que para cada dígito proporcione su patrón de LED encendidos y apagados), lo
que permite ahorrar circuitería externa.
Con frecuencia se trata de visualizar cantidades de más de una cifra, por
lo que se precisa el empleo de varios visualizadores de 7 segmentos. En este
caso (y suponiendo que utilizamos integrados codificadores como el 74LS48)
para cada cifra se deberían emplear cuatro líneas de puertos, de modo que si
tenemos que visualizar números de 6 cifras se necesitarían ¡24 líneas!
En los diseños reales se procura hacer uso de microcontroladores de
mínimo coste, con un limitado número de patillas (como ya se ha comentado en
alguna ocasión, los hay con menos de 16 pines), por lo que suele resultar
habitual que el microcontrolador no disponga de suficientes líneas para
gestionar todos los periféricos requeridos, y emplear uno con más puertos no
resulta económicamente interesante. Una solución que ya conocemos consiste
en acceder a los periféricos en serie en vez de en paralelo, mediante protocolos
serie síncronos como el SPI. Por ejemplo, el MC14499 es un driver para
visualizadores de siete segmentos con conexión serie SPI, que permite manejar
hasta cuatro, aunque pueden conectarse fácilmente varios de ellos para
controlar los visualizadores requeridos [Lipovski 88].

FIGURA 6.20. Visualizadores de siete segmentos multiplexados (visualización dinámica).


Entradas y salidas (II): control de periféricos 263

Otra solución es que un mismo puerto paralelo sea compartido por varios
periféricos, multiplexando la información. En el caso de los 6 visualizadores
podrían emplearse 4 líneas para enviar el dígito BCD, y otras 6 para indicar el
visualizador que lo debe mostrar; en total se requerirían 10 líneas con esta
técnica, frente a las 24 si se conectan de forma directa. Todavía se pueden
ahorrar más líneas si se emplea un decodificador 3 a 8, pues un código de 3 bits
basta para determinar uno de los 6 visualizadores; en este ejemplo tan sólo se
precisarían 7 líneas haciendo uso de esta técnica.
Un ejemplo simplificado que permite visualizar un número BCD de dos
cifras (entre 00 y 99) se muestra en la fig. 6.20. Para ello podemos llevar a
cabo el siguiente procedimiento: poniendo a tierra el colector común del
primer visualizador, sacaremos por el Puerto B del HC11 la cifra de las
decenas, a continuación pondremos a tierra el colector común del segundo (y a
5V la del otro) y colocaremos la cifra de unidades (fig. 6.20). Así, cargando el
valor %0001dcba y ejecutando STAA $1004, el dígito BCD de valor %dcba
aparecería en el visualizador de la izquierda (decenas); repitiendo la operación
con %0010hgfe, %hgfe aparecería en el de la derecha (unidades). Si el proceso
se realiza una y otra vez a suficiente frecuencia (más de 20 veces por segundo),
conseguiremos «engañar» al ojo, que apreciará los dos dígitos encendidos,
representando dos números diferentes. Esta técnica se denomina también
visualización dinámica, puesto que los datos no permanecen estáticos en el
puerto, sino que varían muchas veces por segundo.

6.4.3.6. Teclado matricial


Los teclados se organizan matricialmente; los de únicamente 16 teclas se
denominan hexadecimales, y son muy empleados en sistemas pequeños.
Consisten en un conjunto de pulsadores distribuidos en una matriz (fig. 6.21);
al actuar sobre un pulsador, simplemente se establece una conexión entre dos
hilos, debiéndose determinar el código correspondiente a la tecla pulsada
(codificación del teclado), para lo que se lleva a cabo un proceso de
exploración de teclado (scan): las columnas se mantienen polarizadas a 0 V
por medio de resistencias (fig. 6.22); alternativamente una de las cuatro filas es
puesta a ‘1’, leyéndose a continuación el estado de todas las columnas; si las
cuatro permanecen a ‘0’, quiere decir que no se ha presionado ninguna tecla; en
cambio, si alguna está a ‘1’, la tecla correspondiente a la intersección
fila_activada-columna_activada (coordenadas [Fila,Columna]) habrá sido
pulsada; si en la activación de una fila no se encuentra tecla alguna pulsada, se
pasa a activar la siguiente fila (rastreo o exploración). Finalmente, determinada
264 Microprocesadores y microcontroladores

la fila-columna correspondiente a la tecla pulsada se suministra como salida su


valor (0, 1, 2, ..., F), o bien su traducción a código ASCII.
El proceso de exploración de teclado puede realizarse por software, lo
que resulta barato, ya que el algoritmo lo ejecuta la propia CPU activando y
leyendo determinadas líneas de puertos de E/S generales, y apenas se requiere
de circuitería adicional; la contrapartida es que la rutina de gestión de teclado
puede resultar relativamente compleja y ocupará cierta cantidad de memoria.
Por ejemplo, en la Figura 6.22 se muestra la conexión de un teclado
hexadecimal al puerto C del 68HC11, el cual lo gestionará por programa. Las
4 líneas bajas del puerto C se programarán como entradas (conectadas a las
columnas del teclado), y las altas como salidas (conectadas a las filas). El
siguiente es un ejemplo de algoritmo de gestión del teclado, que puede
codificarse fácilmente en ensamblador:
*** INICIO ***
Fila ← %0000 1000 3) FILTRADO REBOTES
1) EXPLORACIÓN DE TECLADO Esperar (10 ms)
Repetir { 4) VISUALIZAR TECLA
Desplazar_Izda (Fila) Enviar_A_Pantalla (ASCII_tecla)
Si (Fila)=0 ⇒ Fila ← %0001 0000 5) ESPERAR A SOLTAR TECLA
PortC← (Fila)
Repetir {
Columna ← (PortC)
Columna ← (Port C) }
Borrar_Bits_Altos (Columna) }
Hasta_que ( (Columna)=0 )
Hasta_que ( (Columna)≠0 )
6) FILTRADO REBOTES
Tecla ← (Fila):(Columna)
Esperar (10 ms)
2) CONVERTIR A ASCII
*** FIN ***
ASCII_tecla ← Consulta_Tabla(Tecla)

Una alternativa a la gestión por programa es la codificación por hardware,


mediante un circuito codificador de teclado que implementa por hardware la
exploración que determina el código de la tecla pulsada, de forma rápida, sin
intervención de la CPU y sin necesidad de programar. Existen en el mercado
diversos circuitos integrados codificadores de teclado, como el 8279A de Intel,
que incluyen buena parte de los teclados de PC, o los integrados 74C922 y
74C923 de National Semiconductors, éstos últimos para teclados pequeños de
16 y 20 teclas, respectivamente. Si se emplea un circuito codificador de
Entradas y salidas (II): control de periféricos 265

teclado, el hardware resultará más caro (un integrado de este tipo cuesta varios
cientos de pesetas), pero la programación se reducirá enormemente (por lo
tanto, se empleará codificación hardware o software dependiendo de los
requisitos concretos de la aplicación en desarrollo).

FIGURA 6.21. Organización interna de un teclado hexadecimal matricial.

FIGURA 6.22. Exploración de teclado por filas y lectura de columnas (tabla: fila-columna→ASCII).
266 Microprocesadores y microcontroladores

FIGURA 6.23. Codificación de teclado con el 74C922 y conexión al 68HC11.

El 74C922 (fig. 6.23) gestiona por exploración un teclado matricial de 16


teclas, a la frecuencia que marca el condensador conectado a OSC (0,1 µF se
corresponde con unos 600Hz, o 1,66 ms), y filtra los rebotes que se producen
durante un período de tiempo determinado por el condensador conectado a la
patilla KBM (Key Bounce Mask) (1 µF se corresponde con unos 10ms). Las
resistencias que deben polarizar las líneas del teclado empleadas como salida
van incorporadas en el propio integrado. Si mantenemos a 0 la línea de
habilitación de salida /OE (teclado siempre habilitado), el integrado, nada más
detectar que una tecla ha sido pulsada (por exploración de columnas y lectura
de filas), presentará su valor binario en las salidas de datos DOA, DOB, DOC y
DOD, activando a la vez la línea de salida dato disponible DA, que queda a ‘1’
mientras se mantenga la tecla presionada.
Este codificador también incorpora la denominada discriminación de dos
teclas (two-key-rollover): si accidentalmente se presionan dos teclas en vez de
una, el integrado determina la que ha sido pulsada en primer lugar, presentando
su código en las salidas de datos, para, una vez sea ésta liberada, presentar el
código de la segunda.
Los teclados con frecuencia se gestionan mediante interrupciones. Por
ejemplo, el estado del teclado podría muestrearse periódicamente por medio de
la interrupción periódica del microprocesador (p.e., 100 veces por segundo); los
ASCII de la secuencia de teclas que se detectan podrían almacenarse en una
memoria temporal (buffer de memoria) y podrían leerse desde el programa
Entradas y salidas (II): control de periféricos 267

mediante determinadas rutinas (p.e., las kbhit() o getch() del lenguaje C). A
grandes rasgos, ésta es la solución adoptada en los teclados de los PC. Una
alternativa es que la pulsación de una tecla genere directamente una
interrupción, que indique al microprocesador que se ha pulsado una nueva tecla
y que debe leer su código.

6.4.3.7. Pantallas LCD


Los LCD (Liquid Cristal Display), o visualizadores de cristal líquido, son
muy habituales en los sistemas microprocesadores debido a su bajo consumo,
relativamente reducido coste y variedad de tamaños y formatos disponibles
(que permiten seleccionar el más idóneo para cada aplicación). Además, el
contraste de una pantalla LCD es superior al presentado por diodos LED o
visualizadores de siete segmentos, de modo que puede leerse sin problemas en
entornos fuertemente iluminados. Sin embargo, como un LCD no genera luz
por sí mismo, necesita de una fuente de luz externa, por lo que en entornos
poco iluminados se requiere que la pantalla incluya una fuente de luz propia
(una pequeña lámpara), que consume mucha más corriente que el propio LCD.
Como su nombre indica, un visualizador LCD se basa en las propiedades
de los denominados cristales líquidos. Un cristal líquido es un material
formado por grandes moléculas orgánicas alargadas (con forma de bastón); por
debajo de su punto de fusión se trata de cristales convencionales, y, aunque a
temperaturas superiores pasan al estado líquido, las fuerzas de enlace cristalino
no desaparecen por completo, por lo que sus alargadas moléculas tienden a
seguir adoptando una disposición próxima a la cristalina. Hay que aumentar
más la temperatura, por encima de la denominada temperatura de clarificación,
para que las fuerzas cristalinas desaparezcan por completo y se comporte como
un líquido convencional, en el que las moléculas se mueven libremente. Las
pantallas LCD se construyen con materiales en los que el intervalo que va de la
temperatura de fusión al de clarificación comprende la temperatura ambiente,
para que se comporte como un cristal líquido (con lo que estas pantallas
trabajan dentro de un rango de temperaturas limitado), es decir, un líquido que
mantiene ciertas características típicas de los cristales, como son las
propiedades ópticas relacionadas con la polarización de la luz.
En una pantalla LCD el material cristal líquido está dispuesto entre dos
sustratos de vidrio de alta calidad (fig. 6.24). El espesor de la capa de cristal
líquido es de tan sólo unas 7 micras (es decir, la separación entre los dos
vidrios es una décima parte del espesor de un cabello humano). Sobre estos
vidrios se depositan los electrodos de óxido de indio (transparente), a los que se
les da la forma apropiada (puntos, barras conformando siete segmentos, etc.).
268 Microprocesadores y microcontroladores

Sobre este sandwich se coloca un filtro polarizador vertical, y en la base un


polarizador horizontal (cuyo plano polarizador está girado 90º del primero),
más un sustrato que refleja la luz (en otros modelos se coloca un sustrato negro,
que absorbe la luz).
La luz que llega a una pantalla LCD atraviesa el filtro polarizador superior,
por lo que las ondas luminosas oscilan en un único plano cuando inciden sobre
el cristal líquido (la luz solar oscila en todas las direcciones). En ausencia de
tensión eléctrica, las moléculas del cristal líquido tienen la propiedad de girar el
plano de polarización de la luz en 90º, por lo que atravesarán el segundo filtro
polarizador (girado precisamente 90º respecto del superior) y se reflejarán en el
material reflector de la base, con lo que se apreciará luz (no se distingue ningún
punto ni raya del fondo). Si se aplica un campo eléctrico entre un electrodo
superior y el inferior, las moléculas del cristal líquido se disponen
verticalmente, perdiendo sus propiedades cristalinas, con lo que la luz
polarizada por el primer filtro atraviesa tal cual el cristal líquido (su plano de
vibración ya no gira), pero no podrá atravesar el segundo polarizador (de plano
perpendicular al superior), por lo que la luz en este caso no se reflejará en el
reflector de la base: se apreciará una zona oscura, cuya forma depende de la
forma de los electrodos (un punto o una barra). La orientación de las moléculas
por acción del campo eléctrico no es instantánea, por lo que el cristal líquido
tiene un tiempo de respuesta relativamente lento (milisegundos).

Luz solar Luz solar


Filtro polarizador
(vertical)

Vidrio

Electrodos
Cristal líquido
Filtro polarizador
(horizontal)
Fondo reflectante

FIGURA 6.24. Esquema de las capas que componen una pantalla LCD (izda.) y nueva orientación
de las moléculas del cristal líquido situadas entre dos electrodos sometidos a un campo eléctrico
(dcha.).
Entradas y salidas (II): control de periféricos 269

Aunque hemos explicado el funcionamiento básico de una pantalla LCD


de iluminación ambiente y sustrato reflector, hay que indicar que también se
fabrican pantallas con base negra (absorbe la radiación en vez de reflejarla), y
pantallas con base transparente que son iluminadas desde atrás (con lo que
pueden verse en condiciones de reducida iluminación ambiente). Por otro lado,
se fabrican pantallas con los electrodos dibujando estructuras, como los
clásicos siete segmentos, y pantallas con electrodos puntuales organizados
matricialmente (matriz de puntos), que permiten visualizar caracteres
alfanuméricos, símbolos especiales, figuras, etc.
Una celda de la pantalla de cristal líquido (el espacio entre un electrodo
superior y el inferior) se comporta como un condensador, por lo que la
excitación no se realiza con tensiones continuas, sino con ondas cuadradas
bipolares de frecuencia baja (30 a 1.000 Hz), o más normalmente, con formas
de ondas compuestas por varios niveles de tensión (hasta 3-12 V). Estas
formas de ondas especiales se generan mediante un circuito driver de LCD; por
ejemplo, el MC14543N y el 74HC4543 son drivers BCD a LCD de siete
segmentos [Spasov 96]. Existen drivers con interfaz serie, que pueden
conectarse a buses como el SPI [Huang 96]. También es interesante saber que
algunos microcontroladores incorporan en el propio chip un driver de LCD.
En ocasiones, en vez de adquirir por un lado la pantalla de LCD y por otro
el circuito driver, se emplean directamente los denominados módulos LCD, que
incorporan ya en un mismo módulo híbrido pantalla, circuitería de control y
memoria, simplificando en gran medida el desarrollo. Estudiaremos como
ejemplo el módulo LM016-L de Hitachi, de 2 líneas por 16 caracteres
(matriciales), que contiene el controlador HD44780 de Hitachi. Éste último es,
en realidad, un microcontrolador de 4 bits que se comercializa ya programado
para el control de visualizadores LCD y que es empleado en muchos módulos
LCD comerciales, no sólo de Hitachi, sino también de otras casas, como Seiko
(por ello, muchos de los módulos LCD disponibles funcionan de idéntica
manera). El módulo LCD LM016-L incluye:
a) Generador de caracteres basado en ROM, CG-ROM (Character Generator
ROM), con caracteres de 5x7 y 5x10 pixeles.
b) 80x8 bits de memoria RAM, DD-RAM (Data Display RAM), para
almacenamiento de los caracteres a visualizar;
c) Una pequeña área de RAM adicional, CG-RAM (Character Generator
RAM), donde el usuario puede definir sus propios símbolos (8 de 5x7, o 4 de
5x10).
270 Microprocesadores y microcontroladores

d) Dos registros internos de 8 bits, el registro de instrucciones IR (Instruction


Register), y el de datos DR (Data Register), el cual almacena el ASCII del
carácter a visualizar. Ambos se direccionan con la línea RS de selección de
registro (RS=‘0’ direcciona el IR, RS=‘1’ el DR).
Al conectar la alimentación del módulo se ejecuta un reset (power-on
reset), quedando en una situación inicial conocida (tarda 10 ms una vez Vcc
supera los 4,5 V); para que resulte operativo, en primer lugar debe
programarse el modo de funcionamiento deseado:
a) Operación de 4 u 8 bits (para poder trabajar con µP de 4 u 8 bits).
b) Caracteres de 5x7 o 5x10 pixeles.
c) o 2 líneas.
Pueden programarse también una serie de instrucciones, como borrado,
retorno del cursor al inicio, cursor activado o no, pantalla activada o no,
parpadeo, desplazamiento de cursor y/o pantalla, lectura, escritura, etc. Cada
instrucción tiene asociado cierto código de 8 bits que debe almacenarse en el IR
para su ejecución.
Debido a su implementación CMOS, el módulo LCD resulta de bajo
consumo, pero, en general, es mucho más lento que el µP al que va a estar
conectado (normalmente, de tipo HCMOS). Por ejemplo, la ejecución por el
módulo LCD de una instrucción puede tomarle de 40µs a varios ms, mientras
que un ciclo de instrucción del 68HC11 es de únicamente 0,5 µs; es decir,
cuando el 68HC11 ordena la representación de cierto carácter, el borrado de la
pantalla, etc., el módulo LCD tardará un buen rato en completar la operación
solicitada. Para una adecuada comunicación entre microcontrolador rápido y
LCD lento caben dos posibilidades:
1) Consultar por programa el estado del señalizador de módulo ocupado BF
(Busy Flag), que permanece a ‘1’ mientras el módulo está procesando, y
retorna a ‘0’ cuando ha concluido la tarea encomendada (el valor actual de
BF aparece por la línea de datos DB7 si se hace RS=‘0’, R/W=‘1’ y E=‘1’).
2) Esperar un tiempo prudencial (≈10ms), p.e., mediante un bucle de espera.
Una vez que se ha establecido el modo de operación del módulo LCD
mediante una pequeña rutina ensamblador de inicialización programada en el
68HC11, la visualización de un dato se llevará a cabo sin más que enviar su
código correspondiente al registro de datos DR (línea RS=‘1’) y realizar una
transición ‘1’ a ‘0’ sobre la línea E de habilitación del LCD (no confundir con
el reloj E del 68HC11). Muchos de estos códigos de caracteres coinciden con
Entradas y salidas (II): control de periféricos 271

los ASCII estándar (letras, ‘,’, ‘.’, espacio, etc.), pero además en el generador
de caracteres en ROM se incluyen algunos adicionales, como, por ejemplo,
símbolos del japonés, o la letra ‘ñ’. Existe también la posibilidad de que el
usuario genere algunos caracteres propios.
El módulo LCD está diseñado para que resulte sencilla su conexión a los
buses de un sistema microprocesador o al puerto paralelo de un
microcontrolador. Dispone de tres líneas de alimentación, tierra y contraste de
la pantalla, tres de control y 8 de datos:
1. Vcc: Alimentación (+ 5 v.).
2. Gnd: masa (0 v.)
3. Vo: control del contraste de pantalla (Vcc-Vo≈4,4 V a 25 ºC; depende de la
temperatura y del ángulo de visión, por lo que se incluye potenciómetro de
ajuste).
4. RS: Selección de Registro. RS=‘0’ si envío de instrucciones, RS=‘1’ datos.
5. R/W: Lectura (‘1’)/Escritura (‘0’).
6. E: habilitación. En reposo E=‘1’, cuando E=↓ se ejecuta instrucción o
visualiza dato.
7 a 14. DB0-7. Líneas de datos, permanecen en alta impedancia cuando E=‘0’.
Las posibilidades del módulo LCD son numerosas; el interesado deberá
acudir a sus hojas de características para conocer todos los detalles. A
continuación ilustraremos su empleo en un caso particular.
Ejemplo: Modo 8 bits, 16 caracteres y 1 línea. Los pasos a seguir para
programar el módulo de forma que opere en de modo son los siguientes:
1) Conexión de la alimentación. Módulo LCD en situación de reset (power-on
reset).
2) Establecimiento de modo 8 bits, 1 línea: RS=‘0’, DB0-7=%001100xx ($30).
(cada acción se ejecuta cuando E=↓, por lo que hay que hacer por programa
E=‘1’, a continuación E=‘0’, y esperar a que el módulo LCD concluya).
3) Activación del visualizador y del cursor: RS=‘0’, DB0-7=%$0000 1110
($0E).
4) Modo auto-incremento: RS=‘0’, DB0-7=%$0000 0110 ($06)
272 Microprocesadores y microcontroladores

FIGURA 6.25. Ejemplo de conexión del módulo LCD de Hitachi al 68HC11 (solamente se enviarán
datos, por lo que el puerto C se configura como salida y R/W se ha conectado a tierra).

(cada vez que se envíe un nuevo dato el cursor se moverá una posición a la
derecha).
5) Borrado de la pantalla: RS=‘0’, DB0-7=%$0000 0001 ($01). Fin de la
inicialización.
6) Escribir en DR los ASCII de los caracteres a representar: RS=‘1’, DB0-
7=código ASCII.
Otras instrucciones habituales son las siguientes: desplazamiento de
imagen a la izquierda al escribir un carácter ($07), mover el cursor a la
izquierda ($10), retorno del cursor al inicio ($02), borrado ($01), etc.

6.4.3.8. Dispositivos de potencia


Ya sabemos que la capacidad de manejar corriente de los adaptadores
paralelos (como la PIA 6821) o de los puertos de un microcontrolador (como
los del 68HC11) suele ser muy limitada (del orden del miliamperio), por lo que,
cuando se trata de manejar periféricos que requieran un nivel de corriente
moderado (decenas de miliamperios), como grupos de LED o visualizadores de
7 segmentos, hemos empleado buffers triestado (como el 74LS541) como
intermediario entre el puerto y el periférico. Cuando se debe actuar sobre
Entradas y salidas (II): control de periféricos 273

periféricos que trabajen con tensiones o corrientes muy elevadas (lámparas,


motores, etc.), se deberá recurrir ya a dispositivos de potencia convencionales,
como tiristores y triacs.
En el caso de las situaciones intermedias entre las dos descritas (cientos de
miliamperios), como cuando se debe trabajar con lámparas de 12 V, pequeños
motores o relés, es usual el empleo de buffers integrados como los ULN2003 y
ULN2803 (Motorola, Texas Instruments, SGS-Thomson, Sprague). Estos
contienen 7 u 8 transistores Darlington, respectivamente (integrados sobre un
mismo substrato), por lo que en los libros de datos estos circuitos se clasifican
como Darlington transistor arrays; además se integran diodos de protección en
sus colectores para proteger el transistor cuando maneja una carga inductiva,
como los devanados de un motor (fig. 6.26).

ULN 2003
Salida
16 Común

Común

Entrada
(TTL)

GND
1 GND (común)

V (12V)
V (20V)
ULN 2003 ULN 2003

Entradas TTL

Entrada TTL

test de
lámparas

FIGURA 6.26. Arriba, esquema del ULN2003 (izda.) y circuito equivalente del buffer inversor
(dcha.) Abajo, ejemplo del empleo de su empleo para alimentar lámparas (izda.) y una carga
inductiva (dcha.).
274 Microprocesadores y microcontroladores

Funcionalmente, estos circuitos se comportan como buffers inversores de


tipo colector abierto, el ULN2003 y el 2803 admiten en sus entradas señales
tipo TTL, mientras que las versiones ULN2004 y 2804 admiten tensiones
CMOS (de 6 a 15 V). Cada uno de los transistores Darlington que integran
estos circuitos puede drenar corrientes de hasta 500 mA, y soportar tensiones
colector-emisor de hasta 50 V. En la fig. 6.26 puede observarse el esquema de
un ULN2003 (el ULN2803 es idéntico, sólo que integra un buffer más, con lo
que tiene 2 patillas adicionales) y dos aplicaciones: la excitación de lámparas
de 12 voltios y de una carga inductiva.
No profundizaremos más en este tema del control de dispositivos de
potencia mediante µP, pues se escapa del propósito introductorio y generalista
del libro. En [Stiffler 91] se dedica un capítulo entero a la conexión de
microprocesadores a dispositivos de potencia, y a él remitimos al lector
interesado en iniciarse en dicha cuestión. Allí se trata el empleo de transistores
de potencia, tiristores y triacs, circuitos excitadores de potencia (como los ULN
y otros), amplificadores operacionales de potencia, etc. Por otro lado, en las
aplicaciones de potencia obviamente conviene que el circuito de potencia esté
aislado del circuito digital de control, para lo cual ambos se suelen aislar
eléctricamente mediante el empleo de optoacopladores, tema que también se
trata en la obra citada. Hay que hacer notar que debido a los parásitos
electromagnéticos que se originan en la conmutación de potencia, suele resultar
conveniente que el sistema microprocesador esté apantallado, con dichos
dispositivos fuera del apantallamiento y separados del circuito microprocesador
por acoplamiento optoelectrónico.
En definitiva, es creciente la tendencia de incorporar «inteligencia» en
aquellos equipos que hasta hace bien poco eran gobernados exclusivamente por
elementos mecánicos o electro-mecánicos, en la forma de un sistema
electrónico cuyo núcleo es un microcontrolador; en el caso de los dispositivos
de potencia se habla entonces de smart power, o «potencia inteligente».
Aunque un microcontrolador de propósito general, como el 68HC11, puede
emplearse en el control de potencia (en [Kheir 97] se muestran diversas
técnicas de control de motores eléctricos mediante el 68HC11), en la actualidad
existen versiones concretas de microcontroladores que integran drivers de
potencia (p.e., para la excitación de motores). Un ejemplo en este sentido es el
µC 68HC705MC4 de la familia 68HC05 de Motorola, que incorpora drivers
para motores de continua sin escobillas, y el 68HC708MP16, que integra
drivers para motores trifásicos. Es ésta una tendencia en auge que siguen
compañías como Texas, Toshiba o Motorola.
Entradas y salidas (II): control de periféricos 275

FIGURA 6.27. Diagrama de bloques del 68HC11E9. Se incluyen todas las líneas del
microcontrolador, y se señalan todas sus posibles funciones. La tensión VPPE de programación
(que comparte pin con XIRQ) se aplica solamente a las versiones con EPROM (HC711).

6.5. Periféricos integrados en el 68HC11


El 68HC11 integra numerosos puertos y periféricos dentro de su pastilla
(fig. 6.27), facilitando enormemente las tareas relacionadas con control e
instrumentación. Las características concretas de los periféricos varían según
la versión de 68HC11; en la actualidad hay más de sesenta tipos diferentes de
M68HC11 disponibles, agrupados en diversas familias (A, C, D, E, F, G, K,
KA, L, M y P). Absolutamente todos los miembros de la gran familia 68HC11
incluyen puertos de E/S, SCI, SPI, sistema de temporizadores y circuitos de
vigilancia, y la gran mayoría integran también conversor A/D y memoria
EEPROM. Recordemos que todos estos bloques internos se controlan por
medio de los registros situados a partir de la dirección $1000.
Aunque cada familia particular está más orientada a determinado campo de
aplicaciones, y las características concretas de sus periféricos integrados varían
algo entre sí, todos ellos se apoyan sobre las mismas ideas básicas. Mientras no
276 Microprocesadores y microcontroladores

se diga lo contrario, las explicaciones que hemos proporcionado hasta ahora y


las que siguen se refieren a las versiones A8 y E9, consideradas como las más
genéricas (son el punto de partida de todas las demás versiones, algunas
aumentan sus funcionalidades, otras las recortan).
Algunos de los periféricos del HC11 han sido tratados ya a lo largo del
libro; el objetivo de esta sección es completar el estudio de los demás. Los
detalles de cada uno de los periféricos que integra el 68HC11 son muy
numerosos (por ello, el manual de referencia del M68HC11 [Motorola 91]
posee más de 500 páginas de copiosa información), por lo que su estudio
completo y detallado no resulta factible en un texto introductorio. Para
profundizar en los muchos detalles que inevitablemente quedarán en el tintero
habrá que recurrir al manual de referencia [Motorola 91], o a libros como
[Driscoll 94, Huang 96, Lipovski 88, Spasov 96], que tratan exclusivamente y
en profundidad el 68HC11.

6.5.1. Puertos de entrada y salida


El 68HC11 incluye por lo menos cinco puertos paralelos, PA, PB, PC, PD
y PE (o simplemente, A, B, C, D y E); algunas de las líneas de estos puertos
son de entrada, otras de salida, y otras son programables (fig. 6.27):
a) Puerto A: 8 líneas, unas de entrada, otras de salida, alguna de E/S (registro
PORTA, dirección $1000).
b) Puerto B: 8 líneas de salida (PORTA, $1004).
c) Puerto C: 8 líneas programables como entradas o como salidas (PORTC,
$1003).
d) Puerto D: 6 líneas programables como entradas o como salidas (PORTD,
$1008).
e) Puerto E: 8 líneas de entrada, o 4 si el encapsulado es DIP (PORTE,
$100A).
Todos los puertos tienen una función doble: como puerto de E/S o para
acceder a determinados elementos internos. Por ejemplo, los puertos B y C (de
propósito general) se convierten en los buses del sistema cuando el HC11 opera
en modo expandido.
El resto (A, D y E) pueden operar como puertos convencionales o como
líneas de acceso a alguno de los periféricos internos; cada puerto tiene una
dirección asignada y cada periférico tiene sus propios registros de control, de
modo que las líneas se emplean como puerto convencional o para acceder al
Entradas y salidas (II): control de periféricos 277

periférico integrado dependiendo de la dirección concreta sobre la que se


efectúe una operación de lectura o escritura (dirección a partir de la $1000).
Por ejemplo, el puerto E es un puerto de entrada, de modo que si realizamos
una lectura sobre la dirección que tiene asignada ($100A) leeremos la palabra
digital colocada en sus líneas PE0 a PE7 (p.e., la establecida por un conjunto de
interruptores), pero si operamos con los registros colocados a partir de la
dirección $1030 estaremos trabajando con él como puerto de entradas
analógicas (AN0 a AN7) que acceden al sistema de conversión A/D integrado.
Por otra parte, las líneas del puerto A pueden emplearse como entradas y
salidas, o bien como pines del sistema de temporizadores y contadores;
finalmente, las del puerto D se pueden emplear para acceder a los bloques SCI
y SPI de comunicación serie.

6.5.2. Canales serie


Permiten la conexión vía serie con periféricos. Se tienen los dos bloques
conocidos:
a) SCI (Serial Communication Interface). Módulo tipo UART para
comunicaciones serie asíncronas, por ejemplo, con un computador, o entre
diversos microcontroladores conectados por medio de una red local.
b) SPI (Serial Peripheral Interface). Bloque de comunicaciones serie
síncronas, que permite la comunicación serie de alta velocidad con
periféricos próximos al 68HC11, como, por ejemplo, drivers de LCD o de
visualizadores de siete segmentos, conversores A/D y D/A, etc. Su mayor
interés es el ahorro de líneas que supone la conexión de periféricos por
medio de un bus serie.
Ambos bloques, tratados brevemente en la sección 6.3, hacen uso de las
líneas del Puerto D (fig. 6.27).

6.5.3. Sistema de conversión A/D


El bloque de conversión A/D del 68HC11 (que incluyen todas las familias
de microcontroladores HC11, excepto la D) resulta de empleo sencillo y
versátil; aunque no permite trabajar con señales de muy elevada frecuencia, es
adecuado para aplicaciones típicas de entornos industriales, automóvil, etc. (si
se precisan mayores prestaciones, deberá recurrirse a un conversor externo,
preferentemente con salida serie compatible SPI).
278 Microprocesadores y microcontroladores

SCAN continuo o simple MÚLTiples canales o un solo canal


‘0’ Hace 4 conversiones y para ‘0’ convierte un solo canal (el seleccionado)
‘1’ Convierte continuamente 4 ‘1’ convierte los 4 canales del grupo
canales del grupo seleccionado seleccionado

Canal seleccionado,
Conversion Complete Flag
CD a CA
A ‘1’ cuando termina de convertir

$1030 CCF -- SCAN MULT CD CC CB CA ADCTL

7 6 5 4 3 2 1 0

FIGURA 6.28. ADCTL ($1030): registro de control del módulo de conversión A/D del 68HC11.

FIGURA 6.29. Termómetro electrónico basado en el 68HC11.

Este módulo se basa en un conversor de 8 bits o 10 bits por


aproximaciones sucesivas (emplea una técnica denominada redistribución de
carga [Motorola 91]); gracias a un multiplexor analógico, este conversor
permite trabajar hasta con 8 tensiones distintas conectadas a las líneas del
puerto E. En el caso de las familias habituales A y E el conversor es de 8 bits y
el multiplexor de 8 canales, que se corresponden con las líneas PE0 a PE7 (en
los encapsulados DIP sólo se encuentran disponibles 4 canales). Las líneas
VrL y VrH del HC11 son las tensiones de referencia baja y alta del conversor
A/D, a las cuales se asignan los valores binarios $00 y $FF, respectivamente
(por ejemplo, 0 y 5 V, respectivamente).
Entradas y salidas (II): control de periféricos 279

Para manejar el bloque de conversión del 68HC11, en primer lugar debe


colocarse a ‘1’ el bit 7 del registro de OPTION ($1039), lo cual indica al
microcontrolador que debe proporcionar alimentación al A/D; solamente puede
escribirse sobre este registro durante los primeros 64 ciclos de reloj tras reset.
Debe tenerse en cuenta que el programa monitor BUFFALO que contienen en
su ROM interna algunos ejemplares del 68HC11E9 y 68HC11A8 (como los
que se utilizan en las placas de evaluación de Motorola EVB y EVBU) activa
dicho bit, por lo que si trabajamos bajo BUFFALO no es necesario que lo
hagamos nosotros.
El registro de control ADCTL ($1030) permite programar las distintas
modalidades de operación (fig. 6.28); la conversión se inicia justo cuando se
graba con una instrucción como STAA la configuración deseada en dicho
registro. Cada vez que se solicita conversión, el HC11 lleva a cabo siempre 4
conversiones consecutivas, guardando los resultados en las direcciones $1031
a $1034 (registros de resultados ADR1, ADR2, ADR3 y ADR4), pudiendo
corresponder estos datos bien a la conversión de un grupo de cuatro canales
diferentes (bit MULT de ADCTL a 1, lo que indica modo de conversión
múltiple, p.e., para leer la tensión proporcionada por cuatro sensores distintos),
o bien al estado de un mismo canal en cuatro instantes temporales (MULT=0,
modo simple, para leer un sensor cuatro veces consecutivas).
El canal o grupo de canales a seleccionar se indica con los bits CA, CB,
CC y CD del registro ADCTL. Por otra parte, si el bit SCAN vale 1, el HC11
ejecuta conversiones continuamente (sin interrupción); mientras que, si
SCAN=0, ejecuta un solo proceso de conversión (cuatro consecutivas) y se
detiene. Por ejemplo, si se desea convertir a digital el estado de un solo sensor
conectado al canal PE1 y detener a continuación la conversión, se deberá
programar SCAN=0 (no continuo), MULT=0 (un canal), CD=0, CC=0, CB=0
y CA=1 (línea/canal PE1 del puerto E). Es decir, primero se cargaría en A el
valor $01, LDAA #1, iniciándose la conversión al ejecutar STAA $1030.
El final de conversión puede detectarse comprobando por programa
cuándo el señalizador CCF se pone a 1 (bit 7 de ADCTL). Otra opción es la
siguiente: sabiendo que el 68HC11 emplea 32 ciclos de reloj en realizar una
conversión y que siempre va a realizar cuatro consecutivas, puede programarse
una rutina de retraso de 128 ciclos de reloj tras la orden de comienzo de
conversión.
En la fig. 6.29 se muestra como ejemplo un termómetro que permite medir
temperatura ambiente (entre 0 y 40 ºC, aproximadamente). Como sensor de
temperatura se emplea una NTC de 10 K (B≈3.750 ºK) cuyo comportamiento
280 Microprocesadores y microcontroladores

queda linealizado entorno a To=25 ºC mediante una resistencia en serie de unos


6K8 [Pallás 98]. El condensador filtra picos de tensión causados por el ruido, y
la resistencia de 1K conectada al pin del puerto se recomienda como protección
(la corriente que la atraviesa es prácticamente despreciable y apenas hay caída
de tensión en ella). Debido al comportamiento prácticamente lineal entorno a
25 ºC del conjunto resistencia-NTC en serie, puede realizarse la conversión
tensión a temperatura por programa haciendo uso de las instrucciones de
multiplicación y división (MUL, IDIV). Si nos salimos del rango lineal de
operación, deberá trabajarse mediante una tabla tensión-temperatura
almacenada en memoria.
En este tipo de aplicaciones es habitual también el empleo de sensores de
silicio como el LM35 de National Semiconductors (htttp://www.national.com),
de comportamiento lineal en un margen considerable, que alimentado entre 0 y
5 V proporciona directamente una tensión de salida de 10mV por cada grado
centígrado de temperatura [Huang 96].
Para finalizar, recordaremos que las líneas del puerto E pueden emplearse
también como entradas digitales, sin más que leer la dirección $100A (registro
PORTE), de modo que puede registrar señales analógicas y digitales a la vez.

6.5.4. Bloque de temporizadores y contadores


El bloque de temporización (timer) del 68HC11, al cual se accede por el
puerto A (fig. 6.30), es uno de los módulos más potentes y versátiles de este
microcontrolador, ocupando buena parte de su área de silicio. Debido
precisamente a su versatilidad, sus detalles de funcionamiento son numerosos,
por lo que su manejo no resulta sencillo (más de la mitad de los 64 registros de
configuración colocados a partir de $1000 se dedican a este módulo). En este
apartado simplemente realizaremos una pequeña introducción; el lector
interesado en más detalles deberá acudir al manual de referencia de Motorola o
a cualquiera de los libros indicados en la bibliografía (donde se incluyen
además muchos ejemplos de su aplicación).
Este bloque se construye en torno a un contador libre de 16 bits (free-
running counter) conectado al reloj E del 68HC11; cada vez que dicho
contador recibe un pulso de E, su valor se incrementa en uno. Puede obtenerse
el estado actual del contador mediante una instrucción de lectura de dato de 16
bits aplicada sobre el registro de TCNT (Timer CouNTer), de dirección $100E-
$100F (LDD $100E), pero dicho estado no puede modificarse por programa.
Entradas y salidas (II): control de periféricos 281

FIGURA 6.30. ADCTL ($1030): registro de control del módulo de conversión A/D del 68HC11.

Así, en un 68HC11 a 2 MHz el contador se incrementa cada 0,5 µs, de


modo que completa un recorrido completo (de $0000 a $FFFF) en 32,77 ms
(65.536×0,5 µs). No obstante, un bloque de pre-escalado permite modificar la
frecuencia de contaje a 1/2, 1/4 o 1/16 de la del reloj E (pudiendo entonces
contar hasta 131,1, 262,1 y 524,3 ms, respectivamente). Por defecto el pre-
escalado es 1 (no hay pre-escalado); para indicar uno distinto se debe actuar
sobre dos bit del registro denominado TMSK2 ($1024), pero siempre antes de
que transcurran 64 ciclos de reloj tras un reset, pues más tarde, y por motivos
de seguridad, el pre-escalado ya no puede modificarse.
Debe subrayarse que el contador libre funciona de forma completamente
independiente del resto del sistema (incluido el programa); por ello, actúa
siempre en tiempo real, motivo por el cual la utilidad del bloque de
temporización en tareas de control es enorme: generación y medida de
retrasos, generación de formas de onda (cuadradas, rectangulares, PWM),
medida de tiempos y períodos, contaje de eventos, generación de bases de
tiempos, solicitud de interrupciones con periodicidad, etc. Las funciones que
puede efectuar el módulo temporizador se agrupan de la siguiente manera
(tomaremos la versión E9 como ejemplo, fig. 6.30):
a) Captura de entradas o IC (Input Capture) (cuatro IC en el HC11E9). El
módulo de temporización detecta de forma automática (sin intervención de
la CPU) que ha sucedido un evento activo (una transición ‘1’ a ‘0’, o ‘0’ a
‘1’, según se programe) en una línea IC (fig. 6.30); en dicho caso, el actual
282 Microprocesadores y microcontroladores

valor del contador libre queda automáticamente guardado en uno de los


cuatro registros IC (TIC1, TIC2, TIC3, TI4/O5). El usuario puede entonces
comparar por programa el valor registrado con algún valor previo, para así
calcular la anchura de un pulso, el período o frecuencia de una señal, una
velocidad, etc. Las líneas IC permiten generar también interrupciones
enmascarables.
b) Salidas por comparación u OC (Output Compare) (cinco funciones OC en
el HC11E9). El bloque de temporización compara automáticamente en cada
ciclo E el valor actual del contador libre con el almacenado en uno de los
registros OC (TOC1, TOC2, TOC3, TOC4, TI4/O5), y cuando ambos
coinciden desencadena automáticamente una acción sobre un pin OC (lo
pone a ‘1’, a ‘0’ o lo invierte, según se haya programado), activando un bit
señalizador y, si así se ha programado, generando una interrupción. La
función OC permite implementar retrasos, generar ondas de frecuencia
dada, ondas moduladas en anchura (PWM) o solicitar periódicamente una
interrupción IRQ.
c) Acumulador de pulsos o PA (Pulse Accumulator). Lleva la cuenta en el
registro PACNT (8 bits) de los pulsos activos que han llegado a la línea PAI
(Pulse Accumulator Input) del puerto A. Así, la función PA permite contar
el número de pulsos recibidos durante un intervalo de tiempo o medir la
duración de un pulso.
Para ilustrar la utilización del bloque de temporizadores presentaremos un
ejemplo detallado del uso de las salidas por comparación OC (Output
Compare). De las cinco funciones OC del 68HC11E9 trabajaremos con la
segunda, OC2, asociada al bit 6 del puerto A (de ahí su denominación
PA6/OC2, fig. 6.30). El empleo de la función OC2 involucra el manejo del
registro OC2 denominado TOC2 (16 bits, el cual se compara con TCNT), del
registro de control TCTL1 (para programar el funcionamiento de OC2), del
registro de flags TFLG1 (que señala cuándo coinciden TCNT y TOC2) y de la
máscara de interrupciones de TMSK1 (con la que se puede habilitar o
deshabilitar la solicitud de interrupción cuando TCNT y TOC2 coinciden).
Es recomendable que el lector siga la explicación que ofrecemos a
continuación sobre la fig. 6.31. El bloque de temporización en cada ciclo E
compara de forma automática (sin control por programa) el valor actual del
contador libre TCNT con el almacenado en los registros de comparación; en
este caso nos fijamos en TOC2 (fig. 6.31). Cuando TCNT coincide con TOC2,
automáticamente se activa el flag OC2F (del registro TFLG1) y se ejecuta una
acción sobre el pin correspondiente (PA6/OC2 en nuestro caso): se pone a ‘1’,
Entradas y salidas (II): control de periféricos 283

a ‘0’, o invierte su estado, según se haya programado el registro de control


TCTL1 (fig. 6.31). Si el bit correspondiente de TMSK1 se había previamente
programado a ‘1’, además se solicitará interrupción IRQ.

7 6 5 4 3 2 1 0
$100E TCNT
Timer Count (16 bits)
$100F (registro de sólo lectura)

PA6/OC2
flag

OC2F

IRQ
OC2I

$1018 TOC2
Timer Output Compare
$1019 Register (16 bits)
7 6 5 4 3 2 1 0

Acción línea PA6/OC2


00 timer desconectado
01 invierte línea OC2
10 pone línea OC2 a ‘0’
11 pone línea OC2 a ‘1’

$1020 OM2 OL2 TCTL1


Timer Control 1
7 6 5 4 3 2 1 0

Máscara de interrupción de OC2


A ‘0’, interrupción OC2 deshabilitada
(situación por defecto, tras reset).
A ‘1’, interrupción OC2 habilitada

$1022 OC2I TMSK1


Timer Interrupt Mask 1
7 6 5 4 3 2 1 0

Flag de OC2
Se activa (‘1’) cada vez que el contador
coincide con el valor del registro TOC2
Se borra (‘0’) escribiendo un ‘1’ sobre él

$1023 OC2F TFLG1


Timer Flags 1
7 6 5 4 3 2 1 0

FIGURA 6.31. Registros involucrados en la función OC2 del 68HC11.


284 Microprocesadores y microcontroladores

A modo de ejemplo, presentamos a continuación un programa para el


68HC11E9 que genera una onda cuadrada de 1 KHz de frecuencia por el pin 6
del puerto A mediante la función OC2, y sin recurrir a interrupciones.
* Genera una onda cuadrada (1 KHz) mediante OC2 (PA6/OC2)
* Se hace uso de direccionamiento indexado, tomando como base
* $1000, ya que se utilizan las instrucciones que actúan sobre bits
* individuales (BSET, etc.), que solo trabajan en directo o
indexado
ORG $100
LDX #$1000 * comienzo registros HC11
LDAA #%01000000 * $40
STAA $20,X * OC2 modo inversión
* (TCTL1=0100 0000, OM2:OL2=0:1)
otra STAA $23,X * TFLG1, borramos flag OC2 (escribiendo '1')
LDD #$03E8 * RETRASO. Se pone T/2 en unidades de clk
ADDD $18,X * Sumamos el retraso al valor actual de TOC2
STD $18,X * Actualizamos registro TOC2
aunno BRCLR $23,X %01000000 aunno * comprobar flag OC2F
* flag OC2F: cuando TOC2=TCNT=>flag a '1', =>invierte pin PA6/OC2
LDAA #%01000000 * $40
BRA otra
END
Una señal cuadrada como la generada por el programa anterior podría
emplearse para producir sonidos llevándola sobre un altavoz (fig. 6.32).
Recordemos que el empleo del sistema de temporización se explica de forma
muy detallada (incluyendo numerosos ejemplos) en el manual de referencia
[Motorola 91], y en libros como [Huang 96, Spasov 96].

PA6/OC2
+

100 µF
74LS04
8Ω

FIGURA 6.32. Generación de sonidos por altavoz. El integrado 74LS04 genera la corriente
necesaria, y el condensador protege la circuitería digital.
Capítulo 7
Desarrollo de sistemas microprocesadores

7.1. Introducción
Hasta el momento se han estudiado los conceptos fundamentales sobre diseño
de sistemas basados en microprocesadores, tanto a nivel de hardware como de
software; en el presente capítulo abordaremos algunas cuestiones más prácticas,
por ejemplo, hablaremos de los campos de aplicación de los microprocesadores,
de las fases típicas del desarrollo de un sistema, de las herramientas más
habituales, y expondremos también algunas consideraciones que se deben tener en
cuenta en la elección del microprocesador más adecuado para cada aplicación.
Además, existe cierta tendencia a pensar en un sistema microprocesador
como sistema lógico (digital) que debe programarse, pero en el fondo se trata de
un sistema electrónico de elevada complejidad; por ello, a los aspectos más
obvios relacionados con el diseño digital y del software habrá que añadir los
eléctricos/electrónicos y de consumo. Así, resultará importante tener en cuenta
las características eléctricas y temporales de las señales, buses, conexiones,
circuitería, etc., pues, de otra manera, en el desarrollo de un sistema
microprocesador pueden aparecer problemas imprevistos que impidan su correcto
funcionamiento (retrasos en las señales, capacidad de carga de los buses, ruido,
etc.). Algunas consideraciones de este tipo, importantes a la hora de desarrollar
un sistema basado en microprocesador, serán expuestas también en este capítulo.
Desde hace unos años es creciente la tendencia de incorporar cierta cantidad
de electrónica en productos y equipos manufacturados, desde aparatos de
consumo hasta electrodomésticos, pasando por el automóvil, el hogar, las
máquinas industriales, etc. Este «ingrediente» electrónico tiene como fin
introducir cierto componente de «inteligencia» en el equipo, que permita mayores
prestaciones, ahorro de energía, facilidad de uso, etc. Casi todos estos circuitos
electrónicos incluyen uno o más microprocesadores (microcontroladores), por
consideraciones diversas, como simplicidad de diseño, precio y tamaño reducidos,
fiabilidad, reprogramabilidad, etc.
Por lo tanto, sin ser conscientes de ello, estamos rodeados de
microprocesadores tanto en la calle como en casa, en el trabajo y en el ocio. Por
ejemplo, un microcontrolador de ocho bits gestiona el horno microondas, o
controla el contador de la luz; muchos sensores de temperatura inteligentes
292 Microprocesadores y microcontroladores

empleados en el control de la calefacción se basan en sencillos


microcontroladores de 4 bits, lo mismo sucede con los mandos a distancia; en una
consola de vídeo-juegos de gama alta podemos encontrarnos con varios potentes
microprocesadores RISC de 32 bits operando en paralelo; el teclado de un
ordenador es gestionado por un microcontrolador de 8 bits, etc.
El papel de los microprocesadores en el campo de la automoción merece un
capítulo aparte. En un automóvil moderno podemos encontrarnos con más de
veinte microcontroladores de diversas prestaciones: de 4 bits, para el control del
bloqueo del seguro y de la radio; de 8 bits, para el control del sistema de frenado
ABS, el airbag o la suspensión; de 16 bits, para el control de la ignición
electrónica o la servodirección, etc. Se dice que aproximadamente el 30% del
coste de un automóvil moderno de gama alta se relaciona con la electrónica que
incorpora (airbag, suspensión activa, control del motor, elementos de seguridad,
computador de a bordo, navegador, etc.).
En resumen, aunque al hablar de microprocesadores uno piense en el Pentium
de un computador personal, en realidad la inmensa mayoría de los
microprocesadores que se fabrican acaban desempeñando su callada labor en
miles de aparatos y equipos diferentes, a lo cual se hace referencia con el término
computación oculta (hidden computing). Así, el poder de cómputo incorporado
en una lavadora automática es superior al del ordenador que gobernaba las naves
Apolo que consiguieron llevar al hombre a la Luna (en una época previa al
nacimiento del microprocesador).
Este tipo de sistemas microprocesadores que se encargan de controlar
determinado equipo (mando a distancia, lavadora, horno, freno ABS, impresora,
etc., etc.) se denominan sistemas específicos. Éstos (fig. 7.1) reciben información
por medio de sensores y actúan sobre el exterior mediante accionadores de todo
tipo, empleando en ocasiones elementos de potencia; para su desarrollo se hace
uso de componentes activos y pasivos, circuitos analógicos y digitales, se precisan
fuentes reguladas y se requiere amplio conocimiento de todo lo relativo al diseño
de placas y su test. Es decir, el desarrollo de sistemas microprocesadores, lejos de
la idea inicial de sistema lógico que debe programarse, suele involucrar todos los
aspectos de la electrónica, desde la digital y analógica a la instrumentación y
potencia [Williams 96].
Pero no hay que olvidar que en el corazón de este complejo sistema
electrónico existe un programa almacenado en memoria, quien, en definitiva, rige
el sistema. En realidad, la parte más costosa de su desarrollo suele ser
precisamente la realización del programa (en la actualidad aproximadamente el
15% se relaciona con el coste del desarrollo del hardware, y el 85% del software
[Bursky 96]). Podemos indicar como ejemplo que en la memoria ROM del
Desarrollo de sistemas microprocesadores 293

sistema microprocesador que gestiona cierto modelo de teléfono móvil se tiene un


programa escrito en lenguaje C que cuenta con más de un millón de líneas de
código (!!!) [Williams 96].
Todo lo expuesto refleja la enorme importancia que los microprocesadores
poseen en el desarrollo de sistemas electrónicos: para un profesional de la
electrónica resulta tan básico conocer el fundamento del transistor, del
amplificador operacional o dominar la electrónica digital, como saber diseñar y
programar sistemas microprocesadores.

Sensor
Acondicionador
Acondicionador C. A/D

Proceso RAM/ º
µP/µC/DSP
ROM

Actuador/
Carga
Acondicionador/
Acondicionador
Potencia

Fuente de energía

FIGURA 7.1. Diagrama de bloques de un sistema específico, cuyo núcleo es un microprocesador.

7.2. Campos de aplicación de los microprocesadores


El diseño de un sistema electrónico complejo, como el requerido en muchas
aplicaciones de electrónica industrial, consumo, telecomunicaciones, etc., puede
abordarse haciendo uso de diversas opciones:
• Lógica cableada.
• Lógica programable (PLDs: PLA, PAL, FPGA....).
• Circuitos integrados de aplicación específica (ASIC).
• Microprocesadores.
294 Microprocesadores y microcontroladores

Si atendemos únicamente a la complejidad (tamaño) del diseño (en cuanto a


número de puertas lógicas se refiere), el razonamiento hasta hace unos años era el
siguiente. Si el sistema a construir resulta muy simple, puede recurrirse a la
lógica cableada tradicional, mientras que se hace uso de lógica programable
(dispositivos lógicos programables o PLD, como las PLA o PAL) cuando el
diseño es de mayor complejidad (decenas o cientos de puertas lógicas). Para
circuitos con miles de puertas lógicas pueden emplearse circuitos integrados de
aplicación específica o ASIC (Application Specific Integrated Circuit); no
obstante, debido al elevado precio de desarrollo de un ASIC (millones de pesetas),
su realización resulta viable tan sólo si se fabrica un elevado número de
ejemplares (de forma que al repartir el elevado coste inicial entre miles de
circuitos resulte rentable el precio unitario final).
Sin embargo, los dispositivos programables llamados PLD de alta
complejidad (high complex Programmable Logic Devices), como las FPGA
(Field Programmable Gate Array), están planteando una gran competencia a los
ASIC [Petropoulos 95], puesto que permiten incluir un elevado número de puertas
(algunos tipos de FPGA alcanzarán pronto un millón de puertas equivalentes en
un solo chip). Una de las grandes ventajas de estos dispositivos es que resultan
relativamente baratos (miles de pesetas), pudiéndose además disponer al momento
de los ejemplares programados (en el caso de los ASIC, concluida la fase de
diseño, la fábrica de circuitos integrados no puede proporcionar los ejemplares
hasta varios meses más tarde). Algunos de estos chips FPGA son además
reprogramables, lo que aumenta su versatilidad. Debido a todo ello, los ASIC
solamente resultan rentables cuando se trata de realizar grandes series de
circuitos, siendo más ventajoso el empleo de un PLD para series medianas y
pequeñas (así como para el desarrollo de prototipos).
Otra alternativa es el empleo de algún tipo de µP. En [Cahill 93] se
argumenta que la resolución de un problema mediante lógica (cableada o
programable) resulta óptima para circuitos basados en máquinas de reducido
número de estados, mientras que para un relativamente elevado número de
estados este tipo de solución resulta de compleja implementación (mucho tiempo
de desarrollo), siendo más idóneo en este caso el empleo de µP.
Desarrollo de sistemas microprocesadores 295

FIGURA 7.2. Cada problema viene caracterizado por su magnitud y velocidad requerida. En el
gráfico se muestra la solución óptima para cada situación (aunque faltaría incorporar en el gráfico un
tercer parámetro muy importante: el precio de cada alternativa).

Así, en cuanto a tamaño del sistema se refiere, el nicho ocupado por los
microprocesadores se solapa en ocasiones con el de otros dispositivos, como PLD
y ASIC. Sin embargo, otro parámetro importante a tener en cuenta es el
rendimiento (o velocidad de proceso), que resulta ser una restricción importante
en el uso de microprocesadores en determinadas aplicaciones. El
microprocesador funciona a frecuencias de reloj de varios megahertzios, con lo
que puede ejecutar una instrucción en el orden del microsegundo. En general, un
microprocesador deberá ejecutar varias instrucciones para realizar determinada
tarea, por lo que los tiempos que involucran serán en realidad superiores. Por lo
tanto, si la aplicación en curso requiere respuesta lenta (imaginemos una máquina
expendedora de refrescos) un microprocesador puede ser una buena solución,
mientras que si requiere elevada velocidad deberá recurrirse a otros medios.
Esto último sucede, por ejemplo, en telecomunicaciones o en multimedia,
campos en los que deben ejecutarse complejos algoritmos matemáticos en tiempo
real; como un microprocesador convencional no proporciona suficiente velocidad
para estos casos, se ha desarrollado un tipo especial de microprocesador de
elevadas prestaciones denominado procesador digital de señal (DSP) (a veces se
integra un módulo DSP junto con el µP de propósito general). Si aun así no se
obtiene la velocidad requerida, deberá construirse un circuito electrónico
296 Microprocesadores y microcontroladores

específico, mediante una FPGA o un ASIC, que al implementar en hardware las


operaciones más costosas permitirá su empleo en tiempo real.
En resumen (fig. 7.2), para cada problema, y en función del tamaño y
rendimiento requeridos, y del precio, existirá una solución óptima (o unas pocas).
Un microprocesador ofrece flexibilidad (programabilidad) y bajo coste, aunque
con un rendimiento limitado que, no obstante, resulta perfectamente válido para
innumerables aplicaciones (como muchas del campo de la electrónica industrial y
de consumo). Si se requiere un rendimiento superior (especialmente en cuanto a
operaciones matemáticas), un DSP puede ser la solución, aunque su coste resulta
en general más elevado. Si la funcionalidad a incorporar no es muy compleja, o
bien se precisa un rendimiento extraordinario, puede ser aconsejable el desarrollo
de un ASIC, aunque esta solución cuenta con las desventajas de su nula
flexibilidad, largo tiempo de desarrollo y puesta en el mercado, y elevado coste,
por lo que la realización de un ASIC solamente resulta rentable para la
comercialización de grandes series. A medio camino se encuentran los PLD
complejos, como las FPGA, una excelente solución cuando se precisa alto
rendimiento y flexibilidad, y para el desarrollo de prototipos o series pequeñas.
Por último, cuando el problema es tan complejo que resulta difícil de resolver
mediante circuitería electrónica, o simplemente se adapta muy poco a este tipo de
solución (por ejemplo, manejar una base de datos, visualizar datos o monitorizar
un sistema), suele hacerse uso de un recurso habitual que todavía no hemos
contemplado: un computador de propósito general (como un PC). La utilización
de un PC cuenta con la inmensa ventaja de su total generalidad, versatilidad y
amplia disponibilidad.

7.2.1. Microprocesadores y sistemas específicos


En general, se suelen usar microprocesadores en vez de sistemas basados en
lógica cableada, programable o ASIC, cuando en el sistema en desarrollo se dan
algunas de las siguientes circunstancias:
a) Debe incorporar un gran número de funciones distintas.
b) Posee una elevada cantidad de entradas y salidas.
c) Debe almacenar muchos datos en memoria.
d) Debe tomar decisiones en función de la historia del sistema.
e) Requiere la ejecución de numerosas operaciones lógicas y aritméticas.
f) Se precisa de un sistema flexible, que pueda modificarse fácilmente.
g) El ciclo de desarrollo-lanzamiento comercial debe ser corto.
Desarrollo de sistemas microprocesadores 297

Otros equipos, como los autómatas programables o PLC (Programmable


Logic Controller), o los ordenadores personales (PC), también comparten estas
características, pero es claro cuándo debe emplearse un dispositivo de este tipo y
cuándo un microprocesador (resulta difícil imaginar un PC o un autómata
programable controlando un airbag o un termostato).
En particular, resulta interesante saber que los autómatas programables o
PLC se basan en microcontroladores bien conocidos (8051, 68HC11...), que se
incorporan en un sistema robusto (tarjeta y carcasa), que pueda operar con
fiabilidad en un entorno tan hostil como es el industrial. Esto quiere decir que
cuando se trabajan con un autómata, en el fondo se está empleando un sistema
microprocesador que el fabricante proporciona hecho. El autómata programable
será mucho más caro que el sistema microprocesador que cada cual pueda realizar
para su aplicación, pero resultará más fácil de desarrollar y muy fiable en un
entorno industrial. Como siempre, la elección de uno u otro debe realizarse
evaluando todos los pros y contras. Por ejemplo, la automatización de una planta
industrial se realizaría mediante un conjunto de autómatas conectados en red a un
PC que gestiona, mientras que el control de un motor eléctrico puede efectuarse
con un microprocesador pequeño y barato.
Volviendo a los microprocesadores y microcontroladores, éstos son el núcleo
de los denominados sistemas de aplicación específica (fig. 7.1), que ya citamos en
la introducción, los cuales se encuentran totalmente integrados en la aplicación en
la que realizan tareas de control (por ejemplo, el sistema de frenado ABS, la
gestión de una máquina expendedora, el control de un motor, etc.), ejecutando
siempre un mismo programa de control. Una de las características importantes de
estos sistemas es que debe realizarse tanto un diseño del hardware como del
software, ambos a medida de la aplicación. En este sentido, determinadas tareas
podrán realizarse por circuitería o por programa; la elección de una u otra
dependerá de diversas circunstancias, como velocidad de operación, coste final,
tamaño del sistema, etc.
A su vez, y como ya se ha comentado, el diseño del hardware implica tanto el
desarrollo de circuitería digital (el propio sistema microprocesador) como
analógica (sensores, conversores A/D y D/A, actuadores) y de potencia
(alimentación, conmutación de potencia, etc.). De este modo, en el diseño de
sistemas específicos se requiere la cooperación de diversas disciplinas, pues
involucra el empleo de sensores, procesamiento analógico de la señal, conversión
A/D y D/A, diseño de los interfaces con el microprocesador, posible integración
en un ASIC o PLD, etc., además del desarrollo del software.
298 Microprocesadores y microcontroladores

FIGURA 7.3. Algunos campos de aplicación de los microprocesadores.

Estos sistemas de aplicación específica pueden ser clasificados en dos tipos


diferentes. El primero, en el que se emplean microcontroladores sencillos de 4
bits (como el µPD75XL de NEC) y 8 bits (6805 y 68HC11 de Motorola, 8051 de
Intel), son los controladores orientados a eventos (event controllers) [Cook 91],
empleados en tareas de control que no precisen de gran potencia de cálculo, como
máquinas expendedoras, electrodomésticos, etc. Estos pequeños controladores
llevan a cabo las tareas más «sucias», más «oscuras» y con menor reconocimiento
público (cuando uno pone en marcha el microondas o aprieta el freno del coche
no es consciente de que está enviando señales a un microcontrolador). Por lo
tanto, el ciudadano medio emplea a lo largo del día decenas de computadoras
(integradas en un chip) sin darse cuenta.
Un segundo tipo son los denominados sistemas empotrados o embebidos
(embedded systems) [Cook 91], que se basan en el empleo de microprocesadores o
microcontroladores de elevadas prestaciones, como son los de 32 bits. Ejemplos
de aplicaciones de este tipo son las aerospaciales (microprocesadores SPARC),
pilotos automáticos de avión (Motorola 68030, Zilog Z80000), impresoras Láser
(Intel i960, Motorola 68K y ColdFire), videojuegos (muchas máquinas recreativas
de los bares incluían un 68000), etc. Estos sistemas de altas prestaciones se
asemejan más a los computadores convencionales, disponiéndose para ellos de
sistemas operativos en tiempo real (real-time kernels), optimizados para tareas de
control en tiempo real, y que no requieren grandes cantidades de memoria.
Desarrollo de sistemas microprocesadores 299

Los microprocesadores o controladores de 16 bits (como el 80C196 de Intel,


o los 68HC12 y 68HC16 de Motorola) quedarían a mitad de camino de los de 8 y
32 bits, cubriendo el espectro de aplicaciones de nivel medio. Se emplean, por
ejemplo, en disqueteras y en el control de motores de automóviles.

7.2.2. Aplicaciones de los microprocesadores


Las aplicaciones de los µP son innumerables, aunque pueden dividirse en dos
grandes grupos: sistemas de cómputo y aplicaciones específicas. Aunque se
venden muchos más ejemplares para aplicaciones específicas (µC cuyo precio se
sitúa entre las 100 y las 2.000 ptas.), como los grandes microprocesadores para
computadores cuestan decenas de miles de pesetas por ejemplar, producen
mayores ingresos (de ahí el gran negocio de compañías como Intel).
En la tabla 7.1 se muestra una relación de aplicaciones típicas de los µP. De
entre ellas cabe subrayar el empleo de microcontroladores en el automóvil, que
está ocasionando una verdadera revolución desde los años ochenta. Se suele
señalar como origen la normativa de reducción de emisión de contaminantes
promulgada a principios de los años setenta en California, que obligó a
fabricantes como General Motors a introducir sistemas electrónicos (basados en
microprocesadores) que sincronizasen perfectamente la inyección y chispa en los
cilindros del motor. Un microcontrolador derivado del 6800 (el 6801) fue uno de
los primeros empleados para estas tareas.
La aplicación de microcontroladores en el hogar se considera en la actualidad
una nueva revolución en marcha, con aplicaciones como reguladores de
luminosidad, electrodomésticos de todo tipo, telefonía, audio y vídeo, calefacción
y aire acondicionado, alarmas y sistemas de seguridad, control de energía, etc. Ha
sido éste un nicho de mercado «descubierto» recientemente (hasta hace poco las
tres cuartas partes de los aparatos empleados en el hogar no incluían ningún tipo
de dispositivo semiconductor), el cual cuenta con unas posibilidades enormes,
debido a las ventas masivas de estos aparatos.
Para concluir esta sección, expondremos a modo de resumen final algunas de
las ventajas del uso de microprocesadores en el diseño de sistemas electrónicos:
a) Reducción del número de componentes, lo que conlleva la miniaturización del
sistema, reducción de consumo y aumento de la fiabilidad.
b) Programabilidad, que permite la simplificación del diseño y reducción del
tiempo de desarrollo y puesta en el mercado.
300 Microprocesadores y microcontroladores

c) Disminución de costes, causado por los aspectos descritos en los puntos a) y


b), y por la fabricación de series de muchas unidades de un mismo µP, el cual
podrá aplicarse a problemas diversos sin más que reprogramarlo.

7.3. Desarrollo de sistemas microprocesadores


En el desarrollo de sistemas microprocesadores intervienen aspectos
peculiares, que no aparecen en otros campos del diseño electrónico, como la
dicotomía desarrollo del hardware/desarrollo del software; es decir, por una
parte hay que desarrollar cierta circuitería, pero por otra se debe programar el µP.
Trataremos a continuación diversos aspectos relativos a ambas facetas.

7.3.1. Desarrollo del software


En primer lugar, trataremos algunos aspectos en relación al desarrollo del
software. Debido a que buena parte de la complejidad de la parte electrónica del
sistema reside en el propio microprocesador (o microcontrolador), el cual nos lo
da hecho el fabricante, el desarrollo del software suele ser la tarea que más tiempo
(y coste económico) ocupa en el desarrollo de un sistema basado en µP. El coste
del software se ha venido incrementando progresivamente año a año; así, según
un estudio reciente [Bursky 96], en 1980 el 25% del coste del desarrollo del
sistema se relacionaba con la parte software y el 75% con la hardware, mientras
que en la actualidad aproximadamente el 85% es del software y el 15% del
hardware. El motivo fundamental es que, debido al gran desarrollo de los
microcontroladores, en un único (y barato) chip se dispone ya de CPU, memoria,
temporizador, conversor A/D, UART, etc., con lo que la mayor parte del tiempo
la emplearemos en programar todo ello.

7.3.1.1. Programas en lazo abierto y en lazo cerrado


Distinguiremos entre dos tipos de programas, en lazo abierto y en lazo
cerrado. Un programa o rutina en lazo abierto (o de usuario) es aquel que tiene
principio y fin, es decir, que comienza en una instrucción y finaliza en otra. Un
ejemplo sería una rutina que multiplique dos números y muestre por pantalla el
resultado. La mayor parte de los programas que se ejecutan en un computador
son de este tipo, pues comienzan cuando se envía al sistema operativo el comando
de ejecución, y finalizan con una orden como quit o exit, devolviendo el control al
sistema operativo.
Desarrollo de sistemas microprocesadores 301

Consumo y hogar • Terminales puntos de venta Automóvil


• Lavadoras y lavavajillas • Cajeros automáticos • Tablero de mandos.
• Electrodomésticos en general • Sistema de frenado ABS
• Calefacción y refrigeración Comercio e industria • Inyección de gasolina
• Teléfonos y contestadores • Cajas registradoras • Airbag
• Telefonía móvil • Balanzas • Seguridad
• Televisión •Taxímetros
• Equipos y cámaras de vídeo • Parquímetros Intrumentación
• Cámaras fotográficas • Surtidores de gasolina • Intrumental de laboratorio
• Audio • Control de semáforos • Adquisición de datos
• Videojuegos • Maquinas expendedoras • Instrumentación inteligente
• Mandos a distancia • Máquinas recreativas • Medicina y bioingeniería
• Mandos de ascensores • Máquinas de votar • Meteorología
• Seguridad doméstica • Loterías automáticas
• Edificios inteligentes • Control de motores Cálculo y procesamiento
• Automatismos industriales • Computadores
Oficina y negocios • Robótica • Teclados
• Máquinas de escribir • Visión artificial y habla • Impresoras
• Fotocopiadoras • Inteligencia artificial • Periféricos
• Controladoras

TABLA 7.1. Diversas aplicaciones actuales de los microprocesadores.

Los programas o rutinas en lazo cerrado (o de control) no poseen final, sino


que se ejecutan una y otra vez, indefinidamente. Por ejemplo, el sistema
operativo MS-DOS puede considerarse un programa de este tipo. En los sistemas
específicos, construidos en torno a un microprocesador para llevar a cabo tareas
de control, los programas suelen ser en su mayoría de lazo cerrado. Por ejemplo,
el programa escrito en la ROM de un microcontrolador que gestiona el sistema de
frenado ABS comienza a operar cuando el microprocesador recibe la
alimentación, pero se ejecuta indefinidamente, pues su única tarea es controlar los
frenos, y solamente dejará de funcionar cuando el microprocesador deje de recibir
la alimentación.
Por lo tanto, los programas en lazo abierto son típicos de los ordenadores, los
cuales suelen guardarse en un sistema de almacenamiento masivo, como el disco
duro, cargándose en RAM solamente cuando deben ejecutarse. Los programas en
lazo cerrado son típicos de los sistemas específicos, almacenándose en memoria
no volátil (ROM, EPROM, EEPROM, flash), puesto que nada más conectar la
302 Microprocesadores y microcontroladores

alimentación el programa debe estar ya presente en memoria, listo para su


ejecución.

7.3.1.2. Software de sistemas específicos


Con esta perspectiva, profundizaremos en el desarrollo del software para un
microprocesador incorporado en un sistema de medida y control. Deberá tenerse
en cuenta que en este caso la ausencia de un sistema operativo (excepto el caso de
los pequeños sistemas operativos en tiempo real) hace que la aplicación deba
incorporar no sólo el programa principal y las subrutinas, sino que además deberá
gestionar los intercambios de datos con los periféricos, servir las posibles
interrupciones o manejar el estado de reset. Por ello, podemos dividir el código
completo del programa de un microcontrolador en los siguientes módulos:
a) Programa principal. Es el bucle principal mostrado en la fig. 7.5, que se
ejecuta una y otra vez, y desde el cual se llama a las distintas subrutinas. Suele
ser de muy reducido tamaño.
b) Subrutinas. Son conjuntos de instrucciones que ejecutan una determinada
tarea, que pueden ser llamadas desde distintos puntos del programa (por
ejemplo, rutinas de visualización en LCD, toma de datos, lectura de tabla,
cálculo del promedio, cambio de base numérica, lectura y decodificación de
teclado, etc.).
c) Rutina de RESET. Ejecutan el conjunto de acciones que el microprocesador
debe llevar a cabo cuando inicia su trabajo (establecimiento del valor del
puntero de pila, diagnóstico e inicialización de puertos, periféricos y quizás de
memoria, comprobar la configuración del sistema leyendo el estado de
microinterruptores, etc.).
d) Rutinas de servicio de las interrupciones. Son las distintas rutinas que se
ejecutan tras una determinada interrupción, que encierran el conjunto de las
acciones que deben emprenderse ante cada situación de interrupción (por
ejemplo, rutina de servicio del teclado, alarmas, desbordamiento en los
cálculos, etc.).
Desarrollado el código de los diversos módulos, y dependiendo de los
recursos de memoria integrados en el microcontrolador, se determinará a
continuación el lugar concreto del mapa de memoria que ocupará cada uno.
Habrá que añadir además las constantes del programa, tablas de datos, determinar
el lugar de la pila del sistema, etc. Si no hay suficiente memoria integrada, se
deberán añadir pastillas de memoria externas al microcontrolador.
Desarrollo de sistemas microprocesadores 303

Conexión
COMIENZO alimentación COMIENZO

INICIALIZAR RESET

Programa
monitor o :
sistema :
operativo : :
: :
:
:

FIN

A) B)

FIGURA 7.4. A) Software en lazo abierto (en RAM); B) en lazo cerrado (en ROM).

COMIENZO

Rutina RESET
RESET (inicialización) Rutina Servicio
Interrupción (i)
Principal
IRQ Rutina IRQ (i)

Programa
Principal :
: :
: RTI (retorno)
:
:

Rutinas de servicio de las distintas interrupciones

Rutina IRQ (1) Rutina IRQ (2) Rutina IRQ (i)


: : ............ : ............
: : :
RTI (retorno) RTI (retorno) RTI (retorno)

FIGURA 7.5. Software de un sistema microprocesador específico, y ejemplo de solicitud de


interrupción IRQ.

En el caso de los µP de la serie 68XX de Motorola, la memoria RAM


normalmente se encuentra en la parte baja de la memoria, y la no volátil en la alta.
Las variables de programa se guardarán en la RAM, preferiblemente en la página
cero (primeros 256 bytes), ya que permite trabajar en direccionamiento directo,
que ahorra tiempo de ejecución y espacio de programa; normalmente, los
304 Microprocesadores y microcontroladores

colocaremos a partir de la dirección $0000. La pila, que, recordemos, «crece


hacia abajo», suele colocarse en lo alto de la RAM, lo más alejada posible de las
variables o datos, para evitar sobreescribirlos.
El código del programa (principal, subrutinas, reset y rutinas de servicio) se
alojará en memoria no volátil. Cuando se fabrican grandes series (miles de
tarjetas), el programa puede ser grabado en ROM (normalmente integrada en el
microcontrolador), para lo cual simplemente debe suministrarse al fabricante el
fichero con el programa o datos a almacenar, para que éste confeccione las
máscaras de la ROM y nos suministre los circuitos integrados con la ROM
personalizada para nuestra aplicación particular.
En el caso del desarrollo de prototipos o pequeñas series, el programa suele
almacenarse en memoria EPROM. Muchos microcontroladores integran EPROM
en la propia pastilla; normalmente, un determinado tipo de microcontrolador
puede adquirirse en versión EPROM o ROM, y las versiones EPROM a su vez
pueden incluir ventana para su borrado con radiación ultravioleta, o no poseerla.
En el primer caso se habla de versiones con ventana, resultando mucho más caras
(un µC de unas mil pesetas probablemente valdría más de cinco mil si incorpora
ventana), pero muy útiles a la hora de desarrollar prototipos. Los µC con
EPROM pero sin ventana no son reprogramables, por lo que suelen denominarse
microcontroladores OTP (One Time Programmable), o programables una sola
vez.
Algunos microcontroladores integran también memoria EEPROM (que puede
ser escrita y borrada eléctricamente); precisamente, el 68HC11 fue el primer
microcontrolador que integró EPROM y EEPROM en el mismo integrado.
Debido a que tanto la celda básica de EEPROM como la de RAM ocupan mucho
más espacio que la de EPROM (o ROM), los microcontroladores suelen integrar
una limitada cantidad de RAM y EEPROM, y notables cantidades de EPROM (o
ROM). Por ejemplo, el 68HC11E9 incluye 512 bytes de RAM, 512 bytes de
EEPROM y 12 KB de ROM; su variante 68HC711E9 sustituye los 12 KB de
ROM por 12 KB de EPROM.
Aunque la principal utilidad de la EEPROM integrada es el almacenamiento
de tablas de calibración y la salvaguarda del valor de importantes parámetros ante
una inminente caída de la alimentación del sistema, en el caso de algunos
microcontroladores la EEPROM puede albergar también programa. Éste es el
caso del 68HC11, cuya EEPROM integrada además puede grabarse desde un
ordenador PC de una forma muy sencilla haciendo uso del modo de operación del
HC11 denominado autoarranque (bootstrap) [Motorola 88, Martín del Brío 97], lo
que resulta muy útil para el desarrollo de prototipos (se recomienda consultar el
Desarrollo de sistemas microprocesadores 305

apéndice que hace referencia al denominado «Kit del 68HC11», al final del libro).
El 68HC811E2 es la versión que más EEPROM incluye, 2 KB, permitiendo
almacenar un programa de tamaño respetable.
En la actualidad existe una evidente tendencia en el sentido de integrar en
microcontroladores el nuevo tipo de memoria denominada flash. Recordemos
que la memoria flash, como la EEPROM, puede escribirse y borrarse
eléctricamente, con la salvedad de que no puede hacerse byte a byte, sino por
bloques, aunque la memoria flash cuenta con la enorme ventaja de basarse en una
celda mucho más simple que la EEPROM, permitiendo así integrar grandes
cantidades. Los microcontroladores de las familias más modernas, como la
68HC08 (evolución del 68HC05) y la 68HC12 (evolución del 68HC11) integran
ya memoria flash; lo mismo sucede con algunas versiones del 68HC16 (el
68HC916X1 integra 50 KB de memoria flash).
Al parecer, poco a poco se tenderá a sustituir la memoria EPROM por flash,
ya que, contando con densidades de almacenamiento similares, la flash puede ser
reprogramada sin necesidad de incorporar ventana en el encapsulado, permitiendo
además el borrado y re-programación del dispositivo sin necesidad de retirarlo de
la placa donde se encuentre (ello permitiría llevar a cabo actualizaciones del
software, depurar errores, etc., lo cual podría hacerse a distancia, sin más que
mantener el microcontrolador de una aplicación conectado a una red de datos).

7.3.1.3. Una estructura de programa de control: el bucle


secuenciado
En un sistema de control el núcleo procesador debe atender diversas tareas.
Por ejemplo, en un termostato inteligente deberá gestionar sus teclas (que indican
órdenes al termostato, temperatura objetivo, etc.), la pantalla LCD (que muestra la
temperatura actual, la deseada, etc.), realizar indicaciones luminosas o sonoras
(p.e., mal funcionamiento o temperatura sospechosamente elevada), leer el estado
del sensor de temperatura y realizar la propia labor de control (activar el sistema
de calefacción o de refrigeración). Cada una de estas tareas suele tener asignada
una rutina, de modo que el bucle principal del sistema debe llamar a las distintas
subrutinas cuando corresponda, con cierta periodicidad.
Muchas aplicaciones específicas responden a la idea general del ejemplo del
termostato descrito; una forma genérica de abordar todo este tipo de aplicaciones
se describe en [Motorola 95, Sibigtroth 95]. A grandes rasgos, la solución
propuesta consiste en implementar un pequeño programa principal, compuesto
por un bucle cerrado que se ejecuta cada cierto tiempo, denominado tiempo de
ciclo; su comienzo de ejecución viene marcado por la activación de cierto
306 Microprocesadores y microcontroladores

temporizador (como los que integran la mayor parte de los microcontroladores).


Cada vez que se active dicho temporizador se ejecutarán secuencialmente las
tareas que sean precisas (p.e., y en este orden: gestión del teclado, lectura del
sensor de temperatura, visualización en el LCD, emisión de alarma si procede,
actuación sobre la refrigeración o calefacción si procede). Ejecutadas todas, el
sistema quedará en espera de que el temporizador marque el comienzo de un
nuevo ciclo. En este caso, el tiempo de ciclo podría ser simplemente de 50
milisegundos, puesto que en un termostato no se requiere de una elevada
«velocidad de reacción»; el requisito más importante será que el tiempo de ciclo
sea superior a la suma de los tiempos de ejecución de todas las rutinas que pueden
ejecutarse en un solo ciclo.

7.3.1.4. Lenguajes de programación


El último aspecto del desarrollo del software que vamos a abordar es el de los
lenguajes de programación. Así como un computador se programa habitualmente
en lenguajes de alto nivel (C, BASIC, Pascal, FORTRAN, COBOL, etc.), los
microprocesadores incorporados en sistemas electrónicos tradicionalmente venían
programándose en lenguaje ensamblador.
El problema del lenguaje ensamblador es que al estar más próximo a la
máquina resulta muy diferente de la forma de pensar del ser humano, siendo las
instrucciones muy elementales, de manera que la confección de un programa de
mediana longitud se convierte en una tarea larga y tediosa. Además, un programa
escrito en ensamblador resulta de difícil lectura y sujeto a errores difíciles de
detectar y corregir.
Además, cada microprocesador o familia posee su conjunto de instrucciones
específico, con lo que los programas en ensamblador no resultan portables de un
microprocesador a otro, en general. Por ello, si se desea que la tarea que viene
ejecutando determinado microprocesador la realice otro de diferente tipo, el
software previamente desarrollado no podrá aprovecharse tal cual, sino que
deberá ser re-escrito, con la consiguiente pérdida de tiempo. Ello supone también
que las empresas que desarrollan software para un determinado tipo de
microprocesador se ven atadas a la hora de trabajar con un microprocesador
diferente (por ejemplo, uno más moderno, de mayores prestaciones o precio
inferior).
Una posible solución a los inconvenientes del lenguaje ensamblador consiste
en programar los microprocesadores para aplicaciones específicas también
mediante lenguajes de alto nivel (como los computadores). Ello es factible en el
caso de microprocesadores o microcontroladores potentes, como son algunos de 8
Desarrollo de sistemas microprocesadores 307

bits (no todos), o los de 16 y 32 bits, pero puede no resultar viable en el caso de
los menos potentes de 8 bits o de 4 bits, debido a que los recursos limitados que
poseen (pequeño número de registros, tamaño de pila y capacidad de memoria
reducidos) pueden no ser idóneos para el empleo de lenguajes de alto nivel.
Aunque hace ya algunos años se desarrollaron compiladores de Pascal o
BASIC para microprocesadores de 8 bits, realmente el empleo de lenguajes de
alto nivel para microprocesadores y microcontroladores pequeños se ha extendido
solamente desde hace unos cuantos años, sobre todo el del lenguaje C. Una de las
razones quizás sea que C se ha convertido casi en un estándar de los lenguajes de
programación (es sin duda el lenguaje más empleado en todo el mundo), y C
cuenta con la particularidad de poseer instrucciones más próximas a lo que sería
un lenguaje ensamblador típico que el resto de los lenguajes de alto nivel (de
hecho, se suele afirmar que C es un lenguaje de nivel intermedio).
Son fundamentalmente tres las ventajas de programar un microcontrolador de
8 bits (como el 6805, 68HC11 u 8051) en lenguaje C [Gray 95]:
a) Ahorro en tiempo de programación. Un lenguaje de alto nivel resulta más
próximo a la manera de pensar del programador.
b) Portabilidad del código generado. Si se desarrolla una aplicación para un
68HC11 y posteriormente se decide emplear un 8051, buena parte del código
escrito en C sería aprovechable.
c) Mantenimiento del código. El código desarrollado en C será más fácil de leer
y mantener (en el sentido de introducir mejoras o modificaciones en el futuro),
al resultar mucho más legible que el ensamblador.
Por otro lado, las desventajas del empleo de un lenguaje de alto nivel como
es C para la programación de microcontroladores de tipo medio y bajo son las
siguientes:
a) El código generado tiende a ser más extenso que el desarrollado en
ensamblador (una instrucción C equivale a varias ensamblador).
b) Será más lento (debido al punto a) ).
c) Necesita más memoria ROM para guardar el programa (debido al punto a) ).
d) Necesita mucha más memoria RAM, debido al amplio uso de la pila que C (y
otros lenguajes de programación) realiza.
308 Microprocesadores y microcontroladores

Probablemente, la forma óptima de trabajar consista en conjugar las ventajas


del C con las del ensamblador; por ello, los compiladores de C permiten insertar
instrucciones de ensamblador en el propio código fuente C, con lo que puede
emplearse C y ensamblador allí donde cada uno resulte más interesante. Así, la
tendencia actual parece dirigirse hacia la programación del microprocesador en
lenguaje C, pero reservando las rutinas críticas al lenguaje ensamblador. En la
actualidad, la mayor parte de los microcontroladores disponen de compiladores de
lenguaje C, incluyendo los más sencillos de cuatro bits.
No obstante, debe tenerse muy presente que la posibilidad de programar un
microcontrolador en C no quiere decir que el aprendizaje del lenguaje
ensamblador sea una pérdida de tiempo. Todo diseñador de sistemas
microprocesadores, aunque trabaje en lenguaje C, debe dominar la programación
en ensamblador, pues es la forma de comprender cómo opera a un nivel más bajo
el microprocesador y saber qué es lo está haciendo en cada momento.
Conociendo bien el lenguaje ensamblador, y cómo cada instrucción de C se
traduce a instrucciones ensamblador, se conseguirán sin duda desarrollos mucho
más óptimos que si se programa «a ciegas».

7.3.2. Desarrollo del hardware


El otro gran aspecto del desarrollo de sistemas microprocesadores es el
relativo al hardware. Normalmente, el fabricante de un determinado
microprocesador indica en sus hojas de características o notas de aplicación la
forma de construir sistemas basados en él, y proporciona una serie de circuitos de
apoyo a la construcción de sistemas, diseñados para que su conexión al
microprocesador por él fabricado resulte muy sencilla. Por ejemplo, en el caso de
la familia 68XX de Motorola, el fabricante proporciona la PIA 6821, el ACIA
6850, chips de memoria (6810, RAM 128B; 6830, ROM 1KB; 68708, 1KB
EPROM), circuitos de reloj (6870, 6871A y 6871B) y buffers triestado, por citar
tan sólo unos cuantos circuitos de apoyo.
Es importante tener presente que el diseño del hardware queda fuertemente
condicionado por el microprocesador concreto elegido para la aplicación, por lo
que resulta fundamental realizar la elección correcta. De entre los diversos tipos
de microprocesadores disponibles (que expondremos más adelante) suelen ser los
microcontroladores, y de entre ellos los de ocho bits, los más útiles para las
aplicaciones relacionadas con la electrónica industrial. La ventaja del empleo de
un microcontrolador es clara: se trata de todo un sistema microcomputador
integrado en una única pastilla, con lo que si se elige el microcontrolador más
adecuado para realizar el sistema se necesitará poco hardware adicional. Cuantos
más elementos de los que requiere la aplicación estén integrados en el propio chip
Desarrollo de sistemas microprocesadores 309

menos se deberán colocar en la tarjeta, y el sistema resultante será más fiable, de


tamaño más reducido, más barato y de menor consumo.
En este sentido, debe recordarse que en un microcontrolador podemos
encontrarnos integrados en la misma pastilla, junto al núcleo procesador (CPU),
memoria volátil y no volátil, puertos de entrada salida, UART, circuitos de reloj,
conversores, contadores y temporizadores, etc. Algunos pueden contener incluso
buffers para alimentar directamente diodos LED o drivers de visualizadores LCD.
De este modo, un sistema microprocesador basado en un microcontrolador podría
requerir tan sólo de un cristal de cuarzo (o un resonador cerámico, más barato),
resistencias terminadoras de pines, condensadores para filtrado de alimentación o
generación de las fases del reloj, y los propios periféricos.
Como ya se ha comentado con anterioridad, algunas funciones del sistema
pueden realizarse por software o por hardware, cada opción con sus ventajas e
inconvenientes. La elección de uno u otro dependerá de la aplicación concreta.
Esto quiere decir que determinadas funciones que habitualmente se reservan al
hardware pueden realizarse también por software.
Un ejemplo muy claro es el filtrado de los rebotes de pulsadores, que se
expuso en la sección 6.4.3. Éste puede realizarse por hardware, haciendo uso de
biestables, inversores schmitt-trigger, o circuitos específicos de filtrado de
rebotes; o bien software, demorando unos 10 milisegundos la respuesta al
pulsador, dejando así pasar los rebotes. Obviamente, la solución software es más
lenta, pero mucho más barata. Emplear una u otra dependerá de la aplicación
concreta: velocidad de respuesta requerida, nivel de ocupación del
microprocesador y número de pulsadores a filtrar (p.e., los teclados, al incluir un
elevado número de pulsadores, suelen filtrarse por software).
Otro ejemplo típico es el de la comunicación serie asíncrona, como la RS-
232. Los microcontroladores de prestaciones medias y altas integran un bloque
UART (como el SCI del 68HC11) que permite establecer comunicaciones serie
asíncronas con dispositivos lejanos. Sin embargo, los de menores prestaciones
pueden no integrar bloques UART, con lo que si precisan comunicarse en serie
debería colocarse un chip UART externo (como el ACIA 6850), el cual,
paradójicamente, puede resultar más caro que el propio microcontrolador. Una
opción mucho más barata es implementar en software la función de la UART,
haciendo uso de líneas de puertos convencionales como si fuesen las líneas serie
RxD y TxD. Esta implementación de la función de una UART por programa es
una solución bastante habitual en el caso de los microcontroladores de precio y
prestaciones reducidos (en algunos microcontroladores sencillos, como el 6805, el
propio fabricante proporciona un programa-ejemplo ya hecho, que se puede
encontrar en su página web).
310 Microprocesadores y microcontroladores

En resumen, en el desarrollo de sistemas microprocesadores en general, y en


la decisión sobre si determinada función debe implementarse en hardware o en
software en particular, siempre deberá atenderse a la relación prestaciones/precio
óptima.

7.3.3. Fases en el desarrollo de un sistema microprocesador


Establecidas las dos facetas del desarrollo, la hardware y la software, y
subrayada la estrecha relación existente entre ambas, vamos a exponer los pasos
típicos del desarrollo de un sistema microprocesador. Normalmente se aconseja
un estilo de diseño de tipo modular, también llamado descendente, que comienza
con la propuesta de una solución global (de alto nivel), compuesta por un
conjunto de grandes bloques funcionales (CPU, memoria, sistema de E/S, etc.),
para proseguir con la definición del contenido de estos bloques y su
materialización concreta, en hardware y/o en software (circuitos integrados que
componen los bloques funcionales, y su programación, si procede).
Las fases en el desarrollo de un prototipo comprenden la propuesta de una
solución basada en grandes bloques funcionales, el desarrollo del hardware y del
software (el contenido de los grandes bloques), la depuración del sistema
completo y la confección del prototipo final. Más detalladamente, los pasos que
habitualmente se siguen son los siguientes:
1. Especificación de las funciones del sistema.
2. Diseño del esquema de grandes bloques del hardware y del software.
Establecer qué se materializa en hardware y qué se materializa en software.
3. Diseño de bloques del hardware: CPU, memoria, E/S, periféricos.
4. Diseño detallado del hardware (circuitos integrados, PLD, etc.).
5. Depuración del hardware.
6. Diseño de los módulos del software (dilema: ¿empleo de C, ensamblador o
ambos?).
7. Realización detallada del software: programación.
8. Simulación y depuración del programa.
9. Integración del hardware y del software.
10. Depuración global. Posibles modificaciones al hardware y/o software.
11. Grabación del software en EPROM y/o EEPROM.
12. Construcción del prototipo final, pruebas finales, circuito impreso, etc.
Desarrollo de sistemas microprocesadores 311

Obsérvese que, aunque los pasos se han enumerado secuencialmente, el


desarrollo del hardware (pasos 3-5) y el del software (6-8) puede realizarse en
paralelo (fig. 7.6), incluso por personas distintas.

Especificaciones sistema global

Diseño de grandes bloques

Funciones en hardware Funciones en software


(grandes bloques) (módulos)

Diseño detallado del Realización detallada del


hardware software (programación)

Depuración del hardware Simulación y depuración


del software

Integración hard/soft

Depuración global

Programación EPROM/EEPROM

Prototipo final

FIGURA 7.6. Fases del desarrollo de una aplicación basada en microprocesadores.


312 Microprocesadores y microcontroladores

Por último, indicaremos que la construcción de un prototipo puede uno


apoyarse en las denominadas tarjetas de aplicación (o de evaluación) que las casas
comercializan. Éstas consisten en una placa que incluye un sistema mínimo
basado en determinado microprocesador, que normalmente posee una zona libre
que permite la conexión de la circuitería propia de la aplicación haciendo uso de
la técnica de arrollar cables (wire-wrapping). El empleo de estas tarjetas de
evaluación simplifica enormemente el aprendizaje de las características un nuevo
modelo de µP, o el desarrollo de un prototipo.
Normalmente, cada casa comercializa tarjetas de aplicación de sus
microprocesadores a precios relativamente asequibles (depende de cada caso y
cada casa). Un ejemplo es la tarjeta MC68HC11EVBU (EVBU son las siglas de
EVluation Board Universal) de Motorola, sistema mínimo basado en un
MC68HC11E9 que, a un precio moderado (menos de 30.000 ptas.), incluye
además software, libros de datos y notas de aplicación. Otro ejemplo son las
placas de evaluación del 68HC12 denominadas M68HC912BC32 (con memoria
flash) y M68HC12A4EVB (con ROM), o el kit del 68HC05 de referencia
M68HC705JICS, todas ellas de bajo coste.

7.4. Herramientas de desarrollo


Son muy variadas las herramientas que pueden ayudar en el desarrollo de
sistemas microprocesadores. En un caso extremo, puede construirse un sistema
de este tipo con la única ayuda de un compilador de ensamblador, un
programador de EPROM, y depurarlo con un polímetro u osciloscopio. En un
caso más extremo, incluso el microcontrolador puede incluir en su ROM
integrada un programa monitor, con capacidad de compilar programas y
programar EPROM o EEPROM, en cuyo caso ni siquiera se necesitaría el
compilador de ensamblador ni el programador de EPROM (tal es el caso del
MC68HC11E9, con monitor Buffalo integrado, base de la tarjeta
MC68HC11EVBU).
No obstante, el empleo de las numerosas herramientas disponibles para el
desarrollo de sistemas ahorrará mucho tiempo y «sufrimiento». Un conjunto
mínimo de tales herramientas suele denominarse sistema de desarrollo, aunque
esta denominación resulta un tanto confusa, pues se aplica a sistemas de
características muy diferentes. En general, un buen sistema de desarrollo debe
permitir probar y depurar el software, comprobar el sistema global (hardware más
software) con los periféricos conectados y operando en tiempo real (a la
frecuencia de reloj a la que finalmente operará el sistema), así como grabar las
memorias no volátiles que albergarán el programa. El requisito de operación en
Desarrollo de sistemas microprocesadores 313

tiempo real para un sistema de desarrollo es importante (y caro), ya que la


operación correcta de un microprocesador ejecutando paso a paso o a baja
frecuencia determinado programa no garantiza su correcto funcionamiento a la
frecuencia final de la tarjeta.
Hasta hace algunos años estaba extendido el uso de sistemas de desarrollo
autónomos, que disponían de su propio teclado y pantalla CRT, memoria,
sistemas de almacenamiento masivo, etc. En la actualidad, debido a la amplia
disponibilidad de ordenadores personales, la mayor parte de los sistemas de
desarrollo se construyen alrededor de un PC convencional.
Para exponer las características de las distintas herramientas para desarrollo
de sistemas microprocesadores, distinguiremos entre las software y las hardware.

7.4.1. Herramientas software


• Ensambladores. Convierten un fichero escrito en lenguaje ensamblador en
código máquina. Se habla de un ensamblador cruzado (cross assembler)
cuando el compilador de ensamblador se ejecuta en un microprocesador
diferente de aquel para el que se genera el código máquina (por ejemplo,
AS11, compilador del 68HC11 que se ejecuta sobre un x86). Se dice que un
ensamblador es macroensamblador cuando permite el trabajo con las
denominadas macroinstrucciones. Un ensamblador absoluto (como AS11)
genera directamente código ejecutable, mientras que un ensamblador
reubicable genera código independiente de la dirección, la cual debe ser
asignada a continuación por un programa montador linker (sección 4.6).
• Montador (linker). Programa que enlaza (une) subrutinas compiladas con un
ensamblador reubicable y asigna sus direcciones de memoria, generando el
código final ejecutable.
• Compiladores de alto nivel. Compiladores para programas escritos en
lenguajes de alto nivel. En el desarrollo de sistemas microprocesadores
empieza a ser casi inevitable el empleo del lenguaje C.
• Simuladores. Programas que se ejecutan en un ordenador convencional y que
simulan la operación de cierto microprocesador, permitiendo la ejecución
controlada de un programa, visualización del estado de sus registros y de la
memoria, modificación de su contenido, etc. Entre otras funciones incorporan
la posibilidad de ejecución paso a paso (es decir, instrucción a instrucción) e
inserción de puntos de ruptura (lugares del programa donde debe detener su
ejecución para permitir la visualización del estado del microprocesador). Se
emplean para comprobar y depurar la operación del software. En ocasiones se
314 Microprocesadores y microcontroladores

denominan también depuradores (debugger), aunque preferimos reservar este


término para el caso de la depuración de código para el mismo
microprocesador sobre el que estamos trabajando (por ejemplo, depurar un
programa ensamblador para 80486 en un PC basado en un 80486).

7.4.2. Herramientas hardware


• Tarjetas de aplicación (o evaluación). Son tarjetas de propósito general,
normalmente constituyendo un sistema mínimo de determinado
microprocesador, y que permiten el aprendizaje rápido de sus características,
así como el desarrollo de prototipos empleando la misma tarjeta (suelen
reservar una zona de la tarjeta para el montaje de circuitos). Normalmente, el
programa que debe ejecutar la placa se ha compilado (y quizás simulado) en
un PC, y desde él se carga en la memoria de la tarjeta.
• Programador de EPROM. Es una herramienta de suma utilidad, pues nos
permitirá almacenar el programa desarrollado en una EPROM, para ser
ejecutado por el µP. Los denominados programadores universales permiten
también grabar la EPROM integrada de diversos microcontroladores (para lo
cual normalmente hay que incorporar en el programador algún accesorio que
se adquiere aparte). Se emplean desde un ordenador convencional, al que
están conectados, y en el cual se compila el programa.
• Tarjetas programadoras. Algunas casas comercializan tarjetas de bajo coste,
que se conectan al puerto RS-232 del ordenador, permitiendo la programación
de la EPROM de un tipo de microcontrolador.
• Emulador en circuito. Es una de las herramientas más útiles, pero también
más caras. Se trata de un complejo sistema electrónico que emula en tiempo
real la operación del microprocesador (o microcontrolador) y de su memoria,
permitiendo la ejecución del programa paso a paso, o con puntos de ruptura.
El emulador en circuito se construye alrededor de una versión del
microprocesador que se desea emular (a menudo de la misma familia, pero de
gama alta); en ocasiones se construye en forma de placa conectable al bus
interno del PC, en otras es un equipo externo al PC (caja). El emulador, como
su nombre indica, no simula sino que emula, es decir, realiza las mismas
acciones hardware que realizaría el microprocesador que está siendo emulado,
pero siempre bajo el estricto control del ingeniero que desarrolla el sistema.
Para tal fin, el emulador incluye un cable con un conector (pod) que coincide
pin a pin con el microprocesador emulado, proporcionando en cada línea las
señales que el propio microprocesador generaría al ejecutar el programa en
desarrollo, y recibiendo las mismas señales que él recibiría. Este conector se
Desarrollo de sistemas microprocesadores 315

introduce en el zócalo de la tarjeta en desarrollo destinado al propio µP (fig.


7.7), de manera que el emulador en circuito actúa sobre la tarjeta y los
periféricos como lo haría el propio µP emulado, sólo que su acción es
controlada en todo momento por el diseñador desde el ordenador, pudiendo en
cualquier instante detener su operación para poder observar el estado del
sistema (registros, memoria, etc.). Gracias a un emulador en circuito se tiene
un control total sobre la tarjeta y el programa en desarrollo, permitiendo la
comprobación y depuración de ambos, teniendo en cuenta además que se está
operando en tiempo real, es decir, a la misma velocidad que trabajará el
microprocesador final (cosa que nunca sucede con un simulador).
• Analizador lógico. La idea de partida es la misma que la de un osciloscopio,
representar en una pantalla señales, sólo que en este caso se trata de señales
digitales procedentes de los buses del sistema o de cualquier punto de la tarjeta
en desarrollo. El analizador lógico permite registrar y visualizar numerosas
líneas a la vez (16, 32...), para poder observar retrasos, eventos de interés, etc.,
todo ello en tiempo real, pues las señales se almacenan en memoria tal y como
van llegando al analizador, pudiéndolas estudiar detenidamente con
posterioridad.

FIGURA 7.7. Sistema de desarrollo basado en emulación en circuito. El emulador representado es


del tipo conectable a los buses internos del PC.
316 Microprocesadores y microcontroladores

• Otras herramientas: sondas lógicas (puntas de prueba), analizadores de


firmas, etc.
En resumen, un buen sistema de desarrollo debe permitir la depuración del
hardware, la emulación en tiempo real y la grabación de memorias; por ello,
debería contar por lo menos con compilador, emulador en circuito y programador,
manejado todo ello desde un computador. El precio de un sistema de este tipo
depende del tipo de microprocesador (resulta más caro cuanto más potente sea
éste), de la casa que lo fabrica y comercializa, etc.; no obstante, suele ser de
varios cientos de miles de pesetas (ordenador aparte).
Debido al elevado coste de un sistema de desarrollo con emulación en
circuito, con frecuencia se trabaja con medios mucho más modestos, por ejemplo,
con un compilador, un simulador y un programador de EPROM... y aplicando
grandes dosis de ingenio (y de paciencia). Finalmente, indicaremos que las
tarjetas de evaluación suelen ser una excelente opción como «sistema de
desarrollo para pobres».

7.5. Familias de microprocesadores de aplicación industrial


Los tipos de microprocesadores disponibles pueden agruparse en unas
cuantas clases genéricas (de propósito general, microcontroladores y DSP); sin
embargo, cada gran fabricante de semiconductores dispone de diversas familias,
constituidas a su vez por numerosos miembros, por lo que la oferta de
microprocesadores disponible en el mercado es extraordinariamente extensa
(ampliándose además día a día). Enumeramos a continuación unos cuantos
fabricantes de microprocesadores muy conocidos: Intel, Motorola, Zilog, Texas
Instruments, Philips, Digital (DEC), Matra-Harris, SGS-Thomson, Siemens,
Hitachi, Toshiba, NEC, Fujitsu, OKI, Samsung, Sharp, Arizona Microchip,
National Semiconductors, Dallas Semiconductors, IBM, Hewlett-Packard, Analog
Devices, Rockwell, Inmos, AMD, Seiko, Misubishi, Matsushita...
En el siguiente capítulo trataremos más ampliamente las diversas clases de
microprocesadores disponibles, mientras que en este punto solamente nos
interesará resaltar los de mayor interés en las aplicaciones industriales:
a) Microprocesadores de propósito general. O simplemente microprocesadores,
como los clásicos 8080, Z80, 6800, 6502, 8085, 8086, 68000, familia 68K,
familia x86, etc. Los más antiguos incorporan exclusivamente el núcleo
procesador (CPU), mientras que los más modernos y potentes (80486,
Pentium, PowerPC) integran en la misma pastilla memoria caché,
Desarrollo de sistemas microprocesadores 317

coprocesador matemático, controlador de DMA, etc. Los más potentes se


destinan a la realización de sistemas de computación, en tanto que algunos de
los clásicos, como el Z80, el 6502 o el 8086, todavía se emplean en tareas de
control (en algunas ocasiones aparecen como núcleo procesador integrado en
microcontroladores o en ASIC).
b) Microcontroladores, o computadores en un solo chip. Son los µP más
claramente orientados a la electrónica industrial y de consumo, especializados
en el desarrollo de sistemas específicos de control y medida. Se basan en un
núcleo procesador, junto al cual se integra memoria, puertos de E/S y
periféricos (conversores, drivers de visualizadores, etc.). Los más extendidos
son los de 4 y 8 bits (especialmente éstos últimos), muchos de los cuales se
construyen alrededor de un núcleo procesador derivado de un µP clásico,
como el 6800, Z80, etc.
c) DSP o procesadores digitales de señal (Digital Signal Processors). Se trata de
µP orientados al campo del procesamiento de señal, multimedia y
telecomunicaciones (p.e., telefonía móvil), en los cuales deben procesarse
señales digitales mediante algoritmos matemáticos que involucran la
realización de numerosos cálculos (transformada de Fourier, cancelación de
ecos, filtros por programa, compresión de señal, encriptado, etc.). Por ello, los
DSP se diseñan para que puedan ejecutar de forma muy rápida ciertas
operaciones matemáticas (en punto fijo o flotante), incorporando para ello
numerosos registros, operaciones en alta precisión, multiplicador hardware,
registros de desplazamiento especiales, etc. Normalmente no son máquinas
von Neumann, sino basadas en una variante denominada arquitectura Harvard,
en la que coexisten dos espacios de memoria separados, para datos e
instrucciones, cada uno con su propio bus diferenciado. Los DSP se
estudiarán más ampliamente en el próximo capítulo.
Para que el lector se haga una idea de los precios que en la actualidad se
manejan, podemos decir que un microcontrolador típico de 4 bits en versión OTP
(EPROM sin ventana) puede costar en torno a cien pesetas, mientras que uno de 8
bits de gama baja no suele alcanzar las quinientas, llegando a las mil pesetas si es
de gama media, y entre mil y unas 2.000 ptas. si es de gama alta (precio ya
cercano al de los microcontroladores de 16 bits). Obviamente, estos precios se
ofrecen solamente a título ilustrativo; en realidad, el precio de un
microcontrolador depende en gran medida de la versión concreta que se elige, de
si es una versión ROM, OTP o con ventana, y del número de ejemplares que se
adquieren: un microcontrolador que en versión OTP cuesta 250 pesetas puede
valer 3.000 si se compra con ventana, mientras que si se adquieren miles o
318 Microprocesadores y microcontroladores

decenas de miles de ellos en versión ROM el precio puede descender hacia las
cien pesetas.
El precio de los DSP resulta también muy variado, aunque, en general, es
bastante más elevado que el de los microcontroladores. Los de gama más alta
superan las 20.000 ptas., pero los más modestos vienen a costar por debajo de
10.000. Últimamente ha descendido de forma importante el precio de ciertos DSP
de bajas prestaciones (16 bits y punto fijo) cuando se adquieren en grandes
cantidades (Texas y Analog Devices venden los más sencillos por unas 1.000
ptas. si se adquieren 100.000 ejemplares), por lo que se están empezando a utilizar
DSP en aplicaciones antes totalmente vedadas, como las relacionadas con
productos de consumo e industriales (por ejemplo, el control de motores eléctricos
mediante complejos algoritmos matemáticos).
Por último, el precio de los potentes microprocesadores empleados en
aplicaciones de computación resulta obviamente bastante más elevado que el de
los anteriormente expuestos: varias decenas de miles de pesetas para los más
modestos, y superando ampliamente la barrera de las 100.000 ptas. para el caso de
los más modernos y potentes.
En la tabla 3.2 (capítulo 3), se mostraba la posición de cada compañía en el
mercado en cuento a número de microcontroladores vendidos en los últimos años.
La conclusión que extraíamos era que así como Intel es líder indiscutible de
ventas de microprocesadores, Motorola lo es de microcontroladores (y con gran
diferencia respecto de sus competidores). Ya desde mitad de los años setenta
Motorola se distinguió por sus contratos con grandes empresas (como las
automovilísticas), a las que suministra millones de ejemplares de µC cada año.
En resumen, en cada aplicación debe seleccionarse el µP que más se ajuste
por sus características y precio. La ventaja del microcontrolador sobre el
microprocesador en aplicaciones específicas es clara: reducido tamaño del
sistema resultante, menor consumo y precio, mayor fiabilidad y menor tiempo de
diseño. El DSP, destinado en origen al campo de las telecomunicaciones y
multimedia, coincidiendo con la bajada de precios de las versiones más sencillas
ha comenzado a emplearse ya en aplicaciones de consumo e industriales.

7.5.1. Microcontroladores de aplicación industrial


Centrándonos en el mundo de los microcontroladores, la distinción
fundamental reside en el número de bits, y los periféricos y memoria integrados.
En cuanto al número de bits, se tienen µC de 4, 8, 16 y 32 bits. Aunque a primera
vista, debido a la potencia de los de 16 y 32 bits parecen más atractivos, sin duda
alguna los más empleados en la industria siguen siendo los de 4 y 8 bits, debido a
Desarrollo de sistemas microprocesadores 319

la relación prestaciones/precio que ofrecen. Así, según la prestigiosa revista


americana Electronic Design, el 80% de los µC vendidos en la actualidad son de 4
y 8 bits (con precios en la compra de grandes volúmenes desde menos de un dólar
a unos pocos dólares). De una encuesta realizada por la misma revista entre
desarrolladores de sistemas [Bursky 96], se deduce que en la actualidad en el 45%
de los diseños modernos todavía se emplean µC de 8 bits, y se están empezando a
emplear ya los de 64 bits (por ejemplo, en videojuegos).
El tamaño de los microcontroladores más sencillos es muy reducido, muchos
se fabrican en encapsulados de 14 a 20 patillas (el diminuto PIC 12CXXX posee
únicamente 8 pines). Si a ello unimos el bajo consumo (NEC ha introducido un
microcontrolador alimentado a 1,8 V, y Seiko otro a tan sólo 0,9 V) y las ventajas
asociadas a su reprogramabilidad, entenderemos porqué en nuestros hogares
podemos tener hoy en día entre 20 y 40 microcontroladores distribuidos en
diferentes aparatos, y más de 40 en un automóvil de gama alta.
Los microcontroladores de 4 bits poseen pequeña potencia de cálculo, y su
programación resulta algo «encorsetada», por lo que su única razón de
supervivencia es su precio extraordinariamente reducido (su principal mercado es
el sudeste asiático, con fabricantes como Seiko, OKI y NEC). Para sacarles el
máximo partido deben incluir los periféricos justos y necesarios para la
aplicación, pues si no su precio puede elevarse hasta el de los de 8 bits, y dejará
de ser rentable su utilización. Se emplean en mandos a distancia, llaves
inteligentes, etc.
Como se ha comentado, los microcontroladores de 8 bits son todavía en la
actualidad los más ampliamente utilizados, y como su precio tiende a bajar, van
ganando terreno a los de 4 bits. A nivel mundial, algunas de las familias más
destacables son las siguientes:

• Motorola 68XX. Sin duda, los microcontroladores de 8 bits de Motorola


(todos basados en el 6800) son los más vendidos a nivel mundial. No
obstante, este gran grupo comprende diversas familias, siendo las más
destacadas la 6805 y la 68HC11:
El 6805 de Motorola es con toda probabilidad el microcontrolador más
utilizado en el mundo. Se trata de una gran familia de microcontroladores de 8
bits de gama media y baja, con más de 200 miembros, encapsulados desde 16
patillas y posibilidad de diseño a medida. El núcleo procesador es un 6800
«recortado», para ahorrar espacio de silicio y reducir precio. La familia
original, de tecnología HMOS (High density NMOS), se denominó M6805,
mejorada por la CMOS M146805; la más moderna es la 68HC05 (HCMOS).
320 Microprocesadores y microcontroladores

A modo de ejemplo, el modelo MC68HC05K1 (16 pines en formato DIP)


integra 0,5 KB de ROM, 32 bytes de RAM, 10 líneas de E/S, y un
temporizador, a un precio de 0,9 dólares adquirido en grandes cantidades. Las
aplicaciones del 6805 son numerosas, desde tableros de mandos y
electrodomésticos hasta tarjetas monedero y ratones. Diversas compañías
fabrican segundas fuentes. El recientemente introducido 68HC08 es la
evolución natural del 6805, y uno de los microcontroladores que más está
promocionando Motorola de cara al futuro.
El 68HC11 de Motorola es un microcontrolador de 8 bits de gama media-alta,
empleado especialmente en automoción (General Motors, Chrysler,
Volkswagen, Toyota, Ford) y telefonía móvil. Al ser de gama media-alta, sus
prestaciones y precio se aproximan al de los micros de 16 bits, lo cual
representa su principal problema. Incluye RAM, ROM (o EPROM, a elegir) y
EEPROM integrados, y multitud de potentes periféricos, presentándose en más
de cincuenta versiones y existiendo multitud de herramientas de desarrollo
(incluidos compiladores C y fuzzy) y tarjetas de evaluación de precio
asequible. Una segunda fuente es Toshiba. El 68HC11 es muy popular entre
los aficionados y los centros de enseñanza de todo el mundo, debido a su
relación prestaciones/precio, sencillez de uso y desarrollo de sistemas,
existiendo numerosos nodos internet con abundante información, simuladores,
montajes, etc. El 68HC12 representa la evolución hacia los 16 bits del
68HC11; el HC12 es mucho más rápido e incorpora nuevas características,
como instrucciones de lógica borrosa y memoria flash. Por otro lado, el
68HC16 (16 bits también) incluye características DSP.
• Intel MCS-51. La arquitectura 8051, introducida a finales de los setenta por
Intel, es una de las más famosas, no por la importancia de Intel (líder absoluto
en el mercado de microprocesadores, pero compañía «de segunda fila» en el de
controladores), sino porque hace tiempo vendió la licencia del 8051, con lo
que muchos fabricantes comercializan microcontroladores que incluyen un
núcleo procesador en él basado.
Los microcontroladores basados en el 8051 son equiparables al 68HC11 en
prestaciones y precio, aunque, comparado con la linealidad y sencillez del
68HC11, la arquitectura 8051 resulta mucho más «enrevesada» (por ello
pensamos que resulta menos pedagógico que el 68HC11). Tampoco hay que
llevarse a engaño con la frecuencia de reloj exhibida por los 8051, superiores a
las del 68HC11, ya que sus instrucciones precisan en promedio de 12 ciclos de
reloj (frente a los en torno a 3 del HC11). Como todo microcontrolador, posee
múltiples versiones, como las famosas 8051 (con ROM), la 8751 (con
EPROM) y la 8031 (sin memoria integrada).
Desarrollo de sistemas microprocesadores 321

Diversos fabricantes comercializan versiones de la familia 8051, como Philips,


Matra-Harris, Dallas Semiconductors, Siemens, etc. Conservando la
compatibilidad con el juego de instrucciones clásico, introducen mejoras
diversas (p.e., el DS80C323 de Dallas ejecuta instrucciones a un promedio de
4 ciclos de reloj y opera a 18 MHz). La principal del 8051 es la cantidad de
fabricantes que lo han adoptado, por lo que se encuentra muy extendido. La
arquitectura 8051 también ha evolucionado hacia los 16 bits; destacaremos
como ejemplo el 80C51XA de Philips.
• Texas Intruments TMS370. Surgidos a finales de los ochenta a partir de un
contrato con Renault, se utilizan en automoción (Ford los emplea en el control
de inyección), sistemas de aire acondicionado, etc. Una de sus ventajas es que
sus herramientas de desarrollo cuentan con una interesante relación
prestaciones/precio (especialmente, los emuladores en circuito).
• Zilog Z8. Se trata de una familia de microcontroladores de gama baja y media,
de coste reducido. Introducido a mediados de los ochenta (pese a su
denominación, no es descendiente directo del Z80, sino «primo» de este
famoso µP), posee una moderna arquitectura, orientada a registros y bien
dispuesta para la programación en C. Se emplea en aplicaciones no demasiado
complejas, como es el caso de teclados (del 20 al 30% de los teclados de PC
incluyen un Z8), mandos a distancia, telefonía, etc. El número de periféricos
que integra es limitado (p.e., no incluye conversor A/D).
• PIC de Arizona Microchip. La familia PIC incluye numerosos
microcontroladores de gama baja (coste reducido) y algunos de gama no tan
baja. Su arquitectura resulta peculiar, muy diferente a la del resto de los
microcontroladores citados: pocas instrucciones (por lo que el fabricante la
denomina RISC), arquitectura Harvard modificada, pila de tamaño muy
reducido, alta frecuencia de reloj, los elementos más pequeños de la familia ni
siquiera cuentan con sistema de interrupciones, etc. El PIC compite sobre todo
con microcontroladores pequeños, como el Z8, 6805 o el ST6 de SGS-
Thomson; de hecho, la agresiva política de Arizona Microchip ha conseguido
en los últimos años introducirlo de forma importante en el mercado, pasando a
ser uno de los microcontroladores más empleados y conocidos. No obstante,
su peculiar arquitectura no suele resultar idónea para el desarrollo de
aplicaciones complejas y dificulta la programación en C.
• Los japoneses: Hitachi, NEC, Toshiba, Mitsubishi, OKI... Antiguamente
fabricaban segundas fuentes de microprocesadores ya implantados, como los
de Motorola. En la actualidad operan en el mercado con sus propios diseños,
322 Microprocesadores y microcontroladores

aunque con cierta frecuencia se apoyan sobre arquitecturas clásicas como la


68XX, Z80 o 6502. Compañías como Mitsubishi o NEC dominan el mercado
de los de 4 bits. Hitachi es una de las empresas líderes mundiales en el
mercado de los de más elevadas prestaciones gracias a su arquitectura SuperH
(SH), RISC de 32 bits con capacidad DSP (para el tratamiento de gráficos),
que se vende masivamente gracias al mercado de videoconsolas (la clásica
Sega Saturn incluye dos SuperH trabajando en paralelo). Por otro lado, la
nueva videoconsola de Sega, Dreamcast, incorpora el nuevo SH4 de Hitachi,
de 128 bits a 200 MHz, más otros dos µP operando en paralelo para gráficos y
audio, con una potencia de cálculo superior a muchos ordenadores personales.

7.5.2. Elección del microprocesador


Expondremos a continuación algunas consideraciones que deben tenerse en
cuenta a la hora de elegir el microprocesador idóneo a emplear en un sistema
electrónico en desarrollo:
a) Tipo de aplicación. Condiciona la clase de microprocesador. Normalmente se
elegirá entre uno de propósito general (Z80, 8085, 8086, 80486, i960), un
microcontrolador (68HC11, MCS51, 6805, Z8) o un DSP (TMS320 de Texas,
56000 de Motorola, 2100 de Analog Devices). Un sistema industrial o de
consumo incluirá un microcontrolador; determinadas aplicaciones relacionadas
con multimedia o telecomunicaciones requerirán el empleo de un DSP; los
microprocesadores de propósito general se reservan hoy en día para
confeccionar computadores.
b) Potencia/número de bits requeridos (4, 8, 16, 32, 64). En el caso de la
electrónica industrial y de consumo, muy probablemente la elección recaiga en
un microcontrolador de 8 bits, con menor probabilidad en uno de 4 o uno de
16. Raramente se necesitará mayor precisión.
c) Disponibilidad y tradición de uso. Si elegimos para nuestros desarrollos un
microprocesador de interesantes características pero difícil de conseguir, en un
momento dado podríamos no disponer de las unidades necesarias. Los
microprocesadores de mayor tradición suelen ser los más fiables en este
sentido, especialmente si cuentan con segundas fuentes. Es importante tener
en cuenta si la casa va a poder suministrar cantidades suficientes, y las
previsiones de futuro para ese microcontrolador (algunos con el tiempo llegan
a desaparecer, otros se «re-encarnan» en un nuevo tipo más potente).
d) Precio por unidad. Éste depende en gran medida del número de ejemplares
que vayamos a adquirir (no es lo mismo comprar un ejemplar que 10.000). En
el caso de los microcontroladores, recordemos que las versiones ROM son más
Desarrollo de sistemas microprocesadores 323

baratas que las EPROM sin ventana (OTP), y que las más caras de todas son
las EPROM con ventana.
e) Elementos integrados (memoria, líneas de entrada/salida, temporizador,
UART, SPI, conversor A/D, etc.).
f) Capacidad de memoria y velocidad. Debe evaluarse la cantidad y tipo de
memoria integrada (ROM, EPROM, EEPROM, flash). Por otra parte, debe
tenerse en cuenta que la velocidad no la mide solamente la frecuencia de reloj,
pues algunos microprocesadores que operan a más MHz precisan muchos más
ciclos de reloj por instrucción.
g) Consumo. Los microprocesadores clásicos se alimentan a 5 voltios, mientras
que muchos de los modernos lo hacen a 3,3, 2,4 o 1,8 voltios. Su interés
dependerá de la aplicación en desarrollo (resultará crítico en las aplicaciones
portátiles).
h) Soporte software y sistemas de desarrollo, tanto a nivel de disponibilidad,
como de prestaciones y precio.
i) Soporte lenguajes de alto nivel (lenguaje C, lógica borrosa o fuzzy).
j) Soporte técnico (página web, libros de datos y CD ROM, apoyo telefónico por
ingenieros de la casa, etc.).

7.5.3. Encapsulado
Existen multitud de encapsulados diferentes, unos de plástico y otros
cerámicos. Las denominadas series comerciales, más baratas, emplean
encapsulado plástico, soportando temperaturas de 0 a 70 ºC. Las denominadas
series militares emplean encapsulado cerámico, de mayor fiabilidad, soportando
temperaturas de −55 a +125 ºC, pero de un precio más elevado (debe tenerse en
cuenta que siempre se hace referencia a la temperatura del integrado, que
normalmente es superior a la del ambiente que lo rodea).
Los tipos de encapsulados que se emplean en microprocesadores y
microcontroladores son similares a los del resto de los circuitos integrados, sólo
que el número de pines en determinados casos puede resultar enorme. El
encapsulado más clásico es el DIP (Dual In-line Package), a veces también
denominado DIL, siendo comunes los integrados DIP de 16, 20, 24, 28, 40 y 48
patillas. El DIP ha sido utilizado en los microprocesadores más clásicos y se
emplea todavía en los microcontroladores de menos prestaciones, que suelen
poseer un número de patillas relativamente reducido.
Sin embargo, cuando el número de pines se eleva por encima de 40, el
encapsulado DIP ocupa un espacio excesivo, por lo que la industria ha ido
introduciendo nuevos tipos conforme aumentaba el número de pines requerido.
324 Microprocesadores y microcontroladores

El PLCC (Plastic Leaded Chip Carrier), el encapsulado de característica forma


cuadrada cuyos pines se doblan bajo la pastilla, es muy habitual entre los
microcontroladores de tamaño medio. Un ejemplo de este encapsulado es el
PLCC de 52 pines. La versión cerámica se denomina CLCC.
Cuando el número de pines se acerca el centenar se emplean nuevos tipos de
encapsulado. El denominado QFP (Quad Flat Pack), de apariencia parecida al
PLCC pero de patillas muy juntas y dobladas hacia afuera para su montaje
superficial, permite realizar integrados con un elevado número de patillas,
ocupando un reducido espacio. Un ejemplo es el QFP de 160 patillas.

FIGURA 7.8. Diferentes encapsulados del 68HC11A8: DIP-48, PLCC-52 y QFP-64.

Los microprocesadores modernos más potentes, como los de 32 o 64 bits,


requieren incluso de más patillas (p.e., el 486DX solamente para datos y
direcciones necesita ya 64 líneas, haciendo uso además de 25 líneas de
alimentación de +5 V y 28 de tierra). Para estos casos se introduce el encapsulado
PGA (Pin Grid Array), en el que los pines se distribuyen formando una densa
matriz bajo la pastilla del circuito (formando una «cama de pinchos»); un ejemplo
es el PGA de 168 pines utilizado en el 486DX. Un encapsulado recientemente
introducido es el BGA (Ball Grid Array), similar al PGA pero sustituyendo los
pines por pequeñas esferas metálicas (p.e., BGA de 357).
Desarrollo de sistemas microprocesadores 325

Expondremos el caso concreto de nuestro ya familiar 68HC11,


microcontrolador de tamaño medio: mientras que los ejemplares más pequeños
de HC11 (familia D) hacen uso de encapsulados DIP-40, los más grandes emplean
QFP. A modo de ejemplo concreto, el 68HC11A8 se encuentra disponible en
DIP-48, PLCC-52 y QFP-64.

7.6. Consideraciones eléctricas en el desarrollo de sistemas


Como ya adelantamos, se tiende a pensar en el sistema basado en
microprocesador como un sistema digital formado por la conexión de bloques
funcionales (cajas negras de las que solamente nos interesan sus características
entrada/salida), que debe programarse de forma apropiada. Sin embargo, es
importante atender también a su vertiente de sistema electrónico, que a veces
queda en el olvido. Por ejemplo, hay que tener presentes las características
eléctricas y temporales, tanto de las señales como de los buses por los que éstas
circulan, así como las de las «cajas negras» que componen el sistema
(microprocesador, chips de memoria, puertos, etc.). Si no se tienen en cuenta
éstas características eléctricas y de tiempos, en el desarrollo de un sistema
microprocesador pueden surgir problemas imprevistos, como los asociados a
retrasos, ruido eléctrico, de adaptación de niveles lógicos entre circuitos, etc.
En la presente sección realizaremos una breve introducción a este tipo de
cuestiones. Para un estudio posterior recomendamos al lector las siguientes
referencias bibliográficas: se ofrecen perspectivas del tema y ejemplos en las
páginas 152 y 160 del libro [Slater 89], en el capítulo 2 de [Hayes 86] y en
[Pollán 94]; en cuanto a referencias más específicas, la nota de aplicación de Intel
AP-125 Designing microcontrollers systems for electrically noisy environments
[Intel 95] resulta de extraordinario interés, y el libro [Balcells 92] es una
interesante referencia general sobre el problema de las interferencias
electromagnéticas en los equipos electrónicos.

7.6.1. Problemas relativos a los buses


Como ya sabemos, los buses son grupos de líneas que transportan las señales
que intercambian los elementos del sistema microprocesador. Las señales
eléctricas que circulan por los buses son digitales, transportando la información
codificada en ceros (nivel lógico bajo) y unos (nivel lógico alto). Los aspectos
fundamentales que trataremos en este punto hacen referencia a los retrasos de las
señales en líneas y circuitos integrados, la capacidad de carga o fan-out del bus
(es decir, de los circuitos drivers o excitadores de bus), y el ruido eléctrico que
puede aparecer en las señales.
326 Microprocesadores y microcontroladores

7.6.1.1. Retrasos en los circuitos integrados


La primera circunstancia a considerar en la conexión de circuitos integrados o
tarjetas a los buses de un sistema microprocesador es que debe respetarse la
velocidad de trabajo o frecuencia de reloj del sistema, lo cual se traduce en que
los circuitos integrados conectados no deben causar retrasos importantes en las
señales de los buses. Los retrasos en las señales pueden surgir por dos motivos
diferentes, bien a causa de los tiempos de propagación a través de los circuitos
integrados, bien a causa de las capacidades eléctricas de entrada de los circuitos
directamente conectados a los buses. En este punto estudiaremos la cuestión de
los tiempos de propagación en los circuitos integrados, dejando el segundo
aspecto para el siguiente.
Cualquier circuito integrado intermedio, es decir, que reciba un conjunto de
señales de entrada y deba producir una respuesta, debe ser lo suficientemente
rápido como para que los retrasos en las señales debidos a la propagación por el
circuito integrado no afecten a la correcta operación del bus. Estos circuitos
intermedios no son otros que los decodificadores de memoria (puertas lógicas
básicas y decodificadores), la circuitería de control (puertas lógicas) y los buffers
y adaptadores de bus (drivers y transceivers).
Para hacernos una idea del orden de magnitud de los retrasos tolerables en los
circuitos integrados en función de la frecuencia de reloj, observemos la tabla 7.2.
En ella se ha considerado que un retraso debe ser inferior al 20% del período de
operación del bus (marcado por la frecuencia de reloj) para que no afecte
gravemente a su operación.
En la tabla 7.3 se muestra el caso concreto del conocido decodificador 74138,
para distintas familias lógicas. La situación más habitual en el desarrollo de
sistemas basados en microcontroladores de 8 bits es el trabajo a frecuencias
relativamente bajas, de hasta varios MHz, en cuyo caso pueden emplearse las
familias lógicas más comunes, HC (High CMOS), HCT (High CMOS TTL
compatible) y LS (Low-Schottky). De las citadas, las familias HC y HCT, por su
bajo consumo, suelen ser las más habituales.
Por otra parte, la familia ALS (Advanced Low-Schottky), más veloz que la LS
y de menor consumo, puede emplearse a frecuencias de hasta 20 MHz. Debido
precisamente al menor consumo que la LS (carga unos 0,1 mA para el estado
bajo), su empleo es muy interesante para todos aquellos sistemas que operen a
menos de 20 MHz.
Desarrollo de sistemas microprocesadores 327

Finalmente, las familias FAST, AC y ACT se reservan para sistemas que


operan a más de 20 MHz. La familia FAST (Fairchild Advanced Schottky TTL)
presenta un consumo relativamente elevado (unos 0,5 mA para entrada en estado
bajo), mientras que las familias AC y ACT (Advanced CMOS y Advanced CMOS
TTL compatible), de menor consumo, cuentan con el inconveniente de requerir un
diseño de la placa cuidadoso, por problemas de ruido.

Frecuencia de reloj Período (T) Retraso tolerable


(clk) (tiempo de propagación, tp ≈T/5)
clk ≈4 MHz T ≈250 ns tp <50 ns
clk >4 MHz T <250 ns tp <20 ns
clk ≈20 MHz T ≈20 ns tp <10 ns

TABLA 7.2. Retrasos tolerables (tiempo de propagación inferior a un 20% del período de reloj) para
diversas frecuencias de reloj típicas de un sistema microprocesador.

Familia lógica tp máximo tp típico


HC y HCT 50 ns 25 ns
LS 40 ns 20 ns
ALS 20 ns 10 ns
FAST 10 ns 6 ns
AC y ACT 8 ns 5 ns

TABLA 7.3. Retrasos indicados en las hojas de características para el 74138.


328 Microprocesadores y microcontroladores

TTL: RTL DTL S TTL LS TTL ALS TTL


(74S) (74LS) (74ALS)
«Prehistoria»
«Superviviente» Para inter-buses

MOS: PMOS nMOS NMOS CMOS HCMOS


(40) (74HC)
Evolución PMOS Integración
VLSI Diseño general

Muy bajo consumo (3 V): LV CMOS LVT BiCMOS


(74LV) (74LVT)

Alta velocidad (>60 MHz): TTL FAST Advanced CMOS


(74F) (74AC y 74 ACT)

FIGURA 7.9. Familias lógicas. Obsérvese que la línea dominante es lograr circuitos más veloces y/o
de menor consumo.

Hablando en términos generales, las series más empleadas hasta hace unos
años eran la LS y la HC, empleándose cada vez más la HC por su bajo consumo.
En la actualidad cada vez es menor el empleo de la LS, y probablemente
disminuya el de la HC; ambas familias tenderán a ser suplantadas por las más
avanzadas ALS y AC, respectivamente. Si se requiere bajo consumo, la familia
CMOS denominada LV (Low Voltage), que opera con 3 V, es más indicada.

7.6.1.2. Carga de los buses (fan-out)


El otro gran problema asociado a los buses es el relacionado con su capacidad
de carga. Por una parte, los circuitos excitadores de bus solamente pueden
proporcionar una determinada intensidad, que debería resultar suficiente para
mantener los valores de los niveles lógicos en las líneas, teniendo en cuenta las
necesidades de entrada de los integrados destino de los datos; por otra parte, la
capacidad eléctrica de entrada de los circuitos conectados introducirá retrasos en
las señales. Así, pueden distinguirse dos tipos de cargas sobre los buses:
a) Carga Estática (DC). La capacidad estática limita la capacidad de mantener
los niveles lógicos en el bus. Se relaciona con la intensidad que los circuitos
excitadores del bus pueden proporcionar como salida y la que los circuitos
receptores de las señales precisan, de modo que se mantengan los niveles
lógicos en las líneas. Debe tenerse en cuenta que los circuitos TTL precisan
Desarrollo de sistemas microprocesadores 329

corrientes de entrada muchísimo más elevadas que los MOS; por lo tanto,
serán los integrados TTL conectados al bus los que fundamentalmente
determinen las características de carga estática.
b) Carga Dinámica (AC) o capacitiva. Viene determinada por la capacidad
eléctrica de entrada de los circuitos conectados a las líneas del bus, que al
ocasionar retrasos en la propagación de las señales limitará la velocidad de
operación del bus. La capacidad de entrada de los circuitos MOS es muy
superior a la de los TTL; por lo tanto, serán los integrados MOS los que
fundamentalmente determinen las características de carga dinámica del bus.
En definitiva, la capacidad de carga de un bus limita el número de integrados
TTL y MOS que pueden conectarse directamente. En el caso de los sistemas
compuestos por una única tarjeta resulta más difícil que pueda presentarse este
tipo de problemas, al ser el número de circuitos integrados conectados reducido
en general (no obstante, conviene comprobarlo). Sin embargo, en el caso de los
sistemas multitarjeta, como norma deben introducirse amplificadores de bus
(buffers), unidireccionales o drivers para los buses de direcciones y control, y
bidireccionales o transceivers para el de datos. Estos buffers deben conectarse
siempre tan próximos como resulte posible a los conectores de las tarjetas.
Trataremos a continuación los dos parámetros que deberán estudiarse para
determinar si en la operación del sistema en desarrollo en un momento dado
puede verse superada la capacidad de carga de sus buses. El primero de ellos
estará relacionado con la carga estática (intensidades), mientras que el segundo
hará referencia a la carga dinámica (capacidades eléctricas). Buena parte de los
datos que se proporcionan a continuación proceden de [Pollán 94].
En relación a la carga estática, para ambos niveles lógicos (alto y bajo) por
separado debe asegurarse que la suma de las corrientes requeridas por las entradas
de los integrados habilitados, más las corrientes de fuga (leaky currents) de los no
habilitados, sea inferior a la intensidad que puede suministrar el circuito driver de
bus más débil (excitadores o drivers de bus son aquellos circuitos que aportan
datos al bus, como el microprocesador, pastillas de memoria, puertos de entrada,
etc.). Para los integrados MOS las intensidades de entrada Ii son ínfimas, del
orden de los 10 µA, por lo que son los TTL los que determinan este parámetro.
Así, una línea de bus típica suele ser capaz de suministrar menos de 10 mA.
La intensidad que requiere una entrada en estado bajo es del orden de 1 mA para
la TTL estándar, 0,2 mA para la familia LS, 0,1 para la ALS y unos 0,6 para la
FAST. Para el caso de los CMOS es de unos 10 pA, es decir, absolutamente
despreciable. Por ello, el número de integrados TTL que pueden conectarse
directamente a una línea de bus no es muy elevado (por ejemplo, el 6800 puede
330 Microprocesadores y microcontroladores

suministrar alrededor de 2 mA, por lo que solamente puede alimentar una carga
TTL estándar).
Quizás sean los problemas relacionados con las cargas capacitas los más
habituales. La capacidad eléctrica de entrada de un integrado TTL resulta
despreciable frente a la de los integrados MOS, por lo que serán éstos los que
determinen dicho parámetro. Un circuito MOS suele presentar entre 1 y 20 pF de
capacidad de entrada, mientras que los dispositivos excitadores de bus
(microprocesador, memorias, etc.) suelen ser capaces de cargar capacidades entre
100 y 150 pF. Además, debe tenerse presente que las pistas del circuito impreso
contribuyen a la capacidad con alrededor de 1 pF por centímetro, por lo que
deberá procurarse que sean de mínima longitud.
Cada entrada MOS equivale a un condensador, que hay que cargar o
descargar en cada transición (incluso si el integrado se halla deshabilitado);
consideramos que su capacidad típica es de 3 pF. La carga y descarga de
múltiples entradas capacitivas que soporta una línea de bus supone el aumento del
tiempo de conmutación, lo que se traduce en un retraso en la propagación de las
señales. Así, si el fan-out de una línea es n, supuesta un intensidad de 10 mA, y
considerando una capacidad típica de 3 pF, se tendría el siguiente retraso:
nCi ∆V n ⋅ 3 pF ⋅ 5V
∆Q = nCi ∆V ⇒ I ⋅ t = nCi ∆V ⇒ t = = = 1,5 ⋅ n ns
I 10mA
es decir, de aproximadamente 1,5 ns por integrado MOS conectado a la línea, lo
que para n=10 representa unos 15 ns, y para n=100, unos 150 ns, que resulta
sumamente alto.
Por lo tanto, cuando deben conectarse a un bus numerosos integrados, sean
TTL o MOS, hay que emplear circuitos adaptadores o amplificadores de bus
(drivers o transceivers), de tipo triestado y de alta intensidad de salida, que
aumentan la capacidad de carga del bus (es decir, la intensidad suministrable por
sus líneas). Los adaptadores 74244 y 74245 son típicos bus drivers y
transceivers, respectivamente. Por ejemplo, para el caso de la hoy en día muy
habitual serie ALS, la intensidad de salida en estado bajo IOL es de 24 mA en
ambos circuitos, y 15 mA en estado alto IOH. El 74ALS244 presenta tiempos de
propagación menores de 10 ns y el 74ALS245 menores de 20 ns. Otro
amplificador de bus unidireccional típico es el 74241, que solamente se diferencia
del 244 en sus líneas de habilitación.
Desarrollo de sistemas microprocesadores 331

FIGURA 7.10. Esquema lógico del driver 74244 y del transceiver 74245.

FIGURA 7.11. Patillas de los drivers 74241, 74244 y 74541, y del transceiver 74245.

Debido a que los adaptadores de bus deben presentar tiempos de propagación


pequeños y conmutar corrientes elevadas (características típicas de los circuitos
bipolares, como son los TTL), pero al mismo tiempo resulta cada vez más
332 Microprocesadores y microcontroladores

importante reducir el consumo al mínimo (característica de los CMOS), se han


introducido las familias lógicas BiCMOS (Bipolar CMOS), que tratan de
combinar lo mejor de ambas tecnologías. En estos circuitos las entradas son de
tipo CMOS, por lo que precisan pequeñas intensidades (bajo consumo) y
presentan buena inmunidad al ruido, mientras que las salida son de tipo bipolar,
con lo que ganan en velocidad y alta intensidad de salida. La integración
BiCMOS da lugar a series específicamente dirigidas a aplicaciones relacionadas
con los buses (adaptadores, decodificadores de direcciones, control de
lectura/escritura).
Así, la serie ABT (Advanced BiCMOS) puede suministrar unos 32 y 64 mA,
para los niveles lógicos bajo y alto respectivamente, presentando unos tiempos de
propagación menores de 5 ns (74ABT244) y 7 ns (74ABT245). Para hacernos
una idea de la reducción en el consumo, los circuitos de la serie ABT son un 35%
más rápidos que los equivalentes de la serie FAST, pero reduciendo el consumo
en un 95%. Por otra parte, la serie LVT (Low Voltage BiCMOS, BiCMOS de baja
tensión) puede alimentarse con tensiones entre 2,7 y 3,6 voltios, presentando
tiempos de propagación inferiores a 4 ns.
En resumen, en los adaptadores de buses, como el 244 y 245, suelen
emplearse en la actualidad las familias lógicas TTL ALS, F y AS, BiCMOS BCT,
ABT y LVT, y CMOS AC y LVC (Low Voltage CMOS). Para concluir,
recordaremos que estos circuitos adaptadores, como el 74244 y el 245, se emplean
también en la confección de puertos para la conexión de periféricos. No obstante,
en este caso la velocidad de operación no suele resultar crítica, con lo que
normalmente se emplean circuitos de las familias HC y HCT, de consumo muy
inferior (y más baratos).

PIA y ACIA 6800, RAM, ROM cables/pistas

Corriente de fuga 10 µA 10 µA ---

Capacidad eléctrica 10 pF 15 pF 25-30 pF (aprox.)

TABLA 7.4. Corriente de fuga (suministrada por el integrado que haga de driver de bus) y capacidad
eléctrica de las líneas de buses (datos, dirección, RIW) que presentan los integrados típicos de un
sistema basado en el 6800 cuando se sitúan en alta impedancia.
Desarrollo de sistemas microprocesadores 333

El caso del M6800. A modo de ilustración estudiaremos la capacidad de carga de


los buses de un sistema microprocesador basado en un M6800. La mayor parte de
los microprocesadores, aunque construidos con tecnología MOS, poseen salidas
compatibles TTL, pudiendo cargar normalmente uno o dos integrados TTL
estándar (1,6 o 3,2 mA, respectivamente). Las hojas de características del
M6800 (tecnología NMOS) indican que operando a 1 MHz puede alimentar hasta
unos 130 pF y una carga TTL estándar. Si suponemos que los cables aportan
unos 30 pF de carga en total, quedan unos 100 pF para el resto de los integrados
del sistema (RAM, ROM, ACIA, PIA, etc.).
Cuando los integrados de la familia 68XX (memorias, puertos) se sitúan en
alta impedancia, sus pines de datos, direcciones y lectura/escritura presentan unas
corrientes de fuga de unos 10 µA, que deberán ser suministrados por el circuito
que en ese instante haga de driver de bus (por ejemplo, la CPU); asimismo, dichas
líneas presentan una capacidad eléctrica, unos 10 pF en el caso de una PIA o un
ACIA, y de 15 pF en el caso de la CPU, o pastillas de RAM y ROM tipo MOS
típicas [Motorola 75] (tabla 7.4). Como cada elemento de la familia 6800 puede
proporcionar 100 µA y cargar 130 pF, el fan-out varía de 7 a 10 elementos de la
familia, contando con unos 30 pF de capacidad en los cables o pistas [Motorola
75]. Si queremos conectar más elementos deberemos amplificar los buses con
buffers como los estudiados.

7.6.1.3. Ruido eléctrico en las líneas


Otro factor importante en el diseño de sistemas microprocesadores es la
presencia de ruido en las señales que se propagan por las líneas de los buses (fig.
7.12). Aunque el ruido siempre estará presente, el sistema puede diseñarse para
asegurar que se limita a un nivel que no perturbe excesivamente los niveles
lógicos (p.e., TTL acepta fluctuaciones del orden de los 0,4 voltios, más
exactamente de 0,45 V. para el nivel bajo y 1,4 V para el alto).
El ruido, que distorsiona las señales lógicas, puede tener una causa externa o
interna. Son fuentes externas de ruido las radiaciones electromagnéticas
procedentes de equipos eléctricos o electrónicos, así como las fluctuaciones en la
alimentación. La solución en el primer caso pasa por colocar supresores de ruido
en el equipo externo y envolver el nuestro en una carcasa metálica (jaula de
Faraday). Además, conviene aislar galvánicamente las señales de entrada y salida
mediante acoplo optoelectrónico. Para el segundo caso, deben emplearse fuentes
de alimentación reguladas.
334 Microprocesadores y microcontroladores

FIGURA 7.12. Señal lógica ideal y señal real (con ruido). Si la «espiga» en la señal real tuviese
suficiente anchura, algún circuito podría considerarla como un estado lógico alto.

Las fuentes internas de ruido resultan normalmente de menor importancia.


Trabajando a frecuencias bajas, con corrientes pequeñas y cables de conexión de
longitud reducida, el ruido interno puede ser con frecuencia ignorado. El ruido
interno crece al aumentar el tamaño físico del circuito y su velocidad de
operación, debido fundamentalmente a las siguientes causas, que estudiaremos a
continuación: problemas en la distribución de alimentación y tierra, interferencia
entre líneas (cross talk) y efecto de línea de transmisión.
a) Distribución de alimentación y tierra. Algunos circuitos integrados toleran
variaciones de tan sólo un 5% en la alimentación. Para evitar caídas
importantes en la tensión de alimentación se aconseja el empleo de cables
suficientemente gruesos que permitan transportar la corriente necesaria, pistas
cortas para potencia y tierras cuya conexión resulte tan directa como sea
posible. En este sentido, resulta aconsejable realizar la distribución de la
tensión de alimentación y de las tierras mediante pistas muy anchas, formando
láminas o planos. Puede resultar práctico llevar la alimentación a los
integrados mediante estructuras en forma de retícula de conductores, cuya
forma se aproxima a un plano (fig. 7.13).
La conmutación a la vez de muchas puertas lógicas puede causar fluctuaciones
en la tensión de alimentación (fig. 7.14). En los circuitos TTL estas
fluctuaciones se filtran mediante condensadores (denominados de desacoplo) a
dos niveles, global y local (fig. 7.13). El filtrado global suele realizarse con un
condensador electrolítico de unos 10 µF entre tierra y Vcc, situado cerca del
lugar de la tarjeta donde se conecta la fuente de alimentación. Además, se
distribuyen por la tarjeta diversos condensadores cerámicos de unos 10 nF (no
electrolíticos, para evitar la resistencia equivalente en serie que presentan a
frecuencias elevadas), situándose próximos a los circuitos integrados (p.e., un
condensador de 10 nF por cada dos integrados, o incluso por cada integrado).
Desarrollo de sistemas microprocesadores 335

FIGURA 7.13. Distribución en forma de rejilla de las líneas de alimentación y tierra, con
condensadores de filtrado de alimentación (global de 10 µF, y distribuidos de 10 nF).

FIGURA 7.14. Caída de tensión de alimentación (espiga) ocasionada por un consumo instantáneo
elevado. Dicha caída es suavizada por un condensador de desacoplo.

b) Interferencia entre líneas (cross talk). Cuando varias líneas discurren


paralelas y muy próximas (como sucede en los buses), una transición en una
de ellas induce una señal de ruido sobre las adyacentes, que se superpondrá a
las señales que éstas transportan (fig. 7.15a); el fenómeno se denomina
interferencia entre líneas o ruido cruzado. Se trata de un efecto dinámico, que
solamente se produce cuando las señales cambian de estado, induciéndose un
nivel de ruido proporcional a la distancia entre líneas.
Para limitar este tipo de ruido pueden separarse los cables, colocar una línea de
tierra entre dos de señal, o evitar que dos líneas discurran paralelas durante
largas distancias. Debido a la generación de ruido cruzado, no es usual el
336 Microprocesadores y microcontroladores

empleo de cable plano (de hilos paralelos) en la conexión de dispositivos


relativamente lejanos (decenas de centímetros), y, si su empleo resulta
inevitable, se recomienda alternar líneas de señal y de tierra (fig. 7.15b). Para
conexiones de mayor longitud (hasta unos tres metros), se suele hacer uso de
pares trenzados (twisted pairs).
c) Efecto de línea de transmisión. Aunque muchas veces resulta suficiente
considerar los cables como dispositivos ideales, o, a lo sumo, con una
determinada resistencia, en realidad poseen cierta impedancia distribuida Z (R,
L y C). Este efecto, despreciable en ocasiones, resulta importante cuando los
tiempos de propagación de la señal por el cable son relativamente largos
respecto de los tiempos de subida (0 a 1) o de bajada (1 a 0) de las señales o,
en definitiva, cuando se trabaja a frecuencias de reloj elevadas o bien los
cables son largos. En este caso el hilo se comporta como una línea de
transmisión, con una impedancia característica Z0 constante, que la señal
eléctrica «ve» en cada punto, lo que causa dos efectos: 1) la señal no se
transmite instantáneamente sino a unos 0,2 m/ns; 2) la tensión puede variar a
lo largo de la línea.
En una línea de transmisión (fig. 7.16) en cada punto las tensiones y corrientes
instantáneas se relacionan según la ley de Ohm generalizada:
v = Z0 ⋅ i

a)

b)

FIGURA 7.15. a) Ruido cruzado. b) Protección mediante líneas de tierra entre líneas de señal.
Desarrollo de sistemas microprocesadores 337

FIGURA 7.16. Línea de transmisión conectando dos dispositivos.

Por lo tanto, si en el extremo de la línea se conecta un dispositivo de


impedancia RB, se tiene:
v = RB ⋅ i

Si RB=Z0, se satisfacen simultáneamente ambas ecuaciones, en cuyo caso se


dice que la línea está acoplada. Si RB≠Z0, se da un conflicto de acoplo en el
extremo de la línea, al ver el pulso que se está propagando una impedancia
distinta de la característica. Para resolver este conflicto al llegar a la carga B
se produce en v un cambio de amplitud, generándose un pulso de menor
amplitud, que puede proseguir hacia adelante o reflejarse hacia atrás (y que, a
su vez, eventualmente podría volver a reflejarse en A). La señal total será la
suma de todos estos pulsos reflejados de amplitudes decrecientes, que crearán
una distorsión en las señales «puramente digitales» iniciales. Por este motivo,
los puntos extremos de las líneas pertenecientes a una red de datos (como las
informáticas) no se dejan al aire, sino que suelen «cerrarse» con una
denominada resistencia terminadora, que evita estos efectos.
Por otra parte, cuando un hilo de señal se encuentra próximo a uno de tierra se
está comportando como una línea de transmisión, de forma más acusada
cuanto mayor longitud posea el cable y más rápidamente cambien las señales.
Variaciones en la distancia de separación aparentarán impedancias
desacopladas, induciéndose ruido, por lo que se recomienda en estos casos
mantener las líneas a una distancia constante, para que la línea de transmisión
a la que se asemeja resulte uniforme. Con la mayor parte de las familias TTL
y MOS pueden emplearse para distancias de hasta unos 0,5 metros hilos
individuales (cuya impedancia característica suele ser de 150 Ω), pero para
distancias mayores (hasta 3 metros) debe hacerse uso de pares trenzados (100
Ω), compuestos por un hilo de señal y otra de tierra, cuya distancia es
constante y cuyos cruces se presentan uniformemente espaciados. Para
338 Microprocesadores y microcontroladores

distancias mayores deben emplearse buffers, con acoplo de impedancias entre


los dispositivos y la línea de transmisión.

7.6.2. Consideraciones al construir tarjetas de circuito impreso


A la hora de realizar una placa de circuito impreso para un sistema
microprocesador o microcontrolador se suelen apuntar una serie de consejos
prácticos, algunos de los cuales se desprenden de lo comentado en el punto
anterior [Bueno 95]:
a) Colocación de condensadores de filtrado de la alimentación general de la
tarjeta (electrolíticos de unos 10 µF).
b) Colocación de pequeños condensadores locales de desacoplo entre los
terminales de Vcc y tierra de los circuitos integrados (no electrolíticos, de unos
10 nF).
c) Las líneas de alimentación son las causantes de muchos de los problemas, por
lo que conviene que sean las primeras en ser trazadas.
d) Se recomienda la distribución de la alimentación formando rejillas.
e) Se recomienda el empleo de planos de masa, para que las corrientes de retorno
no encuentren elevadas resistencias.
f) En circuitos a doble cara, puede resultar útil colocar en una la mayor parte de
las líneas horizontalmente y en la otra verticalmente.
g) Las líneas de reloj también son una fuente común de problemas. El generador
del reloj o el cristal de cuarzo debe situarse lo más próximo posible al
microcontrolador o microprocesador. Las líneas de reloj tienen que ir siempre
directas a los integrados que las precisen y deben llegar con suficiente
«fuerza».
h) Conviene tener presente la capacidad de carga de los buses, los posibles
retrasos y, en general, todo lo comentado en la sección anterior.

7.7. Consumo y fiabilidad de operación


Concluiremos este capítulo dedicado a diversas cuestiones prácticas
relacionadas con el diseño de sistemas basados en microprocesadores tratando
brevemente dos aspectos muy importantes en el caso de las aplicaciones reales,
como son el consumo y la fiabilidad de operación del sistema.
Desarrollo de sistemas microprocesadores 339

7.7.1. Consumo
El consumo es un aspecto muy importante en todo circuito electrónico de
mediana complejidad, como son los basados en microprocesadores y
microcontroladores (p.e., un «sencillo» 68HC11A8 integra ya más de 100.000
transistores, y un Pentium varios millones), y resulta crítico en las denominadas
aplicaciones portátiles, con alimentación a baterías. Es bien sabido que el
consumo de los circuitos bipolares es superior al de los MOS, y que dentro de los
MOS las familias CMOS son de bajo consumo, existiendo algunas específicas,
como las LV, de muy bajo consumo. También sabemos en el caso de las familias
CMOS que el consumo aumenta al incrementarse la frecuencia de reloj del
sistema.
Un microprocesador antiguo como el 6800, de tecnología NMOS, pese a su
sencillez y baja frecuencia de reloj, presenta un consumo relativamente
importante, de unos 240 mA a 5 V, pudiendo disipar a lo máximo 1,2 W de
potencia. En el caso de los microprocesadores más modernos y potentes (como el
Pentium), de tecnologías CMOS o BiCMOS, al operar a frecuencias de reloj
elevadas e integrar millones de transistores, el consumo puede resultar muy
elevado, por lo que una tendencia actual es reducir la tensión de alimentación (por
debajo de 3 e incluso 2 voltios).
Estudiaremos con más detenimiento el caso del microcontrolador M68HC11,
como ejemplo de cómo se manejan los aspectos relativos al consumo en un
microcontrolador típico actual. El 68HC11 es un microcontrolador diseñado con
la idea de limitar de una manera importante el consumo. Por un lado, al realizarse
en tecnología HCMOS, su consumo ya es en sí mucho más reducido que el de un
microprocesador NMOS como el 6800. Por otro lado, se trata de un diseño
completamente «estático» (no emplea ningún tipo de almacenamiento dinámico
en registros DRAM, como sucedía en el 6800), por lo que, si en una aplicación no
se requieren velocidades de operación importantes, puede reducirse su frecuencia
de reloj. Para aplicaciones de bajo consumo existen dentro de la familia versiones
L (Low Voltage), que pueden trabajar con tan sólo 3 voltios de alimentación,
como, por ejemplo, la M68L11E9.
Además, todos los ejemplares de 6811 incorporan dos instrucciones, WAI y
STOP, que permiten colocarlo en sendos modos de bajo consumo en los períodos
en los que no se requiera del servicio del microcontrolador (p.e., una calculadora
electrónica olvidada encendida en un cajón, o un mando a distancia que no se
acciona). La instrucción WAI almacena los registros en la pila y coloca al HC11
en una situación de «espera interrupción» (WAit for Interrupt), reduciendo su
340 Microprocesadores y microcontroladores

consumo mediante la desconexión de alguno de sus bloques integrados; el HC11


escapa de esta situación cuando recibe una interrupción o reset.
Mayor ahorro energético proporciona la instrucción STOP, que detiene los
relojes del 68HC11, «congelando» su operación; el consumo es en tal situación
reducidísimo (decenas de µA). No obstante, para que STOP opere de esta manera
es necesario que previamente el bit S (el octavo) del registro de estado CCR se
haya colocado a ‘0’, pues, si vale ‘1’ (situación por defecto), STOP se comporta
como una simple instrucción NOP. El 68HC11 se recupera también de la
situación de STOP con una interrupción o mediante un pulso de reset.
El libro de Motorola MC68HC11 E Series Technical Data [Motorola 95]
proporciona los datos sobre el consumo de un 68HC11 de la familia E a 2 MHz
(como el de la placa EVBU) indicados en la tabla 7.5. Destacaremos que en
modo sencillo consume a lo máximo 15 mA alimentado a 5 V; en modo STOP su
consumo desciende hasta 50 µA tan sólo. El chip puede soportar como mucho 85
mW en modo sencillo. Sabiendo que una batería alcalina de 9 V típica tiene una
capacidad de 500 mA⋅h, podemos deducir que un 68HC11E9 a 2 MHz y 5,0 V
consumiendo unos 10 mA podría operar durante 50 horas sin interrupción, pero
en situación de STOP retendría los datos en memoria durante miles de horas
(mucho más de un año). Trabajando a 1 MHz y 3,0 V de alimentación estas cifras
se verían multiplicadas por 4 (200 horas ininterrumpidas en modo normal).

Modo sencillo Modo expandido


Ejecución normal: 15 mA 27 mA
En «wait»: 6 mA 10 mA
En «stop»: 50 µA
Máxima potencia que puede disipar el circuito integrado:
Modo sencillo Modo expandido
85 mW (17 mA a 5 V) 150 mW (30 mA a 5 V)

TABLA 7.5. Consumo del MC68HC11E9 a 2MHz y alimentado a 5,0 V [Motorola 95]: corriente
máxima de alimentación (aportada por la fuente) que soporta el circuito integrado. Si el circuito se
alimenta a 3,0 V, o si se limita la frecuencia a 1 MHz, el consumo se reduce prácticamente a la mitad
en todos los casos (y a la cuarta parte si se reducen ambos).
Desarrollo de sistemas microprocesadores 341

7.7.2. Fiabilidad de operación de los microcontroladores


En muchos sistemas cableados una interferencia que ocurre ocasionalmente
suele tener un efecto momentáneo (fig. 7.12). Sin embargo, si en un sistema
microprocesador un pico de ruido cambia tan sólo un bit de un opcode, la
instrucción que se ejecutará resultará ser completamente diferente de la original,
lo que con elevada probabilidad ocasionará el bloqueo de todo el sistema (que
queda «colgado») [Balcells 92] (p. 179). Por lo tanto, aunque se hayan seguido
estrictas normas de diseño persiguiendo una elevada inmunidad al ruido
electromagnético, si en un momento dado tan sólo una interferencia logra sortear
las barreras establecidas, ésta puede dar al traste con el sistema.
Por ello, los sistemas microprocesadores y microcontroladores que operan en
medios con elevada contaminación electromagnética, como es el industrial o el
automóvil, requieren de mecanismos que permitirán sacarlos de situaciones de
bloqueo debidas a este tipo de perturbaciones.
Uno de los mecanismos que muchos microcontroladores y autómatas
programables incorporan es el denominado «perro guardián» (watch dog), o
sistema de vigilancia, como pueda ser el módulo COP del 68HC11. Si por causa
del ruido el programa queda bloqueado (o bien entra en un bucle infinito por un
error de programación), cuando en su cuenta atrás el contador del sistema de
vigilancia llegue al estado cero reseteará el microcontrolador, devolviéndolo a su
operación normal. Como ya hemos estudiado, además del COP, el 68HC11
incorpora dos dispositivos de vigilancia adicionales, un detector de instrucciones
ilegales y un monitor del reloj del sistema.
En ocasiones, la tensión de alimentación por diversas circunstancias puede
fluctuar y durante unos instantes descender por debajo de la tensión mínima de
alimentación del sistema, pudiéndose recuperar tras unos instantes. La operación
de un microprocesador alimentado por debajo de la tensión que indica el
fabricante es impredecible, pudiendo quedar en una situación de bloqueo; en
determinadas aplicaciones ello puede resultar peligroso (pensemos en el sistema
de frenado ABS con su microcontrolador «colgado»). Para evitarlo, un
dispositivo hardware de seguridad para microprocesadores habitual en los
sistemas específicos son los circuitos detectores de pérdida de alimentación, que
monitorizan continuamente el estado de la tensión Vcc de alimentación. Cuando
se observa que la alimentación desciende por debajo de cierto valor (p.e., 4,5 V),
se activa una línea de interrupción no enmascarable, a lo cual el microprocesador
responderá almacenando en un lugar seguro (memoria EEPROM o NVRAM)
determinados datos de importancia, quedando a continuación en estado de
«espera» o «alto». Cuando tras breves instantes (fracciones de segundo) la
342 Microprocesadores y microcontroladores

alimentación se recupera, el microprocesador retomará los datos salvaguardados y


proseguirá con su operación. Remitimos al interesado en estos temas a los libros
de datos y página web de la compañía MAXIM (http://www.maxim-ic.com), una
de cuyas especialidades son precisamente estos circuitos de vigilancia (algunos
circuitos típicos son el MAX690 y el más completo MAX808N).
La redundancia del hardware es otra técnica que mejora la fiabilidad de la
operación del sistema. Por ejemplo, en el caso del sistema de frenado ABS un
microcontrolador principal se encarga de realizar todas las tareas, mientras que un
segundo microcontrolador (el «suplente», puede que incluso de otra casa
diferente) está en permanente espera de que el «titular» pueda «lesionarse», para
tomar él el control del sistema. En el caso del piloto automático de los aviones,
son tres los sistemas microprocesadores diferentes que gobiernan el aparato, cada
uno ejecutando su propio programa, distinto al de los otros. Cada uno, por lo
tanto, en cada instante sugiere determinada acción, y la que se acaba ejecutando
se decide por mayoría.
Un mecanismo software sencillo que permite comprobar si algún byte del
programa almacenado en memoria ha cambiado a causa de algún pico de ruido, o
bien si se ha producido un error en una transmisión de datos, es el denominado en
inglés checksum, que consiste en conocer cuál es la suma de todos los bytes que
componen el programa (o el bloque de datos que se transmiten) y comprobar de
vez en cuando si dicha suma se mantiene o si ha variado. Para el caso de la
transmisión de datos, es usual también el empleo de la técnica del bit de paridad,
los denominados códigos redundantes, o incluso los autocorrectores.
Capítulo 8
Microprocesadores de altas prestaciones

8.1. Tipos de microprocesadores


Aunque a lo largo del presente texto se ha tratado de proporcionar una visión
general del campo de los microprocesadores, normalmente se ha incidido en el
punto de vista de su aplicación en la industria. Así, se han estudiado en mayor
profundidad µP de capacidad de cálculo modesta, como son los de 8 bits, que,
aparte de ser los más habitualmente empleados en aplicaciones relacionadas con
la electrónica industrial, consumo y automóvil, ilustran perfectamente la mayoría
de los conceptos básicos relativos al desarrollo de sistemas µP (arquitectura y
organización de la CPU, programación, buses, circuitos de soporte y E/S).
No obstante, con el fin de completar el panorama de los microprocesadores
disponibles en la actualidad, en este último capítulo estudiaremos los de mayores
prestaciones, como puedan ser los que se incorporan en los computadores o los
procesadores digitales de señal (DSP), lo cual nos dará pie para realizar una breve
introducción a conceptos más avanzados, como los relativos a las arquitecturas
RISC, la segmentación o el procesamiento paralelo, no contemplados en el caso
de los limitados microprocesadores de 8 bits.

8.1.1. Clasificación de los microprocesadores por su finalidad


Como ya se apuntó en el capítulo anterior, multitud de empresas fabrican
microprocesadores de muy diversas características, de modo que la oferta
disponible en el mercado resulta ser extraordinariamente extensa (fig. 8.1); a
continuación mostraremos diversas posibles clasificaciones. En primer lugar, los
µP pueden clasificarse atendiendo al número de bits; un mayor número de bits
suele traducirse en una mayor potencia de cálculo, pero también supone una más
elevada ocupación de área de silicio y, por lo tanto, un precio superior.
Una clasificación alternativa atiende a la finalidad para la que se han
diseñado; así, podemos hablar de µP de propósito general y de propósito
específico. Los microprocesadores de propósito general constituyen
normalmente la base para la construcción de computadores y servidores para todo
tipo de aplicaciones. Dentro de este grupo distinguiremos los siguientes:
344 Microprocesadores y microcontroladores

INTEL MOTOROLA

4004
8008

MOS Tech.
8080 Rockwell
Zilog 6800
8048 Z80
6502
8085
6802

8086 Z8 Z8000 6801 6809


8051 68000
8088
80186/8 6805
68008
8052 80286 68010
8096

8051 8051 80386 Z80000 68HC11 68020


(Philips) (Siemens) Z180
Z280
80486 68HC05 68030
80C51XA 68HC16
(Philips) Pentium 68040 Motorola
68HC08 + IBM
Pentium Pro 68HC12
Pentium II
Intel+ HP PowerPC
Pentium III IA 64
(Merced)

FIGURA 8.1. Árbol genealógico de las familias de microprocesadores y microcontroladores de Intel y


Motorola.

• Microprocesadores. En este grupo incluimos tanto los clásicos (Z80, 6800,


6502, 8080/8085, 8086, 68000), que integraban exclusivamente una CPU,
como los más modernos (últimos miembros de las familias 68K, 80x86,
PowerPC, Pentium, etc.), que pueden integrar además en la misma pastilla
memoria caché, coprocesador matemático, controladores de DMA, unidades
funcionales diversas (enteros, punto flotante multimedia), etc.
• Máquinas paralelas. Los microprocesadores clásicos operan normalmente en
solitario, como CPU de un sistema electrónico o computador, ejecutando
instrucciones en serie (una tras otra). Sin embargo, hay microprocesadores
orientados al trabajo en paralelo, o a construir sistemas de cómputo para
cálculo paralelo. Estos sistemas van más allá de la arquitectura von Neumann
clásica (serie), al permitir la ejecución de muchas instrucciones a la vez, o bien
aplicar una instrucción sobre muchos datos al mismo tiempo. El transputer de
Inmos y Thonsom (contracción de «transistor» y «computer») es un ejemplo
de µP orientado a estas aplicaciones, aunque se construyen máquinas paralelas
de todo tipo, basadas en unos cuantos DSP o incluso en varios
microprocesadores convencionales (por ejemplo, Pentium).
Microprocesadores de altas prestaciones 345

Por otro lado, los microprocesadores de propósito específico están orientados


a una determinada clase de aplicaciones. Así, se dispone de los siguientes tipos:
• Microcontroladores, o computadores en un único chip. Como ya sabemos, se
trata de microprocesadores orientados a la electrónica industrial y de consumo,
especializados en el desarrollo de sistemas específicos de control y medida, y
cuyo precio resulta en general barato. Se basan en un núcleo procesador o
CPU, junto al cual se integra en el mismo chip memoria, puertos de E/S y
periféricos diversos (conversores, temporizadores, etc.). Los más empleados
son los de 8 bits, muchos de los cuales se construyen alrededor de un núcleo
procesador clásico (como, por ejemplo, un 6800).
• Procesadores digitales de señal o DSP (Digital Signal Processor). Se trata de
microprocesadores especialmente orientados al audio, vídeo, multimedia y
telecomunicaciones, campos en los que se deben procesar en tiempo real
señales digitalizadas haciendo uso de algoritmos matemáticos que involucran
la realización de numerosos cálculos (transformada de Fourier, filtros digitales,
compresión, encriptado, etc.). Por ello, los DSP están especializados en la
ejecución de operaciones matemáticas intensivas a una gran velocidad,
incorporando para ello numerosos registros, multiplicadores hardware,
registros de desplazamiento especiales, etc. Como estudiaremos en la sección
8.5, se basan en una variante de la arquitectura von Neumann denominada
arquitectura Harvard, que posee dos espacios de memoria separados, de datos
y de instrucciones, cada uno con su propio bus.
• Coprocesadores. Se trata de microprocesadores diseñados para operar junto a
un procesador principal, al cual descargan de realizar determinadas tareas. Los
más conocidos son los coprocesadores matemáticos (como el famoso 8087 de
Intel), especializados en la ejecución de operaciones matemáticas de alta
precisión, punto flotante, etc., que los µP clásicos solamente podían realizar
por software. Sin embargo, hoy en día los modernos y potentes µP, como
cualquiera de los de la familia Pentium o PowerPC, integran el coprocesador
matemático en la misma pastilla. Otro tipo de coprocesadores son los de
entradas/salidas, pensados para liberar a la CPU de las tareas que involucran
acciones sobre periféricos (un ejemplo clásico es el 8089 de Intel).
• Procesadores neuronales y borrosos. Los procesadores neuronales son
máquinas paralelas compuestas por numerosos procesadores elementales o
neuronas, constituyendo redes neuronales artificiales (Artificial Neural
Networks), que tratan de emular el comportamiento y propiedades de las
biológicas. Los procesadores borrosos realizan operaciones pertenecientes a la
lógica borrosa (fuzzy logic), que generaliza la lógica booleana para tratar de
346 Microprocesadores y microcontroladores

manejar la imprecisión del mundo real. Ambos están orientados a incorporar


un tipo de inteligencia próxima a la biológica en equipos de consumo,
industriales, de automoción, etc., por lo que están causando una pequeña
«revolución» en la forma de entender la inteligencia artificial, que ahora puede
situarse mucho más cerca del ciudadano medio [Martín del Brío 97b]. En la
sección 8.6 se realizará una breve introducción a este tema.

8.1.2. Clasificación atendiendo a la tecnología de integración


Las clasificaciones que atienden al número de bits o a la finalidad del µP son
muy habituales; sin embargo, en ocasiones los microprocesadores también se
agrupan en función de la tecnología de integración empleada en su
implementación, las cuales marcan las denominadas generaciones:
a) Primera generación (1971-73). Es la de los primeros microprocesadores, de
tecnología PMOS (4 y 8 bits). Se trataba de µP de bajo coste, reducida
velocidad, alimentación doble y no compatibles TTL. Ejemplo: 4004.
b) Segunda generación (1973-78). Microprocesadores integrados mediante
tecnología NMOS, con mayor densidad, más rápidos y compatibles TTL.
Suelen considerarse los microprocesadores «clásicos», que por su sencillez son
a menudo empleados en la enseñanza. Ejemplos: 6800, 6809, 6502, 8085,
Z80.
c) Tercera generación (1978-). Microprocesadores realizados en tecnologías
CMOS convencionales y CMOS mejoradas, de mayor velocidad y menor
consumo que los de la segunda generación. Ejemplo: los µP de 16 bits que
nacen a finales de los años setenta, como el 8086 y el 68000.
d) Podría hablarse de una cuarta generación constituida por microprocesadores
más recientes que hacen uso de tecnología BiCMOS, con la idea de mejorar en
velocidad (bipolar) y reducir el consumo (CMOS). Ejemplo: Pentium.
Durante los años noventa se han venido empleando tecnologías de
integración submicrónicas (de anchura de canal inferior a la micra), como la de
0.35 micras; los microprocesadores más modernos (p.e., Pentium II, PowerPC) se
integran en tecnologías de 0,25 y se empiezan a desarrollar integrados con
tecnologías de 0,18 y 0,12 micras. En los últimos años se han puesto a punto
algunas novedades dentro del proceso de integración, como el empleo de las
tecnologías SOI (Silicon On Insulator), que al introducir una capa aislante (óxido
de silicio) entre el substrato de silicio y la circuitería reduce los efectos parásitos,
lo que permite un incremento del rendimiento en un 20 o 30%. También hay que
destacar el empleo de conexiones de cobre dentro del chip, de menor resistencia
Microprocesadores de altas prestaciones 347

eléctrica que las clásicas de aluminio; el empleo de tecnologías SOI y conexiones


de cobre permite integrar µP más rápidos y de menor consumo. Para que el lector
se haga una idea de las características de los µP más avanzados que incorporan
estas tecnologías, podemos comentar que IBM ha desarrollado una versión con
tecnología SOI de la arquitectura PowerPC a 500 MHz, y Digital (compañía
recientemente adquirida por Compaq) una versión de Alpha a 600 MHz [Burksy
99]. Empleando tecnología SOI (0,12 micras) y conexiones de cobre, IBM ha
desarrollado el PowerPC750/G3 a 580 MHz. A la par, las nuevas tecnologías
permiten incorporar más transistores en el chip; así, Hewlett-Packart ha integrado
la arquitectura PA-RISC junto con 1,5 MB de caché en un único integrado de
21,3x22 mm, con 116 millones de transistores en total (el 8086 incluía menos de
30.000), operando a 500 MHz y alimentado a 2 V [Burksy 99].

8.1.3. Microprocesadores CISC y RISC


Para finalizar, comentaremos que también suele distinguirse entre
microprocesadores de arquitectura CISC o RISC. Aunque la comprensión de lo
que implica esta clasificación involucra conceptos más profundos, que serán
estudiados con más detenimiento en la sección 8.4, presentaremos a continuación
con brevedad algunas de sus características más relevantes:
a) Arquitecturas CISC (Complex Instruction Set Computer), o de gran número de
instrucciones. La tendencia de los ordenadores durante los años cincuenta y
sesenta fue aumentar su potencia incorporando más y más instrucciones, cada
vez más complejas (próximas a las de los lenguajes de alto nivel), con lo que
las unidades de control resultaban cada vez más complicadas, construyéndose
microprogramadas: ésta es la base de la filosofía CISC. Los primeros µP
imitaban a estas CPU, incorporando así numerosas instrucciones. Conforme la
tecnología de integración progresaba, se iban añadiendo más y más nuevas
instrucciones, de ahí que todos los µP clásicos atiendan a este esquema CISC
(por ejemplo, un simple 6800 posee más de setenta instrucciones). Por lo
tanto, el diseño de un µP de estas características tiende a ser cada vez más
enrevesado, debiéndose recurrir siempre a la confección de unidades de control
microprogramadas (lentas y de gran tamaño), y las instrucciones suelen tardar
muchos ciclos de reloj en ejecutarse.
b) Arquitecturas RISC (Reduced Instruction Set Computer), o de reducido
número de instrucciones. Se trata de una tendencia iniciada en los años
ochenta, que en la actualidad se ha impuesto en los µP de muy altas
prestaciones. Una de las ideas sobre las que se apoya es que, al reducir el
número de instrucciones a únicamente una treintena (las más habitualmente
empleadas), la complejidad de la unidad de control se reducirá notablemente,
348 Microprocesadores y microcontroladores

con lo que podrá realizarse cableada en vez de microprogramada (más pequeña


y veloz). Las instrucciones además son muy sencillas y regulares, tendiendo a
operar sobre los registros internos. El resultado es que la ejecución de las
instrucciones resulta más rápida (sobre todo introduciendo la técnica de
segmentación que estudiaremos), y al ocupar la unidad de control cableada
menos área de silicio se podrán incorporar más registros. Las familias clásicas
80x86 y 68K son CISC, pero la enorme potencia de los nuevos RISC, como
SPARC o Alpha, hace que dominen en la actualidad el nicho de mercado de
los computadores de altas prestaciones.
En definitiva, actualmente todos los microprocesadores de altas prestaciones
son RISC, o por lo menos «quasi-RISC» (así podríamos considerar el Pentium),
mientras que la mayoría de los dedicados a tareas más modestas, como los
microcontroladores, siguen siendo CISC en la mayoría de los casos (el PIC de
Arizona Microchip constituye una de las pocas excepciones). En la sección 8.4
abordaremos con mayor amplitud este importante tema.
Realizada esta breve exposición de los diversos tipos de microprocesadores
disponibles, en las próximas secciones ampliaremos algunos de los aspectos
introducidos, especialmente los relacionados con el aumento de prestaciones.

8.2. Microprocesadores de 16 bits: familia Intel 80x86


Una manera de lograr un considerable aumento de prestaciones consiste en
incrementar el número de bits que el microprocesador es capaz de tratar en
paralelo, y ampliar la anchura de su bus de direcciones para permitir el
direccionamiento de más memoria. Así, tras el desarrollo durante los años setenta
de los clásicos µP de 8 bits (8080/85, 6800, 6502, Z80), normalmente con 16
líneas de direcciones (que permiten direccionar hasta 64 KB), se da a finales de la
década el paso natural del desarrollo de µP de 16 bits, como los famosos 8086 de
Intel y 68000 de Motorola. Estos µP poseían entre 20 y 24 líneas de direcciones
(que les permitían acceder de 1 a 16 MB de memoria), juegos de instrucciones
más extensos (con instrucciones específicas para multiplicación, manejo de tablas,
etc.), operaban a frecuencias más elevadas (varios MHz) e incluían más elementos
integrados (registros, memoria, etc.).

8.2.1. El 8086 de Intel


En esta sección estudiaremos el 8086 como ejemplo de µP de 16 bits. El
8086 fue introducido por Intel en 1978; miembro inicial de la prolífica familia
80x86, ha resultado ser uno de los µP de mayor importancia histórica. El 8088 es
Microprocesadores de altas prestaciones 349

una versión derivada del 8086, de similar estructura y funcionamiento (por ello, a
menudo hablaremos del 8086/88), pero con bus externo de 8 bits, lo que permitía
su compatibilidad con los periféricos desarrollados para la familia anterior
8080/8085 (equiparables al 6800).
Es importante establecer ya desde el principio que precisamente la
compatibilidad es a la vez la mayor ventaja y desventaja de los µP de Intel. Esta
compañía se ha distinguido siempre por tratar de mantener la compatibilidad del
software al comercializar nuevas versiones de µP, para poder así aprovechar el
código previamente desarrollado. La gran desventaja de esta tendencia es no
poder sacar el máximo partido de las posibilidades que una nueva tecnología de
integración puede ofrecer, pues los nuevos desarrollos quedan «encorsetados» o
«lastrados» por el peso de la historia (compatibilidad).
Para comprender el porqué de la importancia del microprocesador 8086/88
retrocedamos a 1971. En esta fecha la joven compañía Intel (situada en el Valle
del Silicio en California), entonces especializada en la fabricación de chips de
memoria, inventa el microprocesador, de modo que sus primeros diseños (4004,
8008) no contaban con competencia alguna a principios de los años setenta.
Sin embargo, por la época en la que Intel saca al mercado el 8080 (1974)
multitud de compañías trabajan ya en sus propios diseños (como Motorola en su
6800). A mitad de década los microprocesadores más populares son, sin duda, el
6502 de la compañía MOS y el Z80 de Zilog; por otra parte, Motorola
comercializa el 6809 (la evolución del 6800), que se considera el microprocesador
de 8 bits más potente nunca construido. Intel, consciente de su pérdida de
mercado dentro de un campo que ellos mismos han inventado, trata de recuperar
el terreno perdido fabricando el primer microprocesador de 16 bits, el 8086, pero
Motorola en seguida comercializa el 68000, de 16/32 bits, en opinión de muchos,
más «racional», «elegante» y potente que el 8086.
Dada su delicada situación, Intel emprende una intensa campaña de
marketing tratando de vender su 8086 a diversas empresas (una de las claves del
éxito de Intel ha sido siempre su capacidad de marketing [Malone 96]).
Recordemos que por esta época los microprocesadores se empleaban casi
exclusivamente en tareas de control, sustituyendo lógica digital convencional
(dentro de calculadoras, terminales, etc.). Sin embargo, por entonces se empiezan
a comercializar ya los primeros microordenadores, pequeños computadores
basados en µP de 8 bits como el 6502, Z80, 8080 o 6800, de limitada capacidad
de cálculo, pero de gran atractivo para un amplio sector de aficionados. Avanzada
la década de los setenta una joven compañía denominada Apple alcanza un
enorme éxito con sus microordenadores basados en un 6502.
350 Microprocesadores y microcontroladores

En estas condiciones IBM, que siempre se había distinguido por el desarrollo


de grandes computadores, decide participar en el nuevo mercado de los
microordenadores, pero en vez de diseñar un microprocesador propio decide
emplear alguno de los disponibles en la época, como el 6809, el Z8000
(descendiente del Z80) o el potente 68000. La elección final para la CPU de su
ordenador PC (Personal Computer) recae, sin embargo, en el 8088 de Intel...; esta
decisión hizo que la historia de la electrónica y la informática adquiriera un nuevo
rumbo. El PC tuvo un enorme éxito desde el principio (mucho más del
inicialmente previsto), y en poco tiempo la industria de los computadores
personales resultó ser uno de los negocios más lucrativos del siglo XX, gracias a
lo cual Intel se convertirá en la compañía de electrónica de mayor volumen de
ventas, y Microsoft (que diseña el sistema operativo MS-DOS para el PC)
dominará la nueva industria del software (toda esta historia se narra con detalle en
el estupendo libro [Malone 96]).
Tras esta breve reseña histórica que establece el contexto en el que se
desarrolló el 8086/88, enumeraremos a continuación algunas de sus
características más sobresalientes:
a) Bus de datos 16 bits (en el caso del 8088 externamente se presentan sólo 8
bits).
b) 20 líneas de direcciones (hasta 1 MB de memoria).
c) Más de 100 instrucciones (300 opcodes).
d) Tecnología HMOS (High MOS).
e) 0,2 MIPS (Millones de Instrucciones Por Segundo).
f) 4,77 MHz (versiones posteriores alcanzaron 8 y 12 MHz).
g) 29.000 transistores integrados.
h) Encapsulado DIP-40.

La organización interna del 8086 se estructura en dos unidades funcionales,


la unidad de ejecución y la de interface con el bus (fig. 8.2), las cuales trabajan
con cierta autonomía:
Microprocesadores de altas prestaciones 351

AH AL
BDir (20)
BH BL
Cálculo
CH CL dirección
Registros
DH DL efectiva Σ
propósito
SP general
BP
BDat (16)
DI
SI
CS
BDat ALU (16) DS
SS
ES Control
IP de los
buses Buses
Registros Auxiliares Registros Auxiliares
8086/
8088
Sistema
de
Control
Cola de instrucciones
ALU
Bus Q (8)
1 2 3 4 5 6
Indicadores
:::::::
EU (Execution Unit) BIU (Bus Interface Unit)

FIGURA 8.2. Organización interna del 8086 (en el 8088 la cola es de 4 bytes).

a) Unidad de ejecución o EU (Execution Unit), que contiene la unidad de control


y la ALU, además de parte de los registros, y que se encarga de decodificar y
ejecutar las instrucciones.
b) Unidad de interface con el bus o BIU (Bus Interface Unit), que gestiona los
buses. Esta unidad, de forma autónoma, y cuando los buses del sistema no son
empleados, recoge instrucciones de memoria y las almacena en una cola FIFO
con capacidad para 6 bytes (4 en el caso del 8088), de la cual la EU va
tomando las instrucciones a ejecutar. La BIU obtiene además los registros que
definen los diferentes segmentos de memoria, más la unidad de cálculo de
direcciones efectivas.
El 8086 cuenta con un buen número de registros (todos ellos de 16 bits), cada
uno con su propio papel (fig. 8.3):
a) Registros de propósito general: AX, BX, CX, DX (cada uno puede ser
interpretado como dos registros de 8 bytes, H y L, concatenados, por ejemplo,
AX=AH:AL).
b) Registros de segmento de memoria: CS, DS, SS y ES (definen los segmentos
de código, datos, pila y extendido, respectivamente).
352 Microprocesadores y microcontroladores

15 87 0
AX AH AL Acumulador
BX BH BL Base
CX CH CL Contador
DX DH DL Dato
0 C Acarreo (Carry)
15 0
SP Puntero de pila
P Paridad (Parity)
BP Puntero base
SI Puntero origen
A Auxiliar (Auxiliary Carry)
DI Puntero destino

Z Cero (Zero)
CS Segmento de código
S Signo (Sign)
DS Segmento de datos
T Trampa (Trap)
SS Segmento de pila
I Máscara de int. (Int. Mask)
ES Segmento extra
D Dirección (Direction)
O Desbordamiento (Overflow)
IP Puntero de instrucciones
(contador de programa)

:::::::::: Registro
Indicadores
de estado
(flags)
(flags)
15

FIGURA 8.3. Registros del 8086/88.

c) Punteros: SP, BP, SI y DI (de pila, de base, fuente y destino,


respectivamente).
d) Contador de programa IP (Instruction Pointer).
e) Registro de estado (Status Register), con los siguientes flags: O (Overflow), D
(Dirección), I (máscara de Interrupciones), T (Trap), S (Signo), Z (Zero), A
(Auxiliary carry), P (paridad) y C (carry).
Dos de las características más importantes que definen un microprocesador
son su juego de instrucciones y los modos de direccionamiento que soporta. El
8086 contempla los siguientes modos direccionamiento:
• Inmediato. • Indexado
• Directo por registro • Indexado por registro base.
• Directo • De cadena.
• Indirecto por registro. • De entrada/salida.
• Por registro base.
Microprocesadores de altas prestaciones 353

Y del amplio juego de instrucciones del 8086/88, presentaremos a


continuación las siguientes a modo de ejemplo:
MOV destino, fuente SUB destino, fuente
PUSH fuente MUL fuente (fuente*AX)
POP destino IN
ADD destino, fuente OUT

Una de las características diferenciales tanto del 8086 como de sus


descendientes es lo «enrevesado» de la gestión de su memoria. En el 8086 la
memoria se divide en cuatro áreas que el programador debe definir: área de
código (o de programa), de datos, pila y área extra. Dentro de cada área, a su vez,
se trabaja en segmentos de 64 KB: al comienzo del programa ensamblador se
debe cargar en cada uno de los registros de segmento (CS, DS, SS y ES) un valor
de 16 bits, el cual definirá el segmento de 64 K concreto sobre el que se va a
trabajar en cada caso, dentro de él se necesitan otros 16 bits para señalar la casilla
concreta de memoria a la que se va a acceder.
La BIU del 8086, en función del segmento actual (16 bits) y de la dirección
dentro del segmento (16 bits más), calcula la dirección efectiva o EA (Effective
Address) de 20 bits, que permite direccionar hasta 1 MB de memoria. Puede
observarse que 16+16=32, mientras que se dispone de tan sólo 20 bits para
determinar la dirección, por lo que la confección de la EA no consistirá en el
simple concatenamiento de segmento y desplazamiento (la solución más obvia y
sencilla). Ilustraremos con un ejemplo cómo la BIU construye una EA: si el
8086 debe recoger una instrucción de memoria, y el valor actual del segmento de
código (programa) es CS=3502 y el del contador de programa (puntero de
instrucciones) es IP=103, la BIU desplaza el valor binario de CS cuatro bits hacia
la izquierda (lo que equivale a multiplicar su valor decimal por 16), cantidad a la
que suma el actual valor del IP, construyendo así una dirección efectiva de 20
bits, en este caso: EA=16×CS+IP=56135 (el lector atento habrá deducido de lo
expuesto que los segmentos en los que la memoria del 8086 queda dividida en
realidad se solapan).
Es importante hacer notar que el acceso a memoria en los microprocesadores
de Motorola (como el 6800, 68HC11 o el 68000) resulta muy diferente al descrito
para los Intel, pues en este caso la memoria se gestiona de forma absolutamente
lineal, de modo que su acceso resulta tremendamente simple (una dirección, un
dato; sin segmentaciones extrañas de 64 KB). Otro rasgo distintivo de la familia
80x86 es la separación entre los espacios de memoria y de entradas/salidas, cada
uno con sus propias direcciones e instrucciones particulares (MOV para memoria,
354 Microprocesadores y microcontroladores

IN y OUT para entradas/salidas). En los µP de Motorola, sin embargo, existe un


único espacio, de modo que con instrucciones LDA y STA se puede leer y
escribir tanto en memoria como en los puertos de E/S.

8.2.2. La familia 80x86 de Intel


La familia 80x86, desarrollada durante los años ochenta y noventa a partir del
8086 original, ha tratado siempre de mantener la compatibilidad con sus
antecesores; ello cuenta con la ventaja de permitir la reutilización del software
desarrollado para µP más antiguos, pero como contrapartida se arrastran muchas
«taras históricas», características arquitecturales que en un momento dado se
deben adoptar por no permitir la tecnología disponible la incorporación de
mejores soluciones, y que cuando esa tecnología ya está disponible hay que
mantener por compatibilidad (por ejemplo, la limitación de memoria convencional
accesible desde el MS-DOS a 1 MB, o su estructura segmentada). Por este
motivo, ha resultado habitual en los descendientes del 8086 el no lograrse
prestaciones tan elevadas como podría esperarse en relación al nivel de la
tecnología disponible en ese momento, y que microprocesadores cuyas casas que
en un momento dado «rompen con la tradición» sí consiguen (como sucedió con
la familia 68000 de Motorola con respecto de la 6800).
Presentamos a continuación algunos miembros de la familia 80x86, que
seguro que al lector le resultarán conocidos:
a) 8086 (1978), el origen.
b) 8088, de similares características, pero con bus externo de 8 bits. Incorporado
en el PC original y en el posterior PC/XT.
c) 80186/8, es un 8086/88 con generador de reloj, dos canales de DMA,
controlador de interrupciones y tres temporizadores, todo ello integrado en un
mismo chip. Se emplea en aplicaciones específicas, no en computadores.
d) 80286 (1982), empleado en el PC/AT y PS/2 (modelos 50 y 60). Capaz de
gestionar hasta 16 MB de memoria real, o 1 GB (gigabyte) de memoria virtual.
Puede operar en dos modos, real (emula un 8086) y protegido, éste último
pensado para multitarea. Posee 1 GB de capacidad de direccionamiento,
permite el aislamiento de datos y programa en tareas individuales, etc.