You are on page 1of 173

SISTEMAS ELECTRNICOS DIGITALES

Autores:

Fernndez Martnez Cesreo

Snchez Miralles lvaro
Sistemas Electrnicos Digitales.





1

Captulo 1 Filosofa del libro _______________________________________________ 5
Captulo 2 Arquitectura de un micro_________________________________________ 6
1 Introduccin ______________________________________________________________ 6
2 Objetivos y conceptos a entender en este captulo________________________________ 6
3 Modelo del programador de un micro _________________________________________ 6
3.1 La CPU _________________________________________________________________________ 7
3.2 La memoria______________________________________________________________________ 7
3.3 Codificacin de las instrucciones _____________________________________________________ 9
3.4 Ciclos de ejecucin de una instruccin________________________________________________ 10
3.5 Ejemplo de funcionamiento de la ejecucin de un programa _______________________________ 11
3.6 Distintos niveles de abstraccin de un sistema electrnico digital ___________________________ 13
3.7 Organizacin de un micro a nivel de bloques y buses_____________________________________ 15
4 Cuestiones de comprensin _________________________________________________ 17
Captulo 3 Arquitectura y Mapa de memoria del C167 _________________________ 18
1 Objetivos y conceptos a entender en este captulo_______________________________ 18
2 Arquitectura del C167 _____________________________________________________ 18
2.1 Modelo del programador del C167___________________________________________________ 19
2.2 Ensamblador de C167_____________________________________________________________ 20
2.2.1 Resumen de instrucciones en ensamblador _________________________________________ 23
2.2.2 Modos de direccionamiento_____________________________________________________ 24
2.2.3 Nmeros con signo y sin signo __________________________________________________ 26
2.2.4 Ejemplos bsicos de codificacin en ensamblador ___________________________________ 27
2.3 Mapa de memoria del C167_________________________________________________________ 27
2.3.1 Los registros de propsito general GPRs___________________________________________ 29
2.3.2 Principales SFRs de la CPU_____________________________________________________ 29
3 Cuestiones de comprensin _________________________________________________ 33
4 Ejercicios propuestos ______________________________________________________ 33
5 Prctica 1: Introduccin al Siemens C167 _____________________________________ 40
Captulo 4 Puertos ______________________________________________________ 48
1 Objetivos y conceptos a entender en este captulo_______________________________ 48
2 Puertos paralelo __________________________________________________________ 48
3 Ejercicios propuestos ______________________________________________________ 52
4 Prctica 2: entradas y salidas digitales________________________________________ 53
5 Prctica 3: ensamblar y depurar ____________________________________________ 55
Captulo 5 Perifricos____________________________________________________ 60
1 Objetivos y conceptos a entender en este captulo_______________________________ 60
2 Perifricos del C167 _______________________________________________________ 60
3 El Timer ________________________________________________________________ 61
Sistemas Electrnicos Digitales.





2
3.1 Registro de control T01CON________________________________________________________ 61
3.2 Registros de datos ________________________________________________________________ 62
3.3 Registro de control de interrupciones T0IC_____________________________________________ 62
3.4 Resumen de funcionamiento________________________________________________________ 63
3.5 Ajuste del pre-escalado____________________________________________________________ 63
3.6 Ejemplo de programacin: LEDs a ritmo de reloj ________________________________________ 63
4 Cuestiones de comprensin _________________________________________________ 65
5 Ejercicios propuestos ______________________________________________________ 66
5.1 PWM sencillo (30 min) ____________________________________________________________ 66
6 Prctica 4: timers _________________________________________________________ 68
Captulo 6 Ensamblador__________________________________________________ 71
1 Objetivos y conceptos a entender en este captulo_______________________________ 71
2 Introduccin _____________________________________________________________ 71
2.1 Codificacin de instrucciones _______________________________________________________ 71
3 Operaciones de transferencia de datos________________________________________ 72
3.1 MOV y MOVB __________________________________________________________________ 72
3.2 MOVBZ y MOVBS ______________________________________________________________ 73
3.3 PUSH y POP ____________________________________________________________________ 73
4 Instrucciones para realizar operaciones aritmticas_____________________________ 74
4.1 ADD y ADDB___________________________________________________________________ 74
4.2 SUB y SUBB____________________________________________________________________ 75
4.3 NEG___________________________________________________________________________ 75
4.4 MUL y MULU __________________________________________________________________ 76
4.5 DIV y DIVU ____________________________________________________________________ 76
5 Instrucciones para realizar operaciones lgicas ________________________________ 77
5.1 AND __________________________________________________________________________ 77
5.2 OR____________________________________________________________________________ 78
5.3 XOR___________________________________________________________________________ 78
5.4 CPL ___________________________________________________________________________ 79
6 Instrucciones para realizar desplazamientos de bits_____________________________ 79
7 Saltos ___________________________________________________________________ 81
8 Ejemplos de equivalencias de C y ensamblador ________________________________ 83
8.1 Condicin if_____________________________________________________________________ 83
8.2 Bucle for _______________________________________________________________________ 84
8.3 Bucle while_____________________________________________________________________ 84
9 Instrucciones a nivel de bit _______________________________________________ 85
9.1 Saltos__________________________________________________________________________ 86
9.2 Otras __________________________________________________________________________ 86
10 Directivas de ensamblador _________________________________________________ 88
11 Cuestiones de comprensin _________________________________________________ 90
12 Ejemplo de discusin: medida de ancho de pulso, sin/con filtrado de rebotes ________ 96
13 Ejercicios_______________________________________________________________ 100
Sistemas Electrnicos Digitales.





3
13.1 Acceso a memoria (15 min)_______________________________________________________ 100
13.2 Encendido apagado de LED (10 min) _______________________________________________ 101
13.3 Volcado de memoria (20 min)_____________________________________________________ 102
13.4 Cuenta de pulsos (30 min)________________________________________________________ 103
13.5 Calculadora (40 min)____________________________________________________________ 104
14 Ejercicios resueltos_______________________________________________________ 106
14.1 LEDs e interruptores____________________________________________________________ 106
14.2 Medida de ancho de pulso con rebotes (20 min) _______________________________________ 108
14.3 Medida de ancho de pulso (20 min)_________________________________________________ 110
15 Prctica 5: ejercicios en ensamblador, control de un servo ______________________ 112
Captulo 7 Drivers. El convertidor AD _____________________________________ 115
1 Objetivos y conceptos a entender en este captulo______________________________ 115
2 Concepto de driver_______________________________________________________ 115
2.1 Ejemplos de driver_______________________________________________________________ 115
2.1.1 Driver sencillo del puerto P2___________________________________________________ 116
2.2 Driver del Timer 0_______________________________________________________________ 116
2.3 Driver del convertidor AD_________________________________________________________ 116
3 El convertidor analgico digital (AD)________________________________________ 117
3.1 Registro de control ADCON_______________________________________________________ 118
3.2 Registro de datos ADDAT ________________________________________________________ 119
3.3 Registro de control de interrupciones ADCIC__________________________________________ 119
3.4 Ejemplo de programacin_________________________________________________________ 119
Captulo 8 Programacin en C para micros _________________________________ 121
1 Objetivos y conceptos a entender en este captulo______________________________ 121
2 Tipos de datos para el C167 _______________________________________________ 121
2.1 Nmeros enteros ________________________________________________________________ 121
2.2 Nmeros reales _________________________________________________________________ 123
2.3 Variables lgicas________________________________________________________________ 123
3 Operadores bit a bit ______________________________________________________ 124
4 Instrucciones de control___________________________________________________ 125
5 Bucles__________________________________________________________________ 126
6 Vectores________________________________________________________________ 127
7 Punteros _______________________________________________________________ 129
7.1 El operador &___________________________________________________________________ 130
7.2 El operador *___________________________________________________________________ 131
7.3 Operaciones con punteros_________________________________________________________ 132
8 Funciones ______________________________________________________________ 135
8.1 Variables globales y locales _______________________________________________________ 137
8.2 Paso de parmetros por "referencia" _________________________________________________ 137
8.3 Paso de vectores como parmetros __________________________________________________ 138
9 Cuestiones de comprensin ________________________________________________ 141
10 Ejercicios propuestos _____________________________________________________ 145
Sistemas Electrnicos Digitales.





4
10.1 Timer y puertos (40 min)_________________________________________________________ 145
10.2 Acceso a memoria (40 min)_______________________________________________________ 146
11 Ejercicios resueltos_______________________________________________________ 148
11.1 La calculadora (30 min)__________________________________________________________ 148
11.2 El coche fantstico (20 min) ______________________________________________________ 151
11.3 El autobus (30min) _____________________________________________________________ 153
12 Prctica 6: ejercicios en lenguaje C _________________________________________ 155
Captulo 9 Interrupciones _______________________________________________ 158
1 Objetivos y conceptos a entender en este captulo______________________________ 158
2 Nociones bsicas de interrupciones__________________________________________ 158
3 Recursos utilizados en una interrupcin _____________________________________ 159
4 Ejemplos _______________________________________________________________ 160
5 Prctica 7: interrupciones en C_____________________________________________ 162
Captulo 10 Sistemas digitales complejos ____________________________________ 165
1 Objetivos y conceptos a entender en este captulo______________________________ 165
2 Sistemas muestreados ____________________________________________________ 165
3 Fechado ________________________________________________________________ 167
4 Programacin basada en estados ___________________________________________ 170
Referencias ______________________________________________________________ 172

Sistemas Electrnicos Digitales.





5
Captulo 1 FILOSOFA DEL LIBRO
El objetivo de este libro es optimizar el aprendizaje del lector, presentndole un material
autocontenido que incluye informacin terica, ejemplos, cuestiones de comprensin,
ejercicios propuestos y resueltos, problemas propuestos y resueltos, y finalmente las prcticas
de laboratorio. Adicionalmente, cada captulo tiene una seccin que informa de los conceptos
prioritarios que deben quedar claros en el mismo. La organizacin se ha hecho para conseguir
una sincronizacin perfecta entre los contenidos tericos y de laboratorio, de forma que el
lector pueda conocer qu es lo que tiene que saber para hacer una prctica. Adems todo el
libro sigue un orden que se corresponde con el orden cronolgico de las clases presenciales.

Para optimizar el aprovechamiento del libro se recomienda seguir los siguientes pasos:
Ir leyendo captulo a captulo, en orden secuencial segn el ritmo de las clases
presenciales y del laboratorio.
En cada captulo prestar especial atencin a la seccin de "Objetivos y conceptos a
entender", de forma que se debe tener claro cuando se considera que se han cumplido
esos objetivos.
Una vez que se tenga claro el punto anterior se puede proceder a leer las siguientes
secciones descriptivas y los ejemplos.
El lector puede cerciorarse del entendimiento de los conceptos, haciendo las
cuestiones de comprensin que hay en cada captulo.
Comprobada la comprensin del captulo, el lector debe hacer los ejercicios que se
propongan.
Finalmente existen problemas al final de cada captulo que sirven de material
complementario para adquirir habilidad y destreza en el planteamiento y solucin
de problemas de sistemas digitales.

Por ltimo, cabe resear que es importante reflexionar y pararse a pensar sobre los conceptos
que aparecen en negrita en el texto, ya que aunque no tienen por qu ser conceptos ms
importantes que otros, si es cierto que suelen olvidarse con mayor facilidad y son claves para
entender otros conceptos.

Sistemas Electrnicos Digitales.





6
Captulo 2 ARQUITECTURA DE UN MICRO
1 Introduccin
Para poder utilizar un microcontrolador es necesario conocer su arquitectura; es decir en qu
consiste por dentro desde el punto de vista de un programador, enfocndose en conocer cules
son sus recursos, como son qu instrucciones y modos de direccionamiento soporta, cules
son los registros y su tamao, cmo es el mapa de memoria y cunto tarda una instruccin en
ejecutarse. Cosa muy distinta a lo que es la organizacin de un computador, que consiste en
conocer las tripas del mismo, el hardware, cuantos mdulos tiene y cmo estn conectados
(punto de vista del diseador); nada ms lejos de los objetivos de esta asignatura.
2 Objetivos y conceptos a entender en este captulo
Entender por qu es importante conocer el modelo del programador de un micro.
Entender el modelo del programador, conociendo las unidades de las que consta y
cmo se comunican entre s. para qu sirve el PC?
Entender cmo la CPU ejecuta una instruccin
Entender qu almacena fsicamente una memoria y los niveles de abstraccin que
permiten interpretar esa informacin.
3 Modelo del programador de un micro
Desde el punto de vista del programador, segn el modelo Von Neumann, un micro se ve
como una mquina con los bloques mostrados en la Figura 1:
La unidad de control y la unidad aritmtico lgica (ALU) que junto con los registros
forman la CPU. La ALU es la encargada de realizar las operaciones aritmticas que
requieran cada una de las instrucciones, los registros son celdas de memoria de acceso
rpido y la unidad de control reparte trabajo y coordina el resto de bloques.
La memoria principal, que es la encargada de almacenar datos, programas y resultados
intermedios (ms grande pero ms lenta que el banco de registros).
La unidad de entrada y salida de datos (I/O). Elemento imprescindible para que el
microcontrolador se pueda comunicar con el exterior, de otra forma sera intil.
Gracias a esta unidad se pueden conectar sensores y actuadores al micro, adems de
poderse comunicar con otros micros y sistemas digitales.


Sistemas Electrnicos Digitales.





7
Unidad de
Memoria
Unidad
Aritmtica
y lgica
(ALU)
Unidad de
Control
Unidad de
Entrada
Unidad de
salida
Unidad de
Memoria
Unidad
Aritmtica
y lgica
(ALU)
Unidad de
Control
Unidad de
Entrada
Unidad de
salida
CPU

Figura 1: Modelo Von Neumann de un microcontrolador
A continuacin se pasa a explicar cada una de estas unidades ms en detalle.
3.1 La CPU
La CPU adems de incluir la unidad de control y de la unidad aritmtico lgica, contiene los
registros, que es un banco de memoria acceso de acceso rpido para el almacenamiento de
datos. Se dice que un micro es de 8 bits si estos registros son de 8 bits, es de 16 bits si estos
registros son de 16 bits, etc. De todos los registros que tiene una CPU, desde el punto de vista
de un programador interesa conocer los siguientes:
Rx o registros de proposito general: registros que se usan como lugar de
almacenamiento temporal de un dato. Son bsicos para operaciones en la ALU, ya que
sirven como punto de entrada y salida de la misma, sirven de apoyo para transferir
informacin entre dos posiciones de memoria, etc. En el C167 estos registros son 15 y
se notan por Rx (siendo x un nmero del 0 al 15).
PC o program counter: contiene la direccin de la prxima instruccin a ejecutar. En
el C167 est registro est formado por dos el IP y el CSP.
IR o instruction register: (nico registro que almacena instrucciones en lugar de datos)
registro que contiene la instruccin que se est procesando. Este registro no se puede
usar por un programador, simplemente es parte del hardware necesario para que la
CPU procese instrucciones.
SR o state register: contiene el estado del micro despus de haber ejecutado una
instruccin. Por ejemplo, contiene informacin de si una operacin ha dado un
resultado negativo, si en una suma ha generado un acarreo, etc. En el C167 este
registro se denomina PSW.
3.2 La memoria
La memoria es la encargada de almacenar las instrucciones a ejecutar o programa y los datos
que usa ese programa.
Sistemas Electrnicos Digitales.





8

Los datos estn almacenados en formato binario en celdas de 8 bits.

Por ejemplo el nmero 5 est codificado de la siguiente forma:




Nmeros ms grandes, por ejemplo el 127:



Para manejar nmeros binarios con comodidad se utiliza la base hexadecimal. Los nmeros
binarios agrupados de 4 en 4 bits forman las cifras en hexadecimal.

La memoria est organizada en celdas de 8 bits. A cada celda se asigna una direccin de
memoria, de forma que el micro puede acceder al dato almacenado en dicha celda indicndole
a la memoria (en el bus de direcciones) la direccin de la celda a la que desea acceder, ver
Figura 2.

0000
0001
FFFF
Direccin Dato
05
7F
A0
0000
0001
FFFF
Direccin Dato
05
7F
A0

Figura 2: Organizacin de la memoria
El micro sabe qu direcciones de memoria contienen instrucciones y qu direcciones de
memoria contienen datos:
Toda direccin de memoria que se acceda a travs del registro PC, el micro
interpreta su contenido como una instruccin de programa.
Toda direccin de memoria que se acceda de otra manera se considera como que
contiene un dato; por ejemplo cuando el micro acceda para coger un dato y guardarlo
en un registro de proposito general.
0000 0101 5 0x05
0111 1111 127 0x7F
Sistemas Electrnicos Digitales.





9
3.3 Codificacin de las instrucciones
Las instrucciones tambin estn almacenadas en memoria en formato binario. Por ejemplo, la
siguiente instruccin:




Significa: Suma el dato almacenado en el registro R0 con el dato almacenado en el registro
R1 y deja el resultado en el registro R1.

Esta instruccin podra estar codificada de la siguiente forma

0001 0000 0001 0000 0x1010


Los 16 bits del cdigo de instruccin indican:

Los 4 bits ms significativos almacenan el cdigo de la instruccin (0001 para la
instruccin ADD)
Los 12 bits menos significativos indican cules son los operandos o parmetros de la
instruccin. Para el caso de la instruccin anterior, los 4 bits menos significativos
codifican el nmero de registro que se usa como sumando primero (0000 significa
R0), los 4 siguientes bits codifican el nmero de registro que se usa como sumando
segundo (0001 significa R1) y por ltimo los siguientes bits no se usan.
1
0 3 4 7 12 15
Rs2 Rs1 NA


Utilizando esta codificacin el microprocesador en cuestin podra hacer operaciones de suma
de:
Un mximo de 16 registros de propsito general (dado que slo se utilizan cuatro bits
para codificar el nmero de registros.
Un mximo de 16 instrucciones (cuatro bits para el cdigo de instruccin).

Los micros reales, en particular el C167, tienen ms registros y soportan en amplio conjunto
de operaciones aritmtico/lgicas.

Otro ejemplo posible de codificacin siguiendo este esquema es el siguiente:





add R1,R0
move R0,0x10
Sistemas Electrnicos Digitales.





10
Pone lo que hay en la direccin de memoria 0x10 en el registro R0. La codificacin podra
ser:

0002 0000 0001 0000 0x2010


2
0 7 8 11 12 15
Rs
mem


Los 4 bits ms significativos almacenan el cdigo de la instruccin (0002 para la
instruccin MOV Rx, mem)
Los 8 bits menos significativos codifican la direccin de la memoria de donde se coge
el dato (0x10), los 4 siguientes bits codifican el nmero de registro que se usa como
destino (0000 significa R0).

Estos ejemplos de codificacin indican que:

El nmero de bits necesarios para codificar una instruccin depende del tamao del
microprocesador. Un micro ms grande (con ms registros) necesitar ms bits para
codificar una instruccin dada.
Las instrucciones en memoria necesitarn por tanto ms o menos celdas de memoria
para ser almacenadas.

3.4 Ciclos de ejecucin de una instruccin
La CPU es la encargada de ejecutar las instrucciones que estn en la memoria a partir de la
posicin de la misma que indique el PC. La ejecucin de una instruccin supone la ejecucin
de dos ciclos, ver Figura 3:
1. Ciclo de Fetch: en este ciclo se busca la instruccin que se tiene que ejecutar y se
interpreta para saber qu se tiene que ejecutar. Adems incrementa PC para que apunte
a la siguiente instruccin. Los pasos de este ciclo son:
a. El Contador de Programa (PC) contiene la direccin de la prxima
instruccin a ejecutar
b. El procesador captura la instruccin de memoria
c. La instruccin se carga en el Registro de Instrucciones (IR)
d. El PC se incrementa (salvo en las instrucciones de salto, que el PC ser el
valor de la direccin de salto).
e. Se interpreta la instruccin y se generan las seales de control (decodificacin
instruccin)
2. Ciclo de ejecucin: en este ciclo se ejecuta propiamente lo que indica la instruccin.
La CPU puede ejecutar diferentes instrucciones:
a. Transferencia de procesador a memoria
Sistemas Electrnicos Digitales.





11
b. Transferencia de procesador a I/O
c. Procesado de datos. La ALU efecta una operacin sobre los datos
d. Instrucciones de control. Alteran la secuencia de programa; p.e. J ump
e. Combinacin de las anteriores


Figura 3: ciclos de ejecucin de una instruccin
3.5 Ejemplo de funcionamiento de la ejecucin de un programa
A continuacin se presenta un ejemplo muy importante desde el punto de vista conceptual,
que ilustra cmo un micro ejecuta un conjunto de instrucciones, poniendo de manifiesto los
conceptos explicados en anteriores secciones.

En lenguaje de alto nivel, el ejercicio consiste en sumar los dos nmeros que se encuentran las
direcciones de memoria 0x80 y 0x82, para posteriormente guardar el resultado en la direccin
0x84. Algo similar a la instruccin:

(0x84) =(0x80) +(0x82)

los parntesis indican "lo que hay en la direccin de memoria".

En lenguaje simblico cdigo mquina, que es el que entiende el micro, esta operacin
requiere de tres instrucciones que se apoyan en los registros de proposito general para realizar
la operacin anterior:
move R0,0x80 que en cdigo mquina se representa por 2080(H)
move R1,0x82 que en cdigo mquina se representa por 2182(H)
add R1,R0 que en cdigo mquina se representa por 1010(H)
move 0x84,R1 que en cdigo mquina se representa por 3841(H)

Si se analiza con detalle la codificacin mquina, cada una de las instrucciones (codificadas
en ensamblador, que es el lenguaje ms cercano al cdigo mquina que un programador
conoce) consiste de cuatro dgitos, el primero de ellos representa la operacin a realizar segn
el tipo de parmetros que usa, y los ltimos tres dgitos representan los operandos de la
misma. Es necesario hacer notar que las tres instrucciones son las ms sencillas en las que se
puede descomponer el ejemplo, desde el punto de vista de una mquina, ya cada una de ellas
slo realiza una accin, o bien una transferencia de informacin o bien una operacin con la
ALU.
Sistemas Electrnicos Digitales.





12

Una vez cargado el programa en la posicin 0, la memoria queda como se indica en la

0000
0002
FFFF
2080
2182
A0
0004
0006
1010
3841
0080
0082
0007
0003
Instruccin
Instruccin
Instruccin
Instruccin
Dato
Dato

Figura 4: Memoria despus de cargar el programa ejemplo

Una vez que se manda ejecutar el programa, poniendo PC = 0x0000, se empieza a ejecutar
la primera instruccin, como se muestra en la Figura 5. En la fase de Fetch se coge la
instruccin de la memoria a la que apunta PC y se guarda en I R, quedando I R = 0x2080,
para posteriormente incrementar PC para que apunte a la siguiente instruccin. En la fase de
Execute se ejecuta la instruccin que hay en I R; es decir, se coge el valor que hay en la
direccin de la memoria 0x80 y se pone en R0, quedando R0 = 7. Y as sucesivamente
para las tres siguientes instrucciones, como se puede ver en la Figura 6, Figura 7 y Figura 8.

0000
0002
2080
2182
1010
0002
2080
IR
PC 0080
0082
0007
0003
0000
0007
0000
R1
R0
Fetch
Execute

Figura 5: ejecucin de la instruccin mov R0, 0x80
Sistemas Electrnicos Digitales.





13
0000
0002
2080
2182
1010
0004
2182
IR
PC 0080
0082
0007
0003
0000
0007
0003
R1
R0

Figura 6: ejecucin de la instruccin mov R1, 0x82
0004
0006
1010
3841
0000
0006
1010
IR
PC 0080
0082
0007
0003
0000
0007
000A
R1
R0
0084 0000
R2
ALU: R1 <- R0+R1

Figura 7: ejecucin de la instruccin add R1,R0
0004
0006
1010
3841
0000
0008
3841
IR
PC 0080
0082
0007
0003
000A
0007
000A R1
R0
0084 0000
R2

Figura 8: ejecucin de la instruccin move 0x84, R1

Es importante entender este ejemplo, para entender cmo ejecuta las instrucciones un micro y
por lo tanto comprender mejor los detalles del lenguaje ensamblador para programar un
micro. Este lenguaje es el de ms bajo nivel que se puede programar, el cual tiene una
correspondencia biunvoca entre cdigo mquina e instruccin de ensamblador.
3.6 Distintos niveles de abstraccin de un sistema electrnico digital
Segn al nivel que se trabaje, se puede ver un sistema electrnico de muchas maneras, como
se puede ver en la Figura 9.

El nivel ms bajo o nivel fsico, se corresponde con la interpretacin elctrica y es comn a
todo tipo de sistema electrnico. En este nivel slo hay medidas elctricas de tensin; es el
nivel al que se trabaja cuando se usa el osciloscopio y con las leyes de Kirchhoff.

El segundo nivel o nivel lgico, se corresponde con la interpretacin lgica de las medidas
elctricas del primer nivel. Las medidas de tensin se traducen a ceros y unos, de forma que
por ejemplo un nivel de tensin por debajo de 0.7 Voltios se considera un 0 lgico y un valor
por encima se considera un 1 lgico. Se pueden realizar operaciones en este nivel usando el
lgebra de Bool. A este nivel se sita el cdigo mquina.
Sistemas Electrnicos Digitales.





14

El tercer nivel o nivel de codificacin, se corresponde con la codificacin de esos ceros y unos
en palabras que puedan ser entendidas mejor por una persona. Este nivel s que depende del
sistema electrnico que se use; es decir, del cdigo que se use, ya que existen cdigos que
interpretan los ceros y unos de distinta manera dependiendo para qu se apliquen. Si se quiere
realizar un programa para un micro, la codificacin se llama ensamblador. En caso de que se
quiera trabajar con nmeros, la codificacin puede ser binaria o hexadecimal, interpretando
los nmeros con signo y sin signo. Por ltimo, si lo que se quiere es programar FPGA o
EPLD (lgica programable), la codificacin que se usa es VHDL. Estas codificaciones
dependen dentro de cada aplicacin del dispositivo que se quiera programar; por ejemplo,
existen distintos cdigos ensamblador para diferentes micros.

Finalmente el cuarto nivel, o nivel ms alto de abstraccin, consiste en realizar una
codificacin ms entendible por una persona, que adems sea independiente del dispositivo
que se quiere programar. En caso de que se quieran programar micros, el lenguaje que se usa
es C, que independiente del micro que se quiere programar; es decir, slo existe un lenguaje
C. En caso de que se quiera trabajar con datos, existen varias codificaciones como son la
ASCII, UNICODE, etc, que son iguales para todos sistemas; es decir, slo existe un cdigo
ASCII.


Nivel fsico
Hardware +5V, 0V
Nivel lgico 0's y 1's
Interpretacin 0's y 1's
Ensamblador
Lenguaje C
Interpretacin 0's y 1's
Nmeros con y sin signo
Cdigos de alto nivel
ASCII
PROGRAMAS uC DATOS
Lenguaje VHDL
PROGRAMAS FPGA
ABSTRACCIN

Figura 9: Niveles de abstraccin de un sistema electrnico digital
Existen niveles de abstraccin superiores, pero que no se usan en la programacin de sistemas
electrnicos digitales.

Sistemas Electrnicos Digitales.





15
3.7 Organizacin de un micro a nivel de bloques y buses
Aunque la organizacin de un micro no es el objetivo de la asignatura, es entender qu es un
Sistema Electrnico Digital (SED) es necesario introducir algunos aspectos de organizacin,
como es la composicin a nivel de bloques fsicos y la conexin entre bloques mediante
buses.

En la Figura 10 se muestra el modelo Von Neumann a nivel de bloques y de buses. Un bus no
es ms que un conjunto de lneas comn a varios bloques que permite la comunicacin entre
ellos. En un SED tpico tenemos tres buses:
Bus de direcciones.
Bus de datos.
Bus de control.


CPU
(ALU, Registros
y Control)
Memoria Entrada/Salida
Bus de datos
Bus de direcciones
Bus de control
B
u
s

d
e
l

s
i
s
t
e
m
a
CPU
(ALU, Registros
y Control)
Memoria Entrada/Salida
Bus de datos
Bus de direcciones
Bus de control
B
u
s

d
e
l

s
i
s
t
e
m
a

Figura 10: Modelo Von Neumann a nivel de hardware
Desde la CPU el exterior se ve como direcciones. Cuando se quiere acceder a un dato en la
memoria, la CPU pone en el bus de direcciones la direccin de la memoria donde se encuentra
el dato y la memoria le da el dato en el bus de datos. El bus de control sirve para organizar la
transferencia del dato entre memoria y CPU (o entre I/O y CPU). Por ejemplo, para leer el
dato de la posicin 0x82:

0x82 (CPU) Bus dir ->RD (CPU) Bus control ->0003 (MEM) Bus datos

Esto significa: la CPU pone en el bus de direcciones la direccin del dato a leer (0x82), a
continuacin activa una lnea del bus de control que indica operacin de lectura (RD: Read),
la memoria suministra el dato almacenado en dicha posicin de memoria (3) en el bus de
datos. Por ltimo la CPU recoge el dato del bus de datos y lo almacena en un registro de
proposito general.

Sistemas Electrnicos Digitales.





16
El ciclo de escritura es similar. En este caso la CPU suministra tanto la direccin como el dato
a escribir en memoria (en el bus de direcciones y en el bus de datos respectivamente) y activa
la lnea WR (Write) del bus de control.

Los microcontroladores tienen perifricos y memoria integrados en el chip de CPU, mientras
que los microprocesadores no. Los perifricos sirven para comunicar la CPU con el exterior y
para realizar ciertas tareas sin consumir tiempo de CPU del micro; por ejemplo hay
perifricos que sirven para controlar motores, otros digitalizan seales analgicas, etc. Al
igual que la CPU los perifricos tienen registros que le permiten funcionar. Se dice que un
perifrico est mapeado en memoria si la CPU ve a los registros del perifrico como una
direccin ms de memoria; es decir, el micro accede a los registros del perifrico de la misma
manera que lo hace para acceder a cualquier otra direccin de memoria. El mapa de memoria
describe de forma grfica qu hay en cada rango de direcciones: memoria RAM, ROM o
Perifricos.

Cuando la CPU manda hacer algo a un perifrico se puede quedar a la espera a que ste
termine su labor, preguntndole continuamente si ha terminado, o bien puede configurar al
perifrico de que le avise y le interrumpa cuando termine. En el primer modo de
funcionamiento se dice que la CPU usa polling (es la CPU la que pregunta si ha terminado),
mientras que el segundo modo de funcionamiento se dice que la CPU usa interrupciones (es
el perifrico el que indica a la CPU que ha terminado, interrumpiendo lo que est haciendo en
ese momento). La CPU realiza polling consultado un bit de un registro del perifrico; es decir,
de la misma manera que consulta una direccin de memoria. En cambio las interrupciones
utilizan lneas especficas de comunicacin entre el perifrico y la CPU, las cuales se
encuentran en el bus de control.
Sistemas Electrnicos Digitales.





17

4 Cuestiones de comprensin
A continuacin se enumeran un conjunto de preguntas que ayudan a comprender lo que se ha
descrito en el captulo.

0) Qu significa modelo del programador?





