Introduccion Al 8051
Introduccion Al 8051
Introduccion Al 8051
Universidad de Huelva
INTRODUCCIÓN AL 8051
TERCER CURSO. ELECTRÓNICA DIGITAL
BIBLIOGRAFÍA
1.- Introducción.
Intel diseñó allá por el año 1982, el miembro más importante de la familia de
microcontroladores MCS-51 para aplicaciones industriales, el 8051. Este microcontrolador
contaba con 4K de EPROM y 128 bytes de memoria RAM interna. Posteriormente se fueron
añadiendo más miembros a esta familia que aumentaron la cantidad de EPROM y RAM
internas, posibilitando la creación de programas aún más complejos.
?? CPU.
?? Memoria dedicada a contener programas (ROM).
?? Memoria para soporte de datos temporales (RAM).
?? Módulos de Entrada/Salida (Puertos paralelo y serie, temporizadores, etc).
Con carácter general, los microcontroladores se emplean en los sistemas de control que
reúnan las siguientes propiedades:
?? Electrodomésticos.
?? Automoción.
?? Teclados, displays, impresoras, modems y calculadoras.
?? Instrumentos de medida y sistemas de alarma.
?? Electromedicina.
?? Equipos de audio y video.
?? Paneles de control y comunicaciones móviles.
?? Máquinas de coser y bordar.
?? Juegos electrónicos y tragaperras.
Aunque nos concentramos en la familia del 8051, esto no limita el campo de acción,
puesto que si encontramos el compilador de C apropiado, podemos transferir los ejemplos, a
pesar de las extensiones del lenguaje, a otras familias de microcontroladores. Puesto que la
mayoría de microcontroladores tienen temporizadores internos similares y puertos, los ejemplos
que emplean características internas también se pueden adaptar. Aunque los comandos para
arrancar los temporizadores e interrupciones pueden comportarse de forma diferente, los
principios básicos se mantienen.
2.- Software.
Para escribir un programa en lenguaje de alto nivel no es necesario tener idea de cómo
funciona el hardware por dentro, como sucede con muchos programadores novatos. Como
vamos a usar el lenguaje de programación C bastante, vamos a comenzar viendo un ejemplo
para aclarar el objetivo del tema. Ahora veremos como se transforman las líneas de un programa
en C a las instrucciones máquina especificas que se ejecutan en el microcontrolador.
Para comenzar, usaremos un programa simple que para su funcionamiento necesita como
entradas ocho conmutadores conectados a un puerto de entrada/salida (E/S) y ocho LEDs a un
segundo puerto. El programa lee el patrón de conmutadores, suma tres al valor que ha leído, y
manda el resultado a los LEDs. En otros apartados hablaremos del hardware, pero por ahora
observemos el software que necesitamos y como funciona.
void main(void) {
while(1) {
luces = conmutadores + 3;
}
Este es el programa en C que hace esto. Como pasa con la mayoría de programas en C,
hay varias líneas antes de las instrucciones que hacen la función. Realmente, la única línea que
funciona es la séptima donde se les suma tres a las entradas de los conmutadores antes de enviar
el dato a los LEDs. La segunda línea incluye un fichero que le indica al compilador todos los
detalles hardware específicos a la familia 8051. Las dos líneas siguientes asignan el nombre
luces al puerto 3 (P3) y el nombre conmutadores al puerto 1 (P1). La línea siguiente es necesaria
porque en todo programa C completo necesita una función main, después analizaremos las
subrutinas y funciones. El while(1) es una forma de decir que queremos realizar la operación
una y otra vez sin fin. Las llaves { y }, son como delimitadores para mantener las operaciones
en su lugar y señalar cuando esta comienza y termina.
De esta forma, empleando el entorno de desarrollo suministrado por KEIL, que será el que
empleemos en el laboratorio, y habiendo escrito el programa como muestra la figura.
Seleccionamos del menú adecuado que se compile el fichero haciendo clic en Project, Compile
File.
Ahora, hacemos clic en File, Nuevo y encontramos el fichero de listado que ha generado
el compilador. Aquí están copiadas las partes esenciales.
La última instrucción es la que hace que este programa tenga un bucle sin fin. El salto
corto, código 80H, emplea el segundo byte, con la dirección donde se encuentra la siguiente
instrucción (0008H en este caso) para generar la siguiente dirección (0008H + F8H = 0000H).
El salto corto solo puede llevar a una dirección no más de 128 posiciones en cualquier sentido a
partir de la dirección actual. Emplea menos códigos de instrucción que un salto largo que puede
avanzar o retroceder a cualquier parte en un rango de 16 bits en la familia del 8051.
Comentaremos brevemente la forma en que los códigos de instrucción se componen en el
ordenador y de que forma cambia el puntero de instrucción.
¿ C o Ensamblador ?
Aunque la mejor elección para programar el 8051 es en C, si queremos entender la
operación que realiza internamente tendremos que usar ensamblador. Si escribimos en C, un
compilador realizará el paso de lenguaje de alto nivel a código máquina. Si escribimos en
lenguaje ensamblador, un ensamblador trasladará los nemónicos a los códigos numéricos
equivalentes. Podríamos realizar el ensamblado a mano buscando los códigos en una tabla, pero
esto no se hace en la práctica por lo tedioso que resulta.
- UCP de 8 bits
- Memoria de datos (RAM) de 128 bytes.
- Memoria de programa (ROM) de 4KB (8051).
- 4 puertos de E/S con 8 líneas cada uno.
- 1 puerto de E/S serie.
- 2 contadores-temporizadores de 16 bits programables.
- 1 oscilador para las señales de reloj.
1. Memoria interna de datos: posee 256 bytes, de los cuales 128 se dedican a registros
específicos de la CPU y los restantes a datos, el 8752 posee otros 128 bytes más
accesibles solo mediante direccionamiento indirecto.
2. Memoria interna + externa de código: de los 64 KB totales de esta zona, los 4 KB
inferiores son los que se hallan implementados en el propio chip como ROM
programable en fábrica (el 8752 posee 8 KB). Los 60 KB restantes hay que
conectarlos externamente.
3. Memoria externa de datos: el 8051 puede direccionar hasta 64 KB de memoria
RAM externa.
La figura anterior muestra una vista más detallada, especifica a la familia 8051. Junto con
la UCP, tenemos también memoria ROM y RAM, así como E/S. Se muestra un bus sencillo
aunque direcciones y datos viajan internamente sobre líneas separadas. Por ahora, ignoramos las
interrupciones y los temporizadores.
La siguiente instrucción, ADD A,#03H, tiene lugar enteramente dentro de la UCP tras
haber realizado un ciclo FETCH para leer de memoria el código de la instrucción. El proceso de
la suma hace uso de la unidad lógica aritmética del interior de la UCP. Además de la suma,
existen intrucciones para la resta, multiplicación y división, así como operaciones lógicas como
AND, OR, or exclusiva y complemento.
Además de leer datos de E/S, los bytes de instrucción (código) provienen de la memoria,
por lo que también describiremos esta secuencia.
Dentro de la familia 8051 podemos tener desde 64 a 256 bytes de RAM interna para
almacenaje de datos, esta es la memoria estática más rápida y que tiene los más variados modos
de direccionamiento.
Los registros de función especial (SFR, Special function register) son direcciones de
memoria interna que controlan los “periféricos” disponibles en el chip, como los puertos,
temporizadores e interrupciones, así como otras características del procesador. En el ejemplo del
comienzo con luces y conmutadores, ambos puertos son registros de función especial (P1 en la
dirección 90H y P3 en la B0H). Otros SFRs de interes particular son el acumulador (ACC, en
dirección E0H), el registro B (en 0FH) y el puntero de datos (DPH en 83H y DPL en 82H). La
siguiente tabla muestra todos los SFR del 8051 estándar. Estos SFR figuran principalmente en
las instrucciones.
Con la excepción de unos pocos miembros, los más pequeños, toda la familia del 8051
pueden acceder a un espacio de memoria externa al chip. Para hacer esto, los 8 bits más
significativos de direcciones aparecen en el Puerto 2. Las direcciones más bajas y los datos
aparecen sobre el puerto 0. Para ahorrar patillas (el 8051 original solo tiene cuarenta) el puerto
P0 primero se emplea como los 8 bits menos significativos del bus de direcciones y luego como
bus de datos. Esto se denomina como sabemos multiplexado. Empleamos menos patillas pero se
reduce la velocidad de los accesos a memoria y necesitamos un latch externo de direcciones.
El acceso externo a memoria con el 8051 siempre es más lento tanto por el multiplexado
como porque necesitan una instrucción adicional para acceder a la posición de memoria externa.
Solo disponemos de tres instrucciones para realizar este acceso.
Puertos Paralelo. Los puertos paralelos son grupos de (normalmente ocho) bits sobre
patillas individuales. Un puerto paralelo latchea o retiene su valor hasta que volvemos a mandar
otro valor. Podemos realizar puertos de salida externos con latches de 8 bits (como el 74374).
Un puerto paralelo de entrada pasa los estados de las patillas al microprocesador en el instante
que se ejecuta la instrucción de copia para esa dirección. Podemos realizar puertos de entrada
mediante buffers triestado octales (como el 74244).
patillas de los puertos pueden tener otras funciones especiales, en caso de que las usemos de
esta forma, no debemos usar estas patillas como puertos de entrada o salida.
No hay forma de desactivar o fijar la dirección del puerto. Recordemos que las patillas del
puerto pueden absorber una corriente máxima de 1.6 mA pero solo ofrecer decenas de
microamperios. También, P0 cuando se usa como puerto de E/S (opuesto al bus de datos para
expansión de memoria externa) no dispone de resistencias de pull-up, el dispositivo externo
tendrá que proporcionar el nivel lógico alto.
Puertos Serie. Los puertos serie transfieren bits simples de datos uno tras otro, tomando al
menos ocho transferencias para intercambiar un byte. La forma más común de puerto serie
emplea solo una patilla para cada dirección de la transferencia. Normalmente el hardware
interno maneja los detalles de temporización e incluye los registros de desplazamiento
paralelo/serie. En conjunto, el hardware para esta función recibe el nombre de
transmisor/receptor asíncrono universal (UART). Este elemento descarga al procesador del
trabajo de gestionar la temporización y organizar los bits de forma que el procesador pueda
hacer otras tareas. Es posible mandar información serie directamente sobre patillas de puertos
ordinarios usando software y temporizadores, particularmente cuando la tasa de transmisión es
baja, pero resulta mejor usar el hardware de la UART cuando sea posible.
Para un ciclo fetch, tras un retardo controlado por el reloj, el procesador coloca una señal,
habilitación del almacenamiento de programa (PSEN). Esto provoca que el dispositivo de
almacenamiento de código habilite sus salidas triestado y dirija el bus de datos con el contenido
de la dirección particular de la instrucción que se está pidiendo. Al final de la señal PSEN, una
vez que el byte de código está en el bus, la CPU almacena el código desde el bus de datos.
Consideremos una instrucción que transfiere datos a dispositivos externos. En este caso,
las líneas de control RD o WR entran en juego. Tomemos la instrucción copiar a dato externo
(MOVX). Necesita que el operando se encuentre ya en el acumulador (quizás con MOV
A,#dato) y la dirección de memoria externa que se encuentre en el puntero de datos (DPTR).
Los pasos para ejecutar la instrucción (MOBS @DPTR,A) involucran buscar el byte de
instrucción, decodificarlo, poner el valor de DPTR en el bus de direcciones, poner el valor del
acumulador en el bus de datos, y luego activar la señal WR (escritura en memoria). Esta es la
finalidad de la CPU. Todos lo que hacen los dispositivos de memoria es reconocer la dirección
con su circuitería de decodificación y guardar los datos cuando la señal WR termine.
ALE
Esta señal, habilitación del latch de direcciones (ALE, address latch enable), se usa para
activar un latch externo que capture la parte baja de direcciones colocado sobre P0 antes de que
el dato sea transferido desde o hacia memoria externa.
PSEN
Habilitación del almacenamiento del programa (/PSEN, program store enable) indica que
la ROM debe colocar el código en el bus de datos. /PSEN solo se activa si se produce acceso a
memoria externa. Si colocamos la patilla /EA a masa, todos los accesos se realizan a la ROM
externa. Si dejamos /EA flotante alto, los accesos se realizarán en el rango dentro del chip que
no provocan que la señal /PSEN pase a nivel bajo.
Las formas de onda de la figura muestran un ciclo FETCH externo. Los bordes sugieren
que existen tiempos de subida y bajada asociados con las señales mientras que las señales en
medio (ni 1 ni 0) para P0 muestran el bus en triestado en los intermedios entre la colocación de
los datos. Si enganchamos un osciloscopio a las líneas del bus, podremos observar algo mucho
más indefinido, especialmente durante los tiempos de triestado.
Hay que tener en cuenta que un microprocesador concreto tiene una velocidad máxima
debido a estas transiciones no instantáneas. Mientras más pongamos el chip a su limite superior
de velocidad, más redondeadas aparecerán las señales y más probable será que el
microprocesador no funcione.
RD y WR
Estas señales solo se emplean para los dispositivos de almacenamiento externos y puertos
externos. El siguiente cronograma muestra la temporización de una instrucción MOBS. Si
usamos la instrucción MOBS con el acumulador como destino, generaremos una señal de
lectura y con el acumulador como fuente, una señal de escritura.
Mostrar una instrucción de tres bytes nos permite observar el hecho de que todos los
ciclos fetch involucran dos bytes, por lo que los ciclos fetch de uno o tres bytes incluyen un
ciclo fetch oculto.
3.5.2.- El oscilador
Todos los miembros de la familia del 8051 usan un cristal externo para el oscilador.
Podemos escoger, según el miembro de la familia, una frecuencia del cristal que varia desde 500
KHz a 33 o 40 MHz. Habrá que hojear el manual del fabricante de cada dispositivo en concreto.
Los puertos y otros SFRs también son direccionables a bit, por lo que por ejemplo, P3
puede direccionarse como byte B0H o puede direccionarse con instrucciones de bit desde B0H a
B7H. Los registros que también se pueden direccionar a bit se muestran en cursiva en la tabla.
Todas las direcciones de byte y bits de los SFR están por encima de 7FH para evitar conflictos
con la RAM interna (direccionable de forma directa) y la memoria de bit, direccionable bit a bit.
debe responder solo cuando se de una combinación especifica de bits en el bus de direcciones.
Esto se realiza mediante circuitería digital combinacional sencilla.
Para entender un decodificador hay que ir hacia atrás a partir de la salida y realizar un
análisis. Si la salida está a nivel bajo para activar el sistema, como deben estar las entradas?
Además, si las entradas están de esta forma, que señal genera el decodificador de direcciones?
En el esquema, el 74138 se ha
conectado para seleccionar una EPROM en
0000H, un chip de RAM en 2000H, un chip
de puerto paralelo (8255) en 4000H, y un
chip temporizador (8253) en 6000H. Como
podemos ver de las indicaciones binarias de
bit bajo el esquema, el circuito decodifica
solo las tres líneas superiores de direcciones. Para dispositivos de 8K de RAM o EPROM, todo
el resto de líneas se dirigen al dispositivo en sí. Para el 8255, sucede que solo tiene dos líneas
usadas en el chip (A0 y A1) por lo que el resto son bits no importa.
Este diseño puede reemplazar varios chips de lógica, varias PLDs y a veces varios
dispositivos analógicos. Por ejemplo, en lugar de usar un integrador con una gran constante de
tiempo para tratar una señal analógica, podemos sustituirlo por un conversor voltaje a frecuencia
que alimente el contador de un micro de un solo chip. También se pueden más prestaciones
extra sin consto, modificando tan solo el programa. Puede auto calibrarse, hacerse adaptativo, o
tener cualquier número de otras posibilidades para hacer el sistema más eficiente, más fácil de
calibrar y en definitiva más fácil de usar.
Una vez que hemos perdido los dos puertos, resulta sencillo añadir una RAM externa,
dando dos bits para RD y WR. El esquema siguiente muestra este tipo de sistema con RAM
extra y un dispositivo controlador de puertos 8255.
dirección donde algunos bits de direcciones no están conectados (dan igual) los otros bits se
consideran a nivel bajo normalmente, por lo que el 8255, usando solo los bits A0 y A1
internamente, tendrán direcciones desde (2000H a 3FFFH).
La expansión de la RAM emplea 2 bits de P3 para las señales /RD y /WR. Los controles
para la RAM externa (/RD y /WR) son diferentes de los controles para la EPROM (PSEN) por
lo que el código y los datos externos se pueden encontrar en las mismas direcciones numéricas.
La conexión más simple consiste en su conexión directa con las patillas del
microcontrolador, éste accede al dispositivo escribiendo y leyendo como si se tratase de un chip
de memoria.
También se puede conectar el display a un sistema completo y utilizar las señales /RD,
/WR y A13 para efectuar su decodificación en la parte más alta de direcciones como si se tratase
de una zona más de RAM. El display dispone de dos registros de escritura/lectura, en uno se
escribe la posición del cursor donde se va a escribir el carácter y en el otro registro se escribe el
carácter en cuestión.
En la siguiente figura podemos observar el cronograma necesario que tiene que realizar
el microcontrolador para realizar la escritura de una determinada posición de la memoria del
visualizador.