1) De qu partes consta un microprocesador segn el modelo del programador?









2) Qu significa que un microprocesador sea de 16 bits?



3) Qu diferencia un microprocesador de un microcontrolador?




4) Qu es el PC? Para qu sirve?



5) De qu diferentes formas se te ocurren que se pueden interpretar los bits que se almacenan
en la memoria de un micro?

Sistemas Electrnicos Digitales.





18
Captulo 3 ARQUITECTURA Y MAPA DE MEMORIA DEL
C167
1 Objetivos y conceptos a entender en este captulo
Por orden de importancia:
Entender cmo se almacenan los datos y los programas, as como la ejecucin de los
mismos que permite relacionar ambos.
Entender los modos de direccionamiento
Entender la arquitectura y, sumamente importante, ver la equivalencia entre el modelo
del programador presentado en este captulo y el presentado de forma general en el
captulo anterior.
Empezar a familiarizarse con el ensamblador y la equivalencia que tiene con el C. Por
ello en este captulo se recomienda empezar un esquema, que se seguir completando
en sucesivos captulos, con las equivalencias entre el ensamblador y el C.
Entender cmo se organiza la memoria del C167
Hacerse con la terminologa "direccionar", "modo de direccionamiento", "puntero",
etc.
2 Arquitectura del C167
Es un microcontrolador de 16 bits, lo que implica que la ALU, el bus de datos y los registros
son de 16 bits. Es un micro muy robusto, diseado para tareas de control industrial. Es capaz
de direccionar (pedir direcciones) 16 Mbytes de memoria, es decir, su bus de direcciones es
de 24 bits. Como microcontrolador que es lleva incorporados muchos perifricos integrados
en el chip:
Controladores de comunicaciones serie: para comunicarse con el exterior en serie; por
ejemplo un PC.
Puertos paralelo: para comunicarse con el exterior; por ejemplo para conectar LEDs,
interruptores, un PC, etc.
Temporizadores (timers): para contar eventos, para llevar un computo del tiempo
transcurrido, etc.
Convertidor analgico/digital (A/D): sirve para pasar una seal del dominio analgico
al digital, formato que puede ya procesar el micro.
Moduladores PWM: muy usados en electrnica de potencia para controlar motores,
etc
Sistemas Electrnicos Digitales.





19
2.1 Modelo del programador del C167

El modelo del programador del C167 se muestra en la Figura 11. Tiene una CPU con registros
clasificados en dos tipos: registros de propsito especfico (SFR, tienen una funcin muy
concreta) y registros de propsito general (GPR, se pueden usar para cualquier cosa). Los
GPR son equivalentes a los registros de proposito general que se presentaron en la
arquitectura general de un micro en la seccin 3.1, y se usan como posiciones de memoria de
acceso rpido. Como registros de propsito especfico tenemos, entre otros, el PC (contador
de programa), el PSW (registro de estado) y el SP (Stack Pointer).

Por otro lado, tenemos el modelo de memoria. La memoria est organizada en "celdas" de 1
Byte (8bits). Cada byte tiene una direccin asociada. Las direcciones van desde al 0 hasta la
0xFFFFFF; es decir, se puede direccionar con 24 bits. Para acceder a una celda de memoria
se usa su direccin:
Para la lectura: la CPU pone la direccin en el bus de direcciones de la cual quiere el
dato, mientras indica por el bus de control que la operacin es de lectura. La memoria
devuelve el dato almacenado en la celda en el bus de datos;
dat o = READ ( di r ecci n) .
Para la escritura: la CPU pone el dato en el bus de datos, mientras indica por el bus de
control que la operacin es escritura, y la direccin en el bus de direcciones. La
memoria escribe en la celda direccionada el dato suministrado por la CPU.
WRI TE( dat o, di r ecci n) .

La unidad de entrada y salida se controla a travs de sus SFRs. El acceso a estos es similar al
acceso a memoria; es decir, los SFRs estn mapeados en memoria.

Sistemas Electrnicos Digitales.





20
Memoria
R8
00 0000
00 0001
FF FFFF
R9
R12
R10
R14
R13
R15
R0
R1
R4
R3
R2
R6
R5
R7 PC
R11
PSW
SP
Registros
CPU
00 FE00 00 FE02 00 FE0X I/O
(GPRs)
(SFRs)
(SFRs)

Figura 11: modelo del programador del C167

2.2 Ensamblador de C167
Como se coment en el captulo 2 seccin 3.6, el lenguaje ensamblador es el lenguaje de ms
bajo nivel que entienden las personas, ya que cada instruccin ensamblador se corresponde
con una instruccin cdigo mquina que entiende el micro, es decir, hay una correspondencia
biunvoca entre el ensamblador y el cdigo mquina, entre lo que entienden las personas y lo
que entienden las mquinas.

El programa sencillo presentado en el captulo anterior para una mquina de propsito general
(esta vez en la direccin 0x100, ya que en el C167 no se pueden usar las 0x100 primeras
direcciones)

(0x104) =(0x100) +(0x102)

En lenguaje ensamblador de C167 queda de la siguiente forma:

MOV R0, 0x100
MOV R1, 0x102
ADD R1, R0
MOV 0x104, R0

Sistemas Electrnicos Digitales.





21
El tamao del registro R0 es de 2 bytes (16 bits). Como cada direccin de memoria almacena
nicamente 8 bits (1 byte) son necesarios dos bytes (almacenados en direcciones
consecutivas) para llenar el registro. Por este motivo se ha situado el primer dato en la
posicin 0x100 y el segundo dato dos direcciones ms all (posicin 0x102). (El C167 es un
little endian; es decir, almacena el byte menos significativo del dato, parte baja de R0, en la
direccin par. El byte ms significativo va a la direccin impar de memoria).

A la hora de presentar ejemplos ms complejos usaremos como lenguaje de descripcin
en alto nivel el lenguaje C, que se da por conocido (a nivel bsico). El lenguaje en
ensamblador se explicar en detalle en el captulo 6. En el captulo 7 se explicar el detalle de
las particularidades del lenguaje C en la programacin de micros, y lo que es ms importante
la relacin entre el lenguaje C y el ensamblador.

Para empezar, se va a presentar el primer cdigo ensamblador equivalente al programa
siguiente en C, que no es ms que un bucle para incrementar una variable N veces. Es
necesario recordar que en C j += 1 es equivalente a j = j +1.

f or ( i =1; i <=N; i ++)
j += 1;


Suponiendo que N=5 y que el dato al que representa j se encuentra en la direccin de
memoria 0xfa00, el programa en ensamblador equivalente sera:

500 E0 10 MOV R0, #1 ; r 0 ( i )
502 E0 11 MOV R1, #1 ; auxi l i ar
504 48 05 CMP R0, #5 ; i f i >N
506 AD 05 J MPR cc_sgt , 0x510 ; t hen got o 512H
508 04 F1 00 FA ADD 0xf a00, R1 ; j += 1
50C 08 01 ADD R0, #1 ; i += 1
50E 0D FA J MPR cc_uc, 0x504 ; sal t o si n condi ci n
510
Direccin de
memoria
Codificacin de
la instruccin
Direccin inicial
del programa


A simple vista se pueden observar varias cosas del programa:
En lenguaje ensamblador ms largo que en C
Una lnea de ensamblador se corresponde con una instruccin en cdigo mquina que
almacena en una direccin de memoria.
Cada instruccin de ensamblador se corresponde con una operacin elemental, donde
casi siempre estn involucrados los GPRs
Sistemas Electrnicos Digitales.





22
Las instrucciones se almacenan en memoria en formato binario (1s y 0s), aunque en
se hayan mostrado en hexadecimal por simplificar la notacin.
Las instrucciones ocupan 2 4 bytes. Por ejemplo la instruccin 0x0801 situada en la
direccin 0x50C ocupa 2 bytes, muestras que la instruccin 0x04F100FA situada en la
direccin 0x508 ocupa 4 bytes.
Las instrucciones se almacenan en posiciones de memoria consecutivas. Se ejecutan
de forma secuencial, salvo el los saltos.

De forma concisa cada una de las instrucciones del programa hace lo siguiente, (para ms
informacin y detalles del lenguaje ensamblador ir al captulo 6):
MOV R0, #1. R0 representa la variable i y se inicializa a 1; i = 1. MOV significa en
ingls move, mueve 1 a R0. El #significa que el valor que le acompaa se trata como
literal y no como una direccin de memoria donde buscar el dato.
MOV R1, #1. R1. R1 es una variable temporal que representa la cantidad a sumar a j ,
que aunque siempre vale 1 se necesita para poder invocar a la instruccin de suma.
CMP R0, #5. Compara si R0 es 5. CMP en ingls compare.
J MPR cc_sgt , 0x510. Si es mayor que 5 salta a la direccin 0x510. La instruccin
J MPR, en ingls jump, salta segn la condicin puesta. En este caso cc_sgt , en ingls
signed greater than, est haciendo una comparacin con signo de mayor que. con
qu? como se ver ms adelante, cada instruccin en ensamblador deja una huella en
la CPU despus de ser ejecutada, en concreto en el registro de estado, y es esa huella
como entrada a la comparacin. En este caso la instruccin CMP anterior, dej una
huella que indicaba si R0 era mayor, menor o igual que 5, que se usa en J MPR para
hacer el salto. Generalmente CMP y J MPR van juntos.
ADD 0xf a00, R1. Aade R1 al dato que haya en la direccin de memoria 0xf a00; es
decir, j =j +1. Como se coment con anterioridad la instruccin ADD 0xfa00, #1 no
existe, de ah que fuera necesario guardar en R1 el 1. Esto significa que no todas las
operaciones soportan todo tipo de operandos. Se puede apreciar que no se ha puesto
#0xf a00, ya que 0xf a00 no es un literal sino una direccin de memoria donde buscar el
dato.
ADD R0, #1. Aade 1 a R0; es decir, i = i +1.
J MPR cc_uc, 0x504. Esta instruccin en un salto sin condicin cc_uc, en ingls
unconditional, a la direccin 0x504, precisamente para que el bucle contine.

Es necesario hacer notar que a lo largo de la ejecucin del programa el PC contiene la
direccin de la siguiente instruccin a ejecutar, para ms detalles ver captulo 2 seccin
3.3. Cada vez que la CPU ejecuta una instruccin, incrementa el PC en dos o cuatro, para
que apunte a la direccin de memoria de la siguiente instruccin. En la terminologa de
programacin cuando una variable o registro contiene como dato una direccin de
memoria, se dice que la variable o el registro es un puntero que apunta a una determinada
direccin de memoria.

Sistemas Electrnicos Digitales.





23
Para el C167 existen dos tipos de ensambladores, uno de muy bajo nivel llamado ensamblador
de lnea y otro de alto nivel llamado ensamblador de PC. Nada mejor que un ejemplo para
entender la diferencia entre ambos, ver Figura 12

MOV R0, #1 ; r 0 ( i )
MOV R1, #1 ; auxi l i ar
bucl e: CMP R0, #5 ; i f i >N
J MPR cc_sgt , f i n ; t hen got o f i n
ADD 0xf a00H, R1 ; j += 1
ADD R0, #1 ; i += 1
J MPR cc_uc, bucl e
f i n:
500 MOV R0, #1 ; r 0 ( i )
502 MOV R1, #1 ; auxi l i ar
504 CMP R0, #5 ; i f i >N
506 J MPR cc_sgt , 0x510 ; t hen got o 512H
508 ADD 0xf a00, R1 ; j += 1
50C ADD R0, #1 ; i += 1
50E J MPR cc_uc, 0x504 ; sal t o si n condi ci n
510
Etiquetas (op)
Instruccin Operandos Comentarios (opcional)
En PC
En lnea

Figura 12: comparacin entre ensamblador de lnea y de PC
El ensamblador de lnea es lo ms parecido al cdigo mquina ya que cuando se escribe se
debe tener muy claro en qu direccin de memoria se encuentra cada instruccin, de forma
que cuando se hacen saltos se tiene que poner la direccin de memoria donde se salta. Esto es
as porque cuando se escribe ensamblador en lnea se est escribiendo cdigo mquina
directamente en la memoria, gracias a un programa que est cargado en la pastilla del micro
que se llama monitor y que es capaz de comunicarse una consola del PC y escribir en
memoria el cdigo ensamblador que se quiera.

En cambio el ensamblador de PC admite lo que se llaman etiquetas, que no son ms que
nombres que representan una direccin de memoria, que no se conoce a priori y por lo tanto
se usa la etiqueta en su lugar. Esas direcciones de memoria se resuelven o se conocen cuando
el programa se termina y se ensambla. El programa que ensambla se llama ensamblador y se
ejecuta en un PC, y lo nico que hace es traducir las etiquetas en direcciones de memoria,
traducir cada instruccin a cdigo mquina y situar cada instruccin en una direccin de
memoria. Como resultado se genera un fichero que se puede cargar en la memoria del micro
directamente.
2.2.1 Resumen de instrucciones en ensamblador
Se pueden clasificar las instrucciones de ensamblador en diferentes tipos:
Sistemas Electrnicos Digitales.





24
Transferencia de datos. Son instrucciones que sirven para mover los datos de un lugar
a otro. La instruccin ms importante es mov.
Aritmticas. Son instrucciones que sirven para realizar operaciones aritmticas. Las
ms importantes son: add (suma), sub (resta), cmp (comparacin, resta operandos y
compara con 0), neg (hace el complemento a dos), mul (multiplica), di v (divide).
Lgicas. Realizan operaciones lgicas: and (multiplicacin lgica), or (suma lgica),
cpl (complemento a 1).
Desplazamientos de bits. Desplazan los bits de un registro hacia la derecha o
izquierda. shr (shift right ->derecha), shl (shift left ->izquierda).
Saltos en la ejecucin. Realiza saltos en la ejecucin segn la condicin. j mpr cc_uc
(sin condicin), cc_eq (igual), cc_ne (no igual), cc_ugt (sin signo mayor que), cc_sgt
(con signo mayor que), cc_ul e (sin signo menor o igual que, ...). Para entender cmo
funcionan los saltos ver captulo 6 seccin 7.

Los nmero en ensamblador se suelen usar o bien para literales o para referirse a direcciones
de memoria. Por defecto el nmero que se escribe se considera que est en decimal, si se pone
un 0x por delante el nmero est en hexadecimal.

A continuacin se muestran ejemplos de utilizacin de instrucciones para irse familiarizando
con el ensamblador y el C:
MOV R0, #0x4433. Esto hace R0 = 0x4433
MOV R1, R0. Es equivalente a R1 = R0, por lo tanto R1 = 0x4433
AND R1, #0xFF00. Es equivalente a R1 = R1 & 0xFF00. Un and lgico bit a bit,
quedando R1 = 0x4400.
MOV R2, R0. Es equivalente a R2 = R0, por lo tanto R2 = 0x4433.
AND R2, #0x00FF. Es equivalente a R2 = R2 & 0x00FF. Un and lgico bit a bit,
quedando R2 = 0x0033.
SHR R1, #8. Es R1 = R1 >> 8. Un desplazamiento de bits a la derecha, quedando R1 =
0x0044.
ADD R1, R2. Es una suma aritmtica R1 = R1 + R2, quedando R1 = 0x0077.
CPL R1. Realiza el complemento a 1, en C sera R1 = ~R1, quedando R1 = 0xFF88.
XOR R1, #0xFFFF. Realiza un XOR de R1, en C sera R1 = R1 ^0xFFFF. Este ejemplo es
interesante ya que un XOR con 0xFFFF es lo mismo que un complemento a 1, justo
como el ejemplo anterior.
2.2.2 Modos de direccionamiento
El 167 dispone de los siguientes modos de direccionamiento para acceder a los operandos:
Sistemas Electrnicos Digitales.





25

Direccionamiento Smbolo
Inmediato #data
Directo a GPR Rw, Rb
Directo a SFR o GPR reg
Directo a memoria mem
Indirecto [Rw]
Indirecto con pre-decremento [-Rw]
Indirecto con post-incremento [Rw+]
Indirecto con desplazamiento [Rw+#data16]

A continuacin se describen diferentes ejemplos de utilizacin con la instruccin MOV:

MOV R0, R1 ; Di r ect o a r egi st r o ( R1 - > R0)
MOV R0, #5 ; I nmedi at o ( 5 - > R0)
MOVB RL0, #0 ; I nmedi at o al byt e baj o ( 0 - > R0)
MOVB RH0, #3 ; I nmedi at o al byt e al t o ( 3 - > R0)
MOV R1, 0xFA00h ; Di r ect o desde memor i a
MOV R1, [ R0] ; I ndi r ect o ( ( R0) - > R1)
MOV [ - R0] , R1 ; I ndi r ect o con pr e- decr ement o
MOV [ R0+] , R1 ; I ndi r ect o con post i ncr ement o
MOV R1, [ R0+#4] ; I ndi r ect o con despl azami ent o


La primera instruccin utiliza direccionamiento directo a registro en ambos operandos. La
instruccin carga el contenido del registro R1 en el registro R0, a nivel de word (16 bits).
La segunda instruccin utiliza direccionamiento inmediato (smbolo #) en el segundo
operando. La instruccin carga el nmero 5 en el byte (8 bits) bajo de R0.
La siguiente instruccin carga 0 en el byte alto de R0. La parte baja R0 recibe el nombre de
RL0, mientras que la parte alta recibe el nombre de RH0. No olvidar especificar parte alta
o baja del registro. De lo contrario el ensamblador da el error 74: "Illegal Operand Type".
La instruccin MOV R1, 0xFA00h carga el valor almacenado en la posicin de memoria
0xFA00h en R1, utilizando direccionamiento a memoria (16 bits para la direccin). En el
direccionamiento largo se utilizan los registros DPP's (Data Page Pointers). Ntese que si
en la segunda instruccin olvidramos el smbolo #, en R0 se cargara el contenido de la
posicin 5 de memoria, en lugar del nmero 5.
La instruccin MOV R1, [ R0] carga el contenido de la posicin de memoria apuntada por
R0, en R1. El modo de direccionamiento se conoce con el nombre de "indirecto". (Ntense
los corchetes en R0 para indicar contenido de la posicin de memoria). Si en R0 tenemos
almacenado el valor 0x200, se carga en R1 el contenido de la posicin de memoria 0x200.
En el acceso a memoria se utilizan los DPP's.
Las dos instrucciones siguientes utilizan variantes del modo de direccionamiento
indirecto. Variantes con pre-decremento y con post-incremento. Estas variantes, a parte de
obtener el operando, actualizan el valor del puntero (registro de direcciones). En las
instrucciones con pre-decremento el puntero se decrementa antes de obtener el operando.
Sistemas Electrnicos Digitales.





26
Luego si en R0 se tiene el valor 0x200, la instruccin MOV [ - R0] , R1 decrementa en dos
unidades (R0 = 0x1FE). A continuacin carga el valor almacenado en R1 (2 bytes) en la
posicin de memoria apuntada por R0. En las instrucciones con post-incremento, el
puntero se incrementa despus de obtener el operando. Luego si en R0 tiene el valor
0x200, la instruccin MOV [ R0+] , R1 carga R1 en la posicin de memoria apuntada por R0
(2 bytes), e incrementa (R0 = 0x202) en dos unidades. Las instrucciones con pre-
decremento y con post-incremento actualizan el valor del puntero de acuerdo con el
tamao de operando. Es decir, si el operando es a nivel de byte se suma/resta 1. Si es a
nivel de word, se suma/resta 2 (dos bytes). (Esta es una forma rudimentaria de manejo
automtico de tamaos. Los operadores ++ y - del lenguaje C hacen esto mismo con
cualquier tipo de operandos).
La ltima instruccin MOV R1, [ R0+#4] utiliza un cierto desplazamiento 4. Estos
direccionamientos (indirectos con desplazamiento) no actualizan el valor del puntero. El
desplazamiento sirve nicamente para obtener la direccin del operando.
2.2.3 Nmeros con signo y sin signo
Un nmero negativo es aquel que sumado al mismo positivo da cero. Por ejemplo si se suma
en 16 bits el nmero 0xFFFF y 0x0001 da como resultado 0x10000 que en 16 bits es el
0x0000. Esta aritmtica se llama aritmtica en como fija complemento a 2 y permite deducir
el negativo de un nmero con la ecuacin:
positivo nmero negativo nmero
bits de nmero
_ 2 _
_ _
=

Por ejemplo, en 16 bits, el negativo de 2 es 0xFFFE en hexadecimal o 65534 en decimal:
0002 0 2 0
16
x xFFFE =


En definitiva los nmeros que tienen un uno como bit ms significativo son negativos y los
que no son positivos.

Por lo tanto si se mira en una direccin de memoria del micro y se ve que est almacenado el
nmero 0xFFFE, qu significa?. Puede tener muchos significados:

Puede representar a una instruccin
Puede representar al nmero 65534
Puede representar al nmero -2
Puede representar cualquier tipo de cdificacin que se el usuario quiera

Esto viene a decir, que la interpretacin del contenido de una posicin de memoria
depende del programador, la cul se escenifica en el tipo de instrucciones que use para
decodificarla. Si pone el PC apuntanto a esa direccin de memoria significa que la est
interpretando como una instruccin, si accede a esa direccin de memoria con una instruccin
que tiene en cuenta el signo (MUL, DIV, J MPR cc_sgt,...) entonces la est interpretando
como un nmero con signo y si accede con una instruccin que no tiene en cuenta el signo
(MULU, DIVU, J MPR cc_ugt,...) entonces la est interpretando como un nmero sin signo.

Sistemas Electrnicos Digitales.





27

2.2.4 Ejemplos bsicos de codificacin en ensamblador
A continuacin se muestran dos ejemplos de programacin estructurada en C y su
equivalencia en ensamblador.
2.2.4.1 Condicin
i f ( a == b)
a = 0;

MOV R0, a
CMP R0, b
J MPR cc_ne, next
MOV R0, #0
MOV a, R0
next :

2.2.4.2 Bucle
i = 0;
whi l e ( i <10) {
a[ i ] = i ; i += 1;
}


Es necesario hacer notar que i +=1 es lo mismo que i =i +1;

MOV R0, #0
MOV R1, #1
MOV R2, #0f a00h
ot r o: CMP R0, #10
J MPR cc_sge, next
MOV [ R2] , R0
ADD R0, R1
ADD R2, #2
J MPR cc_uc, ot r o
next :


2.3 Mapa de memoria del C167
El mapa de memoria describe de forma grfica qu hay en cada rango de direcciones:
memoria RAM, ROM o Perifricos. El mapa de memoria del C167 est dividido en
segmentos de 65536 Bytes, cada uno de los cuales se divide a su vez en 4 pginas de 16384
Sistemas Electrnicos Digitales.





28
Bytes. Como la memoria puede llegar a ser de 16MBytes, puede haber 256 segmentos y
256*4=1024 pginas, como se puede ver en la Figura 13. En la tarjeta que se utiliza para las
prcticas de laboratorio todos los segmentos menos el primero tienen memoria ROM. El
primer segmento tiene RAM (externa, esto es, fuera del chip de la CPU). Una pequea parte
del segmento S0 (pgina 3) tiene RAM interna (dentro del chip de la CPU) y los registros, por
ello es el segmento ms importante.

FF FFFF
01 0000
S0 64Kb
256
Segmentos
de 64 kB
Pgina 0
(RAM ext)
Pgina 1
(RAM ext)
Pgina 2
Pgina 3
(RAM Interna)
00 0000
0000
4000
8000
C000
FFFF
16 Mb
S1 64Kb
16 Kb

Figura 13: mapa de memoria del C167

Como se puede ver en la Figura 13, la pgina 0 y 1 del micro son generalmente RAM externa
(ciertas versiones del micro tienen ROM interna). La pgina 3 contiene la RAM interna y los
registros tal como se muestra en la Figura 14:
Desde la direccin 0xF600 hasta la 0xFC00 se encuentra el STACK, que es memoria
RAM para almacenamiento temporal.
Desde la direccin 0xFC00 hasta la 0xFD00 estn mapeados los GPRs. Como los
GPRs son 15 y caben 256 en esa zona de memoria, significa que los GPRs pueden
estar mapeados en distintas direcciones de memoria. Para ms informacin sobre el
mapeo de los GPRs ver seccin 2.3.2.5.
Desde la direccin 0xFD00 hasta la 0xFE00 se encuentra una zona de memoria RAM
que se puede acceder a nivel de bit, es decir, se pueden usar como operandos con
instrucciones que trabajan a nivel de bit.
Desde la direccin 0xFE00 hasta la 0XFFFF se encuentran mapeados los SFRs.

Sistemas Electrnicos Digitales.





29
F600
FC00
FD00
FFFF
FF00
FE00
RAM
SFRs
STACK
GPRs
Acceso bit a bit
SFRs
SFRs acceso bit a bit

Figura 14: Organizacin de la pgina 3 del C167
2.3.1 Los registros de propsito general GPRs
Los registros de propsito general son 16 y se van de R0 hasta R15. Los 8 primeros registros
(R0 a R7) se pueden acceder a nivel de byte (8 bits). En este caso reciben los nombres, por
ejemplo para R0, de RL0 y RH0, y se pueden usar con instrucciones que manejan datos a
nivel de byte. Solamente los 4 primeros registros (R0 a R3) pueden almacenar direcciones
(punteros), para ser usados con modos de direccionamiento indirecto. Para ms informacin
sobre modos de direccionamiento ver seccin 2.2.2 de este captulo. Se encuentran ubicados
en la zona de la memoria que comprende 0xFC00 a 0xFD00, en concreto donde indique el
registro CP.
2.3.2 Principales SFRs de la CPU
En las siguientes subsecciones se describen los principales registros de propsito especfico
que tiene la CPU. En posteriores captulos se tratarn otros SFRs que permiten gestionar los
perifricos del C167.
2.3.2.1 PC (Program Counter)
Como la memoria del C167 puede llegar a ser de 16MBytes, significa que podra haber partes
de un programa que estuvieran situadas en los ltimos segmentos, lo que implica que el PC
debera tener la capacidad de direccionar hasta 16MBytes. Por otro lado, dado que el C167
es un micro de 16 bits, sus registros son de a lo sumo 16 bits. Por lo tanto para poder
direccionar hasta 16 MBytes (24 bits) es necesario usar dos registros. Precisamente por esa
razn el PC del C167 se desdobla en dos registros:
CSP (Code Segment Pointer): registro de 8 bits que almacena el Byte ms alto de PC;
lo que es lo mismo que decir que apunta al segmento en uso por PC.
IP (Instruction Pointer): registro de 16 bits que almacena los 2 Bytes ms bajos de
PC; lo que es lo mismo que decir que apunta a cualquier direccin dentro del
segmento seleccionado por CSP.

Sistemas Electrnicos Digitales.





30
Por ejemplo:
01 0000
Si PC =01 0000
CSP IP


Esto mismo se explica de forma ilustrada en la Figura 15.
FF FFFF
01 0000
S0 64Kb
Segmentos
00 0000
CSP indica
el segmento
en uso de los
255 posibles
S1 64Kb
8 bits
IP indica la zona
del segmento
en uso de las
64k posibles
16 bits

Figura 15
2.3.2.2 PSW (Processor Status Word)
El registro de estado PSW, se encarga de almacenar el estado en el que ha quedado el micro
despus de que se ejecuta una instruccin. Es un registro de 16 bits, del que por ahora slo se
vern los flags de estado, que son los siguientes:
C (flag de acarreo). Para nmeros sin signo, se sabe si ha existido rebose al efectuar la
suma, comprobando el flag de "carry" (flag C) del registro de estado de P. (Este bit
tambin sirve para indicar si ha existido acarreo "negativo" (borrow), que se produce
cuando el substraendo es mayor que el minuendo en una operacin de resta).
V (flag de rebose). Cuando se opera con nmeros con signo se debe comprobar el
estado del flag de "overflow" (flag V). Este flag se pone a 1 si al sumar dos nmeros
positivos se obtiene uno negativo (bit ms significativo a 1), y viceversa. Al sumar dos
nmeros de distinto signo nunca se tiene rebose.
N (flag de nmero negativo). Indica que una operacin ha generado un resultado
negativo. En 8 bits significa que el bit 7 es 1 y en 16 bits significa que el bit 15 es 1.
Z (flag de cero). Indica si una operacin ha obtenido como resultado un cero.
2.3.2.3 SP (Stack pointer)
Sistemas Electrnicos Digitales.





31
Apunta a la zona de Stack, que est comprendida entre la direccin 0xF600 y 0xFC00). El
Stack es una zona de la memoria donde el micro guarda de forma temporal informacin que
necesita para la ejecucin de un programa; por ejemplo, cuando hay una llamada a una
funcin guarda la informacin de la direccin desde donde se llama la funcin para poder
posteriormente seguir la ejecucin por donde iba. El funcionamiento del Stack es de tipo
LIFO (last in, first out). Inicialmente SP apunta a la direccin 0xFC00 y segn se van
almacenando datos en el Stack, el SP va decreciendo. De modo contrario, cuando se van
recuperando datos del Stack, el SP va creciendo. Si SP es igual a 0xFC00 quiere decir que el
Stack no tiene datos, se dice que est vaco.
2.3.2.4 DPPs (Data Page Pointer Registers)
De la misma forma que sucede con el PC, cuando se quiere acceder a una zona de la memoria
del micro para coger un dato, es necesario usar 24 bits. Por ejemplo, si se quiere acceder a un
dato en la direccin 0x0A7000, es necesario partir la direccin en dos trozos, usando un
registro de apoyo de 10 bits denominado DPP0. Existen tambin el DPP1, DPP2 y DPP3, que
se pueden usar indistintamente para poder conseguir los 24 bits necesarios. El concepto es
similar al usado con el PC, pero en vez de utilizar un registro para seleccionar el segmento y
otro para direccionar dentro del segmento, se usa un registro para seleccionar una pgina de la
memoria y otro para direccionar dentro de la pgina. Por ello se dice que la memoria del C167
es segmentada para programas y paginada para datos. El registro DPPx se encarga de
seleccionar la pgina dentro de la memoria seleccionada para coger el dato.

A continuacin se va a resolver el problema de intentar de ejecutar la instruccin siguiente,
que es incorrecta:

MOV R0, 0x0A7000 ; I NCORRECTA


La solucin pasara por usar, por ejemplo, el DPP0 que almacenar los 10 bits ms altos de la
zona que queremos direccionar; en este caso y en binario 00 0010 1001 (DPP0 =0x29). El
resto de la direccin deseada, los 14 bits ms bajos se dejan como estn y se les aade como 2
bits ms altos el nmero de DPP utilizado para resolver la direccin deseada; en este caso el
0.

0000 1010 01 11 0000 0000 0000
00 11 0000 0000 0000
DPP0 10bits
Nmero de DPP
seleccionado
Pgina seleccionada
Segmento seleccionado
MOV DPP0, #0x29
MOV R0, 0x3000


Sistemas Electrnicos Digitales.





32
Otra solucin podra haber usado el DPP2, que se muestra a continuacin:

0000 1010 01 11 0000 0000 0000
10 11 0000 0000 0000
DPP2 10bits
MOV DPP2, #0x29
MOV R0, 0xB000

2.3.2.5 CP (Context Pointer)
Como se coment con anterioridad los GPRs se pueden mapear desde la direccin 0xFC00
hasta la 0xFD00. El registro CP indica donde estn mapeados los GPRs en todo momento, ya
que almacena la direccin de memoria donde se encuentra R0. El resto de registros se
suponen a continuacin. Por defecto el valor de CP es 0xFC00, pero se puede modificar desde
un programa.

En el ejemplo siguiente se muestra como se modifica CP de forma que R0 se sita en la
direccin 0xFC00, haciendo que valga a = 0x1034.

1034 FC00
A050 FC02
FC04 FC04
FF00 FC06
4400 FC08
... ...
Dato Direccin
1034 FC00
A050 FC02
FC04 FC04
FF00 FC06
4400 FC08
... ...
Dato Direccin
R0
R1
R2
R3
R4
...
R0
R1
R2
R3
R4
...
. . .
MOV CP, #0FC00 H
MOV a, R0
. . .


En el siguiente ejemplo, en cambio R0 se sita en la direccin 0xFC04, haciendo que valga a
= 0xFC04.
1034 FC00
A050 FC02
FC04 FC04
FF00 FC06
4400 FC08
... ...
Dato Direccin
1034 FC00
A050 FC02
FC04 FC04
FF00 FC06
4400 FC08
... ...
Dato Direccin
R0
R1
R2
R3
R4
...
R0
R1
R2
R3
R4
...
. . .
MOV CP, #0FC04 H
MOV a, R0
. . .

Sistemas Electrnicos Digitales.





33

3 Cuestiones de comprensin

Practicando con la memoria del micro

1) Escribir en ensamblador un cdigo que escriba el contenido de la direccin de memoria
0x1F0468 en el registro R1. Usar DPP2.







2) Cuantos bits son necesarios para poder direccionar hasta 8 Mbytes de datos? _____


Practicando con la arquitectura del micro

3) Si el microcontrolador est ejecutando la lnea de cdigo de programa 0x1F0468 Cul es
el valor del registro IP y CSP?






4) Qu hay que hacer para que el registro R1 sea mapeado en la direccin de memoria FC06?


4 Ejercicios propuestos

1) Hacer un programa en ensamblador que intercambie el contenido de la direccin de
memoria 0x200 por el de la 0x202.









IP =

CSP =
Sistemas Electrnicos Digitales.





34
2) Hacer un programa en ensamblador que intercambie el contenido de la direccin de
memoria 0x200 por el de la 0x201.






3) Hacer un programa en ensamblador que intercambie el contenido de la direccin de
memoria indicada en el registro R0, por el contenido de la direccin de memoria indicada en
el registro R1.







4) Hacer un programa en ensamblador que busque el valor mximo (a nivel de byte sin signo)
de los datos que hay entre la direccin de memoria 0x200 y 0x300, y lo guarde en R1.




















5) Dadas las condiciones iniciales de los registros y las instrucciones escritas a continuacin,
indicar cmo se modifica la memoria y los registros R0 y R1 en los sucesivos pasos.
Sistemas Electrnicos Digitales.





35
Direccin de
memoria 24
bits (Hex)
Celda 8 bits
(Hex)
00 0200 05
00 0201 00
rh0 rl0 rh1 rl1 00 0202 10
FF 00 00 01 00 0203 02
00 0204 11
00 0205 FF
00 0206 A0
Direccin de
memoria 24
bits (Hex)
Celda 8 bits
(Hex)
00 0200
00 0201
MOV R0, #2 rh0 rl0 rh1 rl1 00 0202
00 0203
00 0204
00 0205
00 0206
Direccin de
memoria 24
bits (Hex)
Celda 8 bits
(Hex)
00 0200
00 0201
MOV R0, 0x202 rh0 rl0 rh1 rl1 00 0202
00 0203
00 0204
00 0205
00 0206
Direccin de
memoria 24
bits (Hex)
Celda 8 bits
(Hex)
00 0200
00 0201
MOV R1, R0 rh0 rl0 rh1 rl1 00 0202
00 0203
00 0204
00 0205
00 0206
Direccin de
memoria 24
bits (Hex)
Celda 8 bits
(Hex)
00 0200
00 0201
MOV 0x200, R1 rh0 rl0 rh1 rl1 00 0202
00 0203
00 0204
00 0205
00 0206
SITUACIN INICIAL DE LA MEMORIA Y REGISTROS
PASO 1
PASO 2
PASO 3
PASO 4
r1
r0 r1
r0 r1
r0
r0 r1
r0 r1

Sistemas Electrnicos Digitales.





36
Direccin de
memoria 24
bits (Hex)
Celda 8 bits
(Hex)
00 0200
MOV R2, #0x4433 00 0201
MOV 0x202, R2 rh0 rl0 rh1 rl1 00 0202
00 0203
00 0204
00 0205
00 0206
Direccin de
memoria 24
bits (Hex)
Celda 8 bits
(Hex)
00 0200
00 0201
MOVB rl0, #4 rh0 rl0 rh1 rl1 00 0202
00 0203
00 0204
00 0205
00 0206
Direccin de
memoria 24
bits (Hex)
Celda 8 bits
(Hex)
00 0200
00 0201
MOVB rh1, [r0] rh0 rl0 rh1 rl1 00 0202
00 0203
00 0204
00 0205
00 0206
Direccin de
memoria 24
bits (Hex)
Celda 8 bits
(Hex)
00 0200
00 0201
MOV r1, [r0+] rh0 rl0 rh1 rl1 00 0202
00 0203
00 0204
00 0205
00 0206
Direccin de
memoria 24
bits (Hex)
Celda 8 bits
(Hex)
00 0200
00 0201
MOVB rl1, [r0+] rh0 rl0 rh1 rl1 00 0202
00 0203
00 0204
00 0205
00 0206
Direccin de
memoria 24
bits (Hex)
Celda 8 bits
(Hex)
00 0200
00 0201
ADD r1, r0 rh0 rl0 rh1 rl1 00 0202
00 0203
00 0204
00 0205
00 0206
PASO 9
PASO 10
PASO 5
PASO 6
PASO 7
r0 r1
r0 r1
r0 r1
r0 r1
PASO 8
r0 r1
r0 r1

Sistemas Electrnicos Digitales.





37
6) Dada la tabla de cdigos de instrucciones y la situacin inicial de los registros CP, IP,
DPP0 y CSP indicar cmo se modifica la memoria cuando se ejecuta el programa de tres
instrucciones cargado en memoria. Indicar en la tabla de la derecha cmo queda la memoria
despus de la ejecucin de la tercera instruccin del programa.


mov R0, R1
Regi st r os
CSP = 00
CP = FC00
DPP0 =0
IP = 020A
Di r ecci n de
memor i a 24
bi t s (Hex)
Cel da 8 bi t s
(Hex)
Di r ec ci n de
memor i a 24
bi t s (Hex)
Cel da 8 bi t s
(Hex)
00 0200 FF 00 0200
00 0201 20 00 0201
00 0202 20 00 0202
00 0203 10 00 0203
00 0204 01 00 0204
00 0205 11 00 0205
00 0206 03 00 0206
00 0207 03 00 0207
00 0208 11 00 0208
00 0209 10 00 0209
00 020A 10 00 020A
00 020B E0 00 020B
00 020C 31 00 020C
00 020D E0 00 020D
00 020E 02 00 020E
00 020F 02 00 020F
00 0210 F0 00 0210
00 0211 F6 00 0211
00 0212 00 00 0212
00 0213 00 00 0213
00 0214 00 00 0214
.. ..
00 FC00 01 00 FC00
00 FC01 02 00 FC01
00 FC02 34 00 FC02
00 FC03 45 00 FC03
00 FC04 65 00 FC04
00 FC05 76 00 FC05
mov 0x202, R0
F0 01
F6 F0 02 02
Escribir aqu la solucin final
E0 10
Cdigo de instruccin Instruccin
mov R0,#1
E0 31 mov R1,#3


Sistemas Electrnicos Digitales.





38


7) Dado el programa siguiente, rellenar los registros y la memoria indicada justo antes de que
el programa ejecute la instruccin de la direccin de memoria 0x514 (final del programa)

mov R1,#1
508
Direccin memoria HEX Cdigo Instruccin
500 mov R0,#1
cmp R0,#5
514 nop CC 00
50A jmpr cc_sgt,0x514
50C add 0xfa00,R1
E0 10
E0 11
48 05
AD 05
04 F1 00 FA
08 01
512 0D FA jmpr cc_uc,0x508
504 F6 F1 00 FA mov 0xfa00,R1
510 add R0,#1
502


CP =FC02
Registros
CSP =
IP =

Sistemas Electrnicos Digitales.





39
Direccin de
memoria 24
bits (Hex)
Celda 8 bits
(Hex)

Sistemas Electrnicos Digitales.





40

5 Prctica 1: Introduccin al Siemens C167
Sistemas Electrnicos Digitales.





41
Sistemas Electrnicos Digitales.





42
Sistemas Electrnicos Digitales.





43
Sistemas Electrnicos Digitales.





44
Sistemas Electrnicos Digitales.





45
Sistemas Electrnicos Digitales.





46
Sistemas Electrnicos Digitales.





47

Sistemas Electrnicos Digitales.





48
Captulo 4 PUERTOS
1 Objetivos y conceptos a entender en este captulo
El objetivo del captulo es entender y aprender a manejar los puertos paralelo del C167. Este
objetivo se consigue cuando se sepa manejar y diferenciar el registro de direcciones (DPx) y
de datos de un puerto (Px).
2 Puertos paralelo
El C167 tiene 9 puertos paralelo, con un total de 111 lneas. Cada lnea se corresponde con un
pin o patita del chip del micro, que tiene 144 pines en total. Los puertos se nombran Px, de
forma que el puerto 0 se llama P0, el puerto 1 se llama P1, etc. Cada puerto consta de un
conjunto de lneas, como mximo 16, que salen al exterior o entran del exterior por los pines
del micro. Existe una correspondencia biunivoca entre pines y lneas. A continuacin se
enumeran los puertos explicando muy someramente su funcin:

El P0 tiene 16 lneas y es el bus de datos del micro que tanto se ha hablado a lo largo
del captulo 2 y 3. Este bus se conecta a las memorias externas y a los perifricos y se
usa para transmitir los datos que contienen los mismos. No se debe olvidar que tiene
16 bits, cada uno corresponde con una lnea, ya que el C167 es de 16 bits.
El P1 tiene 16 lneas y representa la parte baja del bus de direcciones. Este bus se
conecta a las memorias externas y a los perifricos y se usa para que la CPU indique la
direccin de memoria que se quiere acceder para recuperar o escribir un dato. Este bus
es de 24 bits y por ello este puerto nicamente representa a los 16 bits ms bajos del
mismo. Ser necesario usar el puerto 4 para completar el bus.
El P2 tiene 16 lneas y es de propsito general. En el laboratorio, se tienen conectados
en la parte baja del puerto, 8 diodos LED, y en la parte alta del puerto, 8 interruptores.
Pero es muy importante no olvidar que se podra haber conectado cualquier otra cosa
al puerto.
El P3 tiene 16 lneas. Parte de las lneas se usan para un puerto serie, que en el caso
del laboratorio se usa para comunicarlo con el PC. El resto de las lneas son de
propsito general.
El P4 tiene 8 lneas que completan la parte alta del bus de direcciones.
El P5 tiene 16 lneas que se usan como entradas para el conversor A/D. En cada una
de estas entradas se puede conectar una seal analgica, para poder realizar una
digitalizacin de la misma.
El P6 es de 8 lneas y tiene parte del bus de control.
El P7 tiene 8 lneas que son las salidas correspondientes a la unidad de PWM que tiene
el micro.
Sistemas Electrnicos Digitales.





49
El P8 tiene 8 lneas que son las entradas correspondientes a la unidad de "Capture
Compare del micro.

Cada puerto tiene dos registros que sirven para manejarlo, un registro de control (DPx) y
otro de datos (Px). A continuacin se explica cada uno de ellos particularizado para el puerto
2.

DP2 tiene 16 bits, uno para cada lnea (pin) del puerto. Se utiliza para indicar si el pin hace de
entrada o de salida (el pin no puede hacer de entrada y de salida al mismo tiempo). Con un 0
en DP2 se indica que el pin hace de entrada. Con un 1 el pin hace de salida. Por ejemplo, si en
DP2 cargamos 0xFFFF estamos indicando que todos los pines del puerto hacen de salida. Si
cargamos 0x0000 indicamos que todos hacen de entrada. Con 0x00FF la mitad de los pines
del puerto hacen de entrada y la otra mitad de salida.

Una vez configurado el puerto va DP2, ste se maneja a travs de P2. Cuando se lee P2 se lee
el estado de los pines del micro. Cuando se escribe en P2 se escribe en los pines del micro.

En el sistema usado para las prcticas de laboratorio se han conectado diodos LED en parte
baja de P2 (P2.0 a P2.7) e interruptores en la parte alta (P2.8 a P2.15), de la manera que se
muestra en la Figura 16.

+ 5V
P2.0
+ 5V
P2.8

Figura 16: conexin de los LED e interruptores al puerto 2 del C167 de la tarjeta de laboratorio
Con este hardware en DP2 se tiene que escribir 0x00FF.

Cuando se lea P2 se estar leyendo el estado de los pines que hacen de entrada (parte
alta de P2: interruptores).
Cuando se escriba en P2 se actuar sobre los diodos (parte baja de P2).

Ntese que:

Cuando se lee P2 la nica informacin de inters es la que viene de las entradas (la
informacin de las salidas no tiene inters, se desecha)
Sistemas Electrnicos Digitales.





50
Cuando se escribe P2 slo se acta sobre las salidas (en las entradas tenemos el valor
fijado en el exterior va interruptores).
DP2 depende nicamente del hardware conectado y por ello slo se configura una
vez dentro de los programas. De forma que aquellos pines del micro que tengan
conectados actuadores, se configurarn como salidas y los que tengan conectados
sensores, se configurarn como entradas.

Por ejemplo:

Si el interruptor conectado a P2.8 lo ponemos a 5V (actuando manualmente sobre l) y
el resto de interruptores los ponemos a 0V y adems la CPU tiene encendidos todos
los LED, entonces al leer P2 obtenemos 0x0100.
Si en ese momento alguien mueve el interruptor conectado a P2.9, entonces P2 vale
0x0300, lo que permite a la CPU darse cuenta de lo sucedido simplemente leyendo P2.
Si la CPU decide apagar el diodo menos significativo escribir 0x0001 en el puerto. Si
a continuacin se lee el puerto, sin cambiar ninguno de los interruptores, se obtendr
0x0301 (obtenemos en valor que hemos escrito previamente).

A continuacin se muestra un programa que suma dos nmeros de 4 bits, uno representado
por los 4 interruptores conectados a la parte ms alta de P2 (P2.12 a P2.15) y otro
representado por los 4 interruptores conectados desde P2.8 hasta P2.11. El resultado de la
suma se muestra por los LEDs.

La solucin en C sera:

voi d mai n( voi d) {
i nt t emp1, t emp2;
DP2 = 0x00f f ;
whi l e ( 1) {
t emp1 = P2;
t emp2 = t emp1; / * Mej or que " t emp2 = P2 */
t emp1 = t emp1 & 0x0f 00; / * AND bi t a bi t */
t emp1 = t emp1 >> 8; / * SHR r ot ar 8 a l a decha*/
t emp2 = t emp2 & 0xf 000;
t emp2 = t emp2 >> 12;
P2=~( t emp1 + t emp2) ; / * CPL */
}
}


En el ejemplo se puede apreciar que la operacin AND en C es &, que la operacin
desplazamiento de bits a la derecha SHR en C es >>y que el complemento a 1 CPL en C es ~.

El siguiente cdigo presenta la solucin en ensamblador para irse familiarizando con el
mismo y as poder compararlo con el lenguaje C.

Sistemas Electrnicos Digitales.





51
MOV DP2, #0x00f f
bucl e: MOV R0, P2
MOV R1, R0
AND R0, #0x0F00
SHR R0, #8
AND R1, #0xF000
SHR R1, #12
ADD R1, R0
CPL R1
MOV P2, R1
J MPR CC_UC, bucl e


Ntese que el programa maneja DP2 una nica vez en la fase de inicializacin (configuracin
del puerto, antes del bucle while). El manejo de puerto se realiza a travs de P2.
Sistemas Electrnicos Digitales.





52

3 Ejercicios propuestos
1) Hacer un programa en ensamblador que encienda el primer LED de la tarjeta del
laboratorio (situados en la parte baja del puerto 2).













2) Hacer un programa en ensamblador que indique en los LED (parte baja de P2) la posicin
de los interruptores (parte alta de P2) de la tarjeta del laboratorio.







Sistemas Electrnicos Digitales.





53
4 Prctica 2: entradas y salidas digitales
Sistemas Electrnicos Digitales.





54
Sistemas Electrnicos Digitales.





55
5 Prctica 3: ensamblar y depurar
Sistemas Electrnicos Digitales.





56
Sistemas Electrnicos Digitales.





57
Sistemas Electrnicos Digitales.





58
Sistemas Electrnicos Digitales.





59

Sistemas Electrnicos Digitales.





60
Captulo 5 PERIFRICOS
1 Objetivos y conceptos a entender en este captulo
Entender cmo se maneja de forma general cualquier perifrico del micro.
Entender para qu sirve, cmo se maneja y configura el Timer.
Ser capaz de establecer una correspondencia entre el funcionamiento general de un
perifrico y el funcionamiento del Timer.
2 Perifricos del C167
Un perifrico es un dispositivo que tiene todo SED para realizar tareas especficas sin
consumir tiempo de CPU. En el C167 los registros de programacin de los perifricos se
encuentran mapeados en ciertas direcciones de memoria; es decir, se manejan igual que una
posicin cualquiera de memoria, haciendo operaciones de lectura/escritura, ver seccin 3.7.
Estas posiciones de memoria se corresponden con los registros de propsito especfico (SFR)
que tiene el perifrico.

Hay tres tipos de SFRs que permiten programar el perifrico:
Los registros de control o de configuracin: permiten configurar el modo de
funcionamiento del perifrico. Indican cuando el perifrico debe realizar su tarea y
cuando debe parar Start/Stop. La nomenclatura que se usa es xxxCON; es decir, el
nombre de los registros de control siempre acaban en CON.
Registros de datos: almacenan informacin relevante de los resultados o parmetros
necesarios para el funcionamiento del perifrico.
Registros de control de interrupcin: este registro informa de cundo el perifrico
termina la tarea que desempea. El programa que se ejecuta en la CPU se entera de
que el perifrico ha terminado su trabajo haciendo polling (de un bit) de este registro,
o va interrupcin, ver seccin 3.7 para un resumen o el captulo 8 para los detalles. La
nomenclatura que se usa para el nombre de estos registros es xxxIC (Interrupt Control
register).

Generalmente los perifricos suelen tener contacto con el exterior y por ello pueden adems
utilizar un puerto del micro.

El micro tiene muchos perifricos, de los cuales los ms importantes son:
Temporizadores (timers): para contar eventos, para llevar un computo del tiempo
transcurrido, etc.
Convertidor analgico/digital (A/D): sirve para pasar una seal del dominio analgico
al digital, formato que puede ya procesar el micro.
Sistemas Electrnicos Digitales.





61
Controladores de comunicaciones serie: para comunicarse con el exterior en serie; por
ejemplo un PC.
Moduladores PWM: muy usados en electrnica de potencia para controlar motores.
En este captulo slo se describir el Timer.
3 El Timer
Es un perifrico que se encarga de contar los pulsos de una seal. La cuenta la almacena en un
registro de 16 bits. En un momento dado la CPU le manda empezar a contar y cuando rebosa
(llega a 0xFFFF+1), avisa de que ha terminado la cuenta. El C167 tiene muchos Timers, pero
todos se usan de forma similar. Esta seccin explica con detalle el funcionamiento del Timer
0, y por similitud queda descrito el funcionamiento del resto de Timers del micro.

Los registros de programacin del mismo son:
T01CON: es un registro (SFR) de configuracin de 16 bits del Timer 0 y 1 como su
nombre indica. La parte baja del registro, primeros 8 bits, configuran el Timer 0 y la
parte alta configura el Timer 1.
T0: es un registro (SFR) de datos del perifrico de 16 bits que se encarga de llevar la
cuenta del nmero de pulsos detectados. El equivalente para el Timer 1 se llama T1.
T0REL: es el registro (SFR) de 16 bits que indica el valor con el que se carga T0 una
vez que rebosa, sobrepasa su mxima cuenta que es 0xFFFF. Dicho de otro modo, una
vez que el Timer 0 a realizado tantas cuentas como para T0 sobrepase 0xFFFF, en vez
de pasar a valer T0=0, pasa a valer T0=T0REL. De esta forma aunque el Timer 0
termina su tarea, puede seguir contando. El registro equivalente para el Timer 1 es
T1REL.
T0IC: es el registro (SFR) de 16 bits tiene un bit (T0IR) que indica cuando el Timer 0
ha rebosado. El resto de bits sirven para configurar su control por interrupcin

A continuacin se explica en detalle cada uno de estos registros.

3.1 Registro de control T01CON
El registro de T01CON tiene 16 bits y consta de dos partes, una parte baja que configura el
Timer 0 y otra parte alta que configura el Timer 1:

T0I
2 0
T0M
3 4
---
5
T0R ---
6 7
T1I
10 8
T1M
11 12
---
13
T1R ---
14 15


T0M: es el bit 3 e indica el modo de funcionamiento del Timer. Como se ha
comentado el Timer cuenta pulsos, pero no se ha especificado de dnde provienen.
Pues bien, el bit de modo indica si los pulsos provienen del reloj interno que usa la
CPU o no. En el primer caso se dice que funciona en modo timer ya que el origen es
una seal peridica y de frecuencia constante que equivale a un reloj de medida de
Sistemas Electrnicos Digitales.





62
tiempo, y en el segundo se dice que funciona en modo counter, por ejemplo el Timer 0
cuenta los pulsos de la seal que entra por el pin T0IN/P3.0.
T0I: es el pre-escalado y lo forman los bits 0-2. El pre-escalado, como su nombre
indica, es un cambio de escala en la cuenta. Indica el nmero de pulsos de la seal de
reloj que tienen que suceder para que el Timer 0 incremente en 1 su cuenta. De esta
forma se logra que el timer cuente ms despacio, ya que el pre-escalado funciona
como un divisor de frecuencia, dividiendo por:
) 0 3 (
2
I T +

Por ejemplo, para el caso de que el Timer 0 funcione en modo timer, y la CPU use un
reloj de 20 MHz, la salida del pre-escalado es:

T0I
clk = 20MHz
) 0 3 (
2
20
I T
MHz
+

T0R es el bit 6 y sirve para arrancar y para el Timer. Cuando la CPU quiere que
empiece la tarea, pone este bit a 1, y cuando ha terminado de contar, la CPU puede
poner este bit a 0 y deja de contar o bien le deja continuar recargando de forma
automtica T0=T0REL.

3.2 Registros de datos
Existen dos registros de datos de 16 bits cada uno:
T0: es un SFR que almacena la cuenta del Timer 0
T0REL: es el valor al que se inicializa el registro T0 cuando ste rebosa

3.3 Registro de control de interrupciones T0IC
Es un registro de 16 bits que tiene los siguientes bits:
GLVL ILVL
0 1 5 2
T0IE T0IR
6 7 8
15


De todos los bits el nico que interesa por ahora es el T0IR, ya que los dems se vern en ms
detalle en el Captulo 8.
T0IR: es un bit que indica que el Timer 0 ha terminado su tarea; es decir, en el
momento en que el registro T0 pasa de 0xFFFF a 0000.
T0IE: habilita el control por interrupciones.
ILVL: indica el nivel de la interrupcin (0 a 15. Nivel 15 nivel ms alto)
GLVL: grupo del nivel de interrupcin.

Sistemas Electrnicos Digitales.





63
3.4 Resumen de funcionamiento
El Timer cuenta hacia arriba desde el valor inicial de T0, hasta 0xFFFF. En el momento que
supera este ltimo valor se dice que ha rebosado y entonces T0=T0REL. Posteriormente
procede a seguir su cuenta.
Es necesario caer en la cuenta que la primera cuenta va desde el valor inicial de T0 a
0xFFFF. Las siguientes cuentas van desde T0REL a 0xFFFF. El rebose queda registrado en
el bit T0IR del registro T0IC.

T0 T0I
clk
T0IR
T0REL
Pre-escalado
rebose o final de
cuenta
Valor de recarga
despus de un rebose
Almacena la
cuenta


3.5 Ajuste del pre-escalado
El pre-escalado permite al Timer cambiar de escala el ritmo de la cuenta, de forma que en
modo timer puede llegar a contar con nicamente 16 bits durante 3.36s sin rebosar. Como T0I
tiene tres bits, significa que existen 8 escalas o velocidades de cuenta. Por ejemplo, en modo
timer, con un reloj de CPU de 20 MHz, se puede deducir que:
Escala 0 (T0I=0): la velocidad de la cuenta es de 2.5MHz; es decir, incrementa la
cuenta cada 400ns. A esta velocidad el tiempo mximo que puede pasar hasta el
rebose es 26ms, que se corresponde a una cuenta que va desde 0 hasta 0xFFFF,
momento en que rebosa. Por lo tanto, en este ltimo caso el valor inicial de T0 para la
primera cuenta debe ser 0 y para las siguientes T0REL =0.
Escala 1 (T0I=1): la velocidad de cuenta es la mitad de rpida, 1.25 MHz; es decir,
incrementa la cuenta cada 800ns. A esta velocidad el tiempo mximo de rebose es de
52ms (el doble que el caso anterior).
Escalas 2-7: el razonamiento es anlogo, aplicando la ecuacin
I T
MHz
0 2
2
20
+
.
3.6 Ejemplo de programacin: LEDs a ritmo de reloj
Antes de leer la explicacin del ejercicio, sera conveniente intentar entenderlo por uno
mismo, qu Timer usa?, a qu frecuencia cuenta?, cuanto tiempo tarda en rebosar? qu
pasa con el puerto?. Es necesario suponer un sistema como el del laboratorio donde hay LEDs
conectados a la parte baja del puerto P2. Por otro lado, la operacin ^es un XOR; es decir, P2
^= 0xFFFF, es lo mismo que P2 = P2 ^0xFFFF, que es en ensamblador XOR P2, #0xFFFF, que es
Sistemas Electrnicos Digitales.





64
lo mismo que P2 = ~P2, que es lo mismo que en ensamblador CPL P2, que es lo mismo que P2
= compl ement o a 1 de P2. De la misma manera T01CON | = 0x40 es lo mismo que T01CON =
T01CON | 0x40, que es en ensamblador OR T01CON, #0x40.

#i ncl ude <r eg167. h>
mai n( ) {
T01CON = 0x06; / / t i mer a 39 kHz
T0REL = PERI OD; / / Qu val or es son r azonabl es?
T0 = PERI OD;
T0I R = 0; / / f l ag r ebose = 0
T01CON | = 0x40; / / St ar t
DP2 = 0x00FF;
P2 = 0;
whi l e ( 1) {
whi l e( ! T0I R) ; / / bucl e de esper a
P2 ^= 0xFFFF; / / XOR
T0I R = 0; / / f l ag r ebose = 0
}
}


El Timer cuenta a una frecuencia de 39kHz y funciona en modo timer. Lo que supone que
dependiendo de la inicializacin de T0 y T0REL el Timer puede rebosar desde
aproximadamente 25us (cuando PERI OD = 0xFFFF) hasta aproximadamente 1.65s (cuando
PERI OD = 0). En un principio los LEDs estn encendidos. Cuando el programa entra en el
bucle infinito, se comprueba si el timer rebosa (T0I R == 1) y si es as entonces cambia el
estado del puerto P2, apagando los LEDs. Luego el programa vuelve a esperar al siguiente
rebose y despus enciende los LEDs. En resumen el programa enciende y apaga los LEDs de
forma peridica con un periodo que depende de la inicializacin de PERI OD. Para que el ojo
humano perciba el parpadeo de los LED este debe hacerse a una frecuencia inferior a 10Hz,
por ejemplo, PERI OD = 0 es razonable.
Sistemas Electrnicos Digitales.





65

4 Cuestiones de comprensin
1) Deducir la frmula que relaciona el tiempo de rebose del timer (t) con el prescalado (T0I) y
la cuenta inicial (T0); es decir, t =funcin(T0I,T0).






2) Si el tiempo que tarda en rebosar el timer 0 es 2s, cunto vale T0 y T0I (la cuenta inicial y
el preescalado)?. Razona la respuesta






3) Responder a las siguientes preguntas:
a. Cul es el mnimo nmero negativo (aproximadamente) que se puede conseguir
con 16 bits? ____________________________
b. Cul es el mayor nmero positivo (aproximadamente) que se puede conseguir con
16 bits con signo? _________________________
c. Ves alguna incoherencia entre las respuestas que has dado a los apartados 3.a) y
3.b) con la solucin obtenida en el ejercicio 2? Razona la respuesta.



Sistemas Electrnicos Digitales.





66

5 Ejercicios propuestos
5.1 PWM sencillo (30 min)

Hacer un programa que genere una secuencia de pulsos, por el pin P7.0 del micro, de forma
peridica a frecuencia 256kHz. El ancho de cada pulso viene fijada, en milisegundos, por la
variable de 8 bits DC.



































$nonsegment ed

S0 sect i on code at 0H
i ni pr oc NEAR
j mp mai n
i ni endp
S0 ends

DAT sect i on dat a at 200H
DC db 13


DAT ends

SM sect i on code at 300H
mai n pr oc NEAR



















Sistemas Electrnicos Digitales.





67




































mai n endp
SM ends
end

Sistemas Electrnicos Digitales.





68
6 Prctica 4: timers
Sistemas Electrnicos Digitales.





69
Sistemas Electrnicos Digitales.





70

Sistemas Electrnicos Digitales.





71
Captulo 6 ENSAMBLADOR
1 Objetivos y conceptos a entender en este captulo
Los objetivos de este captulo son:
Darse cuenta de que cada instruccin ensamblador se codifica de una forma en
hexadecimal.
Entender los nmeros con signo y sin signo, complemento a 2, qu implica el
overflow y el carry.
Entender cmo funcionan los saltos basndose en los flags del PSW.
Cmo se maneja el stack: cuando se usan funciones y con las instrucciones push y pop
2 Introduccin
El objetivo de este captulo es describir las principales instrucciones de ensamblador para el
microcontrolador Siemens C167. Las instrucciones de ensamblador se caracterizan por los
modos de direccionamiento que soportan, los flags de estado a los que afectan y el tamao de
los operandos que usan.

Los modos de direccionamiento son la forma que se tiene en ensamblador para acceder a cada
uno de los operandos de una instruccin. Se explican en el captulo 2 seccin 2.2.2.

Los flags de estado dan informacin cualitativa del resultado despus de ejecutar una
instruccin. Se explican en el captulo 2 seccin 2.3.2.2.

El 167 maneja operandos de distintos tamaos:
Byte: 8 bits
Word: 16 bits
Bit: 1 bit

2.1 Codificacin de instrucciones
La CPU slo entiende de ceros y unos. Por ello en memoria las instrucciones que tiene que
ejecutar se encuentran codificadas de forma binaria, cdigo mquina. El programa encargado
de traducir del lenguaje ensamblador a cdigo mquina se llama ensamblador. Si se trabaja en
alto nivel, el programa encargado de traducir del lenguaje C a cdigo mquina se llama
compilador.

Sistemas Electrnicos Digitales.





72
La codificacin interna de una instruccin se realiza en 16 o en 32 bits, de los cuales 8 son de
cdigo de operacin o tipo de instruccin, y los dems se usan para codificar los operandos de
la instruccin.

En la Figura 17 y en la Figura 18 se muestran dos ejemplos de cmo se codifica una
instruccin de 16 bits y una de 32 bits respectivamente. En el primer ejemplo la instruccin
ocupa 16 bits porque la codificacin de los operandos se puede hacer en 8 bits, 4 bits para
indicar el primer GPR (que slo hay 16) y 4 bits para indicar el segundo GPR. En el segundo
ejemplo la instruccin ocupa 32 bits porque el primer operando ocupa 8 bits y el segundo 16
bits.

F0 x y F0 x y
Cdigo de
instruccin
Nmero de
GPR

Figura 17: Codificacin de la instruccin MOV Rx, Ry

E6 reg dato E6 reg dato
Cdigo de
instruccin
Nmero de
SFR
Nmero de
16 bits

Figura 18: Codificacin de la instruccin MOV reg, #data
3 Operaciones de transferencia de datos
Todas ellas actualizan nicamente los flags N y Z. Si el resultado es cero se pone a uno el flag
Z y si el resultado es negativo se pone a uno el flag N.
3.1 MOV y MOVB
La instruccin ms utilizada en transferencia de datos es MOV. Equivale a un =en C. La
sintaxis es la siguiente:

MOV op1, op2 ; op1 = op2 a ni vel de Wor d
MOVB op1, op2 ; op1 = op2 a ni vel de Byt e

Transfiere el contenido del operando fuente op2, al operando destino op1. En este
ensamblador el operando fuente siempre est a la derecha y el destino a la izquierda. Es la
instruccin que permite el mayor nmero de combinacin de modos de direccionamiento en
sus operandos. Una regla que vale en un 95% de las veces es suponer que puede con todos los
modos de direccionamiento menos MOV mem,mem y MOV mem,#data. Para ms informacin
de los modos de direccionamiento consultar seccin 2.2.2 del captulo 3.

Sistemas Electrnicos Digitales.





73
3.2 MOVBZ y MOVBS

Si un dato a nivel de byte se va a utilizar a continuacin como dato a nivel de word, es
necesario tener en cuenta si el nmero tiene o no tiene signo. Si el nmero no tiene signo, los
8 bits ms significativos debern ser igual a cero. Si el nmero tiene signo (complemento a
dos) los 8 bits ms significativos debern estar a 0 si el bit 7 est a 0, y estarn a 1 si el bit 7
est a uno. A esta operacin se le conoce como extensin de signo.

Las instrucciones de que dispone el ensamblador de 167 para este propsito son:

MOVBZ op1, op2

Carga el byte en parte baja, extiende (a los 16 bits) con ceros

MOVBZ R0, #0xFF ; r 0 <- 0x00FF
MOVBZ R0, #- 1 ; r 0 <- 255 no r espet a el si gno


MOVBS op1, op2

Carga el byte en la parte baja, extiende (a los 16 bits) con ceros

MOVBS R0, #0xFF ; r 0 <- 0xFFFF
MOVBS R0, #- 1 ; r 0 <- - 1 r espet a el si gno


En la tabla siguiente se exponen dos ejemplos:

-128 (0xFF80) 128 (0x0080) 128 -128 0x80
-1 (0xFFFF) 255 (0x00FF) 255 -1 0xFF
16 bits exten-
diendo signo
16 sin extender
signo
8 bits sin signo 8 bits con signo
-128 (0xFF80) 128 (0x0080) 128 -128 0x80
-1 (0xFFFF) 255 (0x00FF) 255 -1 0xFF
16 bits exten-
diendo signo
16 sin extender
signo
8 bits sin signo 8 bits con signo


3.3 PUSH y POP
Otras instrucciones de transferencia de datos son:

PUSH r eg
POP r eg

La operacin PUSH decrementa el Stack Pointer y carga el operando en la posicin de
memoria apuntada por el mismo. La operacin POP efecta la operacin inversa. El operando
debe ser uno de los GPR's o SFR's.

Sistemas Electrnicos Digitales.





74

Figura 19: Ejemplo de uso de PUSH

Estas instrucciones se suelen usar para guardar los GPRs que se van a usar en una funcin
como variables locales, ya que en caso contrario la funcin modificara el contenido de los
mismos y no funcionara correctamente el programa que llama a la funcin.

4 Instrucciones para realizar operaciones aritmticas
Los flags se actualizan de acuerdo con el resultado de la operacin: N y Z para negativo y
cero, C para el acarreo y V para cambios en el bit de signo.
4.1 ADD y ADDB
Sirve para sumar dos nmeros en, guardando el resultado en el primero. La forma estndar de
la instruccin ADD es:

ADD op1, op2 ; op1 <- op1 + op2


MOV R0, #0x0001
MOV 0xFA00, R0
ADD R0, #0x0009
ADD 0xFA00, R0

Figura 20: Ejemplo de ADD. Finalmente R0 = 0x000A y 0xFA00 = 0x000B

El conjunto de modos de direccionamiento queda bastante restringido con respecto a la
instruccin MOV. Los modos que se pueden usar son:

ADD Rx, Ry
ADD Rx, [ Ry] ; Ry con y = 0. . 3
ADD Rx, [ Ry+] ; Ry con y = 0. . 3
Sistemas Electrnicos Digitales.





75
ADD Rx, #dat a
ADD r eg, #dat a
ADD r eg, mem
ADD mem, r eg

La instruccin ADD admite la variante ADDB para operandos a nivel de byte.

MOV R0, #0x0001
ADDB Rh0, #0x01

Figura 21: Ejemplo de ADDB. Finalmente R0 = 0x0101
4.2 SUB y SUBB
La instruccin SUB sirve para restar dos nmeros. Admite las mismas variantes que la
instruccin ADD. (En este caso el flag de carry C, recoge el borrow. El borrow est a 1
cuando el minuendo es menor que el substraendo).

SUB op1, op2 ; op1 <- op1 op2

MOV R0, #0x01FF
MOV 0xFA00, R0
SUB R0, #0x0009
ADD 0xFA00, R0

Figura 22: Ejemplo de SUB. Finalmente R0 = 0x1F6 y (0xFA00) =0x3F5

A nivel de byte
MOV R0, #0x01FF
SUBB Rh0, #0x01

Figura 23: Ejemplo de SUB. Finalmente R0 = 0xFF

4.3 NEG
La instruccin NEG sirve para obtener el complemento a dos de un nmero. Es equivalente a
restar el operando op1 de 0 y almacenar el resultado en el mencionado operando (en este caso
el flag de C tambin recoge el borrow).

NEG Rx ; Rx <- 0 - Rx

Sistemas Electrnicos Digitales.





76
MOV R0, #0x01FF
NEG R0

Figura 24: Ejemplo de NEG. Finalmente R0 = 0xFE01
A nivel de byte

MOV R0, #0x01FF
NEGB Rl 0

Figura 25: Ejemplo de NEGB. Finalmente R0 =0x0101
4.4 MUL y MULU
Son instrucciones para realizar multiplicaciones de dos nmeros. Admiten dos variantes: con
y sin signo.

MUL Rx, Ry ; [ MDH, MDL] <- Rx * Ry
MULU Rx, Ry

La instruccin MUL admite dos registros como operandos. El resultado viene dado en 32 bits,
que se almacena en el registro MD (registro Multiply/Divide de la CPU, almacenando en
MDL la parte baja de MD, y en MDH la parte alta de MD). En esta operacin nunca se tiene
rebose (C =0). El flag V se pone a 1 si el resultado no cabe en 16 bits (til si se pretende
multiplicar el resultado de este primer producto por algn otro factor.) Los flags Z y N se
actualizan de acuerdo con el valor del resultado. La instruccin MULU es la variante para
operandos sin signo.

MOV R0, #0xFFFF
MOV R1, #0xFFFF
MUL R0, R1
MOV R2, MDL
MOV R3, MDH
MULU R0, R1

Figura 26: Ejemplo de MUL y MULU. Finalmente R2 = 1, R3 = 0, MDL = 0x0001 y MDH = 0xFFFE

4.5 DIV y DIVU
La instruccin DIV divide la parte baja del registro MD (MDL: 16 bits) entre el operando Rx
(tambin de 16 bits).

DI V Rx ; MDL <- MDL / Rx MDH <- MDL mod Rx
DI VU Rx

Sistemas Electrnicos Digitales.





77
El cociente viene dado en 16 bits que se almacenan en la parte baja del registro MD (MDL),
el resto queda en la parte alta (MDH). Caso de que el cociente supere los 16 bits
significativos, o el cociente sea 0, el bit V se pone a 1. La variante DIVU opera con nmeros
sin signo.

MOV R3, #0xFFFF
MOV MDL, R3
MOV R0, #0x0001
DI V R0
MOV R1, MDL
MOV R2, MDH
MOV R3, #0xFFFF
MOV MDL, R3
DI VU R0

Figura 27: Ejemplo de DIV y DIVU. Finalmente R1 = 0xFFFF, R2 = 0, MDL = 0xFFFF y MDH = 0
5 Instrucciones para realizar operaciones lgicas
Las operaciones lgicas trabajan bit a bit dentro de un registro. Se suelen usar para aplicar
"mscaras", una especie de filtro que permite seleccionar ciertos bits de un registro.

Todas ellas actualizan nicamente los flags N y Z. Si el resultado es cero se pone a uno el flag
Z y si el resultado es negativo se pone a uno el flag N.
5.1 AND
Se utiliza para efectuar el producto lgico de dos operandos, bit a bit. La instruccin AND
admite la forma:

AND Rx, op ; Rx <- Rx and op

Admite los mismos modos de direccionamiento que la instruccin ADD. Los flags V y C
quedan a 0 y el resto (A, N) se actualizan de acuerdo con el valor del resultado. La variante
ANDB opera a nivel de byte.

MOV R0, #0x0001
AND R0, #0x0009


Figura 28: Ejemplo de AND. Finalmente R0 = 1
La instruccin AND sirve como mscara, para seleccionar nicamente ciertos bits de un
registro o para borrar bits de forma selectiva.

Sistemas Electrnicos Digitales.





78
AND R0, #0xFFFD

Figura 29: Se quiere poner el bit 1 del registro R0 a 0. O lo que es lo mismo, se seleccionan el resto de bits del
registro R0

5.2 OR
Se usa para efectuar la suma lgica de dos operandos, bit a bit. La instruccin OR admite la
forma:

OR Rx, op ; Rx <- Rx or op

Admite los mismos modos de direccionamiento que la instruccin ADD. La variante ORB
opera a nivel de byte.
MOV R0, #0x0001
OR R0, #0x0009

Figura 30: Ejemplo de OR. Finalmente R0 =9
La instruccin OR sirve como mscara, para seleccionar nicamente ciertos bits de un registro
o para poner a uno ciertos bits de forma selectiva.

OR R0, #0x0002

Figura 31: Se quiere poner el bit 1 del registro R0 a 1. O lo que es lo mismo, se seleccionan el resto de bits del
registro R0

La combinacin de AND con OR permite igualar dos bits de dos registros.

AND R0, #0xFFFD ; se pone a 0 el bi t 1 de R0
MOV R2, R1 ; par a no modi f i car R1
AND R2, #0x0002 ; se sel ecci ona el bi t 1 de R2
OR R0, R2 ; R0. 1 = R2. 1 = R1. 1

Figura 32: Se quiere poner el bit 1 del registro R0 igual que el bit 1 del registro R1.

5.3 XOR
Realiza un OR EXCLUSIVO bit a bit de dos operandos. La instruccin XOR admite la forma:

XOR Rx, op ; Rx <- Rx xor op

La variante XORB opera a nivel de byte.

Sistemas Electrnicos Digitales.





79
MOV R0, #0x0101
XOR R0, #0xFFFF ; R0 <- 0xFEFE

Figura 33: Ejemplo de XOR. Finalmente R0 = 0xFEFE

5.4 CPL
Realiza el complemento a 1 de un nmero. La instruccin CPL admite la forma:

CPL Rx ; Rx <- complemento a 1 de Rx

La variante CPLB opera a nivel de byte.

MOV R0, #0x0101
CPL R0 ; R0 <- 0xFEFE

Figura 34: Ejemplo de CPL. Finalmente R0 = 0xFEFE

6 Instrucciones para realizar desplazamientos de bits

Las instrucciones de desplazamiento SHL y SHR permiten desplazar los bits de un registro un
nmero arbitrario de desplazamientos (a izquierda y derecha respectivamente).

La forma genrica de utilizacin es:

SHL Rx, Ry
SHL Rx, #num; Despl aza numveces a l a i zda l os bi t s de Rx

donde Rx es el operando a desplazar, y Ry da el nmero de desplazamientos.

SHL desplaza los bits hacia la izquierda. El bit de Carry se pone a uno si el bit 15 que sale del
desplazamiento es 1 (en la ltima iteracin). Las posiciones libres que van quedando a la
derecha se rellenan con ceros.

Rx16 bits
C
0


MOV R0, #0x0001
SHL R0, #9

Figura 35: Ejemplo de SHL. Finalmente R0 = 0x0200
Sistemas Electrnicos Digitales.





80
SHR desplaza los bits hacia la derecha. El bit de Carry se pone a uno si el bit 0 que sale del
desplazamiento es 1 (en la ltima iteracin). Las posiciones libres que van quedando a la
izquierda se rellenan con ceros.

Rx16 bits
C
0


Se puede combinar con las operaciones AND y OR para igualar bits de diferentes registros.

AND R0, #0xFFFD ; se pone a 0 el bi t 1 de R0
MOV R2, R1 ; par a no modi f i car R1
AND R2, #0x0001 ; se sel ecci ona el bi t 0 de R2
SHL R2, #1 ; el bi t 0 pasa a ser el bi t 1
OR R0, R2 ; R0. 1 = R2. 1 = R1. 1

Figura 36: Se quiere poner el bit 1 del registro R0 igual que el bit 0 del registro R1.

Las instrucciones de rotacin ROL y ROR permiten rotar los bits de un registro un nmero
arbitrario de desplazamientos (a izquierda y derecha respectivamente), de forma que los bits
que salen por una lado del registro entran por el otro.

La forma genrica de utilizacin es:
ROL Rx, Ry
ROL Rx, #num; Rot a numveces a l a i zda l os bi t s de Rx

donde Rx es el operando a rotar, y Ry da el nmero de desplazamientos.

ROL rota los bits hacia la izquierda. El bit de Carry se pone a uno si el bit 15 que sale del
desplazamiento es 1 (en la ltima iteracin). Las posiciones libres que van quedando a la
derecha se rellenan con el valor del Carry en cada iteracin.

Rx16 bits
C


MOV R0, #0x8001
ROL R0, #9

Figura 37: Ejemplo de ROL. Finalmente R0 = 0x0280 si carry 0 y R0 =0x0380 si carry 1.
ROR rota los bits hacia la derecha. El bit de Carry se pone a uno si el bit 0 que sale del
desplazamiento es 1 (en la ltima iteracin). Las posiciones libres que van quedando a la
izquierda se rellenan con el valor del Carry en cada iteracin.

Sistemas Electrnicos Digitales.





81
Rx16 bits
C

7 Saltos

Como se ha mencionado en las secciones anteriores, el "estado" en el que queda el procesador
despus de ejecutar una instruccin (de transferencia de datos, aritmtica, lgica o de
desplazamiento), queda almacenado en el Registro de Estado, PSW, ver captulo 3 seccin
2.3.2.2. El estado viene definido por los "flags":
N: Negativo.
Z: Cero ("Zero").
V: Rebose ("Overflow").
C: Acarreo o "Carry".
La informacin contenida en estos flags es todo lo que se necesita para realizar el control de
flujo de programa. Por ejemplo, las siguientes condiciones del lenguaje C:

i f ( a == b)
i f ( a ! = b)

se efectan en ensamblador comparando (instruccin CMP, ver apartado siguiente) el valor de
la variable b con el valor de la variable a. Si las dos variables son iguales el procesador pone
el flag de "Zero" a uno (Z=1). Si son distintas el flag permanece a cero. Los saltos
condicionales, J MPR cc, permiten la ejecucin del bloque i f o del bloque el se, de acuerdo
con el resultado de la comparacin.
Cuando la condicin es del tipo desigualdad los flags que se deben comprobar (despus de la
operacin de comparacin) son el Acarreo (Carry, C) para operandos sin signo, y el Rebose
(Overflow, V) para operandos con signo (complemento a dos).
Para facilitar la escritura de programas, el ensamblador de 167 dispone de las siguientes
equivalencias entre alto nivel y ensamblador (ordenadas con criterio de alto nivel):

Comparaciones de igualdad y desigualdad:

Alto nivel Ensamblador Flag
== cc_EQ (equal) Z
!= cc_NE (not equal) [Z]

Sistemas Electrnicos Digitales.





82

Comparaciones de desigualdad (estricta y no estricta):

Alto
nivel
Ensamblador Sin signo Con signo
cc_UGT (unsigned greater
than)
[C] [Z] >
cc_SGT (signed greater
than)
[Z] [ ( N V ) ([N] [V] ) ]
cc_ULT (unsigned less
than)
C <
cc_SLT (signed less than) ( N [V] ) ([N] V )
cc_UGE (unsigned greater
than or equal)
[C] >=
cc_SGE (signed greater than
or equal)
( N V ) ([N] [V] )
cc_ULE (unsigned less than
or equal)
C Z <=
cc_SLE (unsigned less than
or equal)
Z [ ( N [V] ) ([N] V ) ]


La instruccin CMP es similar a la instruccin SUB: resta el operando destino y del operando
fuente y actualiza los flags de acuerdo con el resultado obtenido. Sin embargo, CMP no
actualiza el operando destino.

La operacin admite las siguientes variantes:

CMP op1, op2

op1 es el operando destino, y op2 es el operando fuente. Esta instruccin es idnea para
comparar dos operandos que no se quieren actualizar, antes de un salto con condicin. Admite
la variante CMPB.

En la Figura 38 se muestra un ejemplo. Primero, la instruccin CMP actualiza los flags del
registro PSW de la misma forma que lo hace la instruccin SUB. Segundo, la instruccin
J MPR se encarga de realizar el salto a la lnea next en caso de que R0 sea mayor que R1
(comparacin sin signo, es necesario hacer notar que -1 es mayor que 100 si se compara sin
signo ya que el nmero -1 es 65535 sin signo en 16 bits).

Sistemas Electrnicos Digitales.





83
CMP R0, R1
J MPR cc_ugt , next ; si R0 > R1
. . . .
next :

Figura 38: Ejemplo de salto condicional
Una condicin completa se muestra en la Figura 39.

MOV R0, a
CMP R0, b
J MPR cc_ne, el se
; condi ci n i f
. .
J MPR cc_uc, endi f
el se: ; condi ci n el se
. .
endi f :

Figura 39: Ejemplo de condicin en ensamblador de C167
8 Ejemplos de equivalencias de C y ensamblador

8.1 Condicin if
A continuacin se muestra un ejemplo de condicin en C y ensamblador

i f ( a == b)
. . . ;
el se
. . . ;

Figura 40: Condicin en C

Sistemas Electrnicos Digitales.





84
MOV R0, a
CMP R0, b
J MPR cc_ne, el se
; condi ci n i f
. .
J MPR cc_uc, endi f
el se: ; condi ci n el se
. .
endi f :

Figura 41: Condicin en ensamblador
8.2 Bucle for
A continuacin se muestra un ejemplo de bucle for en C y ensamblador

f or ( i =START; i <= STOP; i ++) {
a = STOP - i ;

Figura 42: bucle for en C

MOV R0, #START ; r 0 ( i )
MOV R1, #STOP
SUB R1, R0 ; r 1 ( STOP- START)
J MPR cc_uc, t est
f or : MOV a, R1
SUB R1, #1
ADD R0, #1 ; i += 1
t est : CMP R0, #STOP
J MPR cc_sl t , f or ; i <= STOP
next :

Figura 43: bucle for en ensamblador
8.3 Bucle while
A continuacin se muestra un ejemplo de bucle while en C y ensamblador

Sistemas Electrnicos Digitales.





85
i = 0;
whi l e ( i <10) {
a[ i ] = i ; i += 1;
}

Figura 44: bucle while en C

MOV R0, #0 ; R0 es i
MOV R1, #1 ; es el i ncr ement o de i
MOV R2, #0xf a00 ; R2 al macena l a di r ecci n de memor i a de a
ot r o: CMP R0, #10
J MPR cc_sge, next
MOV [ R2] , R0
ADD R0, R1
ADD R2, #2
J MPR cc_uc, ot r o
next :

Figura 45: bucle while en ensamblador

9 Instrucciones a nivel de bit

Las instrucciones que operan con bits de forma individual slo se pueden usar contra zonas de
memoria preparadas ello, ver Figura 46
F600
FC00
FD00
FFFF
FF00
FE00
RAM
SFRs
STACK
GPRs
Acceso bit a bit
SFRs
SFRs acceso bit a bit

Sistemas Electrnicos Digitales.





86
Figura 46: Zonas de memoria que permiten usar instrucciones a nivel de bit

Las zonas de RAM interna accesibles bit a bit son:
De la 00 FD00 a la 00 FDFF zona bit a bit.
De la 00 FF00 a la 00 FFFF SFR's accesibles bit a bit.

9.1 Saltos
Las instrucciones J B y J NB permiten realizar un salto en funcin del estado en el que se
encuentra un bit.
J B bi t , di r ; si bi t = 1 ent onces sal t a a di r
J NB bi t , di r ; si bi t = 0 ent onces sal t a a di r


J B C, next ; si C = 1 sal t a next
. . . .
next :

Figura 47: Ejemplo de manejo de JB.

9.2 Otras
La instruccin BSET pone a 1 el bit especificado en op1:

BSET op1

Los bits se especifican dando la direccin de la palabra, punto, nmero de bit. Por ejemplo:

BSET 0xFD00. 2

pone a 1 el bit 2 de la palabra 0x00FD00. El flag N contiene el estado previo del bit (0 si el bit
estaba a 0), y el flag Z es igual a N complementado.

La instruccin BCLR sirve para poner un bit a 0.

Para mover un bit de un lugar a otro se usa la instruccin

BMOV bi t 1, bi t 2 ; bi t 1 = bi t 2

Las siguientes instrucciones realizan operaciones lgicas con un slo bit
Sistemas Electrnicos Digitales.





87

BAND bi t 1, bi t 2 ; bi t 1 <- bi t 1 and bi t 2
BOR bi t 1, bi t 2 ; bi t 1 <- bi t 1 or bi t 2
BXOR bi t 1, bi t 2 ; bi t 1 <- bi t 1 xor bi t 2

En la Figura 48 se muestra algunos ejemplos de uso de estas instrucciones.
; act i va bi t 1 del P2
BSET P2. 1 ;
BCLR C ; Car r y = 0
BMOV V, C ; V=C

Figura 48: Ejemplos de instrucciones "a nivel de bit"
Sistemas Electrnicos Digitales.





88
10 Directivas de ensamblador
Las directivas son unas instrucciones se ponen en el programa y que indican al programa
ensamblador cmo debe ensamblar el cdigo. Estas instrucciones se ejecutan en tiempo de
ensamblado y no en tiempo de ejecucin como el cdigo ensamblador propiamente dicho.
Por eso a veces las directivas de ensamblador se llaman pseudoinstrucciones.

En la Figura 49, se muestra un ejemplo con directivas de ensamblador, que se pasan a explicar
a continuacin.

$nonsegment ed
maxdat a equ 0x10 ; const ant e
D100 section data at 200H
j dsw 10 ; i nt j [ 10] ;
h dw 1 ; i nt h =1;
D100 ends
ej section code at 300H
ej1 proc NEAR
MOV R0, #0
MOV R1, #1
MOV R2, #j
ot r o: CMP R0, #maxdat a
J MPR cc_sge, next
MOV [ R2] , R0
ADD R0, R1
ADD R2, #2
J MPR cc_uc, ot r o
next : NOP
ej1 endp
ej ends
end
Procedimiento ej1
Seccin de cdigo ej
en direccin 0x300
Seccin de datos D100
en direccin 0x200
Final de programa

Figura 49: Directivas de ensamblador

sect i on y ends: delimita las secciones del programa. El programa se puede
dividir en dos tipos de secciones, las secciones de datos y de cdigo:
o Las secciones de datos sirven para reservar memoria para variables. La
nomenclatura es:
nombr e sect i on dat a at xxxH
. . . .
nombr e ends
donde nombre es una etiqueta que indica el nombre de la seccin y xxxH es
la direccin de memoria donde se guarda la primera variable de la seccin. Las
demas se guardan a continuacin. Por ejemplo, en la Figura 49, la variable j se
Sistemas Electrnicos Digitales.





89
guarda en la direccin 0x200 y la variable h se guarda en la direccin 0x20A,
ya que j ocupa 10 posiciones.
o Las secciones de cdigo sirve para reservar memoria para instrucciones de
programa. La nomenclatura es:

nombr e sect i on code at xxxH
. . . .
nombr e ends
dsw: reserva espacios de 2 byte de memoria para una variable. Por ejemplo, en la
primera lnea de la seccin de datos de la Figura 49, se reserva 20 bytes (10 espacios
de 2 bytes) para la variable j; es quivalente a escribir en lenguaje C int j[10].
Existe la variante dsb que reserva espacios de 1 byte de memoria para la variable.
dw: reserva espacios de 2 byte de memoria para una variable y los inicializa. Por
ejemplo, en la segunda lnea de la seccin de datos de la Figura 49, se reservan dos
bytes que se inicializan a 1; es equivalente a escribir en lenguaje C int h. Por
ejemplo, el equivalente a int h[]={2,4}; sera dw h 2,4. Tambin existe la
variante db que reserva espacios de 1 byte.
equ: define una constante; el equivalente en C es #define. Esta directiva se pone
fuera de las secciones. En la primera lnea de la Figura 49 se muestra un ejemplo de
cmo se define la constante maxdata igual a 10.
end: indica final de programa y se pone al final del fichero.
proc: cada seccin de cdigo se puede dividir en varios procedimientos con esta
directiva. La nomenclatura es:

nombr e pr oc NEAR
. . . .
nombr e endp
donde nombre es un etiqueta que indica el nombre del procedimiento y endp indica
el final del procedimiento. Se puede acceder a un procedimiento de la misma manera
que se hace con una lnea de cdigo etiquetada; por ejemplo jmpr nombre.
Sistemas Electrnicos Digitales.





90

11 Cuestiones de comprensin
1) Cmo se codifica el nmero 16 en hexadecimal usando 8 bits?




2) Qu vale R0 despus de ejecutar las instrucciones siguientes?

Movbz R0, #0xFC ;R0 = __________

Movbs R0, #0xFC ;R0 = _________


3) Indicar el valor de PSW despus de ejecutar las siguientes instrucciones (los bits que no se
usan se pueden poner a cero):

mov R0, #0 ;PSW = ___________

add R0, #0x6500 ;PSW = ___________

add R0, #0x6500 ;PSW = ___________

add R0, #0x6500 ;PSW = ___________

4) Qu representa la informacin que almacena R0? (responder a,b c) _____

mov R0, #300
mov R1, [R0]

a) Un dato que podra variar
b) Una direccin de memoria
c) Una constante genrica


5) Qu representa var? (responder a,b c) _____

var equ 0x300
MOV R0, #var


a) Un dato que podra variar
b) Una direccin de memoria
c) Una constante genrica

Sistemas Electrnicos Digitales.





91
6) Cul es el valor de R0? __________

MOV R0,#0x01FF
NEGB RL0


7) Cual es el valor de R2 y R3? R2 =____________ R3 =____________

MOV R0, #0x6FFF
MOV R1, #0xFFFF
MUL R0, R1
MOV R2, MDL
MOV R3, MDH

8) Cual es el valor de R1 y R2? R1 =____________ R2 =____________

MOV MDL, #0xFFFF
MOV R0, #0x0001
DI V R0
MOV R1, MDL
MOV R2, MDH


9) Qu instrucciones de ensamblador hay que programar para hacer que el bit 2 (tercer bit)
del registro R0 sea igual que el de R1 sin llegar a modificar ni el registro R1 ni el resto de bits
del registro R0? (usar mscaras)








Sistemas Electrnicos Digitales.





92


10) Indicar el valor de SP, el de R0 y el valor de la memoria en hexadecimal? La respuesta
debe ir en la secuencia de tablas que se encuentran despus del ejemplo y que cada una se
corresponde con la ejecucin de cada una de las instrucciones del ejemplo.


....
300 MOV R0, #0x54
304 CALLR 400
306 MOV R1, #0x32
....


400 PUSH R0
402 MOV R0, #1
406 POP R0
408 RET

a) J usto despus de ejecutar la instruccin en la direccin de memoria 300


R0 =_____________

SP =_____________


Direccin mem Dato mem (HEX)
00 FC04
00 FC03
00 FC02
00 FC01
00 FC00
00 FBFF
00 FBFE
00 FBFD
00 FBFC
00 FBFB
00 FBFA

b) J usto despus de ejecutar la instruccin en la direccin de memoria 304


R0 =_____________

SP =_____________
Sistemas Electrnicos Digitales.





93


Direccin mem Dato mem (HEX)
00 FC04
00 FC03
00 FC02
00 FC01
00 FC00
00 FBFF
00 FBFE
00 FBFD
00 FBFC
00 FBFB
00 FBFA

c) J usto despus de ejecutar la instruccin en la direccin de memoria 400


R0 =_____________

SP =_____________


Direccin mem Dato mem (HEX)
00 FC04
00 FC03
00 FC02
00 FC01
00 FC00
00 FBFF
00 FBFE
00 FBFD
00 FBFC
00 FBFB
00 FBFA

d) J usto despus de ejecutar la instruccin en la direccin de memoria 402


R0 =_____________

SP =_____________


Sistemas Electrnicos Digitales.





94
Direccin mem Dato mem (HEX)
00 FC04
00 FC03
00 FC02
00 FC01
00 FC00
00 FBFF
00 FBFE
00 FBFD
00 FBFC
00 FBFB
00 FBFA

e) J usto despus de ejecutar la instruccin en la direccin de memoria 406


R0 =_____________

SP =_____________


Direccin mem Dato mem (HEX)
00 FC04
00 FC03
00 FC02
00 FC01
00 FC00
00 FBFF
00 FBFE
00 FBFD
00 FBFC
00 FBFB
00 FBFA


f) J usto despus de ejecutar la instruccin en la direccin de memoria 408


R0 =_____________

SP =_____________


Sistemas Electrnicos Digitales.





95
Direccin mem Dato mem (HEX)
00 FC04
00 FC03
00 FC02
00 FC01
00 FC00
00 FBFF
00 FBFE
00 FBFD
00 FBFC
00 FBFB
00 FBFA

g) J usto despus de ejecutar la instruccin en la direccin de memoria 306


R0 =_____________

SP =_____________


Direccin mem Dato mem (HEX)
00 FC04
00 FC03
00 FC02
00 FC01
00 FC00
00 FBFF
00 FBFE
00 FBFD
00 FBFC
00 FBFB
00 FBFA


Sistemas Electrnicos Digitales.





96

12 Ejemplo de discusin: medida de ancho de pulso, sin/con
filtrado de rebotes

Se quiere medir el ancho de un pulso que entra por un pin del micro. Desarrollar un programa
en C que mida el tiempo (en milisegundos) que est en 1 un pin de un puerto del micro (cada
vez que el pin vuelve a cero se debe esperar de nuevo a que se ponga a 1 para poder medir el
tiempo en el que est a 1).

Supuesto un sistema como el del laboratorio, mostrar el resultado del ancho del pulso en los
diodos situados en la parte baja del puerto P2. Aportar varias soluciones y discutir las ventajas
y desventajas de cada una.

Suponiendo que el pulso lo genera un sistema electrnico (entrada por P7.4) se puede suponer
que los flancos son limpios, no tienen rebotes. Los rebotes surgen cuando es un sistema
mecnico el que provoca los flancos, como por ejemplo un interruptor (entrada por P2.8). En
la siguiente figura se ilustra un flanco sin rebotes y con rebotes.
Con rebotes
Sin rebotes
T


Cuando se producen rebotes suelen durar un tiempo mximo T, que se puede determinar de
forma experimental. En general, un mismo interruptor puede tener ms rebotes unas veces
que otras, pero s que es cierto que se puede siempre encontrar un cota mxima de T.

En todas las soluciones que se proponen a continuacin se debe apreciar que se usa un bucle
infinito, como toda aplicacin que funciona en un micro. Soluciones ms detalladas que las
que se muestran a continuacin en el contexto de un problema real estn en las secciones 14.2
y 14.3.

En un principio se va a valorar la solucin ms sencilla, sin rebotes. Consiste en esperar a que
la seal se ponga a uno, en ese momento se activa el Timer que se pone a medir tiempo, y
justo cuando se detecta que la seal se vuelve a poner a 0 entonces se apaga el Timer y se
actualizan los LED:
Sistemas Electrnicos Digitales.





97
DP2 = 0x00FF;
DP7 = 0;
i ni ci al i zaci on( T0I =7, T0=- 20000) ;
whi l e ( 1) {
whi l e ( P7. 4==0) ;
T0R = 1;
whi l e ( P7. 4==1) ;
T0R=0;
t =T0/ 20;
P2=t ;
}


Este ejemplo tiene la pega de que slo puede medir el ancho de pulso de una lnea y sin
rebotes. Desde el punto de vista de la programacin la solucin es poco modular, ya que
mezcla el uso del Timer con el del puerto.

Una solucin ms modular supone usar un sistema muestreado, donde el periodo de muestreo
es un milisegundo. Se detecta cuando la seal se pone a uno y desde ese momento se muestrea
el pulso cada segundo, incrementando un contador que lleva la cuenta de milisegundos que
mide el ancho del pulso. En el momento que se detecta que la seal vuelve a 0, se actualizan
los LED.
DP2 = 0x00FF;
DP7 = 0;
whi l e ( 1) {
whi l e ( P7. 4==0) ;
cont ador = 0;
whi l e ( P7. 4==1) {
r et r aso( 1ms) ;
cont ador ++;
}
P2 = cont ador ;
}



Sistemas Electrnicos Digitales.





98
Este ejemplo tiene la pega de que slo puede medir el ancho de pulso de una lnea y sin
rebotes. Si se quisiera aumentar la resolucin bastara con llamar a la funcin r et r aso con un
tiempo inferior a 1ms.

La siguiente solucin propuesta, aunque slo trata con una sola lnea, sera capaz de soportar
tantas como se quisieran simplemente haciendo que las variables ant er i or , act ual , cuent a
y cont ador fueran vectores de tantos elementos como seales se quieren monitorizar. La idea
es que el sistema es muestreado siempre y no slo cuando se detecta el flanco, como en el
ejemplo anterior, de forma que cada ms se comprueba si hay un flanco en alguna de las
seales que se monitoriza, en este ejemplo slo se mira la lnea P7.4. Adems se ha aadido
una variable cuent a que indica si en una determinada lnea se ha detectado el pulso y por ello
se est midiendo el ancho del mismo en un determinado instante. Por lo dems el primer i f se
encarga de detectar el flanco de subida de la seal y el segundo i f se encarga de detectar el
flanco de bajada.

DP2 = 0x00FF;
DP7 = 0;
ant er i or = P7. 4;
whi l e ( 1) {
r et r aso( 1/ 8ms) ;
act ual = P7. 4;
i f ( ( ant er i or ! = act ual ) && ( act ual == 1) ) {
cuent a = 1;
}
i f ( ( ant er i or ! = act ual ) && ( act ual == 0) ) {
cuent a = 0;
P2 = cont ador ;
cont ador = 0;
}
i f ( cuent a==1)
cont ador ++;
ant er i or = act ual ;
}


La nica pega de esta solucin es que no tiene en cuenta los rebotes.
A continuacin se muestra una solucin que permite conectar a una determinada lnea una
seal con rebotes. El tratamiento de rebotes es el ms simple que se puede hacer, que consiste
en que una vez que se detecta un flanco, se espera un tiempo T (tiempo mximo que duran los
rebotes) para comprobar si el flanco es de subida o de bajada. Por lo dems es igual que el
ejemplo anterior.
Sistemas Electrnicos Digitales.





99
DP2 = 0x00FF;
ant er i or = P2. 8;
whi l e ( 1) {
r et r aso( 1/ 8ms) ;
act ual = P2. 8;
i f ( ant er i or ! = act ual )
r et r aso( 100ms) ;
act ual = P2. 8;
i f ( ( ant er i or ! = act ual ) && ( act ual == 1) )
cuent a = 1;
el se i f ( ( ant er i or ! = act ual ) && ( act ual == 0) ) {
cuent a = 0;
P2 = cont ador ;
cont ador = 0;
}
i f ( cuent a==1)
cont ador ++;
ant er i or = act ual ;
}


La pega de esta solucin es que se est perdiendo un tiempo de 100ms que no permite
monitorizar otras lneas y que adems es muy superior a lo que los rebotes pueden requerir.
Por ello esta solucin no soporta monitorizar varias seales de forma simultnea.

Por ltimo se presenta una solucin sin ninguna pega, que permite detectar el flanco justo
cuando se terminan los rebotes con independencia de lo que duren. La clave est en suponer
que el tiempo entre cambios de la seal cuando se producen rebotes es inferior a MAX (que
en un sistema real vale con que sea del orden de 3 o 4), ya que se comprueba el flanco en el
momento en el que no ha habido un cambio en la seal durante ms tiempo que MAX; es
decir se ha estabilizado la seal. La variable que comprueba esto es f i l t r ado. Cuando
f i l t r ado llega a 0 quiere decir que la seal se ha estabilizado y por lo tanto, es hora de
determinar si el flanco es de subida o de bajada.

Sistemas Electrnicos Digitales.





100
DP2 = 0x00FF;
DP7 = 0;
ant er i or = P2. 8;
whi l e ( 1) {
r et r aso( 1/ 8ms) ;
act ual = P2. 8;
i f ( ant er i or ! = act ual )
f i l t r ado = MAX;
el se i f ( f i l t r ado >0)
f i l t r ado- - ;
i f ( f i l t r ado==0) {
f i l t r ado = - 1;
i f ( act ual ==1) {
cuent a = 1;
}
el se {
cuent a = 0;
P2 = cont ador ;
cont ador = 0;
}
}
i f ( cuent a==1)
cont ador ++;
ant er i or = act ual ;
}


13 Ejercicios
13.1 Acceso a memoria (15 min)
Dado un sistema digital como la tarjeta que se usa en laboratorio, se pide realizar un programa
que tenga las siguientes caractersticas:

Lee un dato de los interruptores conectados a la parte alta del puerto P2.
Accede a la posicin de memoria
Muestra el contenido de la posicin en los LEDs
Sistemas Electrnicos Digitales.





101

13.2 Encendido apagado de LED (10 min)

Hacer un programa que encienda o apague un LED conectado al pin P2.0 del
microcontrolador C167, segn la posicin de un interruptor que se encuentra conectador en el
pin P2.1.
Sistemas Electrnicos Digitales.





102

13.3 Volcado de memoria (20 min)
Realizar una subrutina en ensamblador que haga una copia de la zona de memoria
comprendida entre la direccin 200H y la 20FH hasta la zona de memoria comprendida entre
la direccin 210H y 21FH.






































$nonsegment ed

S0 sect i on code at 0H
i ni pr oc NEAR
j mp mai n
i ni endp
S0 ends

DAT sect i on dat a at 200H
or i gen dsb 16
dest dsb 16


DAT ends

SM sect i on code at 300H
mai n pr oc NEAR
.


copi a:













f i n: r et

mai n endp
SM ends
end

Sistemas Electrnicos Digitales.





103
13.4 Cuenta de pulsos (30 min)

Supuesto un sistema digital como el del laboratorio, se ha conectado al pin P7.4 del micro una
seal que consiste en una secuencia de pulsos. Realizar un programa que muestre en los
LEDs, conectados a la parte baja del puerto P2, la cuenta del nmero de pulsos que entran por
el pin P7.4.
Sistemas Electrnicos Digitales.





104

13.5 Calculadora (40 min)

Escribir un programa en ensamblador de C167 que consiste en una calculadora que opera con
datos de 4 bits (sin signo) y devuelve un resultado de 8 bits. El funcionamiento es el siguiente:

En los cuatro bits ms altos de P2 se proporciona el primer dato. Este dato se valida
cuando la lnea P2.8 pasa de 0 a 1.
A continuacin se introduce el segundo dato (siguiendo el mismo procedimiento que
para el primer dato).
Por ltimo se introduce la operacin (+: P2.12 =1, -: P2.13=1). La operacin se valida
de la misma forma que los datos. En caso de que no se haya seleccionado una
operacin no se calcula el resultado.
El proceso anterior se repite indefinidamente, mantenindose en la parte baja de P2 el
resultado de la ltima operacin realizada.




























$nonsegment ed

S0 sect i on code at 0H
i ni pr oc NEAR
j mp mai n
i ni endp
S0 ends

DAT sect i on dat a at 200H
r esul t dsb 1
dat o dsb 1



DAT ends

SM sect i on code at 300H
mai n pr oc NEAR


Sistemas Electrnicos Digitales.





105














































































mai n endp
SM ends
end

Sistemas Electrnicos Digitales.





106



14 Ejercicios resueltos
14.1 LEDs e interruptores

Dado un sistema digital como la tarjeta que se usa en laboratorio, se pide realizar un programa
en ensamblador que tenga las siguientes caractersticas:

Lee un dato de los interruptores conectados a la parte alta del puerto P2.
Accede a la direccin de memoria indicada en los interruptores (8 bits ms altos de la
direccin todos a 0).
Analiza los ocho bits del dato almacenado en dicha direccin.
Si hay siete bits a 1 y uno a 0, se indica en los LED ms bajos de P2 la posicin del bit
que se encuentra a 0.
Si todos los bits se encuentran a 1 se ilumina el LED conectado a P2.4.
Si hay ms de un bit a 0 se encienden los cinco LED conectados a las lneas menos
significativas de P2.

voi d mai n( voi d) {
i nt di r ;
unsi gned char dat o, mask, i , n, pos;
DP2 = 0xFF;
whi l e ( 1) {
di r = ( P2 & 0xFF00) >> 8;
dat o = *( ( unsi gned char *) di r ) ;
f or ( i = 0, mask=0x01, n=0; i <8; i ++, mask<<=1) {
i f ( ! ( dat o & mask) ) {
pos = i ;
n++;
}
}
i f ( n==0) {
P2 = ~0x10;
}
el se i f ( n==1) {
Sistemas Electrnicos Digitales.





107










































SM sect i on code at 300H
mai n pr oc NEAR
MOV DP2, #0xFF
bucl e: MOV R0, P2
AND R0, #0xFF00
SHR R0, #8
MOV R4, #0
MOVB RL4, [ R0] ; dat o de l a di r ecci n de memor i a
MOV R1, #0 ; cont ador de f or
MOV R2, #1 ; mscar a
MOV R3, #0 ; cont ador de nmer o de bi t s a 0
i ni _f or : CMP R1, #8
J MPR cc_ugt , f i n_f or
MOV R0, R4
AND R0, R2
J MPR cc_ne, next _f or
MOV R5, R1 ; al macena l a posi ci n del bi t a 0
ADD R3, #1
next _f or : ADD R1, #1
SHL R2, #1
J MPR cc_uc, i ni _f or
f i n_f or : CMP R3, #0
J MPR cc_ne, i f _1
MOV P2, #0xEF ; enci ende LED P2. 4
J MPR cc_uc, bucl e
i f _1: CMP R3, #1
J MPR cc_ne, i f _n
Sistemas Electrnicos Digitales.





108
14.2 Medida de ancho de pulso con rebotes (20 min)

Escribir un programa que mida el tiempo en segundos que un interruptor est a uno. Supuesto
un sistema como el del laboratorio, el programa debe medir el tiempo (en segundos) que est
en 1 el pin P2.8 del micro. Cada vez que el pin vuelva a cero se deber esperar de nuevo a que
se ponga a 1 para poder medir el tiempo en el que est a 1. Mostrar el resultado del ancho de
cada pulso en los diodos situados en la parte baja del puerto P2. Es necesario tener en cuenta
los rebotes que producen los interruptores en la seal.

NOTA: Los rebotes se podran eliminar con un filtro analgico paso bajo, pero tiene el
inconveniente de que usa resistencias y condensadores con valores que dependen mucho de la
temperatura. Es mucho ms robusto realizar un filtrado digital con un micro.

voi d mai n( voi d) {
i nt ant er i or , act ual ; / / est ado ant er i or y act ual de l a seal
i nt cuent a=0; / / i ndi ca si hay que cont ar o no
i nt mseg=0; / / ancho del pul so
i nt f i l t r ado = - 1; / / cont ador que mi de el t i empo en el mi smo
/ / est ado de l a seal cuando se t r at a de un r ebot e
DP2 = 0xFF;
ant er i or = P2 & 0x100;
whi l e ( 1) {
r et r aso( 0, - 2500) ; / / esper a 1ms
act ual = P2 & 0x100;
i f ( ant er i or ! = act ual )
f i l t r ado = MAX;
el se i f ( f i l t r ado >0)
f i l t r ado- - ;
i f ( f i l t r ado==0) { / / si l a seal es est abl e
f i l t r ado = - 1;
i f ( act ual ) {
cuent a = 1;
}
el se {
cuent a = 0;
P2 = ~( mseg/ 1000) ;
mseg = 0;
}
}
i f ( cuent a)
mseg++;
ant er i or = act ual ;
}
}
Sistemas Electrnicos Digitales.





109













































SM sect i on code at 300H
mai n pr oc NEAR
MOV DP2, #0xFF
MOV R0, P2 ; al macena el est ado act ual
AND R0, #0x100
MOV R2, #0 ; cuent a
MOV R3, #0 ; mseg
MOV R4, #- 2500 ; cuent a i ni ci al del t i mer
MOV R5, #0 ; pr eescal ado
MOV R6, #- 1 ; f i l t r ado
bucl e: MOV R1, R0 ; ant er i or = act ual
cal l r et r aso
MOV R0, P2 ; act ual = P2
AND R0, #0x100
CMP R0, R1
J MPR cc_eq, f i l t r ado
MOV R6, #MAX
J MPR cc_uc, f l anco
f i l t r ado: CMP R6, #0
J MPR cc_sl e, f l anco
SUB R6, #1
f l anco: CMP R6, #0
J MPR cc_ne, segui r
MOV R6, #- 1
CMP R0, #0
J MPR cc_eq, cer o
MOV R2, #1
J MPR cc_uc, segui r
cer o: MOV R2, #0
MOV MDL, R3
MOV R3, #1000
DI V R3
MOV R3, MDL
CPL R3
MOV P2, R3
MOV R3, #0
segui r : CMP R2, #0
J MPR cc_eq, bucl e
ADD R3, #1
J MPR cc_uc, bucl e
mai n endp
SM ends
end
Sistemas Electrnicos Digitales.





110
14.3 Medida de ancho de pulso (20 min)

Escribir en ensamblador un programa que mida el ancho de los pulsos de una seal digital.
Para ello el programa debe medir el tiempo (en milisegundos) que est en 1 el pin P7.4 del
micro. Cada vez que el pin vuelva a cero se deber esperar de nuevo a que se ponga a 1 para
poder medir el tiempo en el que est a 1. Supuesto un sistema como el del laboratorio, mostrar
el resultado del ancho de cada pulso en los diodos situados en la parte baja del puerto P2.





































voi d mai n( voi d) {
i nt ant er i or , act ual ; / / est ado ant er i or y act ual de l a seal
i nt cuent a=0; / / i ndi ca si hay que cont ar o no
i nt cont ador =0; / / ancho del pul so
DP2 = 0xFF;
DP7 = 0;
ant er i or = P7 & 0x10;
whi l e ( 1) {
r et r aso( 0, - 2500) ; / / esper a 1ms
act ual = P7 & 0x10;
i f ( ( ant er i or ! = act ual ) && act ual ) {
cuent a = 1;
}
i f ( ( ant er i or ! = act ual ) && ! act ual ) {
cuent a = 0;
P2 = cont ador ;
cont ador = 0;
}
i f ( cuent a)
cont ador ++;
ant er i or = act ual ;
}
}
Sistemas Electrnicos Digitales.





111









SM sect i on code at 300H
mai n pr oc NEAR
MOV DP2, #0xFF
MOV DP7, #0
MOV R0, P7 ; al macena el est ado act ual
AND R0, #0x10
MOV R2, #0 ; cuent a
MOV R3, #0 ; cont ador
MOV R4, #- 2500 ; cuent a i ni ci al del t i mer
MOV R5, #0 ; pr eescal ado
bucl e: MOV R1, R0 ; ant er i or = act ual
cal l r et r aso
MOV R0, P7 ; act ual = P2
AND R0, #0x10
CMP R0, R1
J MPR cc_eq, segui r
CMP R0, #0
J MPR cc_eq, cer o
MOV R2, #1
J MPR cc_uc, segui r
cer o: MOV R2, #0
CPL R3
MOV P2, R3
MOV R3, #0
segui r : CMP R2, #0
J MPR cc_eq, bucl e
ADD R3, #1
J MPR cc_uc, bucl e
mai n endp
SM ends
end



Sistemas Electrnicos Digitales.





112
15 Prctica 5: ejercicios en ensamblador, control de un servo
Sistemas Electrnicos Digitales.





113
Sistemas Electrnicos Digitales.





114

Sistemas Electrnicos Digitales.





115
Captulo 7 DRIVERS. EL CONVERTIDOR AD
1 Objetivos y conceptos a entender en este captulo
Entender qu es el convertidor AD y su funcionamiento.
Entender la similitud en el manejo del conversor AD y el Timer. Se aconseja
esquematizar ambos manejos, para una mayor claridad.
Entender el concepto de driver
2 Concepto de driver
El driver es un conjunto de funciones que sirven para independizar al usuario de los detalles
de manejo de un perifrico, de manera que un posible desarrollador que quiera usar el
perifrico lo nico que tiene que hacer es usar el driver y de esa manera usa el perifrico sin
tener que conocer los detalles de implementacin y manejo del mismo.

Hay dos tipos de funciones dentro de un driver:
Funciones de inicializacin: slo se llaman una vez y sirven para inicializar el driver y
el perifrico.
Funciones de manejo: se llaman tantas veces como se necesiten en la ejecucin de un
programa.

Estas funciones tienen que estar perfectamente documentadas indicando Qu hace?, Qu
parmetros necesita?, Qu devuelve?. Esto es as ya que estas funciones son lo nico que
tiene que conocer cualquier desarrollador que quiera usar al perifrico.

Los drivers tienen las siguientes ventajas:
El desarrollador no tiene que conocerse los detalles de implementacin del perifrico.
Si el perifrico cambia su especificacin o versin, slo hace falta cambiar el driver,
pero no las aplicaciones que usan el driver.
Se puede reutilizar en cualquier aplicacin sin modificarlo.

2.1 Ejemplos de driver
Es necesario hacer notar que para un mismo perifrico se pueden hacer varios drivers, que
permiten independizar su manejo de los detalles de implementacin del mismo. Por ello, los
ejemplos que se muestran a continuacin son una posible versin de drivers. Adems los
drivers suelen estar en ficheros distintos del principal, ya que se usan como libreras, gracias a
su gran posibilidad de reutilizacin.
Sistemas Electrnicos Digitales.





116
2.1.1 Driver sencillo del puerto P2
Aunque el manejo del puerto P2 es tan simple que no se necesita realizar un driver que ayude
a su manejo, se presenta como primer ejemplo ya que ilustra el concepto como tal.
El driver consta de dos funciones de manejo y una de inicializacin.
/* inicializacin del puerto
dir: direccin de los pines del puerto*/
voi d i ni _P2 ( i nt di r ) {
DP2 = di r ;
}
/* funcin que devuelve los datos del puerto P2*/
i nt get _P2( ) {
r et ur n( P2) ;
}
/ * f unci n modi f i ca l os dat os del puer t o P2*/
i nt set _P2( i nt dat os) {
P2 = dat os;
}

2.2 Driver del Timer 0
Un posible driver para el Timer 0 es la funcin retarso que se explic en ???, para un micro
con un reloj de 20MHz.

/ ** f unci n que esper a mi l i seg mi l i segundos. El mxi mo t i empo de esper a
es 26ms*/
voi d r et r aso( i nt mi l i seg) {
T01CON = 0;
T0REL = - mi l i seg*2500;
T0 = T0REL;
T0I C = T0I C & 0x7f ; / / bor r a f l ag de r ebose
T01CON = T01CON | 0x40; / / ar r anca t i mer
whi l e ( ! ( T0I C & 0x80) ) ; / / bucl e de esper a de r ebose
T01CON = T01CON & 0xbf ; / / par a el t i mer
}


Este driver consta de una funcin de manejo y ninguna de inicializacin. Se podra hacer una
funcin de inicializacin que indicara el reloj que tiene el micro y parametrizar la funcin de
manejo en funcin del reloj.
2.3 Driver del convertidor AD
Para ms informacin de qu es un conversor AD y cmo se maneja, leer la seccin 3 de este
captulo. El driver que se muestra a continuacin configura al convertidor AD en modo 0.
Sistemas Electrnicos Digitales.





117
/* funcin que devuelve la conversin AD de un canal
canal: canal objeto de la conversin (4 bits)
devuelve: resultado en 10 bits */
i nt convad( i nt canal ) {
ADCON = canal & 0xF;
ADCI R = 0;
ADST=1;
whi l e( ! ADCI R) ;
r et ur n( ADDAT&0X03FF) ;
}


Este driver consta de una funcin de manejo y ninguna de inicializacin. Un ejemplo de
manejo de este driver se muestra en la seccin 3.4 de este captulo.

3 El convertidor analgico digital (AD)
En esta seccin se va a ver como funciona el convertidor analgico digital, que es un
perifrico ms del micro. Para ms informacin sobre perifricos ver captulo 5.

El convertidor AD se encarga de transformar una tensin analgica del exterior en una digital
de 10 bits:
5V analgicos se corresponden con 0x3FF
0V analgicos se corresponden con 0x000

Para ello usa el puerto P5 del micro. Este puerto tiene 16 bits y se corresponde con 16 pines
del micro que se usan como entradas donde se pueden conectar tensiones analgicas de 0 a
5V. Como existen 16 posibles entradas, se dice que el convertidor AD tiene 16 canales. En
cada instante slo se puede hacer la conversin de un slo canal, pero ste es configurable por
el usuario.

El esquema del convertidor se muestra en la Figura 50. El mundo exterior, analgico, se
conecta a cada pin del puerto P5. Estos pines llegan a un multiplexor que elige uno de los
mismos para realizar la conversin. La eleccin se realiza programando los bits ADCH.
Posteriormente se encuentra el convertidor AD que realiza la conversin a digital del canal
seleccionado. El resultado de esta conversin lo deja en ADDAT (10 bits), e indica a travs
del bit ADCIR que ha terminado de realizar la conversin. De esta manera un programa
podra aprovechar la misma para alguna labor.

Sistemas Electrnicos Digitales.





118
MUX
P5.0 (canal 0)
P5.15 (canal 15)

5V
0V
5V
0V
ANALOGICO
C
o
n
v
e
r
t
i
d
o
r


A
D
ADCH
A
D
D
A
T
ADCIR

Figura 50:Esquema del convertidor AD

La tarea del perifrico finaliza cuando termina la conversin

Los registros de programacin del mismo son:
ADCON: es un registro (SFR) de configuracin de 8 bits.
ADDAT: es un registro (SFR) de datos del perifrico de 16 bits que se encarga de
almacenar el resultado de la conversin.
ADCIC: es el registro (SFR) de 16 bits que indica cuando el convertidor termina su
tarea, y sirve para configurar su control por interrupcin o polling.

A continuacin se explica en detalle cada uno de estos registros.

3.1 Registro de control ADCON
El registro de control consta de 8 bits, como se muestra a continuacin:

ADCH
3 0
ADM
5 4
---
6
ADST ADBSY
7 8


ADCH bits 0-3: estos 4 bits permiten seleccionar uno de los 16 canales posibles donde
hacer la conversin.
ADM bits 4-5: existen cuatro modos de funcionamiento del convertidor. Si ADM vale
0 se realiza una conversin en el canal seleccionado en ADCH. Existen otros modos
que no se van a usar en este curso, que permiten hacer conversiones sucesivas en el
mismo canal, una conversin secuencial en cada uno de los canales o incluso
conversiones sucesivas siguiendo la secuencia de los canales.
Sistemas Electrnicos Digitales.





119
ADST bit 7: es el encargado de controlar el arranque y paro del convertidor. Si se
pone comienza la conversin.
ADBSY bit 8: bit que indica que el conversor AD est ocupado haciendo una
conversin.
3.2 Registro de datos ADDAT
El registro de datos ADDAT tiene 16 bits y almacena el resultado en los 10 bits ms bajos y
en el canal convertido (al que corresponde el resultado) en los 4 bits ms altos.

RESULTADO
9
0
---
12
CANAL
15


3.3 Registro de control de interrupciones ADCIC
Slo merece la pena resaltar que el registro ADCIC tiene un bit ADCIR, que indica que el
conversor AD ha terminado su tarea; es decir, que tiene un resultado en ADDAT. Es
equivalente al T0IR del Timer 0.
3.4 Ejemplo de programacin
A continuacin se describe cmo se programa el convertidor AD. Es importante comparar
este programa con el correspondiente del Timer en el captulo 5 seccin 3.6.
El objetivo del programa es hacer una conversin en el pin P5.0 del micro y mostrar la parte
alta del resultado en los 8 LEDs conectados a la parte baja del puerto P2.

#i ncl ude <r eg167. h>
mai n( ) {
ADCON = 0x00; / / ADM=0, ADST=0, ADCH=0
ADCI R = 0; / / f l ag f i nal = 0
ADCON | = 0x80; / / St ar t ADST=1
DP2 = 0x00FF;
P2 = 0xFFFF;
whi l e ( 1) {
whi l e( ! ADCI R) ; / / bucl e de esper a
P2 = ~( ADDAT >> 2) / / coge 8 bi t s sl o
ADCI R = 0; / / f l ag f i n = 0
ADCON | = 0x80; / / St ar t ADST=1
}
}

Sistemas Electrnicos Digitales.





120
Es necesario darse cuenta de que este programa sera ms modular y entendible si se usase el
driver descrito en la seccin 2.3 de este captulo:

#i ncl ude <r eg167. h>
#i ncl ude ad. h / / l ugar donde est el dr i ver
mai n( ) {
i nt r esul t ado;
DP2 = 0x00FF;
P2 = 0xFFFF;
whi l e ( 1) {
r esul t ado = convad( 0) ;
P2 = ~( r esul t ado >> 2) / / coge 8 bi t s sl o
}
}


Como se puede ver es necesario incluir el driver (#include "ad.h"), para decirle al
compilador que la funcin convad existe.
Sistemas Electrnicos Digitales.





121
Captulo 8 PROGRAMACIN EN C PARA MICROS
1 Objetivos y conceptos a entender en este captulo
El objetivo de este captulo es resumir los conceptos de programacin en C que se usan en
programacin de microprocesadores. Se supone que el lector ha recibido nociones bsicas de
programacin en C antes de leer este captulo. Es muy importante prestar atencin y
esquematizar la relacin que existe entre el C y el ensamblador segn se va leyendo el
captulo.
2 Tipos de datos para el C167
2.1 Nmeros enteros
El C167 admite 3 tipos de enteros que se diferencian en el tamao que tienen. Si se habla de
tipos de datos con signo:
i nt (16 bits): desde -32768 a 32767
char (8 bits): desde -128 a 127
l ong (32 bits): desde -2
31
a 2
31
-1

En caso de que no tengan signo:
unsi gned i nt (16 bits): desde 0 a 65535
unsi gned char (8 bits): desde 0 a 255
unsi gned l ong (32 bits): desde 0 a 2
32
-1

Aunque la codificacin interna de los nmeros en memoria fsica siempre se hace con ceros y
unos, ya que el micro no entiende otra cosa, desde el punto de vista de la programacin se
soportan diferentes bases de codificacin para expresar un nmero:
En base 16, hexadecimal, por ejemplo: char i = 0xf f ; equivale al -1 decimal.
En base 10, decimal, por ejemplo: char i = - 1;

La promocin de nmeros enteros es directa cuando se trata de pasar de un nmero de menor
tamao a uno de mayor tamao:


Sistemas Electrnicos Digitales.





122





Figura 51: Promocin de 8 bits sin signo a 16 bits. El resultado en i = 0x00FF






Figura 52: Promocin de 8 bits con signo a 16 bits. El resultado en i=0xFFFF

La promocin de nmeros enteros en ensamblador tiene instrucciones especiales, como lo son
MOVBZ (para la

Figura 51) y MOVBS (para la Figura 52).

Los operadores ms usados con nmero enteros son:

Operador unitarios : cambia de signo al operando. As en: i = - c; el operador -
toma el valor de la variable c y le cambia el signo. Por tanto si c vale 17, al finalizar
la ejecucin de la instruccin, la variable i contendr el valor - 17.
Operador unitario ++ y - - : dado que una de las aplicaciones principales de los nmeros
enteros en los programas es la realizacin de contadores, que usualmente se
incrementan o decrementan de uno en uno, los diseadores de C vieron aconsejable
definir unos operadores para este tipo de operaciones. El operador incremento se
representa aadiendo a la variable que se desee incrementar dos smbolos +. La
sintaxis es por tanto: Nombr eVar i abl e++. As por ejemplo la lnea: Cont ador ++;
sumara uno a la variable Cont ador . El operador decremento es idntico al de
incremento, sin mas que sustituir los + por - . Siguiendo el ejemplo anterior: Cont ador -
- ; Le restara uno a la variable Cont ador .
Operadores binarios: +, - , *: suma, resta y multiplicacin respectivamente.
Operador binario / ( op1/ op2) : da como resultado la parte entera de dividir op1 entre
op2; es decir, el cociente. As por ejemplo 3/ 2 da como resultado 1, lo que puede
parecer malo, pero an hay cosas peores como 1/ 2, que da como resultado 0, lo cual
tiene un gran peligro en expresiones como: r esul t ado = ( 1/ 2) *3;
Operador binario % ( op1%op2) : devuelve el resto de la divisin entre op1 y op2. El
operador resto se representa mediante el smbolo %. As por ejemplo 4%2 da como
resultado 0 y 1%2 da como resultado 1. Una utilidad de este operador es la de
unsi gned i nt i ;
unsi gned char c = 0xf f ;
i = c;
i nt i ;
char c = 0xf f ;
i = c;
Sistemas Electrnicos Digitales.





123
averiguar si un determinado nmero es mltiplo de otro; por ejemplo el nmero
4580169 es mltiplo de 33 porque 4580169%33 da cero.

NOTA: en C se pueden mezclar asignaciones y operaciones entre dos operandos en un slo
operador, situando el =entre los dos operandos de una operacin; por ejemplo:

op1 += op2; / / es equi val ent e a op1 = op1 + op2;
op1 %= op2; / / es equi val ent e a op1 = op1 %op2;
2.2 Nmeros reales
Al igual que con los enteros, el C167 admite 3 tipos de nmero reales dependiendo de la
precisin que se requiera:
f l oat (16 bits)
doubl e (32 bits)
l ong doubl e (64 bits)

2.3 Variables lgicas
En C no existen las variables lgicas. Cualquier variable entera se puede usar como variable
lgica, de forma que si su valor es 0 entonces equivale a un FALSE y si es distinto de 0
entonces equivale a un TRUE. Por ejemplo:

i nt i = 5;
i nt suma;
whi l e ( i ) {
suma = suma + i ;
- - i ;
}

Figura 53: Ejemplo de variable lgica. Sale del bucle cuando i es igual a cero

Los operadores usados con variables lgicas son los siguientes:
&&: es un AND lgico. Ojo no trabaja bit a bit (no confundir con &)

c = a && b
Si a = 1 y b = 14 c es TRUE Ya que a y b son distintos de
cero
Si a = 0 y b = 32 c es FALSE Ya que a es igual a cero
Tabla 1: Ejemplo de AND lgico


Sistemas Electrnicos Digitales.





124
|| : es un OR lgico. Ojo no trabaja bit a bit (no confundir con | )

c = a | | b
Si a = 0 y b = 0 c es FALSE Ya que a y b son cero
Si a = 32 y b = 0 c es TRUE Ya que a es distinto de cero
Tabla 2: Ejemplo de OR lgico

! : es un NOT lgico. No confundir con ~.

c = ! b
Si b = 14 c es FALSE Ya que b es distinto de cero
Si b = 0 c es TRUE Ya que b es igual a cero
Tabla 3: Ejemplo de NOT lgico

Las posibles condiciones lgicas son:
==: comparacin de igualdad. Ojo no es lo mismo que = (asignacin). No debe
confundirse el operador de asignacin =con el operador relacional de igualdad ==que
no modifica el valor de las variables. Es decir, es totalmente distinto escribir i=7, que
introduce el valor 7 en la variable i independientemente del valor que tuviese sta, que
escribir i==7, que compara el valor de la variable i con la constante 7.
!=: comparacin de desigualdad
>, >=: comparacin mayor que y mayor igual que respectivamente.
<, <=: comparacin menor que y menor o igual que respectivamente.


c = ( a > b) && ( a ! = d)
Si a = 0, d = 0 y b = 1 c es FALSE Ya que a y d son iguales
Si a = 10, d = 0 y b = 1 c es TRUE Ya que a y d son distintos y a
mayor que b

3 Operadores bit a bit
Cuando se programa un micro es muy habitual realizar operaciones a nivel de bit. En C
existen los siguientes operandos que trabajan a nivel de bit:
& ( op1&op2) : realiza un AND bit a bit entre el operando op1 y op2. El equivalente en
ensamblador es AND op1, op2.
| ( op1| op2) : realiza un OR bit a bit entre el operando op1 y op2. El equivalente en
ensamblador es OR op1, op2.
Sistemas Electrnicos Digitales.





125
>> ( op1>>op2) : desplaza op2 bits de op1 hacia la derecha. El equivalente en
ensamblador es SHR op1, op2.
<<( op1<<op2) : desplaza op2 bits de op1 hacia la izquierda. El equivalente en
ensamblador es SHL op1, op2.
^ ( op1^op2) : realiza un XOR bit a bit entre el operando op1 y op2. El equivalente en
ensamblador es XOR op1, op2.
~ ( ~op1) : realiza un complemento a uno del operando op1. El equivalente en
ensamblador es CPL op1.

a = P2; a &= 0x000F; / / Cuant o val e a?
a = P2; a | = 0x000F; / / Cuant o val e a?
a = P2; a >>= 4; / / Cuant o val e a?
a = P2; a <<= 4; / / Cuant o val e a?

Figura 54: Si P2 = 0xFA45, por orden de aparicin a=0x0005, a=0xFA4F, a=0x0FA4 y a=0xA450
4 Instrucciones de control
Es habitual que los programas realicen tareas diferentes en funcin del valor de determinadas
variables. La instruccin if permite definir bloques de cdigo que no son de ejecucin
obligatoria y por lo tanto son bloques de instrucciones que el programa se puede saltar. Esta
decisin depende del valor de una condicin lgica, que a su vez suele depender del valor que
adquieran determinadas variables del programa. Tambin es posible definir dos bloques de
instrucciones alternativos, de manera que slo se ejecute uno u otro en funcin del resultado
de la condicin lgica.

Existen dos formatos bsicos para definir instrucciones que se ejecutan de manera
condicional. Un bloque que se puede ejecutar o no (i f normal), y dos bloques que se
ejecutan uno u otro (bloque i f - el se). El formato en cada caso es el siguiente:



if (condicin) {
...
}


if (condicin) {
// si se cumple a condicin
...

} else {
// si no se cumple la condicin
...
Sistemas Electrnicos Digitales.





126
}

A continuacin se describen situaciones que se deben tener en cuenta cuando se manejan este
tipo de condiciones:

i f ( a == b) {
}
i f ( a = b) {
}

Figura 55: Igualdad versus asignacin. En el caso de la igualdad la condicin se cumple si a es igual a b. En el
caso de la asignacin la condicin se cumple si b es distinto de 0.

i f ( a && b) {
}
i f ( a & b) {
}

Figura 56: AND lgico versus AND bit a bit. En el caso del AND lgico la condicin se cumple si a y b son
distintos de cero. En el caso del AND bit a bit la condicin puede no cumplirse aunque a y b sean distintos de
cero, por ejemplo si a =0xF0F0 y b = 0x0F0F.
5 Bucles
Es habitual que los programas realicen tareas repetitivas o iteraciones (repetir las mismas
operaciones pero cambiando ligeramente los datos). Esto no supone ningn problema para el
programador novato, que despus de aprender a cortar y pegar puede repetir varias veces el
mismo cdigo, pero dentro de un lmite. Se llama bucle de un programa a un conjunto de
instrucciones que se repite varias veces.

El bucle for queda definido por tres argumentos: sentencia inicial, condicin de salida y
sentencia final de bucle. Estos argumentos se escriben separados por punto y coma y no por
coma como en las funciones.

for(sentencia inicial ; condicin ; sentencia final ){
...
}

Como puede apreciarse, la variable i controla el nmero de veces que se ejecuta el bucle.
Por ello a este tipo de variables se les denomina variables de control. Es muy importante
hacer un buen uso del sangrado para facilitar la lectura del programa.

La sentencia inicial se ejecuta antes de entrar en el bucle y la condicin siempre se
comprueba antes de cada iteracin. Por lo tanto, puede ocurrir que nunca se llegue a entrar en
el bucle si desde el principio no se cumple la condicin. Por ejemplo for(i=0; i<-3;
Sistemas Electrnicos Digitales.





127
i++) nunca entra en el bucle. La sentencia final se ejecuta al terminar cada iteracin. Por lo
tanto si no se entra en el bucle esta sentencia no se ejecuta nunca.

Si no se conoce a priori el nmero de iteraciones que deseamos realizar en un bucle se debe
utilizar el bucle while. Este tipo de bucles repiten una serie de instrucciones mientras una
condicin es cierta. La sintaxis es:

while(condicin){
...
}

El funcionamiento del bucle es como sigue: en primer lugar se evala la expresin condicin.
Si el resultado es falso no se ejecutar ninguna de las instrucciones del bucle, el cual est
delimitado, al igual que en el caso del bucle for por dos llaves ({ y }). Por tanto la
ejecucin continuar despus de la llave }. Si por el contrario la condicin es cierta, se
ejecutarn todas las instrucciones del bucle. Despus de ejecutar la ltima instruccin del
bucle se vuelve a comprobar la condicin y al igual que al principio se terminar el bucle si es
falsa o se realizar otra iteracin si es cierta, y as sucesivamente.

do{
...
}while(condicin);

En este caso se ejecutarn las instrucciones y despus se evaluar la condicin. Si es falsa se
contina con la instruccin que sigue al bucle y si es cierta se vuelve a repetir el bucle, se
evala la condicin y as sucesivamente.
6 Vectores
Un vector es un conjunto de datos del mismo tipo que se almacenan en el ordenador en
posiciones de memoria consecutivas y a los cuales se accede mediante un mismo nombre de
variable. La caracterstica fundamental es que todos los datos de un vector son del mismo
tipo, por ejemplo todos son int o todos son double. La definicin de vectores es parecida
a la definicin de variables, salvo que se debe especificar el tamao del vector entre corchetes
[ ]. Por ejemplo, para definir un vector llamado vec que pueda almacenar 10 valores tipo
double se escribe:

double vec[10];

La manera de acceder a los valores de estas variables es ahora diferente, ya que de todos los
elementos que componen el vector es necesario especificar cul queremos modificar. Esta
especificacin se realiza indicando entre corchetes el nmero de orden del elemento, teniendo
en cuenta que la numeracin de los elementos siempre empieza en cero.

vec[0]=54.23; /*Primer elemento del vector*/
vec=4.5; /* ERROR */
Sistemas Electrnicos Digitales.





128
vec[10]=98.5; /* ERROR */

La segunda asignacin no es correcta porque vec no es una variable tipo double sino un
vector y por lo tanto todas las asignaciones deben indicar el nmero de orden del elemento al
que queremos acceder. El vector vec del ejemplo tiene tamao 10 porque fue declarado
como double vec[10] esto significa que almacena 10 elementos. Los 10 elementos se
numeran desde el 0 hasta el 9 y por lo tanto, el elemento 10 no existe y la tercera asignacin
tampoco es vlida. Es importante destacar que el compilador no dara error en el ltimo caso
ya que no comprueba los rangos de los vectores. Este tipo de asignacin hace que el valor
98.5 se escriba fuera de la zona de memoria correspondiente al vector vec, y probablemente
machaca los valores de otras variables del programa. Hay que prestar especial atencin ya que
slo en algunos casos aparece un error de ejecucin (generalmente cuando el ndice del vector
es muy grande de forma que se accede a zonas en las que no hay memora) pero en otras
ocasiones no aparece ningn mensaje de error y el programa simplemente funciona mal
(OJO: es muy difcil de detectar!!).

Como se puede sospechar, la mejor manera de trabajar con vectores es utilizando bucles for,
para iterar en el mismo y o bien inicializar sus valores o bien obtener sus datos que almacena.

Resulta muy til definir los tamaos de vectores y matrices en funcin de parmetros, ya que
luego se pueden modificar fcilmente sin tener que revisar todo el programa. Estos
parmetros se definen con la instruccin #define (semejante a equ en ensamblador) que
es una directiva del preprocesador, al igual que #include.

Existen dos maneras de inicializar vectores: en las instrucciones del programa o en la propia
definicin:

#def i ne MAX 5
mai n( ) {
i nt I ni ci ado[ ] ={1, 5, 8, 4, 3};
i nt Si nI ni [ MAX] ;
i nt i ;
f or ( i =0; i <MAX; i ++)
Si nI ni [ i ] = I ni ci ado[ i ] ;
}

Figura 57: Ejemplo de inicializacin en C de un vector en la propia definicin (Iniciado) o por cdigo (SinIni)
Sistemas Electrnicos Digitales.





129
MAX equ 5
D100 section data at 200H
I ni ci ado dw 1, 5, 8, 4, 3
Si nI ni dsw 5
D100 ends
ej section code at 300H
ej1 proc NEAR
MOV R1, #Si nI ni
MOV R0, #I ni ci ado
MOV R3, #0 ; cont ador
; I ni ci al i za el vect or
i ni : CMP R3, #MAX
J MPR cc_uge, f i n
MOV [ R1+] , [ R0+]
ADD R3, #1
J MPR cc_uc, i ni
f i n: NOP
ej1 endp
ej ends

Figura 58: Ejemplo de inicializacin en ensamblador de un vector en la propia definicin (Iniciado) o por
cdigo (SinIni)

7 Punteros
Los punteros son un tipo de variable un poco especial, ya que en lugar de almacenar valores
(como las variables de tipo int o de tipo double) los punteros almacenan direcciones de
memoria. Utilizando variables normales slo pueden modificarse valores, mientras que
utilizando punteros pueden manipularse direcciones de memoria o valores.

Los punteros se definen igual que las variables normales, pero con un asterisco (*) delante del
nombre de la variable. Por ejemplo:

int a;
int *pa;

En este ejemplo la variable a es de tipo entero y puede almacenar valores como 123 o -24,
mientras que la variable p es un puntero y almacena direcciones de memoria. Aunque todos
Sistemas Electrnicos Digitales.





130
los punteros almacenan direcciones de memoria, existen varios tipos de puntero dependiendo
de la definicin que se haga. Por ejemplo:

int *pti;
char *ptc;

Tanto pti como ptc son punteros y almacenan direcciones de memoria, por lo tanto
almacenan datos del mismo tipo y ocupan la misma cantidad de memoria, es decir, 24 bits
(aunque si se trabaja en el modelo corto de memoria; es decir, slo se trabaja en un segmento,
como es el caso del laboratorio el tamao utilizado es 16 bits). La nica diferencia es que el
dato almacenado en la direccin de memoria contenida en el puntero pti es un entero,
mientras que el dato almacenado en la direccin de memoria contenida en ptc es un char.
Se dice por lo tanto que pti apunta a un entero (puntero a entero) mientras que ptc
apunta a un char (puntero a char). En la Figura 59 aparece un ejemplo en el que pti
apunta a una direccin de memoria (0x200) donde se encuentra almacenado el valor entero 5,
y ptc apunta a otra direccin de memoria (0x202) donde se encuentra almacenado el valor
0x10.

Direccin de
memoria 24
bits (Hex)
Variable en C Valor 8 bits
00 0200 05
00 0201 00
00 0202 c 10
00 0203 02
00 0204 00
00 0205 02
00 0206 00
00 0207 00
00 0208 02
00 0209 02
00 020A 00
00 020B 00
pti
ptc
i

Figura 59
En ensamblador se puede trabajar con punteros usando el direccionamiento indirecto. De
forma que los cuatro primeros registros de propsito general pueden almacenar direcciones de
memoria.
7.1 El operador &
El operador & se utiliza para obtener la direccin de memoria de cualquier variable del
programa. Si nuestro programa tiene una variable entera que se llama i, entonces podemos
obtener la direccin de memoria que el compilador ha preparado para almacenar su valor
escribiendo &i.

Sistemas Electrnicos Digitales.





131
int i; /* variable entera */
int *pti; /* puntero a entero */
i=78; /* inicializo i */
pti=&i; /* pti apunta a i */

Al aplicar el operador & a la variable i no se obtiene el valor entero almacenado en ella
sino la direccin de memoria en donde se encuentra dicho valor. La direccin de la variable i
(&i) se almacena en un puntero a entero, porque es una direccin de memoria donde se halla
un entero.

El compilador dar un aviso si se intenta realizar una asignacin en la que no corresponden
los tipos, por ejemplo al asignar &i a un puntero tipo char *, ya que &i devuelve un
puntero a int. Este tipo de comprobaciones del compilador evita muchos errores de
programacin. Por tanto, hay que estar muy atento a los mensajes del compilador.
Asignaciones entre dos punteros tambin son vlidas siempre que los dos punteros sean del
mismo tipo.

En ensamblador se usa el inmediato #para acceder a la direccin de memoria de un variable,
ver Figura 60.

7.2 El operador *
El operador unitario *, llamado operador de indireccin, permite acceder al valor por medio
del puntero.

int i; /* variable entera */
int *pti; /* puntero a entero */
pti=&i; /* pti apunta a i */
*pti=78; /* equivale a hacer i=78; */

La asignacin *pti=78 introduce el valor entero 78 en la posicin de memoria apuntada
por el puntero pti. Como previamente se ha almacenado en pti la direccin de memoria
de la variable i, la asignacin equivale a dar el valor 78 directamente a la variable i. Es decir,
tras la asignacin pti=&i disponemos de dos maneras de manipular los valores enteros
almacenados en la variable i: directamente mediante i,o indirectamente mediante el puntero
pti.

En ensamblador se usan los corchetes [ ] para acceder al valor que apunta el puntero. En la
Figura 60 se muestra la equivalencia entre C y ensamblador en el manejo de punteros. Es
importante hacer notar que en C es equivalente escribir *( pt i +i ) a escribir pt i [ i ] , por
definicin; ya que ambos acceden al elemento que se encuentra desplazado i unidades de la
direccin de memoria que representa el puntero pt i .

Sistemas Electrnicos Digitales.





132
D100 section data at 200H
i 1 dsw 1
i 2 dsw 1
D100 ends
ej section code at 300H
ej1 proc NEAR
MOV R0, #5 ; R0 r egi st r o auxi l i ar
MOV i 1, R0
MOV R1, #i 1 ; R1 punt er o a i 1
MOV R0, [ R1] ; equi val e a * en C
MOV i 2, R0
ej1 endp
ej ends
mai n( ) {
i nt i 1, i 2;
i nt *pi ;
i 1 = 5;
pi = &i 1;
i 2 = *pi ; / / i 2?
}

Figura 60: Equivalencia entre C y ensamblador en el manejo de punteros
7.3 Operaciones con punteros
Una vez entendido lo que es un puntero veamos las operaciones que pueden realizarse con
estas variables tan especiales. En primer lugar ya se ha visto que admiten la operacin de
asignacin para hacer que apunten a un lugar coherente con su tipo. Pero tambin admite
operaciones de suma y diferencia que deben entenderse como cambios en la direccin a la que
apunta el puntero. Es decir, si tenemos un puntero a entero que almacena una determinada
direccin de memoria y le sumamos una cantidad, entonces cambiara la direccin de
memoria y el puntero quedara apuntando a otro sitio. Es importante diferenciar claramente
las dos formas de manipular el puntero:

*pti+=8;
pti+=8;

La primera lnea suma 8 al entero al que apunta pti y por lo tanto el puntero sigue
apuntando al mismo sitio. La segunda lnea incrementa en 8 el puntero, por lo tanto ste pasa
a apuntar a otro sitio.

El operador ++se utiliza mucho en programacin de micros y permite hacer que el puntero
pase a apuntar al dato que ocupa la siguiente posicin de memoria. La aplicacin fundamental
Sistemas Electrnicos Digitales.





133
de esta operacin es recorrer posiciones de memoria consecutivas. Adems de valer para
fisgonear la memoria del microcontrolador, esto se utiliza para recorrer vectores (cuyos datos
siempre se almacenan en posiciones de memoria consecutivas).

Cada posicin de memoria del micro almacena un byte. Dado que cada tipo de dato ocupa un
nmero de bytes diferente (un char s ocupan 1 byte, un int ocupa 2 bytes), los punteros
de cualquier tipo siempre apuntan al primer byte de la codificacin de cada dato. Cuando se
accede al dato mediante el operador *, el compilador se encarga de acceder a los bytes
necesarios a partir de la direccin almacenada en el puntero. En el caso de punteros a char
slo se accede al byte almacenado en la direccin de memoria del puntero, mientras que el
caso de punteros a int se accede a la posicin de memoria indicada en el puntero y al
siguiente byte. Todo este mecanismo ocurre de manera automtica y el programador slo
debe preocuparse de definir punteros a char cuando quiere trabajar con valores char o
punteros a int cuando quiere trabajar con valores int.

Tambin para facilitar las cosas, la operacin de sumar 1 a un puntero hace que su direccin
se incremente la cantidad necesaria para pasar a apuntar al siguiente dato del mismo tipo. Es
decir slo en el caso de variables que ocupan 1 byte en memoria (variables char) la
operacin de incremento aumenta en 1 la direccin de memoria, en los dems casos la
aumenta ms.

Lo que hay que recordar es que siempre se incrementa un dato completo y no hace falta
recordar cunto ocupa cada dato en la memoria. Por ejemplo, si ptc es un puntero a char
que vale 0x202, la operacin ptc++ har que pase a valer 0x203. Por otro lado si pti es
un puntero a int que vale 0x200, la operacin pti++ har que pase a valer 0x202.


La equivalencia con ensamblador es la siguiente:
MOV R1, [ R2+] i = *pt i ++
MOV R1, [ - R2] i = *- - pt i


En la Figura 61 y Figura 62 se muestra un ejemplo de esta equivalencia.
Sistemas Electrnicos Digitales.





134
MAX equ 5
D100 section data at 200H
VWor d dsw 5
VByt e dsb 5
D100 ends
ej section code at 300H
ej1 proc NEAR
MOV R0, #VWor d; R0 punt er o
MOV R1, #VByt e; R1 punt er o
MOV R2, #0 ; R2 es l a suma
MOV R3, #0 ; R3 es i
MOV R4, #0 ; R4 var t empor al
suma: CMP R3, #MAX
J MPR cc_uge, f i n
MOVB RL4, [ R1+]
ADD R2, R4
ADD R2, [ R0+]
ADD R3, #1
J MPR cc_uc, suma
f i n: NOP
ej1 endp
ej ends

Figura 61: Ejemplo en ensamblador que suma dos vectores de 5 datos

#def i ne MAX 5
mai n( ) {
i nt VWor d[ MAX] ;
char VByt e[ MAX] ;
i nt *pt i ;
char *pt c;
i nt i ; suma;
suma = 0;
pt i = VWor d;
pt c = VByt e;
f or ( i =0; i <MAX; i ++) {
suma += *pt i ++;
suma += *pt c++;
}
}

Figura 62: Ejemplo en C de dos vectores que suma 2 vectores de 5 datos
Sistemas Electrnicos Digitales.





135
Si se quiere incrementar un puntero en ms de una unidad, se puede usar un desplazamiento
usando el operador +:

int vi[10]; /* vector de enteros */
int *pti, i; /* puntero a entero */
pti=vi; /* pti apunta a vi */
i = *(pti+5); /*coge el dato 5 enteros adelante */

El equivalente en ensamblador es:

MOV R1, [ R0+#10] i = *( pt i +5) ; / / en caso de i nt
MOVB RL1, [ R0+#5] c = *( pt c+5) ; / / en caso de char

8 Funciones
Una tcnica muy empleada en la resolucin de problemas complejos es la conocida como
divide y vencers. La manera ms elegante de construir un programa es dividir la tarea a
realizar en otras tareas ms simples. Si estas tareas ms simples no son an lo suficientemente
sencillas, se vuelven a dividir, procediendo as hasta que cada tarea sea lo suficientemente
simple como para resolverse con unas cuantas lneas de cdigo. A esta metodologa de diseo
se le conoce como diseo de arriba-abajo (top-down). Otras ventajas de la divisin de un
problema en mdulos claramente definidos es que facilita el trabajo en equipo y permite
reutilizar mdulos creados con anterioridad si estos se han diseado de una manera
generalista. En C este tipo de mdulos se llaman funciones, que consta de unos argumentos de
entrada, una salida, y un conjunto de instrucciones que definen su comportamiento. Esto
permite aislar la funcin del resto del programa, ya que la funcin puede considerarse como
un programa aparte que toma sus argumentos de entrada, realiza una serie de operaciones
con ellos y genera una salida; todo ello sin interactuar con el resto del programa.
Esta metodologa de diseo presenta numerosas ventajas, entre las que cabe destacar:
La complejidad de cada tarea es mucho menor que la de todo el programa, siendo
abordable.
Se puede repartir el trabajo entre varios programadores, encargndose cada uno de
ellos de una o varias funciones de las que se compone el programa.
Al ir construyendo el programa por mdulos se pueden ir probando estos mdulos
conforme se van terminando, sin necesidad de esperar a que se termine el programa
completo. Esto hace que, tanto la prueba de los mdulos, como la correccin de los
errores cometidos en ellos, sea mucho ms fcil al tener que abarcar solamente unas
cuantas lneas de cdigo, en lugar de las miles que tendr el programa completo.
Una vez construido el programa, tambin el uso de funciones permite depurar los
problemas que aparezcan ms fcilmente, pues una vez identificada la funcin que
falla, slo hay que buscar el fallo dentro de dicha funcin y no por todo el programa.
Si se realizan lo suficientemente generales, las tareas se puede reutilizar en otros
programas. As por ejemplo, si en un programa es necesario convertir una cadena a
Sistemas Electrnicos Digitales.





136
maysculas y realizamos una funcin que realice dicha tarea, esta funcin se podr
usar en otros programas sin ningn cambio. Si por el contrario la tarea de convertir a
maysculas se incrusta dentro del programa, su reutilizacin ser muchsimo ms
difcil.

En resumen la norma bsica es <<Hacer funciones cortas y que hagan una sola cosa!!
(fciles de desarrollar y de depurar, reutilizables)>>

En C las funciones deben ser declaradas (en los ficheros cabecera *.h) y definidas. La
diferencia entre declaracin y definicin consiste en que siempre que se habla de definicin
implica que existe una reserva de memoria para aquello que se define. En cambio en un
declaracin no.

Un ejemplo de definicin de funcin es el cdigo propiamente dicho:


i nt power ( i nt base, i nt n) {
i nt i , p;
p = 1;
f or ( i =1; i <=n; i ++)
p = p * base;
r et ur n p;
}

Figura 63: Ejemplo de definicin de funcin en C
En la Figura 63 se puede observar como una funcin tiene unos parmetros que entran en la
funcin y se usan como variables locales; es decir, si se modifica su valor en la funcin el
programa principal que llam a la funcin no ve afectados sus valores. Adems la funcin
puede devolver un valor en la instruccin r et ur n.

En la Figura 64 se muestra el prototipo o declaracin de la funcin anterior. El prototipo
indica al compilador el nmero y tipo de parmetros de entrada a una funcin y el tipo de
variable de salida de la misma.

i nt power ( i nt base, i nt n) ;

Figura 64: Ejemplo de declaracin de funcin en C
Un ejemplo de manejo de la definicin y declaracin de funcin se muestra en la Figura 65.
Sistemas Electrnicos Digitales.





137
i nt power ( i nt base, i nt n) ;
mai n ( ) {
i nt i , a, b;
a = 2; b =10;
i = power ( b, a) ;
}
i nt power ( i nt base, i nt n) {
i nt i , p;
p = 1;
f or ( i =1; i <=n; i ++)
p = p * base;
r et ur n p;
}

Figura 65: Ejemplo de uso de funcin
En el ejemplo se puede apreciar que el valor de las variables de la funcin mai n a y b no son
alterados por la llamada a la funcin power . Esto se debe a que en C SIEMPRE se pasan los
parmetros por valor a las funciones; es decir, se hace una copia cada variable y se pasa la
propia copia a la funcin. Es necesario declarar la funcin power antes de la definicin de
mai n, para que cuando el compilador empiece a compilar (que lo hace de forma secuencial y
de arriba hacia abajo) el cdigo sepa como se ha definido power y compruebe la correcta
sintaxis de la misma. En caso contrario el compilador indicar que la funcin no se ha
declarado.
8.1 Variables globales y locales
Las variables locales son las que slo se pueden acceder dentro de una misma funcin, que se
componen por las variables pasadas por parmetro y las definidas en la propia funcin. La
vida de una variable local se termina en el momento en el que el programa sale de la funcin.
Por otro lado, las variables globales son las que se encuentra fuera de toda funcin y se
pueden usar desde cualquier lugar del cdigo. La vida de una variable global se corresponde
con el tiempo de ejecucin del programa. El buen estilo de programacin recomienda usar lo
menos posible las variables globales ya que se pueden modificar desde cualquier lugar del
cdigo y por tanto son muy complicadas de depurar.

8.2 Paso de parmetros por " referencia"
Como se ha comentado con anterioridad en C siempre se pasan a las funciones los parmetros
por valor. Por otro lado, dado que una funcin slo puede devolver un valor, se restringen
mucho las posibilidades de hacer funciones complejas que puedan devolver ms de un valor.
Para poder salvar este escollo, existe un truco que permite pasar los parmetros por
"referencia" usando punteros. No es un paso por referencia estrictamente hablando, sino que
Sistemas Electrnicos Digitales.





138
es un paso por valor de un puntero, que equivale a un paso por referencia, ya que aunque no
se puede cambiar la direccin del puntero (ya que se ha pasado por valor y por lo tanto se pasa
una copia), se puede modificar el contenido de la direccin de memoria a la que apunta el
puntero con el operador unario * (derreferenciacin). En la Figura 66 se muestra a la
izquierda un ejemplo de paso de parmetros por valor, en donde a y b quedan inalterados
porque la funcin swap (que pretende cambiar el valor de la variable x por el de la y) est
trabajando con una copia de las variables a y b. En cambio en la derecha se muestra un
ejemplo en el que se pasa por valor los punteros a las variables a y b, y que aunque se trabaja
con las copias de dichos punteros, se puede modificar el valor del contenido de los mismos,
resultando en que a y b intercambian su valor despus de la llamada a la funcin swap.

voi d swap( i nt x, i nt y) {
i nt t emp;
t emp = x;
x = y;
y = t emp;
}
mai n ( ) {
i nt a=5, b=6;
swap( a, b) ;
}
voi d swap( i nt *px, i nt *py) {
i nt t emp;
t emp = *px;
*px = *py;
*py = t emp;
}
mai n ( ) {
i nt a=5, b=6;
swap( &a, &b) ;
}

Figura 66: Ejemplo de paso por valor y paso por "referencia" en C
8.3 Paso de vectores como parmetros
Los vectores se pasan SIEMPRE por "referencia"; es decir, cualquier funcin puede modificar
el valor de cada componente de un vector. Esto es as ya que para pasar un vector por valor
hay que usar su nombre, que no es ms que una constante que indica la direccin de memoria
del primer elemento del vector, ver ejemplo en Figura 67.

Sistemas Electrnicos Digitales.





139
#def i ne MAX 5
i nt max( i nt * v, i nt t am) ;
mai n( ) {
i nt vect or [ ] ={1, 5, 8, 4, 3};
i nt maxi mo;
maxi mo = max( vect or , MAX) ;
}
/ * f unci n que cal cul a el mxi mo de un vect or */
i nt max( i nt * v, i nt t am) {
i nt maxi mo=0; i =0;
f or ( i =0; i <t am; i ++) {
i f ( v[ i ] > maxi mo)
maxi mo = vect or [ i ] ;
}
r et ur n ( maxi mo) ;
}

Figura 67: Ejemplo de paso por parmetro de un vector
Por otro lado, si lo que se quiere es devolver como resultado de una funcin un vector es
imprescindible hacerlo a travs de un parmetro de la misma o no a travs de la instruccin
r et ur n. En la Figura 68 se muestra el tpico manejo errneo de un vector, ya que es una
variable local que desaparece al terminar la funcin y por lo tanto aunque el programa
principal recupere la direccin de memoria devuelta, el vector se encuentra vaco. Por otro
lado, en la Figura 69, Figura 70 y Figura 71 se muestran buenas prcticas de programacin, en
donde se reserva la memoria para el vector en el lugar que va a ser utilizado.

#def i ne MAX 50
mai n( ) {
i nt *pt i ;
pt i = get _vect or _di scr et o( 1, 4) ;
}
/ * f unci n que devuel ve un vect or con l os val or es ent er os
compr endi dos ent r e mi n y max*/
i nt * get _vect or _di scr et o( i nt mi n, i nt max) {
i nt i , vect or [ MAX] ;
f or ( i =mi n; i <max; i ++)
vect or [ i ] = i ;
r et ur n ( vect or ) ;
}

Figura 68: Manejo errneo de vuelta de un vector por una funcin
Sistemas Electrnicos Digitales.





140
#def i ne MAX 50
mai n( ) {
i nt vect or [ MAX] ;
get _vect or _di scr et o( 1, 4, vect or ) ;
}
/ * f unci n que devuel ve un vect or con l os val or es ent er os
compr endi dos ent r e mi n y max*/
voi d get _vect or _di scr et o( i nt mi n, i nt max, i nt * v) {
i nt i ;
f or ( i =mi n; i <max; i ++)
*( v+i ) = i ;
}

Figura 69: Manejo tipo puntero
#def i ne MAX 50
mai n( ) {
i nt vect or [ MAX] ;
get _vect or _di scr et o( 1, 4, vect or ) ;
}
/ * f unci n que devuel ve un vect or con l os val or es ent er os
compr endi dos ent r e mi n y max*/
voi d get _vect or _di scr et o( i nt mi n, i nt max, i nt * v) {
i nt i ;
f or ( i =mi n; i <max; i ++)
v[ i ] = i ;
}

Figura 70: Manejo tipo vector
#def i ne MAX 50
mai n( ) {
i nt vect or [ MAX] ;
get _vect or _di scr et o( 1, 4, vect or ) ;
}
/ * f unci n que devuel ve un vect or con l os val or es ent er os
compr endi dos ent r e mi n y max*/
voi d get _vect or _di scr et o( i nt mi n, i nt max, i nt * v) {
i nt i ;
f or ( i =mi n; i <max; i ++)
*v++ = i ;
}

Figura 71: Uso de post-incremento
Sistemas Electrnicos Digitales.





141
9 Cuestiones de comprensin
1) Dada la siguiente definicin de variable

char c;

Seala con un crculo las opciones correctas:

a) c es un nmero de 8 bits siempre
b) c es un carcter siempre
c) c es un nmero sin signo a veces

2) Seala con un crculo los casos en los que b es igual a 1; es decir, en los que se cumple la
condicin.

CASO A)
i nt a;
b = 0;
a = - 1;
i f ( a)
b = 1;
CASO B)
b = 0;
a = 0;
i f ( a = 0)
b = 1;
CASO C)
b = 0;
a = 0;
i f ( a = 1)
b = 1;
CASO D)
b = 0;
a = 0;
i f ( a)
b = 1;

3) Indica el valor de la variable entera r esul t ado en cada caso

a) r esul t ado = 0x44 && 0x1 = ______________
b) r esul t ado = 0x44 | 0x1 = ______________
c) r esul t ado = ~( 0x44 >> 2) = ______________
Sistemas Electrnicos Digitales.





142

4) Traducir a C el siguiente cdigo en ensamblador. Cada lnea de cdigo ensamblador que se
debe traducir tiene un comentario a su derecha indicando el nmero de lnea que le representa.
Se debe indicar en cada lnea de C la correspondencia con las lneas ensamblador, escribiendo
a la derecha de las lneas en C los nmeros de las lneas ensamblador que correspondan. No se
puede codificar de forma que una lnea en ensamblador tenga asociadas varias en C; es decir,
cada lnea de C tiene al menos una lnea de ensamblador asociada.
















MAX equ -1 ;1

D100 section data at 200H
i dsb 1 ; 2
j dsw 1 ; 3
k dw 1 ; 4
D100 ends

ej section code at 300H
ej1 proc NEAR
MOV R0, #MAX ; 5
MOVB i , RL0 ; 6
MOVBZ R2, i ; 7
MOV j , R2 ; 8
MOV R1, k ; 9
CMP R1, j ; 10
J MPR cc_ugt , f i n ; 11
MOV R0, #0 ; 12
MOV j , R0 ; 13
f i n: J MPR cc_uc, f i n ; 14
ej1 endp
ej ends
Sistemas Electrnicos Digitales.





143

5) Para cada uno de los programas siguientes: Est correctamente programado? En caso
afirmativo Qu saca por pantalla? En caso negativo, razona la respuesta. Debajo de cada
programa se ha dibujado un recuadro que representa la pantalla donde se deben escribir los
resultados.
























6) Hacer un programa en C que sume los elementos de un vector de 5 elementos
a) Usando un bucle f or b) Usando un bucle whi l e.













doubl e *pdAct ual i za( ) ;

mai n ( )
{
doubl e *pd=NULL;
pd=pdAct ual i za( ) ;
pr i nt f ( " 2 %f \ n" , pd[ 0] ) ;
r et ur n 0;
}

doubl e *pdAct ual i za( )
{
doubl e md[ 3] ={1. 2, - 2. 3, - 1. 4};
doubl e *pd=md;
pr i nt f ( " 1 %f \ n" , pd[ 0] ) ;
r et ur n pd;
}
voi d Ef ect o2000( i nt *pa) ;

mai n( ) {
i nt i =74;

Ef ect o2000( &i ) ;
pr i nt f ( " %d" , i ) ;
}

voi d Ef ect o2000( i nt *pa) {
*pa=*pa+1900;
}

Sistemas Electrnicos Digitales.





144
7) Supuesto un sistema digital como el del laboratorio, explica con tus palabras qu hacen los
programas siguientes:

La lnea 6 de este programa coge el contenido de lo que hay en la direccin de memoria
indicada por el valor de dir y lo guarda en dato.






































voi d mai n( voi d) {
i nt di r , dat o;
DP2 = 0xFF;
whi l e ( 1) {
di r = ( P2 & 0xFF00) >>8;
dat o = *( ( char *) di r ) ;
P2 = dat o;
}
voi d mai n( voi d) {
unsi gned char dat o, mask, i , n;
DP2 = 0xFF;
whi l e ( 1) {
dat o = ( unsi gned char ) ( ( P2 & 0xFF00) >> 8) ;
mask=0x01; n=0;
f or ( i = 0; i <8; i ++) {
i f ( ! ( dat o & mask) )
n++;
mask<<=1;
}
i f ( n==0)
P2 = 0xFF;
el se
P2 = 0;
}
Sistemas Electrnicos Digitales.





145
10 Ejercicios propuestos
10.1 Timer y puertos (40 min)
Dado un sistema como la tarjeta del laboratorio, escribir un programa en C que realice las
siguientes operaciones:

Lee los interruptores conectados a la parte alta del puerto P2.
Extrae el valor de los dos interruptores ms significativos, y los utiliza para definir los bits
ms altos del factor de preescalado del timer 0. El bit menos significativo del preescalado
del timer queda a 0. El valor inicial de la cuenta y el valor del rebose del timer quedan
igualmente a 0.
Los 6 interruptores restantes definen dos operandos, de tres bits cada uno de ellos.
El programa realiza la suma y el producto de los dos operandos.
En los diodos conectados a la parte baja del puerto P2 aparecen ambos resultados, de
forma alterna, con sucesivos reboses de timer (con el primer rebose aparece el resultado de
la suma, con el segundo rebose aparece el resultado del producto, y as sucesivamente).

Es necesario tener en cuenta los rebotes de los interruptores.


























#i ncl ude <r eg167. h>







voi d mai n( voi d) {

















}

Sistemas Electrnicos Digitales.





146
10.2 Acceso a memoria (40 min)
Dado un sistema digital como la tarjeta que se usa en laboratorio, se pide realizar un programa
que tenga las siguientes caractersticas:

Lee un dato de los interruptores conectados a la parte alta del puerto P2.
Accede a la direccin de memoria indicada en los interruptores (8 bits ms altos de la
direccin todos a 0).
Analiza los ocho bits del dato almacenado en dicha direccin.
Si hay siete bits a 1 y uno a 0, se indica en los LED ms bajos de P2 la posicin del bit
que se encuentra a 0.
Si todos los bits se encuentran a 1 se ilumina el LED conectado a P2.4.
Si hay ms de un bit a 0 se encienden los cinco LED conectados a las lneas menos
significativas de P2.

Es necesario tener en cuenta los rebotes de los interruptores.




























#i ncl ude <r eg167. h>







voi d mai n( voi d) {


















}

Sistemas Electrnicos Digitales.





147







Sistemas Electrnicos Digitales.





148

11 Ejercicios resueltos
11.1 La calculadora (30 min)
Partiendo de un sistema como el del laboratorio, escribir un programa en C que consiste en
una calculadora que opera con datos de 4 bits (sin signo) y devuelve un resultado de 8 bits. El
funcionamiento es el siguiente:

En los cuatro bits ms altos de P2 se proporciona el primer dato. Este dato se valida
cuando la lnea P2.8 pasa de 0 a 1.
A continuacin se introduce el segundo dato (siguiendo el mismo procedimiento que
para el primer dato).
Por ltimo se introduce la operacin (+: P2.12 =1, -: P2.13=1 y *: P2.14=1). La
operacin se valida de la misma forma que los datos. En caso de que no se haya
seleccionado una operacin no se calcula el resultado.
El proceso anterior se repite indefinidamente, mantenindose en la parte baja de P2 el
resultado de la ltima operacin realizada.
La lnea P2.8 llevar un filtrado de rebotes.

























Sistemas Electrnicos Digitales.





149


Sistemas Electrnicos Digitales.





150












































#i ncl ude <r eg167. h>
#def i ne MAX 3

voi d r et r aso( i nt mseg) ;

voi d mai n( voi d) {
i nt cont ador =- 1, ci cl o=0, dat o[ 3] , r esul t ;
unsi gned i nt ant er i or , act ual , t emp;

DP2 = 0x00FF;
P2 = ~0;
ant er i or = P2 & 0x0100;
whi l e( 1) {
r et r aso( 1) ; / / 1 ms
t emp = P2;
act ual = t emp & 0x0100;
i f ( ant er i or ! = act ual )
cont ador = MAX;
el se i f ( cont ador > 0)
cont ador - - ;
el se ;

ant er i or = act ual ;

i f ( cont ador == 0) {
cont ador = - 1;
i f ( act ual )
dat o[ ci cl o++] = t emp >> 12; / / r ecogi da de dat o
}

i f ( ci cl o == 3) { / / Oper aci ones
ci cl o = 0;

i f ( dat o[ 2] & 0x0001)
r esul t = dat o[ 0] + dat o[ 1] ;
el se i f ( dat o[ 2] & 0x0002)
r esul t = dat o[ 0] - dat o[ 1] ;
el se i f ( dat o[ 2] & 0x0004)
r esul t = dat o[ 0] * dat o[ 1] ;
el se ;

P2 = ~r esul t ;
}
}
}
Sistemas Electrnicos Digitales.





151
11.2 El coche fantstico (20 min)
Se quiere hacer un sistema de luces rojas similar al del coche fantstico, que consiste de 8
luces que se encienden de una en una de forma consecutiva, de izquierda a derecha y de
derecha a izquierda. Para ello se dispone de un microcontrolador C167, de 8 LEDs y de 8
interruptores. Disear un sistema que encienda una luz roja que se vaya moviendo a la
derecha y que cuando llegue al final rebote y vuelva hacia la izquierda, y as sucesivamente.
Dado que el sistema est diseado para venderse y la velocidad de movimiento de la luz
depende del gusto del consumidor, se tiene pensado que se pueda regular dicha velocidad con
8 interruptores.



























Sistemas Electrnicos Digitales.





152

































#i ncl ude <r eg167. h>

voi d r et r aso( i nt pr ees, i nt cuent a) ;

voi d mai n( voi d) {
i nt sent i do = 0, dat o = 0x01;
i nt pr ees, cuent a, t emp;

DP2 = 0x00f f ;

P2 = ~dat o;

whi l e( 1) {
t emp = P2;
pr ees = t emp & 0x0700;
pr ees >>= 8;
cuent a = t emp & 0xF800;
r et r aso( pr ees, cuent a) ;

i f ( ! sent i do) {
P2 = ~( dat o <<= 1) ;
i f ( dat o & 0x80)
sent i do = 1;
}
el se {
P2 = ~( dat o >>= 1) ;
i f ( dat o & 0x01)
sent i do = 0;
}
}
}
Sistemas Electrnicos Digitales.





153
11.3 El autobus (30min)
Se quiere controlar el nmero de personas que hay en un autobs. Para ello se ha equipado al
autobs con dos sensores de contacto (interruptores con rebotes), uno en la puerta de entrada
delantera y otro en la puerta de salida trasera, que detectan el paso de pasajeros. El sensor de
la puerta delantera se ha conectado al pin P2.8 de un micro C167 y cada vez que pasa una
persona produce una transicin de 0 a 1 en el pin. El sensor de la puerta trasera se ha
conectado al pin P2.9 y cada vez que pasa una persona produce una transicin de 1 a 0 en el
pin. Por otro lado, se han instalado 8 LEDs, conectados a la parte baja del puerto P2, en la
cabina del conductor para indicarle el nmero de personas que viajan en el autobs. Si el
nmero de viajeros es mayor que 50, aunque una persona intente subir no se le dejar entrar
ya que el autobs se considera lleno.



























Sistemas Electrnicos Digitales.





154
La solucin propuesta utiliza una funcin filtraP2, que no es ms que una funcin genrica de
filtrado de rebotes del puerto P2. Eso significa que se puede usar en cualquier programa que
requiera filtrado de rebotes en P2. Se podra decir que es un driver del puerto P2 cuando se le
conectan interruptores, ya que el usuario no necesita conocer los detalles del puerto ni de los
interruptores y slo se tiene que preocupar del estado de los mismos. Adems es un driver con
autoinicializacin ya que detecta cundo se utiliza por primera vez e inicializa las variables
que necesita.































#i ncl ude <r eg167. h>
#def i ne MAX 3

voi d r et r aso( i nt mseg) ;

i nt cont ador [ 16] , i ni ci al i zado=0;
unsi gned i nt ant er i or [ 16] , est ado[ 16] ;

i nt f i l t r aP2( i nt nl i nea) { / / f unci n de f i l t r ado genr i ca
i nt act ual , t emp, mascar a, i ;

i f ( ! i ni ci al i zado)
f or ( i =0; i <16; i ++) {
DP2 = 0x00FF;
P2 = ~0;
cont ador [ i ] = 0;
ant er i or [ i ] = 0;
est ado[ i ] = 0;
i ni ci al i zado = 1;
}

t emp = P2;
mascar a = 1;
mascar a <<= nl i nea;
act ual = t emp & mascar a;
i f ( ant er i or [ nl i nea] ! = act ual )
cont ador [ nl i nea] = MAX;
el se i f ( cont ador [ nl i nea] > 0)
cont ador [ nl i nea] - - ;
el se ;

ant er i or [ nl i nea] = act ual ;
i f ( cont ador [ nl i nea] == 0) {
cont ador [ nl i nea] = - 1;
i f ( act ual )
est ado[ nl i nea] = 1;
el se
est ado[ nl i nea] = 0;
}
r et ur n est ado[ nl i nea] ;
}

voi d mai n( voi d) {
i nt per sonas=0;
i nt ant er i or 8, ant er i or 9, act ual 8, act ual 9;

ant er i or 8 = 0;
ant er i or 9 = 0;
whi l e( 1) {
r et r aso( 1) ;
act ual 8 = f i l t r aP2( 8) ;
i f ( ant er i or 8 ! = act ual 8 && act ual 8) / / f l anco de subi da
i f ( per sonas < 50)
per sonas++;
ant er i or 8 = act ual 8;
act ual 9 = f i l t r aP2( 9) ;
i f ( ant er i or 9 ! = act ual 9 && ! act ual 9) / / f l anco de baj ada
i f ( per sonas > 0)
per sonas- - ;
ant er i or 9 = act ual 9;
P2 = ~per sonas;
}
}
Sistemas Electrnicos Digitales.





155
12 Prctica 6: ejercicios en lenguaje C
Sistemas Electrnicos Digitales.





156
Sistemas Electrnicos Digitales.





157

Sistemas Electrnicos Digitales.





158
Captulo 9 INTERRUPCIONES
1 Objetivos y conceptos a entender en este captulo
En este captulo se debe aprender qu es una interrupcin y el proceso que se sigue para
atenderla. Se recomienda adems, que se hagan esquemas que permitan analizar el
paralelismo que hay entre el tratamiento de perifricos por polling y por interrupcin.
2 Nociones bsicas de interrupciones
Cuando la CPU pide realizar una tarea a un perifrico, tiene dos posibilidades para determinar
cuando termina el perifrico:
Estar continuamente preguntando al perifrico si ha terminado, de forma que cuando
el perifrico responda que s, ejecute el cdigo que corresponda aprovechando la tarea
realizada por el perifrico. Este mtodo se llama polling y es el que se ha estado
usando hasta el momento.
Decir al perifrico que avise a la CPU de que ha terminado su tarea. En ese momento
la CPU deja de hacer lo que estaba haciendo (slo en caso de que lo que est haciendo
sea de menor prioridad que la peticin del perifrico) y se pone a ejecutar el cdigo
que corresponda aprovechando la tarea realizada por el perifrico. Este mtodo se
llama interrupcin y es el que se va a explicar en este captulo.

Para que un perifrico funcione en modo interrupcin, es necesario configurarle para ello.
Una peticin de interrupcin de un perifrico slo interrumpe a la CPU

El proceso detallado que se sigue funcionando en modo interrupcin es el siguiente:
1. La CPU inicializa el perifrico, para funcionar en modo interrupcin y se indica el
grado de prioridad de esa interrupcin (prioridad mayor que 0).
2. La CPU se pone a hacer su trabajo normal que tiene la menor prioridad (prioridad 0).
3. Cuando el perifrico termina su tarea, realiza una peticin de interrupcin a la CPU
a travs de una lnea del bus de control denominada IRQ (interrupt request). Para
saber ms sobre los buses de la CPU ver el captulo 2 seccin 3.7.
4. La CPU termina de ejecutar la instruccin que estaba ejecutando.
5. La CPU guarda el PSW y el PC (CSP+IP) en el Stack de forma temporal. Esto es
necesario para saber lo que estaba ejecutando en el momento de la interrupcin (donde
apuntaba PC) y para saber cul es el estado de la CPU en ese instante (PSW).
6. La CPU lanza un ciclo de reconocimiento de interrupcin, para determinar los
perifricos que han solicitado la misma. De entre todos los posibles (56 en total), elige
la interrupcin que tenga mayor prioridad (16 niveles distintos).
7. La CPU lanza la funcin de tratamiento de la interrupcin, que no es otra cosa que
el cdigo que se tiene que ejecutar para aprovechar la tarea realizada por el perifrico
Sistemas Electrnicos Digitales.





159
en cuestin. La direccin de comienzo (denominada vector) de cada funcin que
atiende interrupciones (56 posibles, una por cada tipo de interrupcin) se encuentra en
la tabla de vectores de interrupcin. Por lo tanto la CPU inicializa PC al valor del
vector correspondiente. Durante el tratamiento en PSW se pone el nivel de la
interrupcin.
8. Una vez terminada la ejecucin de la funcin de tratamiento de interrupcin, la CPU
recupera el PC del Stack para seguir ejecutando lo que estaba haciendo antes de la
interrupcin y el PSW del Stack para dejar la CPU en el estado que estaba antes de la
interrupcin, tanto los flags, como el nivel de interrupcin.

3 Recursos utilizados en una interrupcin
Hay 56 posibles fuentes de interrupcin, por ejemplo el Timer 0, el Timer 1, el convertidor
AD,.... Cada fuente de interrupcin tiene:
Un vector de interrupcin, que indica la direccin de memoria de la funcin que hay
que ejecutar cuando se produzca la interrupcin.
Un registro de control de interrupcin, que tiene un nombre xxIC. Por ejemplo el del
Timer 0 es T0IC, el del Timer 1 es T1IC y el del convertidor AD es ADCIC.

El registro de control de interrupciones consta de:
ILVL: 4 bits que indican el nivel de la interrupcin (0 a 15. Nivel 15 nivel ms alto)
(Interrupt Level)
xxIE: bit de habilitacin de la interrupcin (Interrupt Enable). Este bit indica al
perifrico que tiene que funcionar en modo interrupcin. Si vale 0 el perifrico
funciona en modo polling. Por ejemplo para el Timer 0 el bit se llama T0IE, para el
Timer 1 se llama T1IE.
xxIR: bit depeticin de interrupcin (Interrupt Request). Si se pone a 1 el perifrico
est solicitando una interrupcin. Es el bit que se ha usado hasta ahora para saber si el
perifrico haba terminado su tarea. Por ejemplo para el Timer 0 el bit se llama T0IR,
para el Timer 1 se llama T1IR.

GLVL ILVL
0 1 5 2
xxIE xxIR
6 7 8
15
xxIC


Por otro lado, el registro PSW juega un papel muy importante en las interrupciones:

0 3
11
- IEN ILVL
12 15
N Z V C
2 1

Sistemas Electrnicos Digitales.





160



El bit 11, IEN (Global Interrupt Enable), es un bit que permite habilitar o deshabilitar de
forma global las interrupciones. La utilidad radica en que si en algn momento se quiere
ejecutar un trozo de cdigo al cual no se puede interrumpir (zona crtica), se puede poner a
cero este bit, en vez de tener que poner a cero cada uno de los bits xxIE de cada una de las 56
fuentes de interrupcin.

Los 4 bits que van del 12 al 15, indican la prioridad del programa en curso. De forma que una
interrupcin solamente puede interrumpir a la CPU si el ILVL del registro xxIC de la
interrupcin correspondiente, es mayor que el ILVL del PSW. El ILVL del PSW es cero
cuando se ejecuta main.

Por lo tanto para que un perifrico funcione en modo interrupcin es necesario configurarlo
de la siguiente manera:
Habilitar la interrupcin, bit xxIE del registro xxIC.
Poner la prioridad de la interrupcin, ILVL del registro xxIC.
Habilitar de forma global las interrupciones, bit IEN del registro PSW.
4 Ejemplos
A continuacin se muestra un ejemplo que usa el Timer 0 usando interrupciones para llevar a
cabo un calendario. El programa principal muestra en los LEDs conectados en la parte baja de
P2 los minutos transcurridos o las horas dependiendo de un interruptor conectado al pin
P2.15.

Es importante darse cuenta de la sintaxis de la funcin de tratamiento de interrupcin. No se
la pueden pasar parmetros, ya queNO se puede invocar explicitamente. Es la propia CPU
la que hace que se ejecute cuando el Timer rebosa. El nmero 0x20 que aparece en la
definicin de la funcin indica el vector de interrupcin que usa para ser invocada por la
CPU. La CPU sabe que es la funcin que atiende al Timer 0 NO por llamarse timer0 sino
por corresponder al vector de interrupcin 0x20 que es el que atiende las peticiones del
Timer 0. Como no se pueden pasar parmetros a la funcin de interrupcin, la comunicacin
de la misma con el programa principal se debe hacer usando variables globales.

Dado que la funcin de tratamiento de la interrupcin se ejecuta a mayor prioridad que el
resto del cdigo, es necesario que sea corta; es decir, est absolutamente prohibido poner
algn bucle en la misma. En caso contrario podra suceder que el resto de cdigo no tuviera
casi tiempo de CPU para ejecutarse.
Sistemas Electrnicos Digitales.





161
#i ncl ude <r eg167. h>
#i ncl ude <st di o. h>
#def i ne PERI OD - 2500
i nt t i cks, sec, mi n, hour ;
voi d mai n( voi d) {
t i cks = sec = mi n = hour = 0;
T01CON = 0x00;
T0REL = PERI OD; / * set r el oad val ue */
T0 = PERI OD;
T0I C = 0x44; / * set T0I E and I LVL = 1 */
I EN = 1; / * set gl obal i nt er r upt enabl e f l ag */
T0R = 1; / * st ar t t i mer 0 */
DP2 = 0x00FF;
whi l e( 1) {
i f ( P2 & 0x8000) P2 = ~mi n;
el se P2 = ~hour ;
}
}


voi d t i mer 0( voi d) i nt er r upt 0x20 {
t i cks++;
i f ( t i cks == 1000) {
t i cks = 0; sec++;
i f ( sec == 60) {
sec = 0; mi n++;
i f ( mi n == 60) {
mi n = 0; hour ++;
i f ( hour == 24)
hour = 0;
}
}
}
}


Sistemas Electrnicos Digitales.





162
5 Prctica 7: interrupciones en C
Sistemas Electrnicos Digitales.





163
Sistemas Electrnicos Digitales.





164

Sistemas Electrnicos Digitales.





165
Captulo 10 SISTEMAS DIGITALES COMPLEJOS
1 Objetivos y conceptos a entender en este captulo
Este captulo nicamente pretende dar metodologas que faciliten resolver sistemas digitales
complejos. No son los nicos mtodos que se pueden usar, pero s es cierto que siguen un
estilo de programacin y de resolucin de problemas bueno; es decir, buscan una buena
mantenibilidad, flexibilidad y escalabilidad del sistema.
2 Sistemas muestreados
Un sistema muestreado se basa en que cada cierto intervalo de tiempo, llamado periodo de
muestreo, realiza determinadas tareas sncronas. La ventaja de estos sistemas es que se sabe
con bastante precisin en qu momento se ejecutan las tareas, lo que les hace ideales para
llevar un control de tiempo o realizar mediciones. Por otro lado, las tareas muestreadas
dejan ms tiempo libre de CPU, ya que entre intervalos de muestreo la CPU queda libre.

Volviendo al ejemplo del captulo 6 seccin 12, si se quiere medir el ancho de un pulso que
entra por lnea P7.4 la solucin de un sistema sin muestrear es la siguiente:

DP2 = 0x00FF;
DP7 = 0;
i ni ci al i zaci on( T0I =7, T0=- 20000) ;
whi l e ( 1) {
whi l e ( P7. 4==0) ;
T0R = 1;
whi l e ( P7. 4==1) ;
T0R=0;
t =T0/ 20;
P2=t ;
}

Esta solucin no es muestreada porque est mirando continuamente de forma asncrona el
estado del pin P7.4. Para poder determinar el ancho del pulso tiene que usar un Timer, ya que
por la propia ejecucin de lneas de cdigo no sera factible estimar este tiempo.

En cambio en un sistema muestreado la solucin se basa en el uso de un reloj que lleva la
cuenta del periodo de muestreo, y slo se mira el estado de la lnea una vez en cada intervalo.
La ventaja es que el chequeo de la lnea no consume casi CPU y se hace a intervalos
Sistemas Electrnicos Digitales.





166
regulares, lo que supone que contando el nmero de intervalos se puede tener una medida del
ancho del pulso.

#i ncl ude <r eg167. h>
#i ncl ude <st di o. h>
#def i ne PERI OD - 2500
i nt cuent a=0, ant er i or , act ual , cont ador ;
voi d mai n( voi d) {
T01CON = 0x00;
T0REL = PERI OD; / * set r el oad val ue */
T0 = PERI OD;
T0I C = 0x44; / * set T0I E and I LVL = 1 */
I EN = 1; / * set gl obal i nt er r upt enabl e f l ag */
T0R = 1; / * st ar t t i mer 0 */
DP2 = 0x00FF;
DP7 = 0;
ant er i or = P7. 4;
whi l e( 1) ;
}
voi d t i mer 0( voi d) i nt er r upt 0x20 {
act ual = P7. 4;
i f ( ( ant er i or ! = act ual ) && ( act ual == 1) ) {
cuent a = 1;
}
i f ( ( ant er i or ! = act ual ) && ( act ual == 0) ) {
cuent a = 0;
P2 = cont ador ;
cont ador = 0;
}
i f ( cuent a==1)
cont ador ++;
ant er i or = act ual ;
}


La clave para un buen funcionamiento consiste en estimar correctamente el periodo de
muestreo, ya que si es demasiado pequeo, la CPU no queda libre, y si es demasiado grande
puede haber problemas de resolucin y sensibilidad. La regla ptima a seguir para calcular el
periodo de muestreo es la siguiente:
1. Determinar el periodo de muestreo de todas las tareas que tenga que realizar la CPU.
2. Escoger el mximo comn divisor de todos ellos.

Sistemas Electrnicos Digitales.





167
Por ejemplo, si un sistema tiene que medir el ancho de pulso con una resolucin de 1
milisegundo y adems generar un pulso de 350 microsegundos en algn momento, claramente
el periodo de muestreo es el mximo comn divisor de 350 us y 1 ms, que es 50 us.
3 Fechado
Cuando el funcionamiento de un sistema depende del tiempo, que suele ser casi siempre, es
necesario llevar un reloj calendario. Aunque se puede hacer de muchas maneras, en esta
seccin se pretende dar una metodologa para hacer programas que dependan del tiempo de
forma sencilla y simple.

Lo primero que es necesario saber es la medida mnima que se quiere poder contabilizar; es
decir, la resolucin de la medida de tiempo. En caso de ser un sistema muestreado, esta
resolucin coincide con el periodo de muestreo.

En segundo lugar, cada medida de tiempo que se quiere tener supone la creacin de un nuevo
contador de tiempo. Por ejemplo, si se quiere ejecutar el evento 1 cada segundo y el evento 2
cada 350 milisegundos, para un periodo de muestreo de 1 ms, el cdigo resultante sera:

Sistemas Electrnicos Digitales.





168
#i ncl ude <r eg167. h>
#i ncl ude <st di o. h>
#def i ne PERI OD - 2500
i nt mseg_event o1=0, mseg_event o2=0;
voi d mai n( voi d) {
T01CON = 0x00;
T0REL = PERI OD; / * set r el oad val ue */
T0 = PERI OD;
T0I C = 0x44; / * set T0I E and I LVL = 1 */
I EN = 1; / * set gl obal i nt er r upt enabl e f l ag */
T0R = 1; / * st ar t t i mer 0 */
whi l e( 1) {
i f ( mseg_event o1 == 1000) {
mseg_event o1 = 0;
/ / pr ogr amar aqu el event o 1
}
i f ( mseg_event o2 == 350) {
mseg_event o2 = 0;
/ / pr ogr amar aqu el event o 2
}
}
}
voi d t i mer 0( voi d) i nt er r upt 0x20 {
mseg_event o1++;
mseg_event o2++;
}


En caso de trabajar con polling el cdigo sera:
Sistemas Electrnicos Digitales.





169
#i ncl ude <r eg167. h>
#i ncl ude <st di o. h>
#def i ne PERI OD - 2500
i nt mseg_event o1=0, mseg_event o2=0;
voi d mai n( voi d) {
T01CON = 0x00;
T0REL = PERI OD; / * set r el oad val ue */
T0 = PERI OD;
T0I C = 0x44; / * set T0I E and I LVL = 1 */
I EN = 1; / * set gl obal i nt er r upt enabl e f l ag */
T0R = 1; / * st ar t t i mer 0 */
whi l e( 1) {
r et ar do( 1) ; / * 1 ms*/
mseg_event o1++;
mseg_event o2++;
i f ( mseg_event o1 == 1000) {
mseg_event o1 = 0;
/ / pr ogr amar aqu el event o 1
}
i f ( mseg_event o2 == 350) {
mseg_event o2 = 0;
/ / pr ogr amar aqu el event o 2
}
}
}


En caso de que la medida de tiempo sea asncrona; es decir, se hiciera a partir de un evento
que no se puede predecir cundo sucede, sera el propio evento el que pondra a cero el
contador.
Sistemas Electrnicos Digitales.





170
#i ncl ude <r eg167. h>
#i ncl ude <st di o. h>
#def i ne PERI OD - 2500
i nt mseg_event o1=0;
voi d mai n( voi d) {
T01CON = 0x00;
T0REL = PERI OD; / * set r el oad val ue */
T0 = PERI OD;
T0I C = 0x44; / * set T0I E and I LVL = 1 */
I EN = 1; / * set gl obal i nt er r upt enabl e f l ag */
T0R = 1; / * st ar t t i mer 0 */
whi l e( 1) {
i f ( ) { / / si sucede event o 1
mseg_event o1 = 0;
}
i f ( mseg_event o1 == 1000) {
/ / pr ogr amar aqu el event o 2
}
}
}
voi d t i mer 0( voi d) i nt er r upt 0x20 {
mseg_event o1++;
}


4 Programacin basada en estados
Cuando se quiere resolver un problema complejo siempre existe una frase que se debe aplicar
"divide y vencers". Pues bien, existen muchas maneras de llevar esto a cabo, la
modularizacin en funciones, el diseo top-down (disear primero a alto nivel con grandes
bloques y luego ir diseando dentro de cada bloque los detalles), etc. En esta seccin se va a
explicar cmo abordar un problema complejo usando estados. Es un diseo top-down con
gran modularizacin. Consiste en modelar cada uno de los posibles procesos de un sistema en
lo que se llama una mquina de estados. En esta seccin no se pretende exponer una teora
rigorosa sobre las mquinas de estados, ya que no es objetivo del libro, sino de dar ideas de
cmo se pueden resolver problemas software usando un mtodo que se le puede ocurrir a
cualquiera.
A cualquier desarrollador se le puede ocurrir que los pasos a seguir para resolver un problema
complejo segn un diseo top-down y modular son:
1. Determinar qu procesos independientes existen en el sistema que se quiere
desarrollar
Sistemas Electrnicos Digitales.





171
2. Para cada uno de esos procesos, se deben determinar las etapas de las que consta y
cul es la inicial.
3. Una vez determinadas las etapas, se deben definir las variables que hacen que el
proceso vaya de una etapa a otra.

De forma equivalente se puede definir este mtodo segn una metodologa basada en estados:
1. Determinar las mquinas de estado que tiene el sistema
2. Para cada mquina de estado, se deben determinar cuales son los estados de los que
consta.
3. Una vez determinados los estados, se deben definir las variables que definen los
cambios de estado

Desde el punto de vista software este mtodo quedara:
1. Definir una funcin por cada mquina de estados y definir una variable global que
permita conocer el estado actual en que se encuentra la mquina. Por ejemplo:

int estado_actual=0;
void maquina(){...}

2. Definir una funcin de estado, por cada estado de cada mquina de estados. Estas
funciones sern invocadas desde la funcin que controla cada mquina de estados
segn el valor de la variable estado_actual.

void maquina(){
if (estado_actual == 0)
estado0();
else if (estado_actual == 1)
estado1();
}

3. Dentro de cada funcin de estado, se deben programar las condiciones de paso de un
estado a otro en funcin de variables.

void estado0(){
if (var > 0)
estado_actual = 1
}


Las transiciones de un estado a otro pueden suceder por el paso de tiempo, en ese caso la
variable que se usa en la comparacin ser un contador de tiempo asncrono, tal y como se
explic en la seccin 3 de este captulo.




Sistemas Electrnicos Digitales.





172
REFERENCIAS
[1] B.W. Kernighan && D.M. Ritchie. The C Programming Language. Prentice Hall.
[2] Instruction set manual for the C166 family of Infineon 16-bit Single Chip Microcontrollers. Infineon
Technologies AG.

You might also like