Вы находитесь на странице: 1из 69

Ensamblador AVR

El hardware del microcontrolador


El concepto detrs del ensamblador es hacer accesible los recursos de hardware del procesador. Estos
recursos son todos los componentes del hardware, como la unidad central de proceso (CPU) y su
seridor de matemticas, la unidad aritm!tico"l#$ica (A%U), las unidades de almacenamiento diersas
(RA& interna y e'terna, el almacenamiento EEPR(&), los puertos y las caracter)sticas de los bits de
control del puertos, los tempori*adores, los conertidores A+ y otros dispositios.
El acceso al hardware es directo y no mediante driers u otras inter,aces -ue proporcionan los sistemas
operatios. Es el control directo de la inter,a* serial o el conersor A+, no hay una capa entre usted y
el hardware. Como premios a sus es,uer*os, el e-uipo completo est a sus #rdenes, no s#lo la parte -ue
el dise.ador del compilador y el pro$ramador del sistema o,recen para usted.
/C#mo traba0a la CPU1
%o ms importante para la comprensi#n del ensamblador es entender como ,unciona la CPU.
%a CPU lee las instrucciones de la memoria de pro$rama (,lash), las traduce y las e0ecuta en arios
pasos. En los AVR, las instrucciones estn escritas como n2meros de 34 bits en la memoria ,lash y se
leen de all) (primer paso). El n2mero le)do a continuaci#n se traduce (56 paso) como por e0emplo llear
el contenido de los re$istros R7 y R3 a la A%U (tercer paso), sumarlos (86 paso) y escribir el resultado
en el re$istro R7 (96 paso). %os re$istros son simples almacenes de : bits de ancho de los -ue se puede
leer o escribir y llear directamente a la A%U.
Al$unos e0emplos de codi,icaci#n de las instrucciones;
(peraci#n de laCPU C#di$o binario Cod. <e'.
Eniar a la CPU a dormir 3773.7373.3777.3777 =9::
>umar el re$istro R3 al re$istro R7 7777.3377.7777.7773 7C73
Restar el re$istro R3 del re$istro R7 7773.3777.7777.7773 3:73
Escribir la constante 3?7 al re$istro R34 3337.3737.7777.3737 EA7A
&ultipli-ue el re$istro R@ con el re$istro R5 y escribir el resultado
a los re$istros R3 (&>A) y R7 (%>A)
3773.3377.7733.7737 =C@5
Por lo tanto, si la CPU lee en he'adecimal =9:: de la memoria ,lash, detiene su ,uncionamiento y no
trae ms instrucciones. Bo preocuparse, hay otro mecanismo necesario antes de -ue la CPU e0ecute
esto, y adems, se puede despertar a la CPU.
E0ecutando las instrucciones
>i la CPU lee 7C73 he'adecimal, se suma el re$istro R3 al re$istro R7 y el resultado se escribe en el
re$istro R7. Esto se e0ecuta como se muestra en la ima$en.
3
En primer lu$ar la instrucci#n (palabra de 34 bits) se lee de la memoria ,lash y es traducida al
e0ecutable. E. si$uiente paso conecta los re$istros a las entradas de la A%U y suma su contenido. A
continuaci#n, el resultado se escribe en el re$istro.
>i la CPU lee =C5@ he'adecimal del ,lash, los re$istros R@ y R5 son muliplicados y el resultado se
escribe en R3 (los : bits ms altos) y R7 (los : bits ms ba0os). >i la A%U no soporta la multiplicaci#n,
no est e-uipada con el hardware para la multiplicaci#n (por e0emplo en un Attiny3@), la instrucci#n
=C5@ no hace nada en absoluto, ni si-uiera abrir una entana de error.
En principio, la CPU puede e0ecutar 49.9@4 (34 bits) instrucciones di,erentes. Bo obstante, debido a
-ue 3?7 deben escribirse en un re$istro espec),ico, y adems los alores son de entre 7 y 599 en
cual-uier re$istro de entre R34 y R@3, la cantidad de instrucciones da 594C34D8.7=4 de los 49.9@4
te#ricamente posibles. %a instrucci#n de car$a directa de una constante c (c?...c7) y los re$istros r
(r@...r7, r8 son siempre 3 y no codi,icados), es codi,icado como esto;
Ait 39 38 3@ 35 33 37 = : ? 4 9 8 @ 5 3 7
%+E R,C 3 3 3 7 c? c4 c9 c8 r@ r5 r3 r7 c@ c5 c3 c7
Por -u! esos bits se colocan as) en la palabra de instrucci#n si$ue siendo secreto de AF&E%.
%a suma y resta re-uieren @5 C @5 D 3.758 combinaciones y los re$istros ob0etio (tar$et) R7...R@3
(t8...t7) y los re$istros ,uente (source) R7...R@3 (s8...s7) son codi,icados as);
Ait 39 38 3@ 35 33 37 = : ? 4 9 8 @ 5 3 7
A++ Rt,Rs 7 7 7 7 3 3 s8 t8 t@ t5 t3 t7 s@ s5 s3 s7
>UA Rt,Rs 7 7 7 3 3 7 s8 t8 t@ t@ t3 t7 s@ s5 s3 so
Por ,aor, no aprendan estas colocaciones de bits, no lo necesitar ms adelante. >#lo hau -ue entender
c#mo se codi,ica y se e0ecuta una palabra de instrucci#n.
Enstrucciones en ensamblador
Bo hay necesidad de aprender la colocaci#n de bits en los n2meros de 34 bits por-ue en ensamblador
utili*ar abreiaturas llamadas mnemot!cnicos para ayudar a la memoria. %a representaci#n
he'adecimal =9:: en ensamblador es la abreiatura G>%EEPH, -ue es ms ,cil de recordar.
>umar simplemente es GA++H. %os dos re$istros -ue se suman estn representados como parmetros.
>implemente escriba GA++ R7,R3H, -ue se traduce a la palabra de 34 bits 7C73. %a traducci#n es
reali*ada por el ensamblador. %a CPU s#lo entiende 7C73. El ensamblador traduce la l)nea a la palabra
de 34 bits, -ue se escribe en la memoria ,lash. %a CPU la lee de la memoria ,lash y la e0ecuta. Cada
instrucci#n de la CPU tiene su correspondiente mnemot!cnico y iceersa. %a capacidad de la CPU
determina el alcance de las instrucciones -ue estn disponibles en ensamblador. El len$ua0e de la CPU
es la base, la mnemotecnia s#lo representa la capacidad de la propia CPU.
+i,erencias con los len$ua0es de alto niel
En los len$ua0es de alto niel las construcciones no son dependientes del hardware o la capacidad de
una CPU. Esas construcciones traba0an con procesadores di,erentes si hay un compilador del len$ua0e
para las diersas ,amilias de procesadores. El compilador traduce las construcciones del len$ua0e al
5
len$ua0e binario del procesador. Un I(F( en Aasic se parece a un J&P en ensamblador, pero hay una
di,erencia de concepto entre los dos. Una trans,erencia de c#di$o de un procesador a otro, s#lo
,unciona si el hardware es capa* de hacer lo mismo. >i un procesador de una CPU no tiene acceso a un
tempori*ador de 34 bits, el compilador de un len$ua0e de alto niel tiene -ue simularlo utili*ando un
tempori*ador de : bits y un c#di$o de consumo"tiempo. >i hay disponibles tres tempori*adores y el
compilador est escrito para s#lo dos o uno, el hardware disponible no se utili*a, por lo -ue se depende
totalmente de la capacidad del compilador, no de las capacidades de la CPU.
(tro e0emplo se muestra con la instrucci#n G&U%H. En ensamblador, el procesador de destino
determina si se puede utili*ar esta instrucci#n o se tiene -ue escribir una rutina de multiplicaci#n. >i en
un len$ua0e de alto niel se utili*a una multiplicaci#n, el compilador inserta una biblioteca matemtica
-ue multiplica todo tipo de n2meros, incluso si s#lo tiene n2meros de : bits y s#lo con utili*ar &U% le
bastase. %a librer)a le o,rece un n2mero entero pe-ue.o, una palabra lar$a y otras rutinas de
multiplicaci#n -ue no son necesarias. Un pa-uete completo de cosas -ue realmente no necesita, as) -ue
te -uedas pronto sin memoria ,lash en un AVR muy pe-ue.o y tienes -ue cambiar a un 'me$a de @9
pines con puertos no utili*ados s#lo por tener su $ran librer)a con rutinas super,luas ocupando espacio
en la memoria ,lash. Eso es lo -ue se obtiene a partir de un simple G C H sin ni si-uiera pedirlo.
Ensamblador no es len$ua0e m-uina
+ebido a -ue el ensamblador se acerca ms al hardware -ue cual-uier otro len$ua0e, a eces se le
llama len$ua0e m-uina. Esto no es correcto por-ue la CPU s#lo entiende instrucciones de 34 bits en
,ormato binario. %a cadena GA++ R7,R3H no se puede e0ecutar, y el ensamblador es mucho ms
simple -ue el len$ua0e m-uina. %as similitudes entre el len$ua0e m-uina y ensamblador son una
caracter)stica, no un error.
Ent!rprete y ensamblador
Un int!rprete traduce c#di$o cercano al len$ua0e humano a c#di$o binario para la CPU. El int!rprete
tiene estas caracter)sticas;
Primero lee la secuencia de te'to GA D A K AH (nuee caracteres de un byte cada uno),
tira los cuatro espacios en blanco del te'to,
locali*a las ariables A y A (ubicaci#n en los re$istros o >RA&, la precisi#n, lon$itud, etc),
identi,ica el si$no K como operador,
prepara una secuencia de m-uina e0ecutable -ue es e-uialente a la ,ormulaci#n del te'to.
En consecuencia, el c#di$o m-uina resultante ser)a arias palabras lar$as, leer y escribir ariables de
y a >RA&, sumar enteros de 34 bits, $uardar y restaurar re$istro de la pila, etc...
%a di,erencia entre el int!rprete y el ensamblador es -ue despu!s de ensamblar la CPU obtiene sus
palabras e0ecutables directamente. En la interpretaci#n, la CPU pasa la mayor parte del tiempo
reali*ando la tarea de traducci#n. %a traducci#n puede re-uerir de 57 # 577 pasos de CPU, antes de -ue
se puedan e0ecutar @ # 8 palabras. %a elocidad de e0ecuci#n es muy lenta. Esto no es problema si hay
una elocidad de relo0 muy rpida, pero no es apropiado en situaciones de tiempo cr)ticas, donde se
re-uiere una rpida respuesta a un eento. Badie sabe en -ue est ocupada e'actamente la CPU y
cuanto tiempo re-uiere.
Bo tener -ue pensar en problemas de tiempo conduce a la incapacidad del pro$ramador para resoler
problemas de tiempo y esta i$norancia le mantiene incapa* de resoler estas cosas si es necesario.
@
%en$ua0es de alto niel y ensamblador
%os len$ua0es de alto niel a.aden ciertas capas de separaci#n no transparente entre la CPU y el
c#di$o ,uente. Un e0emplo de concepto poco transparente son las ariables. %as ariables pueden
almacenar un n2mero, una cadena de te'to o un simple alor booleano. En el c#di$o ,uente, un nombre
de ariable representa un lu$ar donde se encuentra dicha ariable y hay -ue declararla; el tipo, si es un
n2mero y su ,ormato, una cadena y su lon$itud, etc.
Para aprender ensamblador solo hay -ue olidar el concepto de ariable de los len$ua0es de alto niel.
Ensamblador s#lo sabe de bits, re$istros, bytes y bytes de >RA&. %a e'presi#n ariable no tiene
nin$2n si$ni,icado en ensamblador. Adems, los t!rminos relacionados como GtipoH son in2tiles y no
tienen tampoco nin$2n sentido a-u).
%os len$ua0es de alto niel re-uieren la declaraci#n de ariables antes de su primer uso en el c#di$o
,uente, c#mo por e0emplo, si es un byte (: bits), palabra doble (34 bits), entero (39 bits ms uno de
si$no), etc. %os compiladores de estos len$ua0es tienen -ue ubicar las ariables declaradas en al$2n
lu$ar del espacio de almacenamiento disponible, incluyendo los @5 re$istros. >i esta posici#n se selec"
ciona a cie$as por el compilador o si se utili*a al$una re$la de prioridad, como lo hace el pro$ramador
en ensamblador cuidadosamente, depende -ui*s del precio del compilador. El pro$ramador s#lo
puede tratar de entender -ue criterio utili*# el compilador cuando puso la ariable. El poder de
decisi#n se le ha dado al compilador -ue GliberaH al pro$ramador de los problemas de decisi#n, pero lo
conierte en un GesclaoH del compilador. En la instrucci#n GA D A K AH si A se de,ine como un
carcter y A como un n2mero (por e0emplo 5), la ,ormulaci#n no es aceptada por-ue los caracteres no
se pueden sumar con n2meros. %os pro$ramadores de alto niel creen -ue la eri,icaci#n de tipos les
preiene de una pro$ramaci#n sin sentido. %a protecci#n -ue el compilador proporciona en este caso
mediante el error de tipo, es ms bien in2til; la adici#n de 5 a la letra GLH, por supuesto, debe dar G<H
como resultado. El ensamblador le permite hacer esto, pero no un compilador.
El ensamblador le permite sumar y restar n2meros como ? o 8: a cada byte almacenado, no importa
-ue tipo de cosas haya en el almacenamiento de bytes. Esto es decisi#n del pro$ramador, no de un
compilador. >i cuatro re$istros representan un alor de @5 bits o cuatro caracteres A>CEE, si esos
cuatro bytes se colocan del ms ba0o al alto o iceersa o me*clados por completo, es s#lo cuesti#n del
pro$ramador. Ml es el maestro de la colocaci#n, nadie ms. %os tipos son desconocidos, todo se com"
pone de bits y bytes en el almacenamiento disponible. El pro$ramador no solo tiene la tarea de or$a"
ni*ar sino tambi!n la tarea de optimi*ar. E$ual pasa con otras re$las. (l)dese de la mayor)a de las
re$las en ensamblador. Para pro$ramar ensamblador es preciso contar con al$unas re$las tambi!n, pero
di,erentes; %a mayor)a son creadas por el pro$ramador para ayudarse a s) mismo. As) -ue usted puede
pro$ramar como -uiera, no lo -ue el compilador decida por usted o lo -ue los pro,esores te#ricos creen
-ue ser)a buenas re$las de pro$ramaci#n. %os pro$ramadores de alto niel son adictos a una serie de
conceptos -ue se interponen en el camino de aprendi*a0e del ensamblador; separaci#n en di,erentes
nieles de acceso en el hardware, controladores y otros inter,aces. En ensamblador esta separaci#n es
una tonter)a. %a separaci#n les condiciona a numerosas soluciones si -uieren hacerlo de una manera
#ptima. Encluso los pro$ramadores puristas de alto niel rompen estas re$las. En ensamblador nada le
impide ser creatio, tiene acceso total al hardware, a la memoria, cual-uier cosa se puede cambiar. %a
responsabilidad es 2nicamente del pro$ramador -ue tiene -ue usar su cerebro para eitar con,lictos de
acceso al hardware. %a otra cara de la ,alta de mecanismos de protecci#n es la libertad de hacer lo -ue
-uiera y como -uiera, ir desarrollando sus propias re$las para eitar errores de e0ecuci#n.
/Nue es lo -ue es realmente ms ,cil en ensamblador1
Fodas las palabras y los conceptos -ue el pro$ramador de ensamblador necesita estn en la ho0a de
datos del procesador; las instrucciones y la tabla de puertos. OPa estQ Con esto ya se puede construir
8
al$o. Bo son necesarios otros documentos. /Como se inicia el tempori*ador1 (est escrito en
GFimer.>tart)G%+E R34,7'75H y G(UF FCCR7,R34H. /C#mo se reinicia a cero1 RC%R R34H y G(UF
FCCR7,R34R, todo est en la ho0a de datos. Bo hay necesidad de consultar una documentaci#n ms o
menos buena de c#mo el compilador de,ine esto o a-uello. Bo hay palabras especiales dise.ados por el
compilador y los conceptos -ue hay -ue aprender estn todos en la ho0a de datos. >i desea utili*ar un
contador de tiempo en el procesador para un ,in determinado puede utili*ar cual-uier modo de los 39
posibles modos di,erentes, no hay nin$una re$la en la ,orma de acceder al contador de tiempo, para
detenerlo o reiniciarlo, etc.
/Nue en un len$ua0e de alto niel es ms ,cil escribir GA D A K AH -ue R&U% R34,R3?R1 Bo mucho.
>i A y A no se de,inen como bytes o si el procesador es muy pe-ue.o y no entiende &U%, el simple
&U% tiene -ue ser intercambiado con otro c#di$o ,uente tal como ,ue dise.ado por el pro$ramador de
ensamblador o copiar y pe$ar y adaptarlo a sus necesidades. Bo hay nin$una ra*#n para importar una
librer)a opaca, simplemente descarte la pere*a en su cerebro y comience a aprender.
El ensamblador le ense.a directamente como ,unciona el procesador. +ebido a -ue un compilador no
se hace car$o de las tareas, usted es completamente el capitn del procesador. %a recompensa por esto
es -ue se le concede acceso a todo. >i lo desea puede pro$ramar una elocidad en baudios de 89,89
bps en el UARF, un a0uste de elocidad -ue no le permite un pc con windows por-ue el sistema opera"
tio s#lo permite m2ltiplos de ?9 (/por-ue1 +ebido a -ue hist#ricamente los escritores de teletipos
mecanicos ten)an las ca0as de en$rana0es dise.adas para hacer una selecci#n rpida de ?9 o @77 bps).
>i adems, desea un re$istro de 3 byte y medio en lu$ar de uno de 3 o de 5, /por-ue no pro$ramar su
propio dispositio con ensamblador1 Nuien es capa* de pro$ramar en ensamblador tiene una idea de
todo lo -ue el procesador le permite. El procesador entero est a la orden del pro$ramador. +e esta
manera puede adoptar soluciones de alta sensibilidad de ,orma ,ina y est!tica.
<ardware para la pro$ramaci#n en ensamblador AVR
%a inter,a* E>P (pro$ramaci#n en sistema) le permite leer y escribir el pro$rama en la memoria ,lash y
en la EEPR(& inte$rada. Esta inter,a* traba0a en serie y solo necesita tres lineas de se.al;
>CS; Una se.al de relo0 para despla*ar los bits -ue se escriben en la memoria en un re$istro de
despla*amiento interno y para despla*ar los bits -ue se an a leer de otro re$istro de despla*a"
miento.
&(>E; %a se.al de datos -ue en)a los bits -ue se escriben en el AVR.
&E>(; %a se.al de datos -ue recibe los bits le)dos desde al AVR.
Estos tres pines se conectan internamente a la m-uina de pro$ramaci#n s#lo si
cambia el pin de RE>EF (a eces tambi!n llamado R>F o restart) a cero. +e lo
contrario, durante el ,uncionamiento normal del AVR, estos pines son
pro$ramables como lineas de entradaTsalida como todos los dems.
>i desea utili*ar estos pines para otros ,ines durante el ,uncionamiento normal
y en el sistema de pro$ramaci#n, tendr -ue tener cuidado de -ue estos dos
ob0etios no entren en con,licto. En $eneral, habr -ue disociarlos por medio
de resistencias o un multiple'or.
Bo es necesario pero si recomendable en el modo E>P (in"system"
pro$rammin$), -ue el hardware de pro$ramaci#n suministre la tensi#n de
alimentaci#n. Esto re-uiere dos lineas adicionales entre el pro$ramador y el
AVR; IB+, Fierra com2n o polo ne$atio y VFI (tar$et olta$e), tensi#n de
alimentaci#n (por lo $eneral K9.7 oltios). Esto suma 4 lineas entre el hardware
9
pro$ramador y el AVR, y se llama cone'i#n E>P4 se$2n la de,inici#n de Atmel.
%os standards siempre tienen standards alternatios -ue se utili*aron anteriormente. Esta la base
t!cnica -ue constituye la industria del adaptador. En este caso, el standard alternatio se dise.# como
E>P37 y ha sido utili*ado en la placa >FS577, tambi!n llamada inter,a* CAB+A. Foda)a es un stan"
dard muy e'tendido e incluso la placa >FS977 ms reciente est e-uipado con !l. El E>P37 tiene una
se.al adicional para un led ro0o, -ue indicar)a -ue el pro$ramador estar)a haciendo su traba0o. Es una
buena idea, solo tiene -ue conectar el led con una resistencia y la tensi#n de alimentaci#n positia.

<erramientas para pro$ramar en ensamblador AVR
El editor,
el pro$rama ensamblador,
la inter,a* de pro$ramaci#n de chips y
el simulador.
<ay dos posibles )as;
1. Fodo en un pa-uete y
2. Cada tarea se reali*a con un pro$rama espec),ico y los resultados se an almacenando en
archios espec),icos.
Ieneralmente se eli0e la primera )a, pero para comprender el mecanismo subyacente, amos a
describir la 5U )a, -ue muestra la ,orma de un archio de te'to con palabras de instrucci#n en la
memoria ,lash.
Estructuraci#n del c#di$o ensamblador
%a estructura bsica de un pro$rama en ensamblador AVR consta de ;
comentarios,
in,ormaci#n de encabe*ado,
c#di$o al inicio del pro$rama y
estructura $eneral.
Comentarios
El te'to ms 2til en un pro$rama de ensamblador son los comentarios.
>i usted necesita entender c#di$o anti$uo -ue escribi#, a eces a.os antes, apreciar el tener al$unas
su$erencias y toda)a me0or, lo -ue ocurre en cada linea de c#di$o. >i le $usta mantener sus ideas en
secreto y ocultarlas contra si mismo y los dems, no use los comentarios. Un comentario empie*a con
un punto y coma. Fodo lo -ue si$ue por detrs en la misma linea ser i$norado por el compilador. >i
tiene -ue escribir un comentario de arias lineas, comience cada linea con un punto y coma. Cada
pro$rama en ensamblador debe comen*ar as);
V
V ClicW.asm, Pro$rama para conmutar un rel! de abierto a cerrado cada 5 se$undos
V Escrito por I. >chmidt, 2ltima modi,icaci#n; 37T7?T5773
V
Pon comentarios en todas las partes del pro$rama, ya sea en una subrutina completa o una tabla. En el
comentario hay -ue hablar de las caracter)sticas de la subrutina y las condiciones preias necesarias
4
para llamarla o e0ecutarla. Fambi!n se pueden mencionar los resultados de la subrutina en caso de -ue
ms tarde se puedan encontrar errores o para ampliarla despu!s. %os comentarios de una sola l)nea se
a.aden mediante un punto y coma en la linea despu!s del comando;
%+E R34,7'7A VA-u) se car$a al$o
&(V R3?,R34 Vy se copia en otro lu$ar
En,ormaci#n de encabe*ado
En la parte superior o encabe*ado del pro$rama debe ir el prop#sito y ,unci#n del mismo, el autor, la
ersi#n y otros posibles comentarios. +espu!s deber)a ir el tipo de procesador para el cual est escrito,
las constantes pertinentes y una lista con los nombres de los re$istros. El tipo de procesador es espe"
cialmente importante, ya -ue los pro$ramas en ensamblador no se suelen e0ecutar en di,erentes tipos
de chips sin cambios. %as instrucciones no son entendidas i$ual por todos los tipos de chips. Cada
dispositio tiene di,erentes caracter)sticas y capacidades de EEPR(& y >RA&. Fodas estas carac"
ter)sticas especiales se incluyen en un archio de encabe*ado -ue se denomina ''''de,.inc, donde
'''' es el tipo de chip como 5@3@, tn5@5@ o m:939. Estos archios estn disponibles y los proporcio"
na Atmel. Es un buen estilo de pro$ramaci#n incluir este archio al comien*o de cada pro$rama;
.B(%E>F V Bo liste lo si$uiente en el archio de lista
.EBC%U+E Rm:939de,.incR V Emportaci#n del archio de de,iniciones
.%E>F V Cambiar a lista de nueo
%a ruta de acceso, donde se puede encontrar este archio, es necesaria si usted no traba0a con el
so,tware estudio de AF&E%. +urante el ensamble, por de,ecto, se $enera un ,ichero C.lst -ue lista los
resultados. Este ,ichero podr)a ser muy lar$o si se incluye el ,ichero de encabe*ado. %a directia
.B(%E>F omite el listado hasta -ue no se uela a actiar. Veamos breemente el archio de
encabe*ado. En primer lu$ar este archio de,ine el tipo de procesador;
.DEVICE ATMEGA8515 ; El tipo de dispositivo de destino
La directiva .DEVCE hace que el ensamblador compruebe si estn disponibles todas las instrucciones
para este tipo de AVR. El resultado es un mensaje de error si se utilizan secuencias de cdigo que no
estn definidas para este tipo de procesador. El archivo de encabezado define tambin los registros XH,
XL, YH, YL, ZH y ZL. Esto es necesario si usted va a utilizar los punteros de 16 bits X, Y o Z para acceder
a los bytes de mayor y menor peso (higher o lower) por separado. Todas las ubicaciones de los puertos
tambin se definen en el archivo de encabezado. Un nmero hexadecimal indica donde se encuentra
definido un puerto en el dispositivo. Los puertos se definen con los nombres que vienen en las hojas de
daros para cada procesador. Esto tambin se aplica a los bits individuales de cada puerto. El acceso de
lectura al bit 3 del puerto B se hace usando el nombre PNB3 tal como se define en la ficha tcnica. En
otras palabras, si usted olvida de incluir el archivo de encabezado se encontrar con un montn de men-
sajes de error durante la ejecucin del ensamblaje. Los mensajes de error que se produzcan no necesa-
riamente tienen que estar relacionados con que falta el archivo de encabezado. Otras cosas que deberan
estar al principio de sus programas son las definiciones de registros con los que trabaja, por ejemplo:
.DEF mpr = R16 ; Deine !n n!evo nom"re p#r# el re$istro R16
Esto tiene la ventaja de tener una lista completa de los registros y adems poder ver los registros que
todava estn disponibles sin utilizar. Cambiar el nombre de los registros evita conflictos en su uso y
adems los nombres son ms fciles de recordar.
Al principio del programa y ms adelante hay que definir las constantes, especialmente las que tienen un
papel relevante en diferentes partes del programa. Tales constantes, por ejemplo la frecuencia Xtal a la
que debe ajustarse el programa, si utiliza en la placa la interfaz serie, se definen as:
?
.E%& ' = ()))))) ; deini*i+n de re*!en*i# ,t#l
As), desde el principio del c#di$o ,uente se puede er rpidamente para -ue relo0 se ha escrito el pro$rama,
mucho ms ,cil -ue buscar esta in,ormaci#n perdida dentro de 38:5 l)neas de c#di$o ,uente.
%o -ue se debe hacer al iniciar el pro$rama
+espu!s de haber hecho la cabecera debe comen*ar el c#di$o del pro$rama. Al principio del c#di$o se
debe colocar los ectores de reset "y de interrupci#n" (er su ,unci#n en la secci#n JU&P). A medida
-ue se produ*can saltos relatios se deben colocar detrs las respectias subrutinas de sericio de
interrupci#n. En el caso de dispositios Atme$a con mayor memoria ,lash, las instrucciones de salto se
pueden colocar a-u), pero siendo cuidadoso. <ay a-u) un poco de espacio de sobra para al$unas
subrutinas antes de colocar el pro$rama principal, -ue siempre comien*a con la iniciali*aci#n del
puntero de pila, el establecimiento de los re$istros con los alores por de,ecto y la iniciali*aci#n de los
componentes de hardware -ue se an a utili*ar. El c#di$o si$uiente es espec),ico para cada pro$rama.
El Ensamblador
Fenemos un archio de te'to con caracteres A>CEE. El si$uiente paso es traducir el c#di$o de tal ,orma
-ue pueda ser comprendido por el chip AVR. Esto se llama ensambla0e, -ue si$ni,ica Gponer las
palabras de instrucci#n de ,orma correctaH. El pro$rama -ue lee el archio de te'to y produce otro de
salida se llama Ensamblador. En su ,orma ms simple es una aplicaci#n de l)nea de comandos -ue
cuando se le llama recibe como ar$umentos la ruta del archio de te'to y al$unos modi,icadores
opcionales para comen*ar a ensamblar las instrucciones -ue encuentra en el citado archio. >i su editor
de te'to permite llamar a pro$ramas e'ternos esto es una tarea ,cil. >i no, es ms coneniente escribir
un pe-ue.o archio por lotes o script (de nueo con un editor). Este archio por lotes deber)a tener una
l)nea como esta; PathToAssembler\Assembler.exe -options PathToTextfile\Textfile.asm
Al hacer click en el lugar
del editor que llama al
programa externo o en el
archivo por lotes se incia
el ensamblador de linea
de comandos.
%a entana pe-ue.a
in,orma de proceso
completo de traducci#n.
En este caso no hay
errores. >i se producen
estos son noti,icados
0unto con su tipo y
n2mero de l)nea. El
ensamblador ha
producido una palabra
de c#di$o resultante de
la instrucci#n RJ&P
-ue se ha usado. El
ensamblador de nuestro
2nico archio de te'to
asm ha producido otros cuatro archios, aun-ue no
todos se aplican a-u).
Uno de estos cuatro nueos archios, FE>F.EEP,
:
contiene lo -ue se a a escribir en la EEPR(& del AVR. Esto no es muy interesante en este caso, ya
-ue no se $enera nin$2n contenido para la EEPR(&, por lo -ue el ensamblador lo -ue hace es elimi"
nar este archio por-ue est ac)o. El si$uiente archio, FE>F.<EX, es ms releante ya -ue contiene
las instrucciones con las -ue se a a pro$ramar el chip.
%os n2meros he'adecimales se escriben en ,orma A>CEE especial, 0unto con la in,ormaci#n de la
direcci#n y una suma de comprobaci#n, esto para cada linea. Este ,ormato se llama intel he'adecimal,
es muy anti$uo y proiene del mundo de la in,ormtica.
El tercer archio,
FE>F.(AJ, ser presentado
ms adelante, este archio
es necesario para simular
un AVR. >u ,ormato es
he'adecimal y de,inido por
AF&E%.
El contenido de un editor he'adecimal se parece a esto. Atenci#n, este ,ormato de archio no es
compatible con el so,tware de pro$ramaci#n. El archio ob0 s#lo lo $eneran al$unos ensambladores de
Atmel, no espere estos archios en todos los ensambladores.
El cuarto archio, FE>F.%>F, es un
archio de te'to. >u contenido se puede
er con un simple editor. El archio
muestra el pro$rama con todas sus
direcciones, instrucciones y mensa0es
de error en un ,ormato le$ible. Puede
necesitar este archio en casos en los
haya errores por motios de depura"
ci#n. Estos archios de listado solo se
$eneran si se incluye la opci#n corres"
pondiente en la linea de comandos y si
la directia .B(%E>F no lo suprime.
Programacin del chip
Para pro$ramar el c#di$o he'adecimal, tiene -ue disponer de !l en un archio de te'to y de un
so,tware de pro$ramaci#n AVR. Este so,tware lee los archios .<EX y trans,iere su contenido ya sea
bit a bit (pro$ramaci#n serie) o byte a byte (pro$ramaci#n en paralelo) a la memoria ,lash del AVR.
=
%a ima$en ser)a un e0emplo, pero ten$a en cuenta -ue la entana -ue aparece es del so,tware AVR
E>P.e'e, un pro$rama hist#rico -ue ya no distribuye Atmel. Ahora hay otros pro$ramas similares. El
so,tware $rabar nuestro c#di$o en la memoria de pro$rama del chip. El hardware de pro$ramaci#n y
distintas alternatias de so,tware para di,erentes sistemas operatios estn disponibles en internet.
&encionamos a-u) PonyPro$5777 como un e0emplo para la pro$ramaci#n en paralelo o por el puerto
de comunicaci#n serial.
>imulaci#n en el so,tware >tudio
Al$unas eces, aun-ue el ensamblado no produ*ca errores, el c#di$o no reali*a e'actamente lo -ue
deber)a cuando se $raba en el chip. Festear el so,tware directamente en el chip podr)a ser complicado,
especialmente si usted tiene un hardware m)nimo sin oportunidad de mostrar los resultados proisio"
nales o las se.ales de depuraci#n. En estos casos el pa-uete de so,tware >tudio de Atmel o,rece opor"
tunidades ideales para la depuraci#n. El c#di$o del pro$rama puede ponerse a prueba paso a paso para
er los resultados.
%as im$enes -ue mostramos a continuaci#n han sido tomadas de la ersi#n 8 de >tudio, -ue est
disponible $ratuitamente preio re$istro en el sitio web de Atmel. %a aplicaci#n >tudio tiene todo lo
necesario para desarrollar, depurar, simular y $rabar sus pro$ramas de ensamblador en el tipo de AVR
de su elecci#n.
El primer cuadro de dilo$o le pre$unta si -uiere abrir un proyecto ya en curso o si a a empe*ar uno
nueo. +espu!s de marcar nueo proyecto, el bot#n si$uiente le llea a la con,i$uraci#n de su nueo
proyecto. En este cuadro de dilo$o selecciona GAtmel AVR AssemblerH como tipo de proyecto, le
asi$na un nombre (en este caso test3) y despu!s una ubicaci#n para el proyecto donde se tiene acceso
de escritura. El bot#n si$uiente abre el cuadro de dilo$o de selecci#n de dispositios.
37
Como plata,orma de
depuraci#n seleccionar
AVR simulador o AVR
simulador 5. Como dispo"
sitio, a-u) ,ue seleccio"
nado un Atme$a:.
>e cierra esta entana con
el bot#n ,inali*ar y se abre
una $ran entana -ue
contiene un mont#n de
di,erentes sub"entanas.
%a entana de la i*-uierda le permite er y manipular todos los archios del proyecto. En el centro, la
entana del editor le permite escribir el c#di$o ,uente (no se preocupe por los colores, el resaltado de
sinta'is es a$re$ado por el editor). En la parte in,erior i*-uierda est la entana de Gconstrucci#nH
donde deben aparecer los mensa0es de error. En el lado derecho una rara entana de entradaTsalida con
la parte in,erior en blanco (la eremos ms adelante).
Fodas las entanas se pueden redimensionar y despla*ar independientemente por la pantalla.
33
+espu!s de escribir su pro$rama completo en c#di$o ,uente, aya al men2 construir (build), pinche en
el submen2 construir y el resultado se mostrar en la entana de construcci#n.
Ase$2rese de leer todo el contenido de la entana una e* ya -ue le brindar mucha in,ormaci#n. >i ha
echo todo correctamente aparecer un circulo erde con un mensa0e indicndoselo, de lo contrario
aparecer un circulo ro0o.
+espu!s puede ir a los men2s +ebu$, Ver, <erramientas y Procesador, cambiar su tama.o o posici#n, o
modi,icar su contenido. +eber)a tener este aspecto;
%a entana del editor
tiene ahora una
,lecha amarilla. Esta
,lecha apunta a la
si$uiente instrucci#n
-ue se e0ecutar
(realmente es una
simulaci#n).
%a entana de
procesador muestra
el alor actual del
contador de pro$ra"
ma (el pro$rama se
inicia en la direcci#n
7), el puntero de
pila, un contador de
ciclos y un cron#"
metro. >i pulsa en el
pe-ue.o G+H a la
i*-uierda de la
palabra GRe$istersH
se muestra el conte"
nido de los @5 re$is"
tros (todos estn
ac)os al inicio de la
simulaci#n).
Ahora amos a proceder con la primera instrucci#n. En el men2 G+ebu$H y despu!s Gstep intoH o
simplemente pulsando L33 se e0ecuta la primera instrucci#n.
35
%a instrucci#n
Gldi rmp,7b33333333H
car$a el alor binario
3333.3333 en el re$istro
R34.
%a ,lecha amarilla ya ha
aan*ado una instrucci#n
hacia aba0o, se encuentra
ahora en la instrucci#n
(UF.
En la entana de procesa"
dor, el contador de pro"
$rama y el de ciclos han
aan*ado uno a su e*.
El re$istro 34, en la lista
de re$istros, est en ro0o
y muestra el alor 7'LL
en he'adecimal, -ue en
binario es 3333.3333.
Aan*ando un paso ms
se e0ecuta la instrucci#n
(UF (pulsando la tecla
L33 por e0emplo) y
muestra la si$uiente
in,ormaci#n.
%a instrucci#n Gout ++RA,rmpH escribe 7'LL al puerto llamado ++RA. Ahora la acci#n se encuentra
en la entana ET(. >i se pulsa en el pe-ue.o G+H a la i*-uierda de P(RFA, se muestra el alor 7'LL en
el puerto ++RA de dos ,ormas di,erentes; como 7'LL en la parte superior de la entana y con : cua"
draditos en ne$ro en la parte in,erior.
Pulsamos 5 eces L33 y se escribe 7'99 en el P(RFA. Como era de esperar, hay cambios en el
contenido del P(RFA. <ay ahora cuatro casillas en ne$ro y las otras cuatro en blanco.
3@
(tros dos L33 y se escribe 7'AA en el P(RFA y se ha inertido el color en los cuadraditos. Es lo -ue
se esperaba. Pero, /-ue ha ocurrido en PEBA1 Fiene los colores opuestos a P(RFA, i$ual -ue los ten)a
el P(RFA en el paso anterior. PEBA es un puerto de entrada para los pines e'ternos. Como la direcci#n
de los puertos en ++RA estn ,i0ados para ser salidas, PEBA si$ue el estado de los pines en P(RFA
0usto en ciclo ms tarde. Bo hay nada mal a-u). Para comprobarlo, basta con pulsar L33 arias eces
para comprobar -ue es correcto.
Esta es una pe-ue.a muestra del so,tware simulador. El simulador es capa* de mucho ms, asi -ue
debe ser aplicado e'tensiamente en los casos de errores de dise.o. Enesti$ue los elementos de los
men2s, hay muchas cosas -ue se pueden mostrar. Por el momento, antes de se$uir 0u$ando con el
simulador, hay -ue aprender al$unas cosas bsicas del len$ua0e ensamblador, as) -ue de0aremos el
so,tware studio por un tiempo.
/Nu! es un re$istro1
%os re$istros son dep#sitos especiales con capacidad de : bits y se en as);
Ait ? Ait 4 Ait 9 Ait 8 Ait @ Ait 5 Ait 3 Ait 7
38
Fen$a en cuenta la numeraci#n de los bits, el menos si$ni,icatio es el cero (matemticamente 5
0
D 3).
Un re$istro puede almacenar n2meros del 7 al 599 sin si$no, o n2meros de "35: a 35? (n2meros
enteros con el bit ? de si$no). Fambi!n puede alamacenar un alor -ue representa un carcter
codi,icado en A>CEE (por e0em. YAY), o tan s#lo : bits indiiduales -ue no tienen relaci#n entre s) (por
e0em. : banderas indiiduales, utili*adas para se.alar : alores booleanos).
%as caracter)sticas especiales de los re$istros, comparndolas con otras ,ormas de almacenamiento,
son;
estn conectados directamente con la unidad central de proceso, llamada acumulador.
Pueden ser utili*ados directamente en las instrucciones de ensamblador, ya sea como destino de
un resultado o para leer el contenido y e,ectuar un clculo o trans,erencia.
%as operaciones con su contenido solo re-uieren una palabra de instrucci#n.
<ay @5 re$istros en un AVR. (ri$inalmente su denominaci#n a de R7 a R@3, pero se les puede
cambiar el nombre a otro ms si$ni,icatio con una directia del ensamblador. Un e0emplo;
.+EL Re$istroPre,erido D R34
%as directias de ensamblador siempre empie*an con un punto, a di,erencia de las instrucciones y
eti-uetas -ue BUBCA empie*an con un punto. Fen$a en cuenta -ue las directias s#lo tienen sentido
para el ensamblador, no producen nin$2n c#di$o e0ecutable en el chip de destino. El nombre
GRe$istroPre,eridoH no se mostrar en el c#di$o he'adecimal ensamblado, por lo -ue no podr ser
deriado de !ste.
En lu$ar de utili*ar el nombre de re$istro R34, ahora podremos utili*ar nuestro propio nombre
GRe$istroPre,eridoH si -ueremos utili*ar R34 en una instrucci#n. Fenemos -ue escribir un poco ms de
te'to cada e* -ue usemos este re$istro, pero en cambio, tenemos una asociaci#n de lo -ue podr)a ser
el contenido de este re$istro.
El uso en la linea de instrucci#n;
LDI RegistroPreferido, 150
-ue si$ni,ica car$ar el n2mero 397 inmediatamente en el re$istro R34 (%oa+ Enmediate). %+E car$a un
alor ,i0o o una constante al re$istro. Fras el ensamblado o traducci#n de este c#di$o a binario o
he'adecimal, el pro$rama almacenado en el chip luce as);
)))))) E-)6
Esto aparecer en el listado, el archio C.lst producido por el ensamblador -ue es un simple archio de
te'to. Fodos los n2meros estan en ,ormato he'adecimal. El primero (777777) indica la direcci#n en la
memoria ,lash donde se escribe y el se$undo (E=74) es el c#di$o de la instrucci#n. E=74 indica al
procesador tres cosas di,erentes en una sola palabra, aun-ue no lo ea directamente;
Un c#di$o bsico de instrucci#n de car$a, sin#nimo de %+E,
el re$istro de destino (R34), donde se a a escribir el alor 397, y
el alor de la constante (397).
Bo tiene -ue recordar todo esto. El ensamblador sabe como traducirlo para dar ,inalmente E=74 y el
AVR lo e0ecutar.
39
En una instrucci#n dos di,erentes re$istros pueden desempe.ar una ,unci#n. Un e0emplo ,cil de una
instrucci#n de este tipo es la instrucci#n de copia, &(V. El nombre de esta instrucci#n induce a
con,usi#n por-ue el contenido de un re$istro no se puede moer (/-ue -uedar)a en el re$istro si se
muee el contenido a otra parte1). &e0or deber)a llamarse C(PP, ya -ue lo -ue hace es copiar el
contenido de un re$istro a otro re$istro. +e esta manera;
.DEF Re$istro.reerido = R16
.DEF /troRe$istro = R15
0DI Re$istro.reerido1 15)
M/V /troRe$istro1 Re$istro.reerido
%as dos primeras l)neas de este peda*o de pro$rama son directias -ue de,inen los nueos nombres de
los re$istros R34 y R39. Como se mencion# antes, estas dos lineas no producen c#di$o para el AVR.
%as l)neas con las instrucciones %+E y &(V producen el si$uiente c#di$o;
)))))) E-)6
)))))1 2F)1
-ue escribe el alor 397 en el re$istro R34 y copia su contenido al re$istro de destino R39. AVE>(
E&P(RFABFE; El primer registro es siempre el registro de destino donde se escribe el resultado.
Esto es di,erente a como se lee o escribe y puede con,undir al principio, pero de i*-uierda a derecha o
de derecha a i*-uierda, son simples conenciones.
Re$istros di,erentes
El principiante -ue -uiera escribir las instrucciones de arriba de esta manera;
.DEF /troRe$istro = R15
0DI /troRe$istro1 15)
<a perdido. >olo los re$istros R34 a R@3 car$an una constante de inmediato con la instrucci#n %+E.
R7 a R39 no hacen esto. Esta restricci#n no es muy ,ina, pero no pudo eitarse durante el proceso de
construcci#n del con0unto de instrucciones de los AVR. >in embar$o, hay una e'cepci#n a esta re$la; el
establecimiento a cero de un re$istro. %a instrucci#n;
CLR RegistroPreferido
es lida para todos los re$istros.
Esta restricci#n, adems de en la instrucci#n %+E, se da en las si$uientes instrucciones;
AND Rx,K ; and-bit al registro Rx con un valor constante K,
CBR Rx,M ; Borrar todos los bits del registro Rx y establecerlos al valor de la mscara constante M,
CP Rx,K ; Compara el contenido del registro Rx con un valor constante K,
SBC Rx,K ; Reste la constante K y el valor actual de la bandera de acarreo al contenido del
registro Rx y almacena el resultado en este ltimo.
SBR Rx,M ; Establecer a 1 todos los bits del registro Rx, que son 1 en la mscara constante M,
SER Rx ; Establecer a 1, todos los bits del registro Rx (igual que LD Rx,255),
SUB Rx,K ; Restar la constante K del contenido del registro Rx y almacenar el resultado en
este ltimo.
En todas estas instrucciones, el re$istro debe ser cual-uiera de entre R34 y R@3. >i a a utili*ar estas ins"
trucciones, hay -ue seleccionar uno de estos re$istros para operar. Es ms corto y ms ,cil de pro$ra"
mar. Esta es una ra*#n ms por la -ue se debe utili*ar la directia para de,inir el nombre de un re$istro.
34
Registros de puntero
Una ,unci#n e'tra muy especial se de,ine para los pares de re$istros; R5?;R54, R5=;R5: y R@3;R@7.
El papel es tan importante -ue estas pare0as tienen nombres cortos e'tra en ensamblador AVR; X, P y
Z. Estos nombres cortos son entendidos por el ensamblador. Estos pares son re$istros de puntero de 34
bits, capa* de apuntar a las direcciones con un m'. 34 bits de lon$itud, por e0emplo en lu$ares de
>RA& (X, P o Z) o en lu$ares de memoria de pro$rama (Z).
Acceder a posiciones de memoria con punteros
El byte ms ba0o del puntero de 34 bits se encuentra en el re$istro in,erior y el ms alto en el re$istro
superior. Ambas partes tienen su propio nombre. El byte ms alto de Z se denomina Z< (DR@3) y el
ms ba0o es Z% (DR@7). Estos nombres estn de,inidos en el ensamblador. +iidir una palabra de 34
bits constante en sus dos bytes y escribir estos en un re$istro de puntero se hace como si$ue;
.EQU address = RAMEND ;RAMEND es la direi!" de 1# $its %&s alta de la %e%oria 'RAM, ()e
;est& defi"ida e" el orres*o"die"te ar+i,o de a$eera -def.i",
LDI ./,/I0/1direi!"2 ;Cargar el M'3 1$4te %&s sig"ifiati,o2 de la 5direi!"5
LDI .L,L671direi!"2 ;Cargar el L'3 1$4te %e"os sig"ifiati,o2 de la 5direi!"5
El acceso a travs de registros de puntero se programa con instrucciones diseadas especialmente.
El acceso de lectura se denomina LD (LoaD) y el acceso de escritura ST (Store). Ejemplos con el
puntero X (del mismo modo se puede usar Y y Z para tal fin):
Puntero Secuencia ejemplos
X %ecturaTescritura de direcci#n X, no cambia el puntero LD R1,X o ST X,R1
X+ %ecturaTescritura desdeThacia direcci#n X e incremento del
puntero despu!s en uno
LD R1,X+ o ST X+,R1
-X Primero, disminuir el puntero en uno y lecturaTescritura
desdeThacia la nuea direcci#n, despu!s
LD R1,-X o ST -X,R1
%ectura de la memoria de pro$rama ,lash con el puntero Z
>#lo hay una instrucci#n para el acceso de lectura en el espacio de almacena0e del pro$rama. >e de,ine
para el puntero Z y -ue se denomina %P& (car$a de memoria de pro$rama). %a instrucci#n copia el
byte de la direcci#n del pro$rama Llash a Z y al re$istro R7.
Como la memoria de pro$rama est or$ani*ada por palabras (una instrucci#n en una direcci#n se
compone de 34 bits o 5 bytes o 3 palabra), el bit menos si$ni,icatio selecciona el byte in,erior o
superior (7 D byte ba0o, 3 D byte alto). +ebido a esto la direcci#n ori$inal se debe multiplicar por 5 y el
acceso est limitado a 39 bits o @5 WA de memoria de pro$rama. +e esta manera;
0DI 3414IG4526#ddress7
0DI 3010/8526#ddress7
0.M
+espu!s de esta instrucci#n, la direcci#n debe ser incrementada para apuntar al si$uiente byte en la
memoria de pro$rama.
Como se utili*a muy a menudo, se ha de,inido una instrucci#n especial de incremento de puntero;
ADI8 3011
0.M
3?
ADI8 5Add Immedi#te 8ord7. De esta manera se pueden sumar hasta un mximo de 63. Hay que
tener en cuenta que le ensamblador espera la parte baja, ZL, del registro de puntero como primer
parmetro. Esto es algo confuso ya que la adicin se hace como una operacin de 16 bits. La ins-
truccin complementaria, que resta un valor constante entre 0 y 63 al registro de puntero de 16 bits,
se llama 9:I8 59!:tr#*t Immedi#te 8ord7. ADW y SBW son vlidas para los pares de registros de
punteros X, Y y Z y para los pares de registros R25:R24 en tanto que no tienen un nombre extra y no
se permite el acceso a posiciones de memoria de programa o SRAM. El par R25:R24 es ideal para
manejar valores de 16 bits.
Como el incremento despu!s de la lectura es muy a menudo necesario, los nueos tipos de AVR sopor"
tan la instrucci#n
LPM R,Z+
Esto permite llevar el byte ledo a cualquier ubicacin R y auto-incrementa el puntero de registro.
Listas en la memoria flash de programables
Ahora que sabemos cmo leer desde la memoria flash es posible que desee colocar una lista de
constantes o una cadena de texto. C#mo insertar una lista de alores en la memoria de pro$rama1
Esto se hace con las directias del ensamblador .+A y .+[ con las -ue se pueden insertar listas de
alores por bytes o por palabras. (r$ani*ar listas por bytes tiene este aspecto;
.D: 12;1(516<18- ;una lista de cuatro bytes, escritos en ,orma decimal
.D: =T>is is # te?t.= ;una lista de caracteres de un byte, escrito como te'to
>iempre se debe colocar un n2mero par de bytes en cada l)nea. +e lo contrario el ensamblador a.adir
un byte cero al ,inal, lo -ue podr)a no ser deseado.
Una lista similar de palabras se parece a esto;
.D8 12;(516<8- ;una lista con dos palabras constantes
En lu$ar de constantes tambi!n se pueden colocar eti-uetas (por e0emplo, los ob0etios de salto) en esa
lista, as);
0#"el1@
A ... #'!B #l$!n#s instr!**iones ... C
0#"el2@
A ... #'!B #l$!n#s instr!**iones ... C
0ist#@
.D8 0#"el110#"el2 ;!n# list# de eti'!et#s por p#l#"r#s
Las etiquetas deben comenzar en la columna 1 y tienen que terminar con ":". Tenga en cuenta que
en la lectura de las etiquetas de la lista con LPM (y el incremento posterior del puntero) se obtiene
primero el byte ms bajo de la palabra y despus el byte superior.
Acceso a los registros con punteros
Una aplicacin muy especial para los registros de puntero es el acceso a los mismos registros. Los
registros se encuentran en los primeros 32 bytes del espacio de direcciones del chip (desde la
direccin 0x0000 a la 0x001F). Este acceso slo es vlido si tienes que copiar el contenido de algn
registro hacia la SRAM o la EEPROM o leer estos valores desde ellas hacia algn registro. Es ms
comn el uso de punteros para el acceso a tablas con valores fijos en el espacio de memoria de
programa. Como ejemplo, una tabla con 10 valores diferentes de 16 bits, donde se carga el 5 valor a
R25:R24, as :
3:
MDT#"le@
.D8 )?12;(1)?2;(51)?;(561)?(5681)?56<8 ;V#lores de l# t#"l# or$#niE#d#
.D8 )?6<8-1)?<8-A1)?8-A:1)?-A:C1)?A:CD ;por p#l#"r#s
Re#d5@ 0DI 3414IG45MDT#"le627 ;dire**i+n en l# t#"l# #l p!ntero 3
0DI 3010/85MDT#"le627 ;m!ltipli*#do por 2 p#r# el #**eso "Dte # "Dte
ADI8 3011) ;p!ntero #l '!into v#lor de l# t#"l#
0.M ;le*t!r# del 09: de l# memori# de pro$r#m#
M/V R2(1R) ;*opi# 09: #l re$istro de 16 "its
ADI8 3011 ;p!ntero #l M9: en l# memori# de pro$r#m#
0.M ;le*t!r# del v#lor M9: de l# t#"l#
M/V R251R) ;*opi# M9: #l re$istro de 16 "its
Este es s#lo un e0emplo. >e puede calcular la direcci#n de la tabla en Z de un cierto alor de entrada,
lleando los respectios alores de la tabla. %as tablas pueden ser or$ani*adas byte a byte y tambi!n
por caracteres.
Recomendaciones de uso de los re$istros
%as si$uientes recomendaciones, si se si$uen, pueden decidir si usted es un pro$ramador en
ensamblador e,ica*;
+e,inir nombres para los re$istros con la directia .+EL, no utili*ar nunca su nombre directo
R'.
>i necesita acceso al puntero resere los re$istros R54 a R@3para tal ,in.
Un alor de 34 bits situarlo me0or en R59;R58.
>i tiene -ue leer de la memoria del pro$rama, por e0emplo tablas ,i0as, resere Z (R@3;R@7) y
R7 para tal ,in.
>i usted planea tener acceso a bits indiiduales dentro de ciertos re$istros (por e0emplo,
banderas de testeo), el utilice los re$istros R34 a R5@ para tal ,in.
%os re$istros necesarios para las matemticas estn me0or situados de R3 a R39.
>i tiene re$istros ms -ue su,icientes, colo-ue las ariables en los re$istros.
>i se -ueda corto de re$istros, colo-ue tantas ariables como sea necesario en >RA&.
Puertos
/Nu! es un puerto1
%os puertos en los AVR son puertas de la unidad central de proceso a los componentes de hardware y
so,tware interno y e'terno. %a CPU se comunica con estos componentes, lee de ellos o les escribe,
como los contadores o los puertos paralelos, etc. El puerto ms utili*ado es el re$istro de banderas,
donde se se.ali*an las operaciones y se leen las condiciones de bi,urcaci#n.
<ay 48 puertos di,erentes, -ue no estn ,)sicamente disponibles en todos los tipos de AVR.
+ependiendo del espacio de almacenamiento y otros componentes internos, los di,erentes puertos
estn disponibles y accesibles o no. %os puertos -ue pueden ser utili*ados en un determinado tipo de
ar con su correspondiente procesador estn especi,icados en las ho0as t!cnicas de datos. %os Atme$a
y AFXme$a ampliados tienen ms de 48 puertos, pero el acceso a los puertos ms all de \4@ es
di,erente (ese ms adelante).
%os puertos tienen una direcci#n ,i0a, con la cual se comunica la CPU. %a direcci#n es independiente
del tipo de AVR. As), por e0emplo, la direcci#n de puerto del puerto A es siempre 7'3: (en notaci#n
he'adecimal. 7'3: en decimal es 58). Usted no tiene -ue recordar estas direcciones de los puertos, ya
3=
-ue tienen un alias coneniente. Estos nombres se de,inen en los archios Y include Y (archios de
cabecera) para los di,erentes tipos de AVR y -ue son proporcionados por el ,abricante. %os archios
incluyen una l)nea -ue de,ine la direcci#n del puerto A de la si$uiente manera;
.ENU P(RFA, 7'3:
As) -ue s#lo tenemos -ue recordar el nombre del puerto A, no su ubicaci#n en el espacio de
entradasTsalidas del chip. El archio de inclusi#n :939de,.inc est inolucrado en la directia de
ensamblador;
.EBC%U+E RC;]al$2nlu$ar]:939de,.incR
y los re$istros del :939 tambi!n son de,inidos en este archio.
%os puertos por lo $eneral se or$ani*an como n2meros de : bits, pero tambi!n puede contener hasta :
bits indiiduales -ue no tienen mucho -ue er entre s). Estos bits tienen un si$ni,icado y tienen su
propio nombre asociado en el archio de inclusi#n, por e0emplo para habilitar la manipulaci#n de un
solo bit. %a conenci#n de nombre se da para no tener -ue recordar estos bits y su posici#n. En las
ho0as de datos se pueden encontrar las tablas de puertos.
El acceso de escritura a los puertos
A modo de e0emplo, el re$istro de control $eneral del &CU, llamado &CUCR, consiste en un n2mero
de bits de control -ue controlan las propiedades $enerales del chip. <e a-u) los detalles del puerto
&CUCR del AF=7>:939, tomados de las ho0as de datos del dispositio (otros puertos son similares);
Es un puerto empacado de : bits de control con sus propios nombres (E>C77, E>C73, ...). >i -uiere
eniar a su AVR a un pro,undo sue.o, tiene -ue mirar en su ho0a de datos como con,i$urar los bits
implicados, As);
.+EL Re$istroPre,erido D R34
%+E Re$istroPre,erido, 7b77377777
(UF &CUCR, Re$istroPre,erido
>%EEP
%a instrucci#n (UF trae el contenido de Re$istroPre,erido, con el bit >E (>leep"Enable"Ait) actiado,
al puerto &CUCR. El bit >E permite al AVR irse a dormir, cada e* -ue la instrucci#n >%EEP apare*"
ca en el c#di$o. Fodos los bits del puerto &CUCR tambi!n se pueden establecer con las instrucciones
anteriores. >i el bit >& (>leep"&ode) se establece a cero, el AVR entrar en un modo denominado
GduermeelaH; no se e0ecutarn ms instrucciones pero el chip reacciona toda)a al tempori*ador y
otras interrupciones de hardware. Estos eentos interrumpen el sue.o del AVR si tienen -ue noti,icar a
la CPU.
%a ,ormulaci#n anterior no es muy transparente, por-ue R7b77377777R no es ,cil de recordar, y no se
e ,cilmente -ue se ha establecido en una de estas instrucciones. Por lo tanto, es una buena idea
,ormular la instrucci#n %+E de la si$uiente manera;
LDI RegistroPreferido, 1<<SE
57
Esta ,ormulaci#n indica al ensamblador;
Fomar un uno (G3H),
%eer la posici#n del bit >E, tal como se de,ine en la lista de s)mbolos del archio de cabecera
:939de,.inc, -ue da un alor de 9 en este caso,
+espla*ar (G^^H) el 3 cinco eces a la i*-uierda (G3^^9H) en los pasos;
3) inicial; 7777.7773, 5) primer despla*amiento a la i*da.; 7777.7737, @) se$undo despla*. a la
i*da.; 7777.7377 y as) sucesiamente hasta 4) -uinto despla*. a la i*da.; 7737.7777.
asociar este alor a Re$istroPre,erido e insertar esta instrucci#n %+E en el c#di$o.
/Como se hace si se -uieren establecer en la misma instrucci#n %+E, los bits >& y >E al mismo
tiempo1 >&D3 y >ED3 establecen al AVR en modo apa$ado (power down), por lo -ue s#lo llee esto
a cabo si entiende cules son las consecuencias. %a ,ormulaci#n es la si$uiente;
LDI RegisroPreferido, (1<<SM) | (1<<SE)
Ahora, el ensamblador calcula primero el alor del primer tramo, (3 ^^>&), un R3R se despla*# cuatro
eces a la i*-uierda y se produce 7773.7777, a continuaci#n, calcula el se$undo tramo, (3 ^^>E ), un
R3R se despla*a cinco eces a la i*-uierda produciendo 7737.7777. El R_R entre los dos alores produce
una operaci#n AEF"(R ente ellos por cada bit uno a uno. El resultado de hacer esto con 7773.7777 y
7737.7777 da en este caso 7733.7777, -ue es el alor deseado para la instrucci#n %+E. A pesar de -ue
la ,ormulaci#n;
(!!"#$ | (!!"%$
podr)a, en el primer ista*o, no ser ms transparente -ue el alor resultante;
&&.&&&&
para un principiante, es ms ,cil de entender -ue los bits del &CUCR estn propuestos a ser manipula"
dos con esta instrucci#n %+E. Especialmente si usted tiene -ue leer y entender el c#di$o al$unos meses
ms tarde los bits >& y >E son una indicaci#n de -ue a-u) se est estableciendo el modo sleep o dor"
mir. +e otra manera, tendr)a -ue consultar el libro de datos del dispositio con mucha ms ,recuencia.
El acceso de lectura a los puertos
%eer el contenido de un puerto es posible en la mayor)a de los casos con la instrucci#n EB. %a si$uien"
te secuencia;
.DEF Re$istro.reerido = R16
IF Re$istro.reerido1 MC&CR
lee los bits del puerto &CUCR para el re$istro de nombre Re$istroPre,erido. Como al$unos puertos
tienen bits sin de,inir y sin usar, estos se leen siempre como ceros.
&s a menudo -ue la lectura de los : bits de un puerto, hay -ue reaccionar a un determinado estado de
un bit dentro de un puerto. En ese caso, no necesita leer todo el puerto solo aislar el bit releante. Para
ello, ciertas instrucciones proporcionan la circunstancia de e0ecutar otras instrucciones dependiendo
del estado de cierto de bit de al$2n puerto (er la secci#n de salto).
Acceso de lectura"modi,icaci#n"escritura a los puertos
Es posible actiar o desactiar determinados bits de un puerto sin cambiar bits de otro puerto y adems
sin leer o escribir los otros bits del puerto. <ay dos instrucciones -ue son >AE (>et Ait ET() y CAE
(Clear Ait ET(). %a e0ecuci#n es as);
53
.EQU 3itAti,o=0 ;El $it ()e se ,a a a%$iar
'3I Port3, 3itAti,o ;'e esta$lee e" 1
C3I Port3, 3itAti,o ;'e $orra esta$lei8"dolo a ero
Estas dos instrucciones tienen una limitaci#n; s#lo se pueden mane0ar los puertos con una direcci#n
ms ba0a de 7'57, por encima de esta direcci#n no se pueden acceder los puertos de esta manera.
+ebido a -ue el puerto &CUCR de los e0emplos anteriores tiene la direcci#n he'adecimal `@:, los bits
del mismo no se pueden establecer o borrar de esta manera. Bo obstante todos los bits de los puertos
-ue controlan los pines e'ternos del AVR (P(FF', ++R', PEB'), si son accesibles de esta manera.
Asi$naci#n de memoria de acceso al puerto
Para pro$ramadores e'#ticos o dispositios $randes como los Atme$a y AFXme$a, donde Atmel se
-ued# sin direcciones de acceso a puertos, !stos se pueden acceder tambi!n usando instrucciones de
acceso >RA&, como por e0emplo >F y %+. >#lo tiene -ue sumar 7'57 para la direcci#n de puerto y ya
tiene direcciones de acceso (recordar -ue las primeras @5 direcciones estn asociadas a los re$istros).
Por e0emplo;
.DE9 RegistroPreferido = R1#
LDI :/,/I0/1P6R;3<=>2
LDI :L,L671P6R;3<=>2
LD RegistroPreferido,:
Nue s#lo tiene sentido en ciertos casos, ya -ue re-uiere ms instrucciones, tiempo de e0ecuci#n y
l)neas de ensamblador, pero es posible. Es tambi!n la ra*#n de por -ue la locali*aci#n para la primera
direcci#n de >RA& es 7'47 y 7'377 en al$unos tipos de AVRs ms $randes.
Puertos releantes de los AVR en detalle
%a si$uiente tabla contiene los puertos ms utili*ados del Gpe-ue.oH AF=7>:939. Bo ,i$uran todos en
esta lista. Al$unos de los tipo &EIA y AF=7>88@8T:9@9 se omiten. En caso de duda consulte la re,e"
rencia ori$inal.
Componente Nombre de Puerto Registro de Puerto
Acumulador >REI Re$istro de Estado
Pila >P%T>P< Puntero de Pila
>RA& T Enterrupci#n e'ternas &CUCR Re$istro de control $eneral &CU
Enterrupciones e'ternas IE&>S Re$istro de mscara de interrupci#n
IELR Re$istro de bandera de interrupci#n
Fempori*ador de interrupci#n FE&>S Re$istro de mscara de contador de interrupci#n
FELR Re$istro de bandera de contador de interrupci#n
Fempori*ador 7 de : bits FCCR7 Re$istro de control de contadorTtempori*ador 7
FCBF7 Fempori*adorTcontador 7
Fempori*ador 3 de 34 bits T''(A Re$istro de control de contadorTtempori*ador 3 A
T''() Re$istro de control de contadorTtempori*ador 3 A
T'*T Fempori*adorTcontador 3
+'(A Re$istro de comparaci#n de salida 3 A
55
+'() Re$istro de comparaci#n de salida 3 A
,'(-./ Re$istro de captura de entrada
Fempori0ador de vigilancia 12T'( Re$istro de control del tempori*ador de i$ilancia
Acceso EEPR(& EEAR Re$istro de direcciones EEPR(&
EE+R Re$istro de datos EEPR(&
EECR Re$istro de control EEPR(&
Enter,a* peri,!rico serie >PE >PCR Re$istro de control peri,!rico serie
>P>R Re$istro de estado peri,!rico serie
>P+R Re$istro de datos peri,!rico serie
Comunicaci#n serial UARF
1;ra"s%isor?Ree*tor As@"ro"o
U"i,ersal)
U+R Re$istro de datos UARF
U>R Re$istro de estado UARF
UCR Re$istro de control UARF
UARR Re$istro de elocidad de transmisi#n (baud rate) UARF
Comparador anal#$ico AC>R Control de comparador anal#$ico y Re$istro de estado
Puertos ET( (entradaTsalida) P(RF' Re$istro de puerto de salida
++R' Re$istro de direcci#n de puerto
PEB' Re$istro de puerto de entrada
El re$istro de estado como puerto ms utili*ado
Con mucho, el puerto ms utili*ado es el re$istro del estado, con sus : bits. Por lo $eneral, el acceso a
este puerto se hace mediante con,i$uraci#n automtica, borrado de bits por la CPU o acumulador, acceso
por lectura o rami,icaci#n a ciertos bits de este puerto y en al$unos casos es posible la manipulaci#n di"
recta de estos bits utili*ando las instrucciones de ensamblador >e' o Cl' donde ' se.ala el bit. %a mayo"
r)a de estos bits estn actiados o desactiados por el acumulador para operaciones de test, comparaci#n
o clculo.
%os bits -ue ms se utili*an son;
"Z; >i est a 3, la instrucci#n anterior tuo como resultado cero.
"C; >i est a 3, la instrucci#n anterior caus# un acarreo del bit ms si$ni,icatio.
%a si$uiente lista tiene todas las instrucciones de ensamblador para actiar o desactiar los bits de estado
en ,unci#n del resultado de la e0ecuci#n de la instrucci#n anterior;
Bit Clculo Lgico Comparacin Bits Desplazamiento Otro
3 A224 A2'4 A2,14
2%'4 ,*'4 "5)4 "5),4
")'4 ")',4 "),1
A*24 A*2,4
+(4 +(,4 %+(4
'+#4 *%64
")(4 ')(
'P4 'P'4 'P,
)'-( 34
)"%T 34 '-34
"%34 T"T
A"(4 -"-4 -"(4 (+-4
(+( '-(
' A224 A2'4 A2,14
"5)4 "5),4 ")'4
")',4 "),1
'+#4 *%6
'P4 'P'4 'P,
)'-( '4
)"%T '4 '-'4
"%'
A"(4 -"-4 -"(4 (+-4
(+(
-
B
A224 A2'4 A2,14
2%'4 ,*'4 "5)4 "5),4
")'4 ")',4 "),1
A*24 A*2,4
+(4 +(,4 %+(4
'+#4 *%64
")(4 ')(
'P4 'P'4 'P,
)'-( *4
)"%T *4 '-*4
"%*4 T"T
A"(4 -"-4 -"(4 (+-4
(+(
'-(
5@
V
A224 A2'4 A2,14
2%'4 ,*'4 "5)4 "5),4
")'4 ")',4 "),1
A*24 A*2,4
+(4 +(,4 %+(4
'+#4 *%64
")(4 ')(
'P4 'P'4 'P,
)'-( 74
)"%T 74 '-74
"%74 T"T
A"(4 -"-4 -"(4 (+-4
(+(
'-(
>
"),1
" "
)'-( "4
)"%T "4 '-"4
"%"
" "
<
A224 A2'4 "5)4
"5),4 ")'4 ")',
*%6 'P4 'P'4 'P,
)'-( /4
)"%T /4 '-/4
"%/
" "
F " " "
)'-( T4
)"%T T4 )"T4
'-T4 "%T
" "
E " " "
)'-( ,4 )"%T
,4 '-,4 "%,
"
(%T,
%os detalles de los puertos ms comunes se muestran en una tabla adicional (ane'o).
SRAM
Casi todos los dispositios AVR disponen de memoria RA& esttica ">RA&" (al$unos pocos anti$uos
no la llean). >#lo los pro$ramas muy simples en ensamblador, pueden eitar el uso de este espacio de
memoria, por tener toda la in,ormaci#n necesaria en los re$istros. >i te -uedas sin re$istros debes ser
capa* de pro$ramar la >RA& para utili*ar ms espacio.
/Nu! es la >RA&1
%a >RA& es una memoria -ue no es
directamente accesible por la CPU
(unidad aritm!tica l#$ica "A%U" a
eces llamada acumulador) como si
son los re$istros. >i se accede a estos
espacios de memoria hay -ue utili*ar
un re$istro como almacenamiento
proisional.
En el e0emplo, se muestra como un
alor de >RA& se copia en el re$istro
R5 (3U instrucci#n), se hace un clculo
con un alor en el re$istro R@(5U ins"
trucci#n) y despu!s, el resultado se
uele a escribir en la misma ubicaci#n de la >RA& (@U instrucci#n, no mostrada a-u)).
Por lo cul, es claro -ue las operaciones con alores almacenados en la >RA& son ms lentas de reali*ar
-ue utili*ando re$istros. >in embar$o, incluso el ms pe-ue.o de los AVR tienen 35: bytes de >RA&
disponibles, mucho ms de lo -ue pueden contener los @5 re$istros.
%os AVR desde el AF=7>:939 en adelante, o,recen la capacidad de conectar RA& e'terna adicional,
ampliando la interna 935 bytes. +esde el punto de ista del ensamblador, a la >RA& e'terna se accede
como >RA& interna. Bo hay instrucciones adicionales.
/Para -u! ,ines puedo usar >RA&1
Adems de almacenamiento simple de los alores, la >RA& o,rece oportunidades adicionales para su uso.
Bo s#lo es posible el acceso con direcciones ,i0as, sino tambi!n el uso de punteros, por lo -ue se puede
58
pro$ramar el acceso ,lotante a la >RA&. As), se pueden crear b2,,eres de anillo para almacenamiento
proisional de alores o tablas (ariables) de clculo. Esto no es muy ,recuente con los re$istros, por-ue
adems de ser pocos, se pre,ieren para el acceso ,i0o.
A2n ms habitual es el acceso mediante un despla*amiento de una direcci#n ,i0a a partir de un re$istro de
puntero. En este caso, una direcci#n ,i0a se almacena en un re$istro puntero, un alor constante se suma a
esta direcci#n y la lecturaTescritura se hace con un despla*amiento de esa direcci#n. Este tipo de acceso a
tablas es mucho ms e,ica*.
Pero el uso ms releante de la >RA& son las llamadas a la pila. >e pueden poner alores (ariables) en la
pila, ya sea el contenido de un re$istro -ue es temporalmente necesario para otro ,in, ya sea una direcci#n
de retorno antes de llamar a una subrutina o la direcci#n de retorno antes de atender una interrupci#n.
/C#mo usar >RA&1
+ireccionamiento directo
Para copiar un alor a una posici#n de memoria de la >RA& tiene -ue de,inir la direcci#n. %as direccio"
nes >RA& -ue puede utili*ar abarcan desde la direcci#n de inicio (muy a menudo 7'7747 en pe-ue.os
AVRs, 7'7377 en Atme$a ms $randes) hasta el ,inal ,)sico de la >RA& (en el AF=7>:939 el lu$ar
accesible de la >RA& interna ms alto es 7'759L, er la ho0a de datos de cada AVR para los detalles).
Con la instrucci#n;
>F> 7'7747, R3
el contenido del re$istro R3 se copia en la primera direcci#n de memoria 7'7747. Con;
%+> R3, 7'7747
el contenido de la >RA& en la direcci#n 7'7747 se copia en el re$istro. Este es el acceso directo con una
direcci#n -ue tiene -ue ser de,inida por el pro$ramador.
%os s)mbolos de,inidos en el archio de inclusi#n Cde,.inc, >RA&a>FARF y RA&EB+, permiten
colocar las ariables en el espacio de >RA&, por lo -ue es me0or utili*ar estas de,iniciones para acceder al
-uinceao byte de memoria, as);
%+> R3,>RA&a>FARFK39
%os nombres simb#licos se puede utili*ar para eitar la manipulaci#n de direcciones ,i0as, -ue re-uieren
mucho traba0o, si lue$o se -uiere cambiar la estructura de los datos en la >RA&. Estos nombres son ms
,ciles de mane0ar -ue los n2meros he'adecimales, por lo -ue ocuparse de dar un nombre como;
.E%& MD.reerred9tor#$eCell = 9RAMG9TART
9T9 MD.reerred9tor#$eCell1 R1
Si, el nombre es ms largo, pero ms fcil de recordar. Use cualquier nombre que crea conveniente.
Puntero a direcciones
Otro tipo de acceso a la SRAM es a travs de punteros. Se necesitan dos registros para este fin que contengan
la direccin de 16 bits. Como hemos visto en la divisin de registros de puntero, los registros de puntero son los
pares de registros X (XH:XL, R27:R26), Y (YH:YL, R29:R28) y Z (ZH:ZL, R31:R30), que permiten el acceso
directo a la ubicacin que elija (ej.: ST X, R1). O despus de decrementar la direccin con por ej.: ST -X, R1 o
despus de incrementarla (ST X+, R1). Un acceso completo a una hilera de tres celdas de memoria lucira as:
59
.E%& MD.reerred9tor#$eCell = 9RAMG9TART
.DEF MD.reerredRe$ister = R1
.DEF Anot>erRe$ister = R2
.DEF AndHetAnot>erRe$ister = R;
0DI ,41 4IG45MD.reerred9tor#$eCell7
0DI ,01 0/85MD.reerred9tor#$eCell7
0D MD.reerredRe$ister1 ,I
0D Anot>erRe$ister1 ,I
0D AndHetAnot>erRe$ister1 ,
Con los punteros es fcil operar, tanto como en otros idiomas a parte del ensamblador, que dicen ser ms
fciles de aprender.
Puntero con desplazamiento
La tercera construccin es un poco ms extica y slo programadores experimentados deben usar esto en
ciertos casos. Vamos a suponer que en nuestro programa a menudo se necesita acceder a tres lugares de
SRAM consecutivos. Vamos a suponer tambin que an disponemos de un par de registros de puntero de
repuesto, por lo que puede darse el lujo para el siguiente propsito. Si queremos utilizar las instrucciones ST /
LD siempre tenemos que cambiar el puntero si accedemos a otra ubicacin de las tres del ejemplo anterior.
Para evitar esto (y para confundir a los principiantes) se invent el acceso con desplazamiento. Durante este
acceso el valor del registro no se modifica. La direccin se calcula temporalmente sumando un desplazamiento
fijo. En el ejemplo anterior el acceso a la ubicacin 0x0062 se vera de la siguiente manera. Primero, el registro
de punteo se ajusta a nuestra ubicacin central SRAM_START:
.E%& MD.reerred9tor#$eCell = 9RAMG9TART
.DEF MD.reerredRe$ister = R1
0DI H41 4IG45MD.reerred9tor#$eCell7
0DI H01 0/85MD.reerred9tor#$eCell7
En algn lugar ms adelante del programa me gustara escribir en la celda 2 por encima de SRAM_START:
9TD HI21 MD.reerredRe$ister
%a correspondiente instrucci#n para la lectura >RA& con un despla*amiento tambi!n es posible;
0DD MD.reerredRe$ister1 HI2
Fen$a en cuenta -ue el 5 no se suma realmente a P, s#lo temporalmente durante la e0ecuci#n de esta
instrucci#n. Para Gcon,undirH ms, esto s#lo se puede hacer con los pares de re$istro Z e P, no se puede
hacer con el puntero X. +e cada 377 casos, el uso de esta t!cnica se muestra ms e,ica* en un solo caso,
as) -ue no importa si no entiende esto en detalle. Es s#lo para e'pertos y necesario s#lo en al$unos casos.
El uso de >RA& como pila
El uso ms com2n y releante de la >RA& es como pila. %a pila es como una torre de blo-ues. Cada
blo-ue -ue se a.ade a en la parte superior de la torre, cada llamada a un alor elimina el blo-ue ms
alto de la torre. %a eliminaci#n de blo-ues de la base o de cual-uier porci#n ba0a de la torre es
demasiado complicado y desestructurar)a el con0unto de la pila, por lo -ue se recomienda no probar
nunca esto. Esta estructura de pila se denomina %EL( (%ast"En"Lirst"(ut, el 2ltimo en entrar es el
primero en salir).
+e,inici#n de >RA& como pila
Para usar la >RA& como pila se re-uiere primero el establecimiento del puntero de pila. Mste es de 34 bits
y es accesible como puerto. El doble re$istro se denomina >P<;>P%. >P< contiene el octeto ms si$ni,i"
catio y >P%, el menos si$ni,icatio.
54
Esto s#lo es lido, si el tipo de AVR tiene ms de 594 bytes de >RA&. >i no, >P< no es necesario, no
est de,inido, y no se debe ni se puede utili*ar. En los si$uientes e0emplos asumiremos -ue tenemos una
>RA& con ms de 594 bytes.
Para construir la pila, el puntero de pila se car$a con la direcci#n disponible ms alta de la >RA&. (En
nuestro caso la torre crece hacia aba0o, hacia las direcciones ba0as, s#lo por ra*ones hist#ricas y para
OGcon,undirH a los principiantesQ).
.DEF Re$istro.reerido = R16
0DI Re$istro.reerido1 4IG45RAMEFD7 ;"Dte #lto
/&T 9.41Re$istro.reerido ;del p!ntero de pil#
0DI Re$istro.reerido1 0/85RAMEFD7 ;"Dte "#Jo
/&T 9.01Re$istro.reerido ;del p!ntero de pil#
Por supuesto, el valor RAMEND es especfico para el tipo de procesador y est definido en el archivo de
inclusin. En el archivo 8515def.inc la lnea:
.e'! RAMEFD =K25F ;Lltim# dire**i+n del *>ip
El archivo 8515def.inc se incluye en la directiva de ensamblador:
.IFC0&DE =C@M#l$Lnl!$#rM8515de.in*=
al principio de nuestro cdigo fuente ensamblador.
Por lo tanto, se define la pila ahora, y no tiene que preocuparse ms por el puntero de pila debido a que las
manipulaciones de este indicador son automticas en su mayora.
El uso de la pila
El contenido de los registros se ponen en la pila de la siguiente manera:
.&94 Re$istro.reerido ;.one el v#lor en l# *im# de l# pil#
En caso de que el valor deje de tener inters, como el puntero de pila se decrementa despus de ponerlo, no
tiene que preocuparse. Si necesitamos el contenido de nuevo, simplemente aadimos la siguiente instruccin:
./. Re$istro.reerido ;0eer de n!evo el v#lor de l# *im# de l# pil#
Con POP acaba de obtener el valor que fue puesto por ltima vez en el tope de la pila. Poner y quitar registros
tiene sentido si:
El contenido es necesario algunas lneas de cdigo ms tarde,
todos los registros estn en uso, y si
no existe otra opcin de almacenar ese valor en otra parte.
Si estas condiciones no se dan, el uso de la pila para guardar los registros es intil y una prdida de tiempo de
procesador.
Donde ms sentido tiene el uso de la pila es con las subrutinas, donde despus de ejecutarlas se tiene que
volver a la ubicacin del programa que llam a la subrutina. Este pone la direccin de retorno (el valor actual
del contador de programa) en la pila y salta temporalmente a la subrutina. Cuando acaba sta, se coje la
direccin de retorno de la pila y se carga de nuevo en el contador de programa. La ejecucin del programa
contina exactamente en la instruccin siguiente en la que estaba el programa cuando ocurri la llamada:
RCALL algo ;Saltar a la etiqueta "algo"
[.] aqu despus se continuar con el programa.
Aqu el salto a la etiqueta "algo" en algn lugar del cdigo del programa,
algo: ;esta es la direccin del salto.
[.] aqu hacemos algo
5?
[.] termina, y se vuelve a desde donde se hizo la llamada
RET
Durante la ejecucin de la instruccin rcall el contador de programa se incrementa. Una direccin de 16 bits se
inserta en la pila en dos pasos (2 PUSH), el %>A y el &>A. Al lle$ar a la instrucci#n REF, el contenido
del contador de pro$rama se uele a car$ar con estos dos bytes (5 P(P) y desde a-u) contin2a la e0e"
cuci#n. Bo tiene -ue preocuparse por la direcci#n de la pila desde donde se car$a el contador, ya -ue
esta direcci#n se $enera automticamente, incluso si se llama a otra subrutina dentro de la anterior sub"
rutina, la pila ,unciona bien. >e ponen dos direcciones de retorno en la parte superior de la pila, la de la
subrutina anidada encima de la -ue llama, -ue cuando termina su e0ecuci#n retorna a la subrutina -ue
la llam# y !sta a su e* hace lo propio. &ientras haya su,iciente memoria >RA&, todo est bien.
El sericio de interrupciones de hardware no es posible sin la pila. Una interrupci#n, como su nombre
indica, interrumpe la e0ecuci#n normal del pro$rama. +espu!s de la e0ecuci#n de la rutina de sericio a
la interrupci#n, el pro$rama debe oler 0usto a donde estaba cuando se produ0o la interrupci#n. Esto
no ser)a posible si no se pudiera almacenar la direcci#n de retorno en la pila.
%as enormes enta0as de tener una pila para poder atender las interrupciones son la ra*#n por la -ue
hasta el ms m)nimo AVR sin necesidad de >RA&, ten$a el menos una pe-ue.a pila en hardware.
Errores comunes en la operaci#n de pila
%os principiantes, como es normal, cometen una $ran cantidad de errores cuando comien*an a apren"
der a utili*ar la pila.
Bo es muy inteli$ente el uso de la pila sin establecer o de,inir primero el puntero de pila. +ebido a -ue
este puntero se establece en cero al inicio del pro$rama, apunta a la direcci#n 7'7777 -ue es donde se
encuentra el re$istro R7. Poner un byte (PU><) escribiendo en dicho re$istro, sobreescribir)a su con"
tenido anterior. Un PU>< adicional escribir)a en 7'LLLL -ue es una posici#n inde,inida si no tiene
memoria >RA& e'terna. RCA%% y REF deolern direcciones e'tra.as en la memoria de pro$rama
y puede estar se$uro de -ue no habr nin$una adertencia como la aparici#n de una entana diciendo
al$o as) como Gacceso ile$al a direcci#n de memoria ''''H.
(tros errores comunes son olidarse de sacar de la pila un alor puesto anteriormente o intentar sacar
un alor sin haberlo puesto antes. Fambi!n puede suceder en al$2n caso, el desbordamiento de pila por
deba0o de la primera direcci#n >RA&. Esto se da cuando se produce una llamada recursia sin ,in.
+espu!s de alcan*ar la direcci#n ms ba0a de >RA& los si$uientes PU>< escriben en los puertos
(desde 7'779L hasta 7'7757), y los si$uientes en los re$istros (de 7'773L a 7'7777). >i esto contin2a,
cosas diertidas e impredecibles pueden suceder en el chip. Eite este error, Oincluso puede destruir su
hardware e'ternoQ
>alto y Rami,icaci#n
A-u) hablaremos de todas las instrucciones -ue controlan la e0ecuci#n secuencial de un pro$rama. >e
inicia con la secuencia de arran-ue del procesador, contin2a con saltos, interrupciones, etc.
Control secuencial de la e0ecuci#n del pro$rama
/Nu! sucede durante un reinicio1
Cuando al AVR se le suministra la tensi#n de alimentaci#n y el procesador comien*a su labor, se actia
una secuencia de reinicio. %os puertos se establecen a sus alores iniciales, tal como se de,ine en la
ho0a de datos del dispositio y el contador de pro$rama se establece a cero y en esta direcci#n
5:
comien*a la e0ecuci#n del pro$rama, donde debemos tener nuestra primera palabra de c#di$o. Pero no
s#lo durante el encendido se actia esta direcci#n;
>i se produce un reset e'terno en el pin de reset el dispositio e0ecuta un reinicio.
>i lle$a a su alor m'imo el contador del perro $uardin (watchdo$) tambi!n se e0ecuta un
reinicio. El tempori*ador de i$ilancia es un relo0 interno -ue debe ser reseteado de e* en
cuando por el pro$rama, de lo contrario, se reinicia el procesador.
Usted puede llamar a reinicio por un salto directo a esa direcci#n (!ase la secci#n salto "0ump"
ms adelante).
El tercer caso no es un reset real, por-ue no se e0ecuta el rea0uste automtico de alores de re$istros y
puertos a un alor por de,ecto bien de,inido. Por lo tanto, nos olidamos de esto por el momento. El
a0uste del watchdo$ a cero para eitar un reinicio re-uiere la e0ecuci#n de la instrucci#n;
WDR
+espu!s de la e0ecuci#n de un reset, con el establecimiento de re$istros y puertos a los alores por
de,ecto, el c#di$o en la direcci#n 7777 (tipo palabra) comien*a a e0ecutarse en el procesador. El
contador de pro$rama se incrementa en uno y la si$uiente palabra de c#di$o est ya en el bu,,er de
lectura. >i la instrucci#n e0ecutada no re-uiere un salto se e0ecuta la si$uiente inmediatamente. Esta es
la ra*#n por la -ue los AVR son tan rpidos, cada ciclo dde relo0 e0ecuta una instrucci#n si no se
producen saltos.
%a primera instrucci#n de un archio e0ecutable se encuentra siempre en la direcci#n 7777. Para
indicar al compilador (ensamblador del pro$rama) -ue nuestro c#di$o ,uente empie*a a-u) y ahora,
puede colocarse al principio una directia especial;
.C9EG
./RG ))))
La primera directiva. CSEG, permite al compilador cambiar su salida a una seccin de cdigo, es decir
define el inicio de un segmento de cdigo. Todo lo siguiente se traduce como cdigo y se escribe en la
seccin del procesador de la memoria de programa. Otro segmento destino sera la seccin EEPROM del
chip, donde tambin se pueden escribir bytes o palabras.
.E9EG
%l tercer segmento es la secci8n de "(A#.
.D9EG
E'cepto en la EEPR(&, donde el contenido es realmente lo -ue est pasando en la EEPR(& durante
la pro$ramaci#n del chip, el contenido del se$mento +>EI no est pro$ramado para el chip. Bo tiene
posibilidad de $rabar contenido en >RA&. As) -ue +>EI. s#lo se utili*a para el clculo de la eti-ueta
correcta durante el proceso de ensamblado. Un e0emplo;
.D9EG ;0#s si$!ientes son deini*iones de eti'!et# dentro del se$mento 9RAM
.rimer#V#ri#"le:Dte@
.:HTE 1 ;El p!ntero D9EG se m!eve >#*i# #rri"# !n "Dte
9e$!nd#V#ri#"le.#l#"r#@
.:HTE 2 ;El p!ntero D9EG se m!eve >#*i# #rri"# dos "Dtes
Ter*er#V#ri#"le:!er@
.:HTE ;2 ;El p!ntero D9EG se m!eve >#*i# #rri"# ;2 "Dtes
5=
As, slo se definen tres etiquetas en el cdigo, no se produce contenido.
%a directia (RI en el se$mento de c#di$o, pasa por encima de la primera palabra de c#di$o y
manipula la direcci#n donde debe ir, es decir establece el inicio ((RiIin) del pro$rama.
En los pro$ramas dise.ados para -ue de todas ,ormas empiecen en la direcci#n 7'7777, las directias
C>EIT(RI son triiales y puede pasarlas por alto sin $enerar error. Podr)amos comen*ar en 7'7377,
pero no tiene nin$2n sentido real cuando el procesador comien*a su e0ecuci#n en 7777. >i desea
colocar una tabla e'actamente en un determinado lu$ar del se$mento de c#di$o, puede utili*ar .(RI,
pero ten$a cuidado con lo si$uiente; Con .(RI solo se da el salto hacia delante, nunca hacia atrs. Por
lo -ue hay -ue tener cuidado tambi!n, ya -ue el salto ,or*ado por .(RI en espacio de memoria ,lash
donde se ubica el c#di$o corriente, est lleno de la instrucci#n 7'LLLL. Esta instrucci#n no hace nada,
solo ir a la si$uiente instrucci#n, asi -ue ase$urese de -ue su e0ecuci#n no salte en medio de tal espacio
inde,inido.
>i en el principio de su secci#n de c#di$o desea establecer una se.al clara, despu!s de las de,iniciones
con las directias .+EL y .ENU, puede uasr la secuencia C>EIT(RI como una se.al para usted,
aun-ue no hubiera sido necesario hacerlo.
Como la primera palabra de c#di$o est siempre en la direcci#n cero, a este lu$ar se le llama tambi!n
el ector de reset. Fras !ste, las si$uientes posiciones en el espacio de memoria, las direcciones
7'7773, 7'7775, etc, son ectores de interrupci#n. Estas son las posiciones a las -ue salta la e0ecuci#n
si se produce una interrupci#n interna o e'terna. Estos ectores son espec),icos para cada tipo de
procesador y dependen del hardware interno (!ase ms adelante). %a instrucci#n para reaccionar ante
una interrupci#n dada debe ser colocada en el ector adecuado. >i se utili*an interrupciones, el primer
c#di$o en el ector de reset, debe ser una instrucci#n de salto, para sortear estos otros ectores. Cada
ector de interrupci#n -ue se plani,i-ue -ue est! habilitado, debe tener una instrucci#n de salto a la
rutina de sericio de interrupci#n respectia. >i el ector no se utili*a, lo ms indicado es poner una
instrucci#n REFE (Retorno de interrupci#n) ,icticia. %a secuencia t)pica del pro$rama al principio es
como si$ue;
.C9EG
./RG ))))
RNM. 9t#rt ;el ve*tor de reset
RNM. Int9ervRo!t1 ;l# r!tin# de servi*io de l# 1O interr!p*i+n
RETI ;instr!**i+n i*it*i# de interr!p*i+n sin !s#r
RNM. Int9ervRo!t; ;l# r!tin# de servi*io p#r# l# ;O interr!p*i+n
A...C aqu ponemos las otras instrucciones del vector de interrupcin
A...C D #'!B es !n "!en l!$#r p#r# l#s r!tin#s de servi*io de interr!p*i+n
Int9ervRo!t1@
A...C C+di$o de l# r!tin# de servi*io de l# 1O interr!p*i+n
RETI ;Fin#l de l# 1O r!tin# de servi*io
Int9ervRo!t2@
A...C C+di$o de l# r!tin# de servi*io de l# ;O interr!p*i+n
RETI ;Fin#l de l# 2O r!tin# de servi*io
A...C otro *+di$o
9t#rt@ ;Aqu el inicio del programa
A...C A'!B el pro$r#m# prin*ip#l
La instruccin "RJMP Start resulta en un salto a la etiquete Start:, que se encuentra algunas lneas
debajo. Recuerde que las etiquetas terminan siempre con un " : . Las etiquetas que no cumplan esta
condicin no se tienen en cuenta, dando un mensaje de error "Undefined label" (etiqueta no definida)
y se interrumpe la compilacin.
Ejecucin lineal del programa y bifurcaciones
@7
La ejecucin del programa es siempre lineal, si nada cambia la ejecucin secuencial. Estos cambios
pueden producirse por la ejecucin de una interrupcin o de instrucciones de ramificacin.
Ramificacin
La ramificacin se suele producir en funcin de alguna condicin llamada bifurcacin condicional.
Como ejemplo vamos a suponer que queremos construir un contador de 32 bits utilizando los
registros R1 a R4. El byte menos significativo en R1 se incrementa en uno. Si el registro se desborda
durante la operacin (255 + 1 = 0), incrementamos R2. Si se desborda R2, incrementamos R3 y as
sucesivamente.
El incremento en uno se hace con la instruccin NC. Si ocurre un desbordamiento durante la
ejecucin de NC R1, el bit cero en el registro de estado se establece a 1 (el resultado de la
operacin es cero). El bit de acarreo en el registro de estado se establece a 1 cuando hay un
desbordamiento, no cambia cuando se ejecuta NC. Se trata de no confundir al principiante pero el
acarreo se puede utilizar para otros fines. Si no hay desbordamiento podemos salir de la secuencia
de conteo.
Si el bit cero est establecido a 1, se debe ejecutar el incremento del registro superior siguiente. La
instruccin de ramificacin que se utiliza en este caso es BRNE (Branch if Not Equal). La secuencia
de conteo del contador de 32 bits debera tener este aspecto:
IFC R1 ;in*rement# el *ontenido del re$istro R1
:RFE Go/n;2 ;si no es *ero1 ir # l# r#m# Go/n;2@
IFC R2 ;in*rement# el *ontenido del re$istro R2
:RFE Go/n;2
IFC R;
:RFE Go/n;2
IFC R(
Go/n;2@
Esto es todo. La condicin opuesta a BRNE es BREQ (Branch Equal).
Cul de los bits de estado, tambin llamados banderas del procesador, cambian durante la ejecucin
de una instruccin, se muestra en las tablas de cdigos de instrucciones, consulte la lista de
instrucciones. Al igual que el bit cero se podran utilizar otros bits de estado, como por ejemplo,
Eti'!et#s :RCCP:RC9; "#nder# de #*#rreo ) 5:RCC7 o 1 5:RC97
Eti'!et# :R94; i$!#l o m#Dor
Eti'!et# :R0/; menor
Eti'!et# :RMI; menos
Eti'!et# :R.0; mQs
Eti'!et# :RGE; M#Dor o i$!#l 5*on "it de si$no7
Eti'!et# :R0T; menor 5*on "it de si$no7
Eti'!et#s :R4CP:R49; "#nder# medio des"ord#miento1 ) o 1
Eti'!et#s :RTCP:RT9; "it T ) o 1
Eti'!et#s :RVCP:RV9; "#nder# de *omplemento # dos1 ) o 1
Eti'!et#s :RIEP:RID; interr!p*i+n #*tiv#d# o des#*tiv#d#
para reaccionar a las diferentes condiciones. La ramificacin siempre se produce si se cumple la
condicin. La mayora de estas instrucciones se utilizan muy poco. Para el principiante, con el bit
cero y el de acarreo son suficientes.
El tiempo durante la ejecucin del programa
Como se ja mencionado anteriormente, el tiempo necesario para ejecutar una instruccin es igual a
un ciclo de reloj del procesador. Si el procesador corre a una frecuencia de reloj de 4 Mhz, una
@3
instruccin requiere de microsegundo 250 ns. A 10 MHz requerira 100 ns. El tiempo requerido
es tan exacto como lo sea el reloj interno o externo o Xtal. Si necesitamos el tiempo exacto, un AVR
es la solucin. Tenga en cuenta que hay algunas instrucciones que requieren dos o ms ciclos como
las instrucciones de ramificacin (si se produce la ramificacin) o la lectura/escritura secuencial de
SRAM. Consulte la tabla de instrucciones para los detalles.
Para poder definir el momento exacto, debe haber una oportunidad de no hacer nada ms que
retrasar la ejecucin del programa. Se pueden utilizar otras instrucciones que no hagan nada, pero
es mejor utilizar la instruccin NOP (no-operation). Esta es la instruccin ms inoperante:
NOP
Esta instruccin no hace ms que perder tiempo de procesador. A 4 Mhz, necesitamos justo cuatro
instrucciones NOP para consumir 1 s. No hay otros ocultos significados aqu en la instruccin NOP.
Para un generador de seal de 1 Khz no es necesario aadir 4.000 instrucciones NOP a nuestro
cdigo fuente. En este caso se utilizara un contador de software y algunas instrucciones de
ramificacin con los que se construira un bucle que se ejecuta un determinado nmero de veces y
hacen el retardo con exactitud. Un contador podra ser un registro de 8 bits que se decrementa con la
instruccin DEC, as por ejemplo, de esta manera:
C0R R1 ;!n *i*lo de reloJ
Co!nt@
DEC R1 ;!n *i*lo de reloJ
:RFE Co!nt ;dos p#r# l# "i!r*#*i+n1 !no por l# no "i!r*#*i+n
Esta secuencia consume (1) + (255*2) + (1*3) = 514 ciclos de reloj 128,5 s a 4 MHz.
Fambi!n se puede utili*ar un contador de 34 bits para hacer un retardo e'acto de esta ,orma;
0DI 3414IG45655;57 ;!n *i*lo de reloJ
0DI 3010/85655;57 ;!n *i*lo de reloJ
Co!nt@
9:I8 3011 ;dos ciclos de reloj
:RFE Co!nt ;dos p#r# l# "i!r*#*i+n1 !no por l# no "i!r*#*i+n
Esta secuencia consume (1+1) + (65534*4) + (1*3) = 262,141 ciclos de reloj 65.535,25 s a 4 Mhz.
Si se utilizan ms registros para construir contadores anidados se puede llegar a cualquier retraso, y
ste es tan exacto como lo sea la fuente de reloj, incluso sin un temporizador de hardware.
Las macros y la ejecucin del programa
A menudo se tienen que escribir secuencias de cdigo idnticas o similares en diferentes ocasiones y
lugares en el cdigo fuente. Si quiere puede escribirlo una sola vez utilizando una macro para evitar
el cansancio de escribir la misma secuencia varias veces. Las macros son secuencias de cdigo, que
una vez diseadas y comprobado su correcto funcionamiento, se insertan en el cdigo por el nombre
de la macro.
Como ejemplo vamos a suponer que tenemos que retrasar varias veces el tiempo de ejecucin del
programa en 1 s con un reloj de 4 Mhz. En algn lugar del fichero fuente se define una macro:
.MACR/ Del#D1
F/.
F/.
F/.
F/.
.EFDMACR/
@5
Esta definicin de la macro an no produce ningn cdigo, no hace nada. El cdigo slo se producir
si se llama a esa macro por su nombre:
A...C en #l$Ln l!$#r del *+di$o !ente
Del#D1
A...C el *+di$o v# #'!B
Esto hace que cuatro instrucciones NOP sean insertadas en el cdigo en ese lugar. Adicionales
"DELAY1" insertaran otras cuatro instrucciones NOP.
Si la macro tiene secuencias muy largas de cdigo o si tiene poco espacio de almacenamiento de
cdigo, debe evitar el uso de macros y utilizar subrutinas en su lugar. Al llamar a una macro por su
nombre, puede agregar algunos parmetros para manipular el cdigo producido, pero por ahora esto
es lo que debe saber como principiante acerca de las macros.
Subrutinas
Al contrario que las macros las subrutinas hacen ahorrar espacio de almacenamiento de programa.
La secuencia se almacena una sola vez en el cdigo y luego se puede llamar desde cualquier parte
del mismo. Para asegurar la ejecucin continua de la secuencia siguiente despus de ejecutar la
subrutina, se necesita volver a la secuencia llamadora. Para un retraso de 10 ciclos se necesitara
por ejemplo esta subrutina:
Del#D1)@ ;l# ll#m#d# de l# s!"r!tin# re'!iere #l$!nos *i*los
F/. ;retr#so de !n *i*lo
F/. ;retr#so de !n *i*lo
F/. ;retr#so de !n *i*lo
RET ;Volver de l# ll#m#d#
Para que se pueda saltar a ellas, las subrutinas siempre empiezan con una etiqueta. En el ejemplo la
etiqueta es "Delay10:. Le sigue tres instrucciones NOP y una instruccin RET. Si se cuentan los
ciclos se encuentran 7 (3 para las NOP y 4 para la RET). Las 3 que faltan son para llamar a la
subrutina:
A...C@
RCA00 Del#D1)
A...C mQs #del#nte en el *+di$o !ente
Rcall es una llamada relativa. La llamada se codifica como salto relativo. La distancia relativa desde
la rutina llamadora hasta la subrutina es calculada por el compilador. La instruccin RET salta de
nuevo a la rutina llamadora. Tenga en cuenta que antes de hacer llamadas a subrutinas debe esta-
blecer el puntero de pila, debido a que la direccin de retorno debe ser puesta en la cima de la pila
durante la instruccin RCALL.
Si desea ir directamente a alguna otra parte del cdigo, tiene que utilizar la instruccin de salto:
A...C en #l$Ln l!$#r del *+di$o !ente
RNM. Del#D1)
Ret!rn@
A...C mQs #del#nte en el *+di$o !ente
Tenga en cuenta que RJMP tambin es una instruccin de salto relativo con la distancia limitada.
Slo los AVRs Atmega tienen una instruccin JMP que permite saltos en el espacio completo de
memoria flash, pero esta instruccin requiere dos palabras y ms tiempo de instruccin que RJMP
por lo que es mejor evitarla si es posible.
La rutina que salt no puede utilizar la instruccin RET en este caso, porque RJMP no coloca la
direccin actual de ejecucin en la pila. Para volver de vuelta al lugar de la llamada se requiere
@@
agregar otra etiqueta y la rutina llamada salta de nuevo a esta etiqueta. Este salto no es como llamar
a una subrutina porque no se la puede llamar desde distintas ubicaciones del cdigo.
RCALL y RJMP son bifurcaciones incondicionales. Para ir a otro lugar de forma condicionada tiene
que combinarlas con otras. Una llamada a subrutina condicionada, sde puede hacer con las
siguientes (confusas) instrucciones. Si quiere llamar a una subrutina en funcin de cierto bit de un
registro puede utilizar la siguiente secuencia:
9:RC R11< ;9#lt#r l# si$!iente instr!**i+n si el "it < en el re$istro 1 es )
RCA00 &p0#"el ;0l#m#d# # s!"r!tin#
SBRC es Skip siguiente inst. si Bit x en Registro es Clear (=Cero). La instruccin RCALL a "UpLabel
solo se ejecuta si el bit 7en el registro R1 es 1, ya que la siguiente instruccin a SBRC se saltara si
fuese 0. Si se quisiera que sea al contrario, llamar a la subrutina en caso de que el bit
correspondiente fuese 0, se utilizara la instruccin SBRS. La siguiente instruccin a SBRS/SBRC
puede ser de una palabra o de doble palabra. En todo caso, el procesador sabe el salto que tiene
que hacer, pero tenga en cuenta que los tiempos de ejecucin son diferentes. Para saltar ms all de
la siguiente instruccin, SBRS/SBRC no se pueden utilizar.
Si tuviera que saltar una instruccin para el caso de dos registros que tuvieran el mismo valor se
puede utilizar la siguiente extica instruccin (que se utiliza raras veces):
C.9E R11R2 ;Comp#r#r R1 D R2 D s#lt#r l# si$!iente instr!**i+n si son i$!#les
RCA00 Al$!n#9!"r!tin# ;0l#m#d# # Al$!n#9!"r!tin#
Si por ejemplo tuviera que saltar la instruccin siguiente en funcin de determinado bit de un puerto,
se utilizaran las instrucciones SBC y SBS (Skip si el Bit /O es Clear -o Set-), as:
9:IC .IF:1) ;9#lt#r l# si$!iente instr!**i+n si el "it ) en el p!erto : es )
RNM. AT#r$et ;9#lt#r # l# eti'!et# At#r$et
La instruccin RJMP slo se ejecuta si el bit 0 en el puerto B est alto. Esto es algo confuso para el
principiante. El acceso a los bits de puerto se limita a la mitad inferior de los puertos, los 32 puertos
superiores no se pueden utilizar aqu.
Ahora, a modo de ejemplo, otra extica aplicacin para expertos. Supongamos que tenemos un
interruptor de bits con 4 interruptores conectados al puerto B. Dependiendo del estado de esos 4 bits
habra que ir a 16 lugares diferentes en el cdigo. Entonces tenemos que leer el puerto y utilizar
varias instrucciones de bifurcacin para ir al lugar adecuado. Como alternativa, se puede escribir una
tabla que contenga las 16 direcciones as:
MDT#"@
RNM. Ro!tine1
RNM. Ro!tine2
A...C
RNM. Ro!tine16
En el cdigo copiamos la direccin de la tabla para el registro de puntero Z:
0DI 3414IG45MDT#"7
0DI 3010/85MDT#"7
y sumamos el estado actual del puerto B (en R16) a esta direccin
ADD 301R16
:RCC Fo/verloR
IFC 34
Fo/verloR@
@8
Ahora podemos ir a esta ubicacin en la tabla, ya sea para llamar a una subrutina:
ICA00 ;ll#m# # l# s!"r!tin# '!e se en*!entr# en l# dire**i+n 3
o como un salto sin camino de regreso:
INM. ;ir dire*t#mente # l# dire**i+n en 3
El procesador carga el contenido del par Z en el contador de programa y contina la operacin all.
Mejor que bifurcar una y otra vez!
nterrupciones y ejecucin del programa
A menudo tenemos que reaccionar a condiciones de hardware u otros eventos. Un ejemplo es un
cambio en un pin de entrada. Usted puede haber programado un bucle que pregunta si se produce
un cambio en un pin para tomar una decisin. Este mtodo se llama pollin$ (sondeo), que se aseme-
ja a una abeja dando vueltas en crculo buscando nuevas flores. Si no hay otras cosas que hacer y el
tiempo de respuesta no importa, se puede dedicar el procesador a esto. Si tiene que detectar pulsos
de menos de 1 s, este mtodo no sirve. En este caso, se necesita programar una interrupcin.
Una interrupcin se activa por ciertas condiciones de hardware. Todas las interrupciones de hardware
estn deshabilitadas de forma predeterminada en el reset, por lo que hay que activar la condicin en
primer lugar. Se establecen primero los bits de puerto correspondientes que permitan habilitar las
interrupciones. El procesador tiene un bit en su registro de estado que le permite habilitar el respon-
der a las interrupciones, la bandera de habilitacin de interrupcin. La activacin general de respues-
ta a las interrupciones requiere de la instruccin:
9EI ;9et Int En#"le :it
Despus, para estar habilitadas, cada interrupcin por separado requiere adems la manipulacin en
el puerto correspondiente.
Si se produce la condicin que lleva a la interrupcin, por ejemplo, un cambio en un bit de un puerto,
el procesador pone en la pila (habiendo habilitado primero el puntero de pila) el valor actual del con-
tador de programa. Sin esto, el procesador no sera capaz de volver al lugar donde se produjo la in-
terrupcin (que puede ser en cualquier momento y en cualquier lugar durante la ejecucin del pro-
grama). Despus, el procesador salta a la ubicacin predefinida, el vector de interrupcin, y ejecuta
la instruccin. Por lo general, sta suele ser una instruccin de salto (JUMP) a la rutina de servicio de
la interrupcin, que se encuentra en algn lugar del cdigo. El vector de interrupcin es una localiza-
cin especfica del procesador y va en funcin de los componentes de hardware y de la condicin
que conduce a la interrupcin. Cuntos ms componentes de hardware y ms condiciones, ms vec-
tores. Los diferentes vectores para algunos tipos de AVR antiguos se enumeran en la tabla siguiente.
El primer vector no es de interrupcin, es el de reset que no realiza ninguna operacin con la pila.
Nombre
Direcc. del vector de interrupcin
Provocada por
2313 2323 8515
RESET 0000 0000 0000 /ard9are (eset4 Po9er-+n-(eset4 1atchdog (eset
NT0 0001 0001 0001 Cambio de nivel en el pin externo NT0
NT1 0002 - 0002 Cambio de nivel en el pin externo NT1
TMER1CAPT 0003 - 0003 Captura de eventos en Timer/Counter 1
TMER1 COMPA - - 0004 Timer/Counter 1 = Compare value A
TMER1 COMPB - - 0005 Timer/Counter 1 = Compare value B
TMER1 COMP1 0004 - - Timer/Counter 1 = Compare value 1
@9
TMER1 OVF 0005 - 0006 Timer/Counter 1 Overflow
TMER0 OVF 0006 0002 0007 Timer/Counter 0 Overflow
SP STC - - 0008 Transmisin serie completa
UART TX 0007 - 0009 UART Disponible un carcter en el bfer
UART UDRE 0008 - 000A UART transmisor corri vaco
UART TX 0009 - 000B UART Todo enviado
ANA_COMP - - 000C Comparador Analgico
Hay que tener en cuenta que la capacidad de reaccionar ante los acontecimientos es muy diferente
para los diferentes AVRs. Las direcciones son secuenciales, pero las mismas para los diferentes
tipos. Consulte la hoja de datos para cada tipo de AVR.
Cuanto ms alto sea un vector en la lista, mayor es su prioridad. Si dos o ms componentes tienen
una condicin de interrupcin en espera al mismo tiempo, el vector con la direccin ms alta gana.
La interrupcin inferior tiene que esperar hasta que la interrupcin superior este servida. La deshabili-
tacin de interrupciones bajas durante la ejecucin de la rutina de servicio de una primera interrup-
cin se realiza con una bandera del procesador que la rutina de servicio debe volver a activar una
vez que acabe. Para volver a establecer el bit de estado hay dos formas. La rutina de servicio puede
terminar con la instruccin:
RETI
Este retorno de la rutina restaura el bit despus de que la direccin de retorno se ha cargado al
contador de programa.
La segunda forma es activar el bit con la instruccin:
9EI ;9et Interr!pt En#"led
RET ;Volver
Esto no es igual que con RET ya que las interrupciones posteriores ya estn habilitadas antes que el
contador de programa se cargue con la direccin de retorno. Si otra interrupcin est pendiente, su
ejecucin ya ha comenzado antes que la direccin de retorno se haya extrado de la pila. Dos o ms
direcciones estaran anidadas en la pila. Normalmente no tiene porqu producir error, pero es un ries-
go innecesario. Es mejor utilizar RET y evitar este flujo innecesario en la pila.
Un vector de interrupcin slo puede contener una sla instruccin de salto con respecto a la rutina
de servicio. Si una interrupcin est indefinida o no se utiliza hay que asociarla con una instruccin
RET, para el caso de que suceda la interrupcin errneamente antes de haber escrito la rutina de
servicio. En algunos casos es absolutamente necesario para responder a estas falsas interrupciones.
Puede darse el caso de que la respectiva rutina de servicio no restablezca automticamente la ban-
dera de interrupcin del perifrico. Entonces una simple RET restablecera la interrupcin que de
otro modo no acabara nunca. Esto se ds con algunas de las interrupciones del UART.
Tenga en cuenta que dispositivos grandes tienen una organizacin de palabra doble en la tabla de
vectores. En estos casos, en lugar de RJMP, debe ser utilizada la instruccin JMP y la instruccin
RET seguida por una NOP para que apunte a la direccin siguiente de la tabla de vectores.
Como despus de que entra una interrupcin, la ejecucin de las interrupciones de menor prioridad
est bloqueada, las rutinas de servicio a interrupcin deben ser lo ms cortas posible. Si usted nece-
sita tener una rutina grande para servir a la interrupcin, utilice uno de los dos mtodos siguientes. El
primero es permitir interrupciones con SE (Set nterrupt Enabled) en la rutina de servicio cada vez
que haya terminado con las tareas ms urgentes. Aunque no es muy inteligente. Es ms conveniente
llevar a cabo las tareas urgentes, establecer la bandera en un registro en algn lugar de reaccin
@4
lenta y regresar a la interrupcin inmediatamente.
Una regla importante para las rutinas de servicio de int. es:
La primera instruccin es siempre para salvar los indicadores de estado del procesador en un
registro o en la pila.
Haga esto antes de usar las instrucciones que podran cambiar las banderas del registro de estado.
La razn es que el programa principal interrumpido slo podra estar en un estado mediante los
indicadores de estado y la interrupcin acaba de cambiar las banderas a otro estado. Cosas diverti-
das que ocurren de vez en cuando. Por lo tanto, la ltima instruccin antes de RET es copiar las
banderas en un registro para traerlas de vuelta al puerto de estado o poner el contenido del registro
de estado en la pila para restaurarlo a su estado anterior. A continuacin se muestran ejemplos de
cmo hacerlo:
"alvando en un registro:
Isr@
IF R1519REG ;$!#rd#r "#nder#s
A... more instr!*tions...C
/&T 9REG1R15 ;rest#!r#r "#nder#s
RETI ;volver de l# interr!p*i+n
Salvando en la pila:
Isr@
.&94 R15 ;s#lv#ndo el re$istro en l# pil#
IF R151 9REG
A...more instr!*tions...C
/&T 9REG1R15 ;rest#!r#r "#nder#s
./. R15
RETI ;volver de l# interr!p*i+n
El mtodo de abajo es ms lento. El mtodo de arriba requiere un registro exclusivamente a tal fin.
En general: Todos los registros utilizados en una rutina de servicio deben ser reservados exclusiva-
mente a este efecto o deben ser guardados en la pila y restaurados a finales de la rutina de servicio.
Dentro de una rutina de servicio de int., nunca cambie el contenido de un registro que es utilizado en
alguna otra parte del programa, sin restaurarlo.
Debido a estos requisitos bsicos, un ejemplo ms sofisticado para una rutina de servicio de int.:
.C9EG ;#'!i empieE# !n se$mento de *+di$o
./RG )))) ;en l# dire**i+n *ero
RNM. 9t#rt ;el ve*tor de reset en l# dire**i+n ))))
RNM. I9ervi*e ;)))1@ primer ve*tor de int.1 r!tin# de servi*io IFT)
ASC otros ve*tores
9t#rt@ ;#'!B comienza el programa principal
A...C #'!B p#r# l# deini*i+n de l# pil# D otr#s *os#s
I9ervi*e@ ;aqu comienza la rutina de servicio de int.
.&94 R16 ;guardar registro enla pila
IF R1619REG ;leer el registro de estado
.&94 R16 ;y ponerlo en la pila
A...C aqu la rutina de servicio de int. hace algo y utiliza el registro R16
./. R16 ;o"tener el re$istro de "#nder# #nterior de l# pil#
@?
/&T 9REG1R16 ;restaurar el anterior estado
./. R16 ;obtener el contenido anterior de R16 de la pila
RETI ;D retorn#r desde int.
Parece un poco complicado, pero es un requisito previo para usar interrupciones sin que se produz-
can errores graves. Saltar PUSH R16 y POP R16 si no se puede permitir reservar el registro para
uso exclusivo dentro de la rutina de servicio. Como una rutina de servicio de int. no puede ser inte-
rrumpida (a no ser que se permitan otras interrupciones dentro de la rutina) todas las diferentes ruti-
nas de servicio de int. pueden utilizar el mismo registro.
Ahora deber ser claro por qu permitir interrupciones dentro de una rutina de servicio de int. y no al
final con RET no es una buena idea.
Clculos
Aqu hablaremos de todas las instrucciones necesarias para el clculo en lenguaje ensamblador
AVR. Esto incluye los sistemas de numeracin, ajustes de bits, desplazamiento y rotacin, sumar,
restar o comparar y formatos de conversin.
Sistemas de numeracin en ensamblador
Los siguientes formatos de nmeros son comunes en ensamblador:
Nmeros enteros positivos (bytes, palabras, palabras largas, etc)
Nmeros enteros con signo (enteros pequeos y grandes)
Dgitos codificados en binario (BCD)
BCD empacado.
ASC con formato numrico.
Si usted viene de un lenguaje de alto nivel olvide los formatos predefinidos de nmero. El ensambla-
dor no tiene ese concepto ni sus limitaciones: usted es el dueo de su propio formato.
Nmeros enteros positivos (bytes, palabras, etc)
El nmero entero menor que se maneja en ensamblador es un byte de ocho bits. ste cdigo
numrico abarca desde el 0 al 255. Estos bytes encajan exactamente en un registro del MCU.
Los nmeros ms grandes deben estar basados en este formato base, com ms de un registro.
Dos bytes producen una palabra (desde 0 a 65.535), tres bytes forman una palabra larga (desde 0 a
16.777.215) y cuatro bytes forman una palabra doble (desde 0 a 4.294.967.295).
Un byte, una palabra o una palabra doble se pueden almacenar en cualquier registro que se elija.
Las operaciones con estos bytes se programan byte a byte, por lo que no hay que ponerlos en una
fila. Formar una fila para almacenar una palabra doble podra ser as:
.DEF r16 = dR)
.DEF r1< = dR1
.DEF r18 = dR2
.DEF r1- = dR;
Los registros dw0 a dw3 estn en una fila pero no es necesario. Si tenemos que iniciar esta palabra
doble (por ejemplo, 4.000.000) al comienzo de una aplicacin, puede tener este aspecto:
.E%& dRi = ()))))) ;se deine l# *onst#nte
0DI dR)10/85dRi7 ;09: # R16
0DI dR11:HTE25dRi7 ;"its 8 .. 15 # R1<
0DI dR21:HTE;5dRi7 ;"its 16 .. 2; # R18
0DI dR;1:HTE(5dRi7 ;"its 2( .. ;1 # R1-
@:
Hemos dividido este nmero decimal, llamado dwi, en sus partes binarias byte4 a byte1 y empacado
en un paquete de 4 bytes. Ahora se pueden hacer clculos con esta palabra doble.
Nmeros enteros con signo
A veces, aunque en casos raros, se necesita hacer clculos con nmeros negativos. Un nmero
negativo se define por interpretar el bit ms significativo de un byte como bit de signo. Si es 0 el
nmero es positivo. Si es 1 es negativo. Si el nmero es negativo por lo general no se almacena el
resto del nmero tal como est, sino que usamos su valor invertido. nvertido significa que -1 no se
escribe como 1000.0001, sino como 1111.1111. Esto significa: restar 1 a 0 (y olvidar el desborda-
miento). El primer bit es el bit de signo, lo que indica que se trata de un nmero negativo. Se utiliza
este formato diferente (restar el nmero de 0) porque la suma de -1 (1111.1111) y 1 (0000.0001) da
exactamente cero, si se olvida el desbordamiento producido con la operacin (el noveno bit).
En un byte el nmero entero ms grande que se maneja es 127 (binario 01111111)y el ms pequeo
es -128 (binario 10000000). En otros lenguajes de programacin este formato de nmero se llama
entero corto. Si usted necesita un mayor rango de valores puede aadir otro byte para formar un
valor entero ms grande, que va desde 32.767 .. -32.768, cuatro bytes proporcionan un rango desde
2147483647 .. -2147483648, llamado en otros lenguajes entero largo o doble.
Dgitos en codificacin binaria, BCD
Hemos hablado anteriormente del formato ms eficaz para usar el espacio disponible con nmeros
enteros positivos o con signo. Otro formato menos denso y ms fcil de entender y manejar es
almacenar nmeros decimales en bytes, un dgito en cada byte. El dgito decimal se almacena en su
formato binario en un byte. Cada dgito comprendido entre 0 .. 9 necesita 4 bits (valores binarios
0000 .. 1001) y los cuatro bits superiores del byte son siempre ceros. Para manejar el valor 250 se
necesitan por lo menos tres bytes, por ejemplo:
Valor de bit 128 6 32 16 8 2 1
R16, Digito 1 = 2 0 0 0 0 0 0 1 0
R17, Digito 2 = 5 0 0 0 0 0 1 0 1
R18, Digito 3 = 0 0 0 0 0 0 0 0 0
;Iinstr!**iones de !so@
0DI R1612
0DI R1<15
0DI R181)
Se puede hacer clculos con estos nmeros, pero es un poco ms complicado en ensamblador que
calcular con valores binarios. Las ventajas de este formato es que se pueden manejar nmeros tan
grandes como se quiera, siempre y cuando haya suficiente espacio de almacenamiento. Los clculos
son tan precisos como haga falta (por ejemplo, si programa el AVR para aplicaciones de banca), y se
pueden convertir muy fcilmente a cadenas de caracteres.
BCD empacado
Si se empaquetan dos dgitos decimales en un byte no se pierde tanto espacio de almacenamiento.
Este mtodo se llama empacado de dgitos en codificacin binaria. Las dos parte de un byte se
llaman nibble superior e inferior. El nible superior por lo general tiene el dgito ms significativo, que
conlleva ventajas para hacer los clculos (instrucciones especiales en ensamblador AVR). El nmero
decimal 250 lucira as en el formato BCD empacado:
@=
!"te d#gito valor 8 2 1 8 2 1
2 4 y 3 02 0 0 0 0 0 0 1 0
1 2 y 1 50 0 1 0 1 0 0 0 0
;Instr!**iones p#r# *oni$!r#r@
0DI R1<1)?)2 ;"Dte s!perior
0DI R161)?5) ;"Dte inerior
Para establecer los bits apropiados a su posicin de nibble correcta puede utilizar la notacin binaria
(0b...) o la hexadecimal (0x...).
Los clculos con BCD embalado son un poco ms complejos comparndolos con la forma binaria. El
cambios de formato a cadenas de caracteres es casi tan fcil como con BCD y la longitud de los
nmeros y la precisin de los clculos slo estn limitadas por el espacio de almacenamiento.
Nmeros en formato ASC (Cdigo Estndar Americano para ntercambio de nformacin)
Muy similar al formato BCD desempaquetado es almacenar nmeros en formato ASC. Los dgitos
del 0 al 9 se almacenan utilizando su representacin en ASC. Este es un formato muy antiguo,
desarrollado y optimizado para los teletipos, innecesariamente complicado para el uso con ordenador
y muy limitado para un rango de distintos idiomas (slo 7 bits por carcter). Hoy en da todava se
utiliza mucho en las comunicaciones debido a que no se ha echo un esfuerzo por parte de los progra-
madores de sistemas operativos para encontrar un sistema de caracteres ms eficaz. Este antiguo
sistema slo es superado por el conjunto de caracteres de teletipo europeo de 5 bits llamado Baudot
o por el cdigo Morse, que todava es utilizado por algunas personas de dedos nerviosos.
En el sistema de cdigo ASC el dgito 0 decimal es representado por el nmero 48 (0x30 hexadeci-
mal, 0b0011.0000 binario) y el dgito 9 por el 57 (0x39 hexadecimal, 0b0011.1001 binario). ASC no
fue diseado al principio para tener estos nmeros en el conjunto de cdigo ya que existen caracte-
res instruccin como EOT (%nd +f Transmission$ para el teletipo. As que hay que sumar 48 a un BCD
(o establecer los bits 4 y 5 a 1) para convertir un BCD a ASC. Cargar el nmero 250 a un conjunto
de registros que representaran a este nmero se vera asi:
0DI R181T2T
0DI R1<1T5T
0DI R161T)T
La representacin ASC de estos caracteres se escribiran en los registros.
Manipulacin de bits
Para convertir un nmero BCD en su representacin en ASC necesitamos establecer los bits 4 y 5 a
1. En otras palabras, necesitamos hacer una operacin OR al BCD con un valor constante 0x30
hexadecimal. En ensamblador esto se hace as:
/RI R161)?;)
Si tenemos un registro que ya est establecido en 0x30 hexadecimal podemos hacer el OR con este
registro para convertir el BCD:
/R R11R2
Traer un carcter ESC de un BCD es tambin fcil. La instruccin
AFDI R161)?)F
87
aisla los 4 bits bajos (=el nibble inferior). Tenga en cuenta que OR y AND slo son posibles con
registros por encima de R15, utilice los registros desde R16 a R31.
Si el valor hexadecimal 0x0F ya est en el registro R2, puede hacer AND al carcter ASC con este
registro:
AFD R11R2
Las otras instrucciones para manipulacin de bits en un registro tambin estn limitadas para los
registros por encima de R15. Se formularan de esta manera:
9:R R161)"))11)))) ;poner "its ( D 5 # !no
C:R R161)"))11)))) ;poner "its ( D 5 # *ero
Si uno o ms bits de un byte tienen que ser invertidos puede utilizar la siguiente instruccin (que no
es vlida para usarla con una constante):
0DI R161)"1)1)1)1) ;invertir todos los "its imp#res
E/R R11R16 ;en el re$istro R1 $!#rd#ndo el res!lt#do en el mismo
Para invertir todos los bits de un byte (se llama complemento a uno):
C/M R1
que invierte el contenido en el registro R1 y reemplaza los ceros por uno y viceversa. A diferencia de
que del complemento a dos, que convierte un nmero positivo con signo a su complemento negativo
(restando de cero). Esto se hace con la instruccin:
FEG R1
As que +1 (decimal: 1) produce -1 (1.1111111 en binario), +2 produce -2 (1.1111110 en binario), y as
sucesivamente.
Adems de la manipulacin de los bits en un registro, es posible la copia de un slo bit con el
denominado T-bit del registro de estado. Con
:9T R11)
el bit T se carga con una copia del bit 0 del registro R1. El bit T puede ser activado o desactivado y su
contenido se puede copiar a cualquier bit de cualquier registro:
C0T ;poner # *ero el TU"it1 o
9ET ;poner # 1 el TU"it1 o
:0D R212 ;*opi#r el TU"it #l "it 2 del re$istro R2
Desplazamiento y rotacin
El desplazamiento y la rotacin de nmeros binarios se hace mediante el mtodo de multiplicar y
dividir por dos. El desplazamiento tiene varias sub-instrucciones.
La multiplicacin por dos se realiza desplazando todos los bits de un byte una posicin a la izquierda
y escribiendo un cero en el bit menos significativo. Esto se conoce como desplazamiento lgico a la
izquierda o LSL (logical shift left). El antiguo bit 7 del byte se lleva al bit de acarreo del registro de
estado.
090 R1
83
La divisin inversa por dos es la instruccin llamada LSR (logical shift right) desplazamiento lgico a
la derecha.
09R R1
Aqu, en el antiguo bit 7, que ahora es el bit 6, se pone un cero, y el antiguo bit de la posicin 0 se
lleva al bit de acarreo del registro de estado. El bit de acarreo puede ser utilizado para redondear
hacia arriba y hacia abajo (Si est en 1 se suma 1 al resultado). Por ejemplo, la divisin por cuatro
con redondeo:
LSR R1 ;divisin por 2
BRCC Div2 ;saltar si no se redondea
NC R1 ;redondear
Div2:
LSR R1 ;otra vez divisin por 2
BRCC DivE ;saltar si no se redondea
NC R1 ;redondear
DivE:
As, la divisin es fcil con los binarios siempre y cuando se divida por mltiplos de 2.
Si se usan enteros con signo, el desplazamiento lgico a la derecha sobreescribir el bit 7 de signo.
La instruccin ASR (arithmetic shift right) desplazamiento aritmtico a la derecha, deja al bit 7 sin
tocar, desplazando los 7 bits bajos e inserta un cero en el bit 6.
ASR R1
Al igual que con el desplazamiento lgico, el antiguo bit 0 se lleva al bit de acarreo del registro de
estado.
Qu hay acerca de multiplicar por 2 una palabra de 16 bits? El bit ms significativo del byte menor
se desplaza para obtener el bit ms bajo del byte mayor. En este paso se establece el bit ms bajo a
cero, pero tenemos que cambiar el bit de acarreo del paso anterior del byte inferior por el bit 0 del
byte superior. Esto se denomina rotacin. Durante la rotacin, el bit de acarreo del registro de estado
se desplaza al bit 0 y el antiguo bit 7 se desplaza al bit de acarreo.
LSL R1 ;Desplazamiento lgico a la izquierda del byte inferior
ROL R2 ;Rotacin a la izquierda del byte superior (Rotate Left)
La primera instruccin es el desplazamiento lgico a la izquierda que desplaza el bit 7 al bit de
acarreo. La instruccin ROL rota el bit 0 del byte superior. Despus de la 2 instruccin el bit de
acarreo tiene el antiguo bit 7 del byte superior, que puede ser utilizado tanto para indicar un exceso
de capacidad o desbordamiento (en el caso de clculos de 16 bits) o para rotar en siguientes bytes
superiores (si los clculos son de ms de 16 bits).
Tambin es posible la rotacin a la derecha, dividiendo por 2 y desplazando al acarreo el bit 7 del
resultado:
LSR R2 ;desplazamiento lgico a la derecha, el bit 0 al acarreo
ROR R1 ;Rotacin a la derecha y desplazar el bit al acarreo
Como se ve es fcil dividir con nmeros grandes y el aprendizaje de ensamblador no es tan
complicado.
La ltima instruccin, ROR (Rotate Right), se utiliza con mucha frecuencia para desplazar cuatro bits
en un solo paso con los paquetes BCDs. Esta instruccin cambia un nibble superior por el inferior y
viceversa. En el ejemplo tenemos que cambiar el nibble superior a la posicin del nibble inferior. En
85
lugar de hacer
ROR R1
ROR R1
ROR R1
ROR R1
se puede hacer con una sola instruccin
SWAP R1
Esta instruccin intercambia el nibble superior por el nibble inferior. Tener en cuenta que el contenido
del nibble superior ser diferente segn se aplique uno u otro de estos dos mtodos.
Sumar, restar y comparar
Sumar y restar nmeros de 16 bits
Para empezar complicadamente, se van a sumar dos nmeros de 16 bits en los registros R1:R2 y
R3:R4 (en esta notacin, el primer registro es el byte ms significativo y el segundo el menos
significativo).
ADD R2,R4 ;primero se suman los dos bytes bajos
ADC R1,R3 ;a continuacin los dos bytes bajos+
En lugar de un segundo ADD usamos ADC en la segunda instruccin, que significa sumar y llevar o
acarrear, que se establece o no durante la primera instruccin, en funcin del resultado.
Para restar R3:R4 de R1:R2
SUB R2,R4 ;primero el byte bajo
SBC R1,R3 ;despus el byte alto
Otra vez el mismo truco: en la segunda instruccin restamos otro 1 si en el resultado de la primera ha
habido un exceso de capacidad o desbordamiento.
Comparar nmeros de 16 bits
Ahora comparamos la palabra de 16 bits en R1:R2 con la que hay en R3:R4 para evaluar si es ms
grande. En lugar de SUB utilizamos la instruccin de comparacin CP y en lugar de SBC utilizamos
CPC:
CP R2,R4 ;compara los bytes bajos
CPC R1,R3 ;compara los bytes altos
Si ahora se establece o pone a 1 la bandera de acarreo R1:R2 es ms pequeo que R3:R4.
Comparar con constantes
Ahora se compara el contenido del registro R16 con una constante: 0b10101010.
CP R16,0xAA
Si despus de esta operacin el bit Zero del registro de estado se establece en 1, el registro R16 es
igual a 0xAA. Si se establece el bit de acarreo, como ya sabemos, es que es ms pequeo. Si no se
ha establecido ninguno de estos dos bits en el registro de estado, es que es ms grande.
8@
Para comprobar si por ejemplo R1 es cero o negativo
TST R1
Si se establece en 1 el Z-bit, el registro R1 es cero y podemos seguir con las instrucciones BREQ,
BRNE, BRM, BRPL, BRLO, BRSH, BRGE, BRLT, BRVC o BRVS de ramificacin alrededor de un
pequeo bit.
Matemticas con paquetes BCD
Ahora algunos clculos con paquetes BCD. La suma de dos paquetes BCD puede dar lugar a dos
desbordamientos distintos. El acarreo habitual muestra un exceso de capacidad, si el nibble mayor
es ms de 15 decimal. El otro desbordamiento se produce del nibble inferior al superior, si al sumar
dos nibbles bajos da ms de 15 decimal.
Por ejemplo, podemos sumar 2 BCDs empacados como 49 (=hex 49) y 99 (=hex 99) para producir
148 (=hex 148). Esta suma en clculo binario da como resultado un byte con un valor hexadecimal
de 0xE2, sin producirse desbordamiento del byte. Pero en el nibble inferior si se produce
desbordamiento porque 9+9=18 y el nibble inferior solo puede manejar nmeros hasta 15. El
desbordamiento se aade al bit 4, el bit menos significativo del nibble superior, que es correcto, pero
el nibble inferior debe estar en 8 y est a slo 2 (18 = 0b0001.0010). Hay que sumar 6 a dicho nibble
para obtener el resultado correcto. Esto es lgico porque cada vez que el nibble inferior alcanza ms
de 9 hay que sumarle 6 para corregirle.
El nibble superior es totalmente incorrecto, porque es 0xE y debe ser de 3 (con un desbordamiento
en el siguiente dgito superior del BCD empacado). Si sumamos 6 a 0xE obtenemos 0x4 y se esta-
blece el acarreo (=0x14). As que el truco est en primero sumar estos dos nmeros y a continuacin
aadir 0x66 para corregir los 2 dgitos del BCD empacado. Pero un momento, y si la suma del
primer y segundo nmero no da lugar a un desbordamiento del siguiente nibble, es decir no da una
cifra superior a 9 en el nibble inferior? Aadir 0x66 producira entonces un resultado totalmente
incorrecto. Solamente se le aade 6 al nibble inferior si este se desborda al nibble superior por una
cifra superior a 9. Lo mismo con el nibble superior.
Cmo sabemos si se produce un desbordamiento del nibble inferior al superior? El MCU establece a 1
el bit H en el registro de estado, que es el bit de acarreo a la mitad. A continuacin se muestra el algo-
ritmo para los diferentes casos posibles despus de sumar dos nibbles y despus de sumar 0x6 hex.
1. Sumar los nibbles. Si ocurre un desbordamiento (C para el nibble superior o H para el nibble
inferior) sumar 6 para corregir, sino, hacer el paso 2.
2. Sumar 6 al nibble. Si ocurre un desbordamiento (C resp. H) ya est hecho. Si no, restar 6.
Para programar un ejemplo, supongamos que tenemos 2 BCDs empacados en R2 y R3, R1 realizar
el desbordamiento y R16 y R17 estn disponibles para los clculos. R16 es el registro de la adicin pa-
ra sumar 0x66 (con el registro R2 no se puede sumar un valor constante) y R17 se utiliza para corregir
el resultado en funcin de las correspondientes banderas. La suma de R2 y R3 se podra ver as:
0DI R161)?66 ;p#r# s!m#r )?66 #l res!lt#do
0DI R1<1)?66 ;p#r# l!e$o rest#r del res!lt#do
ADD R21R; ;sumar los dos digitos BCDs
:RCC FoCD1 ;saltar a NoCy1 si no se produce desbordamiento de byte
IFC R1 ;incrementar el siguiente byte superior
AFDI R1<1)?)F ;no rest#r 6 #l ni""le #lto
FoCD1@
:R4C Fo4*1 ;ir si no ha ocurrido un acarreo a la mitad
AFDI R1<1)?F) ;no rest#r 6 del ni""le "#Jo
Fo4*1@
88
ADD R21R16 ;sumar 0x66 al resultado
:RCC FoCD2 ;ir si no a habido acarreo
IFC R1 ;incrementar el siguiente byte superior
AFDI R1<1)?)F ;no rest#r 6 del ni""le #lto
FoCD2@
:R4C Fo4*2 ;ir si no ha ocurrido un acarreo a la mitad
AFDI R1<1)?F) ;no restar 6 del nibble bajo
Fo4*2@
9&: R21R1< ;rest#r l# *orre**i+n
Un poco ms corto:
ADD R21R16
ADD R21R;
:RCC FoCD
IFC R1
AFDI R161)?)F
FoCD@
:R4C Fo4*
AFDI R161)?F)
Fo4*@
9&: R21R16
Pregunta para pensar: Por qu es igualmente correcto, la mitad de corto y menos complicado, y
dnde est el truco?
Conversin de formato de nmeros
Cualquier formato numrico se puede convertir a cualquier otro formato. Ya se vi anteriormente la
conversin de BCD a ASC (manipulacin de bits). Ahora veremos otras.
Conversin de BCD empacado a BCD, ASC o Binario
La conversin de paquetes BCD no es complicada. Primero tenemos que copiar el nmero a otro
registro. Al valor copiado le intercambiamos los nibbles con la instruccin SWAP. La parte superior se
despeja a cero por ejemplo hacindole una operacin AND con 0x0F y nos queda el nibble el antiguo
nibble superior que se puede utilizar tal cual (BCD) o estableciendo el bit 4 y 5 a 1 para convertirlo al
juego de caracteres ASC. Despus volvemos a copiar el byte y tratamos con el nibble inferior sin
hacerle intercambio como antes y obtenemos el BCD inferior.
La conversin de dgitos BCD a binario es ms complicada. Dependiendo de los nmeros que se ma-
nejen, primero hay que despejar a cero los bytes necesarios para hacer la conversin. A continuacin
comenzamos con los dgitos BCD ms altos que hay que multiplicarlos por 10. Con el fin de hacer esta
multiplicacin, hay que copiar el resultado en otro lugar. A continuacin se multiplica el resultado por 4
(dos desplazamientos a la izquierda). Sumando el nmero copiado anteriormente a esto produce una
multiplicacin por 5. Ahora, una multiplicacin por 2 (un desplazamiento a la izquierda) produce el re-
sultado multiplicado por 10. Por ltimo se aade el BCD y se repite el algoritmo hasta que se han con-
vertido todos los dgitos decimales. Si durante una de estas operaciones se produce un acarreo del re-
sultado, el BCD es demasiado grande para ser convertido, por lo que este algoritmo maneja nmeros
de cualquier longitud, siempre y cuando estn preparados los registros para los resultados.
[Conversin de un nmero decimal de 5 digitos en BCD a binario natural de 16 bits.
;El mximo nmero a convertir ser pues el b'1111111111111111'=0xFFFF=d'65535'
; El metodo usado para la conversin de un nmero BCD a binario natural, se basa en que cada
dgito de un nmero codifcado en BCD tiene un peso igual a la potencia de diez asociada a su
posicin. ara convertir el nmero BCD a su equivalente binario slo es necesario multiplicar cada
dgito BCD por su peso correspondiente ! luego sumar todos los productos parciales obtenidos, el
resultado es el nmero binario natural buscado.
89
; Es decir el valor de un nmero B! de 5 d"#itos se puede expresar como$
;
10%& !ecenas'illar ( 10%3 'illares ( 10%) entenas ( 10 !ecenas ( *nidades =
10+10+10+10 !ecenas'illar ( 10+10+10 'illares ( 10+10 entenas ( 10 !ecenas (
*nidades
;
; Finalmente una subrutina aplica el si#uiente al#oritmo$
10,10,10,10 !ecenas'illar ( 'illares- ( entenas- ( !ecenas- ( *nidades = .esultado
;
; El resultado se obtiene en 16 bits/ es decir en ) re#istros de 0 bits1]
Conversin de binario a BCD
La conversin de binario a BCD es menos complicado. Para convertir 16 bits en binario restamos
10.000 (0x2710) hasta que se produce un desbordamiento, dando el primer dgito. A continuacin
repetimos con 1.000 (0x03E8) dando el segundo dgito y as sucesivamente con 100 (0x0064), 10
(0x000A) y el resto es el ltimo dgito. Las constantes 10.000, 1.000, 100 y 10 se pueden almacenar
en palabras en la memoria de programa y organizadas en una tabla:
DezTab:
.DW 10000, 1000, 100, 10
y as pueden ser ledas de la tabla por palabra con la instruccin LPM.
Una alternativa es una tabla que contenga el valor decimal de cada bit en 16 bits binarios:
.DB 0,3,2,7,6,8
.DB 0,1,6,3,8,4
.DB 0,0,8,1,9,2
.DB 0,0,4,0,9,6
.DB 0,0,2,0,4,8 ;y as sucesivamente hasta
.DB 0,0,0,0,0,1
A continuacin se cambian los bits individuales en binario desplazando hacia el registro de la izquierda
el acarreo. Si es un uno, se suma al nmero de la tabla resultado de la instruccin LPM. Esto es ms
complicado de programar y un poco ms lento.
Un tercer mtodo consiste en calcular el valor de la tabla partiendo de 000001, mediante la suma del
BCD consigo mismo, cada vez despus de haber cambiado a la derecha un bit al binario y sumndole
el resultado BCD.
Hay varios mtodos y hay que aplicar el ms optimo.
Multiplicacin
Para multiplicar 2 binarios de 8 bits, se puede hacer como con nmeros decimales:
1234 * 567 = ?
--------------------------------------------
1234 * 7 = 8638
+ 1234 * 60 = 74040
+ 1234 * 500 = 617000
--------------------------------------------
1234 * 567 = 699678
=========================
84
Estos son los pasos del ejemplo:
Se multiplica el primer nmero por la cifra menos significativa del segundo nmero.
Se vuelve a multiplicar el primer nmero por 10 y por el siguiente dgito significativo del
segundo nmero y se suma el resultado al anterior.
Y se vuelve a multiplicar el primer nmero por 100 y por el siguiente dgito (ahora el ms
significativo) del segundo nmero y se suma el resultado al anterior obtenindose el resultado
final.
Multiplicacin binaria
Ahora en binario. La multiplicacin por 10 en decimal lleva a la multiplicacin por 2 en binario. Esta
multiplicacin se hace facilmente ya sea por la suma de la cantidad a si misma o bien por el despla-
zamiento de todos los bits una posicin a la izquierda y aadiendo un cero a la derecha.
Programa en ensamblador AVR
En el cdigo fuente siguiente se muestra la multiplicacin en ensamblador.
; M!lt8.#sm m!ltipli*# 2 nLmeros de 8 "its prod!*iendo !n res!lt#do de 16 "its
;
.F/0I9T
.IFC0&DE =C@M#vrtoolsM#ppnotesM8515de.in*=
.0I9T
;
; Fl!Jo de l# m!ltipli*#*i+n
;
; 1.0os "in#rios m!ltipli*#dos se despl#E#n "it # "it en el "it de #*#rreo. 9i es !n !no se s!m# #l res!lt#do D
; si no es !no *#m"i# de posi*i+n D no se s!m#
; 2.El nLmero "in#rio se m!ltipli*# por 2 D se despl#E# !n# posi*i+n # l# iE'!ierd# poniendo !n *ero en l#
; posi*i+n dere*># '!e '!ed# v#*B#.
; ;.9i el "in#rio # m!ltipli*#r no es *ero1 se repite el *i*lo.
;
; Registros usados
;
.DEF rm1 = R) ; el nLmero "in#rio # m!ltipli*#r 58 :it7
.DEF rm> = R1 ; almacenamiento temporal
.DEF rm2 = R2 ; el nLmero "in#rio *on el '!e se v# # m!ltipli*#r 58 :it7
.DEF rel = R; ; Res!lt#do 09: 516 :it7
.DEF re> = R( ; Res!lt#do1 M9:
.DEF rmp = R16 ; Re$istro m!ltiprop+sito p#r# l# *#r$#
;
.C9EG
./RG ))))
;
rJmp 9TART
;
9TART@
ldi rmp1)?AA ; eJemplo "in#rio 1)1).1)1)
mov rm11rmp ; ten el primer re$istro
ldi rmp1)?55 ; eJemplo "in#rio )1)1.)1)1
mov rm21rmp ; en el segundo registro
;
; Aqu empieza la multiplicacin de los dos binarios en rm1 y rm2, el resultado ir a reh:rel (16 bits)
;
M&0T8@
;
; V#lores de ini*io despeJ#dos # *ero
*lr rm> ; almacenamiento temporal despejado
*lr rel ; registros de resultados despejados
*lr re>
8?
;
; Aqu comienza el ciclo de multiplicacin
;
M&0T8#@
;
; .#so 1@ se rot# el "it mQs "#Jo del se$!ndo nLmero "in#rio # l# "#nder# de #*#rreo 5se divide por 2 D se rot#
; !n *ero #l "it <7
;
*l* ; a cero el bit de acarreo
ror rm2 ; bit 0 al acarreo, bits 1 a 7 una posicin a la derecha, el valor en el acarreo al bit 7
;
; .#so 2@ :i!r*#*i+n dependiendo si es !n *ero o !n !no lo '!e se ># rot#do #l "it de #*#rreo
;
"r** M&0T8" ; saltar la suma si el acarreo es cero
;
; .#so ;@ 9!m#r los 16 "its en rm>@rml #l res!lt#do *on el des"ord#miento desde el 09: #l M9:
;
#dd rel1rm1 ; sumar el LSB de rm1 al resultado
#d* re>1rm> ; sumar el acarreo y el MSB a rm1
;
M&0T8"@
;
; .#so (@ M!ltipli*#r rm>@rm1 por 2 516 "its1 despl#E#miento # l# iE'!ierd#7
;
*l* ; # *ero el "it de #*#rreo
rol rm1 ; rot#r 09: # l# iE'!ierd# 5m!ltipli*#r por 27
rol rm> ; desplazar el MSB una posicin a la izquierda y llevar el acarreo
;
; .#so 5@ Compro"#r si tod#vB# >#D !nos en el se$!ndo nLmero "in#rio D si los >#D1 # m!ltipli*#r
;
tst rm2 ; VTodos los "its # *eroW
"rne M&0T8# ; si no, seguir en el bucle
;
; Fin#liE#*i+n del# m!ltipli*#*i+n1 res!lt#do en re>@rel
;
; "!*le sin in
;
0//.@
rJmp loop
Rotacin binaria
Para entender la operacin de multiplica-
cin, es necesario comprender las instruc-
ciones de rotacin binaria ROL y ROR.
Estas instrucciones desplazan todos los bits
de un registro una posicin a la izquierda
(ROL) o a la derecha (ROR). La posicin
que queda vaca se llena con el contenido
del bit de acarreo del registro de estado y el
bit que sale del registro se desplaza al bit de
acarreo. Esta operacin se demuestra
utilizando 0xAA como ejemplo para ROL, y
0x55 como ejemplo para ROR.
Hardware de multiplicacin
Todos los ATmega, ATXmega, AT90CAN y AT90PWM incluyen un multiplicador de hardware que
puede llevar a cabo multiplicaciones de 8 bits en slo dos ciclos de reloj. As que cuando haya que
hacer multiplicaciones y el software no necesite ejecutarse en chips AT90S -o ATtiny-, se puede
8:
utilizar esta caracterstica de hardware.
A continuacin se muestra cmo multiplicar
binarios 8 por 8
" 16 por 8
" 16 por 16
" 16 por 24
Multiplicacin por hardware de binarios 8 por 8
Se hace de forma simple y directa: Si
los dos binarios que se van a mul-
tiplicar estn en los registros R16 y
R17 slo hay que poner
mul R16,R17

El resultado de la multiplicacin de es-
tos dos binarios de 8 bits pude ser de
hasta 16 bits de longitud, por lo que el
resultado se escribir en los registros
R1 (byte ms significativo) y R0 (byte
menos significativo). Esto es todo.
El programa muestra la simulacin en
el software Studio. Se multiplica el
decimal 250 (hex FA) por el decimal
100 (hex 64), en los registros R16 y
R17.
Despus de la ejecucin, los registros
R0 (LSB) y R1 (MSB) contienen el
nmero 61A8 hex. o
25.000 decimal.
Y si. Slo requiere dos
ciclos, o 2 microsegundos
con un reloj a 1 Mcs/s.
Multiplicacin por hard-
ware de binarios 16 por 8
Hay que multiplicar un
binario ms grande? El
hardware est limitado a
8, por lo que tenemos que emplear algunas buenas ideas. Para resolver el problema con binarios
mayores vamos a ver en primer lugar la combinacin de 16 y 8. La comprensin de este concepto
ayuda a entender el mtodo por el que ser capaz de resolver ms tarde el problema de la
multiplicacin de 32 por 64 bits.
Primero las matemticas: un binario de 16 bits m1M:m1L es simplemente dos binarios de 8 bits m1M
y m1L, donde el byte ms significativo m1M es multiplicado por 256 decimal o por 100 hex.
Recordemos por ejemplo que el decimal 1234 es simplemente (12 multiplicado por 100) ms 34, o )1
multiplicado por mil) ms (2 multiplicado por 100) ms (3 multiplicado por 10) y ms 4.
8=
As que el binario de 16 bits m1 es igual a
256*m1M ms m1L, donde miM es el MSB y
m1L es el LSB. Multiplicar m1 por un binario
de 8 bits m2 es formulado matemticamente:
- m1 * m2 = (256*m1M + m1L) * m2,
- 256*m1M*m2 + m1L*m2.
As que slo tenemos que hacer dos multiplicaciones y sumar ambos resultados. Si ves tres
asteriscos en la frmula, se siente: la multiplicacin por 256 en el mundo binario no requiere ningn
hardware en absoluto, porque es un simple movimiento en el byte de orden superior. Al igual que la
multiplicacin en el mundo decimal se hace simplemente moviendo el primer nmero a la izquierda y
escribiendo un cero como dgito menos significativo.
Vamos a un ejemplo prctico. Primero necesitamos algunos registros para
Cargar los nmeros m1 y m2,
proporcionar espacio para el resultado que podra tener 24 bits de longitud.
;
; .r!e"# de m!ltipli*#*i+n por >#rdR#re 16 por 8 "its
;
; Deini*i+n de los re$istros@
;
.de Res1 = R2
.de Res2 = R;
.de Res; = R(
.de m10 = R16
.de m1M = R1<
.de m2 = R18
Primero cargamos los nmeros:
;
; C#r$#ndo los re$istros
;
.e'! m1 = 1))))
;
ldi m1M14IG45m17 ;8 "its #ltos de m1 en m14
ldi m1010/85m17 ;8 "its "#Jos de m1 en m10
ldi m2125) ;*onst#nte de 8 "its en m2
Los dos nmeros se cargan en R17:R16 (10000 decimal = 2710 hex) y R18 (250 dec = FA hex).
A continuacin, primero se multiplica el LSB:
;
; M!ltipli*#ndo
;
m!l m101m2 ;m!ltipli*#ndo el 09:
mov Res11R) ;copiando el resultado al registro de resultado
mov Res21R1
97
La multiplicacin del LSB, 10 hex por FA hex produce
0FA0 hex, que se escribe en los registros R0 (LSB A0
hex) y R1 (MSB 0F hex). El resultado se copia en los
bytes inferiores del registro de resultado, R3:R2.
Multiplicacin del MSB de m1 por m2:
m!l m1M1m2 ;m!ltipli*#ndo el M9:
La multiplicacin del MSB de m1, 27 hex, por m2, FA
hex, produce 2616 hex en R1:R0
Ahora se realizan dos pasos a la vez, la multiplicacin
por 256 y sumar el resultado con el anterior. Esto se
hace mediante la suma de R1:R0 a Res3:Res2 en lugar
de a Res2:Res1. R1 slo se puede copiar a Res3 y
entonces R0 se suma Res2. Si se establece el acarreo
despus de la suma, el siguiente byte alto Res3 se
incrementa en uno.
mov Res;1R1 ;*opi# el M9: #l res!lt#do del "Dte ;
#dd Res21R) ;D s!m#r el 09: #l res!lt#do del "Dte 2
"r** FoIn* ;si no >#D #*#rreo1 s#lt#r
in* Res;
FoIn*@
El resultado en R4:R3:R2 es 2625A0 hex, 2500000 en
decimal, lo que es obviamente correcto.
Adems, estas operaciones consumen 10 ciclos que con
un reloj de 1 Mhz son 10 microsegundos. Mucho ms
rpido que la multiplicacin por software.
Multiplicacin por hardware de binarios 16 por 16
Ahora que tenemos claros los principios, debera ser
fcil hacer 16 por 16. El resultado ahora requiere 4 bytes
(Res4:Res3:Res2:Res1, ubicados en R5:R4:R3:R2). La
frmula sera:
m ; m<=(<>?;m# @ m-$ ;
(<>?;m<# @ m<-$
=?>>A?;m#;m<# @
<>?;m#;m<- @
<>?;m-;m<# @
m-;m<-
Obviamente ahora hay que hacer 4
multiplicaciones. Comenzamos con la
primera y la ltima que son las ms
sencillas: sus resultados simplemente
se copian en las posiciones correctas
de los respectivos registros de resul-
tado. Los resultados de las multiplica-
ciones de en medio se aadirn a los
93
registros de resultado tambin de en medio llevndonos los posibles acarreos al byte ms significa-
tivo. Para esto hay un simple truco fcil de entender:
;
; .r!e"# de m!ltipli*#*i+n >#rdR#re 16 por 16
;
; Deini*i+n de re$istros
;
.de Res1 = R2
.de Res2 = R;
.de Res; = R(
.de Res( = R5
.de m10 = R16
.de m1M = R1<
.de m20 = R18
.de m2M = R1-
.de tmp = R2)
;
; Cargar valores de entrada
;
.e'! m1 = 1))))
.e'! m2 = 25)))
;
ldi m1M14IG45m17
ldi m1010/85m17
ldi m2M14IG45m27
ldi m2010/85m27
;
; M!ltipli*#ndo
;
*lr R2) ;DespeJ#r p#r# #*#rreo
m!l m1M1m2M ;M!ltipli*#r M9:s
mov Res;1R) ;*opD to M98 Res!lt
mov Res(1R1
m!l m101m20 ;M!ltipli*#r 09:s
mov Res11R) ;*opD to 098 Res!lt
mov Res21R1
m!l m1M1m20 ;M!ltipli*#r 1M *on 20
#dd Res21R) ;9!m#r #l res!lt#do
#d* Res;1R1
#d* Res(1tmp ;s!m#r #*#rreo
m!l m101m2M ;M!ltipli*#r 10 *on 2M
#dd Res21R) ;9!m#r #l res!lt#do
#d* Res;1R1
#d* Res(1tmp
;
; M!ltipli*#*i+n >e*>#
;
La simulacin muestra los siguientes pasos:
La carga de dos constantes 10000 (2710 hex) y 25000
(61A8 hex) en los registros del espacio superior de
registros...
Multiplicacin de los dos MSBs (27 y 61 hex) y copia del
resultado a los registros R1:R0 desde los registros de
resultado superior R5:R4...
95
Multiplicacin de los dos LSBs (10 y A8 hex) y copia del resultado en R1:R0 desde los registros de
resultado inferior R3:R2...
Multiplicacin del MSB de m1 con el LSB de m2 y suma del resultado en R1:R0 de los registros de
resultado de los bytes del medio. No hay acarreo...
Multiplicacin del LSB de m1 con el MSB de m2
y suma del resultado en R1:R0 de los registros
de resultado de los bytes del medio. No hay
acarreo. El resultado es 0EE6B280 hex,
250000000 decimal, obviamente correcto.
Para esta multiplicacin son necesarios 19 ciclos
de reloj, que es mucho ms rpido que el
software de multiplicacin.
Tambin: el tiempo requerido ser siempre de
exactamente 19 ciclos y no depende de los n-
meros de entrada, como pasa con la multiplica-
cin por software que produce acarreo, en la que
hay que aadir un cero.
Multiplicacin por hardware de binarios 16 por 24
La multiplicacin de un binario
de 16 bits 'a' con un binario de
24 bits 'b' produce resultados
con una longitud de hasta 40
bits. El esquema de multiplica-
cin requiere seis multiplica-
ciones de 8 por 8 bits suman-
do los resultados en la posi-
cin apropiada de los registros
de resultados.
Cdigo fuente en ensamblador:
; M!ltipli*#*i+n >#rdR#re 16 por 2(
.in*l!de =m8de.in*=
;
; Deini*i+n de re$istros
.de #1 = R2 ; deine 16U"it re$ister
.de #2 = R;
.de "1 = R( ; deine 2(U"it re$ister
.de "2 = R5
.de "; = R6
.de e1 = R< ; deine ()U"it res!lt re$ister
.de e2 = R8
.de e; = R-
.de e( = R1)
.de e5 = R11
.de *) = R12 ; re$istro de #D!d# p#r# s!m#r
.de rl = R16 ; re$istro de *#r$#
;
9@
; C#r$# de *onst#ntes
.e'! # = 1)))) ; m!ltipli*#dor #1 >e? 2<1)
.e'! " = 1)))))) ; m!ltipli*#dor "1 >e? )F(2()
ldi rl1:HTE15#7 ; *#r$# de #
mov #11rl
ldi rl1:HTE25#7
mov #21rl
ldi rl1:HTE15"7 ; *#r$# de "
mov "11rl
ldi rl1:HTE25"7
mov "21rl
ldi rl1:HTE;5"7
mov ";1rl
;
; DespeJ#r re$istros
*lr e1 ; DespeJ#ndo re$istros de res!lt#dos
*lr e2
*lr e;
*lr e(
*lr e5
*lr *) ; DespeJ#ndo re$istro de #D!d#
;
; M!ltipli*#*i+n
m!l #21"; ; tXrmino 1
#dd e(1R) ; s!#mndo #l res!lt#do
#d* e51R1
m!l #21"2 ; tXrmino 2
#dd e;1R)
#d* e(1R1
#d* e51*) ; 5s!m#ndo posi"le #*#rreo7
m!l #21"1 ; tXrmino ;
#dd e21R)
#d* e;1R1
#d* e(1*)
#d* e51*)
m!l #11"; ; tXrmino (
#dd e;1R)
#d* e(1R1
#d* e51*)
m!l #11"2 ; tXrmino 5
#dd e21R)
#d* e;1R1
#d* e(1*)
#d* e51*)
m!l #11"1 ; tXrmino 6
#dd e11R)
#d* e21R1
#d* e;1*)
#d* e(1*)
#d* e51*)
;
; >e*>o.
nop
; El res!lt#do de"e ser )25():E()) >e?
La ejecucin completa requiere
10 ciclos de reloj para la carga de las constantes,
6 ciclos de reloj para despejar (poner a cero) los registros y
98
33 ciclos de reloj para la multiplicacin.
Divisin
No, desafortunadamente no existe divisin por hardware, hay que hacerlo por software.
Divisin decimal
Comenzamos con la divisin decimal para comprender mejor la divisin binaria. Se parte de dividir
por ejemplo, 5678 entre 12:
5678 : 12 = ?
-----------------------------------
- 4 * 1200 = 4800
--------
878
- 7 * 120 = 840
------
38
- 3 * 12 = 36
----
2
Resultado 5678 : 12 = 473 con Resto 2
================================
Divisin Binaria
En binario, la multiplicacin del segundo nmero como en el ejemplo decimal anterior no es necesa-
ria debido al hecho de que slo tenemos 0 y 1 como dgitos. Los nmeros binarios tienen mucha ms
cantidad de dgitos que su equivalente decimal, por lo que la transferencia de la divisin decimal a su
equivalente binaria es un poco inconveniente. As que el programa funciona de una manera diferente.
La divisin de un nmero binario de 16 bits entre un binario de 8 bits en ensamblador AVR se
muestra en el siguiente cdigo:
; Div8 divide !n nLmero de 16 "its entre !n nLmero de 8 "its 5.r!e"#@ 16U"itUn!m"er@ )?AAAA1 8U"itUn!m"er@ ;
; )?557
.F/0I9T
.IFC0&DE =C@M#vrtoolsM#ppnotesM8515de.in*= ; ajuste la ruta correcta en su sistema!
.0I9T
; Re$istro
.DEF rd1l = R) ; 09: del nLmero de 16 "its '!e se divide
.DEF rd1> = R1 ; M9: del nLmero de 16 "its '!e se divide
.DEF rd1! = R2 ; registro provisional
.DEF rd2 = R; ; n!mero de 8 "its por el '!e se divide
.DEF rel = R( ; 09: res!ltado
.DEF re> = R5 ; M9: res!ltado
.DEF rmp = R16; registro multiproposito para carga
;
.C9EG
./RG )
rJmp st#rt
st#rt@
; C#r$#r los nLmeros en los re$istros #propi#dos
ldi rmp1)?AA ; )?AAAA a dividir
mov rd1>1rmp
mov rd1l1rmp
99
ldi rmp1)?55 ; )?55 por el que se divide
mov rd21rmp
; Divide rd1>@rd1l "D rd2
div8@
*lr rd1! ; despejar registro provisional
*lr re> ; 5los re$istros de res!lt#do
*lr rel ; tambin se utilizan para contar hasta 16 para los pasos de la divisin
in* rel ; se est#"le*e en 1 en el #rr#n'!e7
; Aqu comienza el ciclo de la divisin
div8#@
*l* ; despejar el bit de acarreo
rol rd1l ; rotar el bit superior siguiente del nmero
rol rd1> ; al registro provisional (se multiplica por 2)
rol rd1!
"r*s div8" ; se llev# !n !no # l# iE'!ierd#1 por lo '!e se rest#
*p rd1!1rd2 ; resultado de la divisin 1 0?
"r*s div8* ; s#lt#r l# rest# si es menor
div8"@
s!" rd1!1rd2; rest#r el nLmero por el '!e se divide
se* ; est#"le*er el "it de #*#rreo1 el res!lt#do es !n 1
rJmp div8d ; s#lt#r #l *#m"io del "it de res!lt#do
div8*@
*l* ; despeJ#r el "it de #*#rreo1 el "it res!lt#nte es !n )
div8d@
rol rel ; rot#r el "it de #*#rreo # los re$istros de res!lt#do
rol re>
"r** div8# ; mientr#s se# *ero se$!ir *on el *i*lo de divisi+n
; Fin de l# divisi+n
stop@
rJmp stop ; "!*le sin in
Pasos del programa durante la divisin
Definicin y seleccin de los registros para los nmeros binarios de la divisin
Preajuste del registro provisional y el par de registros de resultado (los registros de resultado
son preseleccionados en 0x0001).
El binario de 16 bits en rd1h:rd1l se rota bit a bit al registro provisional rd1u (multiplicacin por
2) si se rota un 1 a rd1u, el programa bifurca al paso 4 de la resta inmediatamente,
el contenido del registro provisional se compara con el nmero de 8 bits en rd2, si este es ms
pequeo se resta del registro provisional y el bit de acarreo se establece a 1. Si rd2 es mayor,
no se hace la resta y el bit de acarreo se establece a 0,
el contenido de la bandera de acarreo se rota al registro de resultado reh:rel a la derecha,
si es un cero se rota fuera del registro de resultado y se repite el bucle de la divisin. Si es un 1
se ha completado la divisin.
Si no se entiende la rotacin, esta operacin est expuesta en la seccin de la multiplicacin.
Conversin de nmeros
En ensamblador es muy frecuente la conversin de nmeros porque en los procesadores el clculo
se hace en binario mientras que las personas en un terminal prefieren nmeros decimales. Para que
haya comunicacin desde el interior de una rutina en ensamblador con una persona, es necesaria la
conversin de nmeros. Hay que aprender un poco como se realiza la conversin entre diferentes
sistemas numricos.
Por favor consulte el sitio web en http://www.avr-asm-tutorial.net/avr_en/calc/CONVERSON.html
si usted necesita el cdigo fuente o una mejor comprensin.
Las fracciones decimales
94
Primero, no utilice punto flotante a menos que no quede ms remedio. El punto flotante deja sin
recursos al AVR y necesita un tiempo de ejecucin extremo. Si se encuentra en este dilema y piensa
que ensamblador es demasiado complicado puede preferir basic u otros lenguajes como C o Pascal.
Pero si no es as y prefiere utilizar ensamblador, aqu se muestra como realizar la multiplicacin con
nmeros reales de punto fijo en menos de 60 microsegundos e incluso, en casos especiales en 18
microsegundos, a 4 MHz de frecuencia de reloj, sin necesidad de trucos caros como extensiones de
procesador de punto flotante.
Esto se hace volviendo a las races de las matemticas. La mayora de las tareas con nmeros
reales de coma flotante se pueden hacer utilizando nmeros enteros. Con stos, es fcil y rpido
programar en ensamblador. El punto flotante se queda en el cerebro del programador y se aade en
algn lugar de la secuencia de dgitos decimales. Nadie se da cuenta y este es el truco.
Conversiones lineales
A modo de ejemplo: un convertidor AD de 8 bits toma muestras de una seal de entrada en el rango
desde 0,00 a 2,55 voltios y devuelve el resultado en sistema binario en el rango desde $00 a $FF. El
resultado, una tensin, se muestra en una pantalla LCD. Es un ejemplo muy fcil: el binario se
convierte a una cadena decimal ASC entre 000 y 255, y hay que insertar la coma decimal justo
detrs del primer dgito y ya est!
Pero el mundo de la electrnica es a veces ms complicado. Por ejemplo, el convertidor AD devuelve
un hexadecimal de 8 bits para la tensin de entrada de entre 0,00 y 5,00 voltios. Ahora nos
quedamos confusos y no sabemos como proceder. Para mostrar el resultado correcto en la pantalla
LCD, tendramos que multiplicar el binario por el resultado de la divisin 500/255, que es 1,9608.
Este es un nmero tonto ya que es casi 2, pero slo casi, y no queremos esta inexactitud de un 2%
mientras que tenemos un convertidor AD con un margen de error en torno a 0,25%. Para afrontar
esto, se multiplica la entrada por el resultado de 500 / 255 * 256, que es 501,96, y luego se divide por
256. Por qu primero se multiplica por 256 y luego se vuelve a dividir por 256? Para una mayor
precisin. Si multiplicamos la entrada por 502 en lugar de por 501,96, el error es del orden del
0,008%, suficiente para nuestro convertidor AD, podemos vivir con eso. Y dividir por 256 es una tarea
fcil, porque es una potencia muy conocida de 2. Al dividir con nmeros que son potencia de 2, el
AVR se encuentra cmodo y funciona muy rpido. Al dividir entre 256, el AVR es incluso ms rpido,
porque slo tenemos que quitar el ltimo byte del nmero binario, ni siquiera hay desplazamiento o
rotacin.
La multiplicacin de un binario de 8 bits con el binario de 9 bits 502 (1F6 hex) puede tener un
resultado superior a 16 bits, as que tenemos que reservar 24 bits o 3 registros para el mismo.
Durante la multiplicacin, la constante 502 se ha de desplazar a la izquierda (multiplicacin por 2)
para aadir estas cifras con el resultado y se hace un desplazamiento cada vez que cambia el
nmero de entrada. Como esto puede necesitar hasta 8 desplazamientos a la izquierda, necesitamos
otros tres bytes para esta constante. As que podemos optar por la siguiente combinacin de
registros para la multiplicacin:
N$mero Valor%e&emplo' (egistro
Valor de entrada 255 R1
multiplicando 502 R4:R3:R2
resultado 128,010 R7:R6:R5
Despus de colocar el valor 502 (00.01.F6) en los registros R4:R3:R2 y despejar los registros de
resultado R7:R6:R5, la multiplicacin es la siguiente:
1. Test, si el nmero de entrada es cero, hemos terminado.
9?
2. Si no, en el nmero de entrada se desplaza a la derecha un bit, que se lleva al acarreo y se
coloca un cero en el bit 7. Esta instruccin se llama Logical-Shift-Right o LSR.
3. Si el bit de acarreo es 1, le sumamos el multiplicando (en el paso 1 el valor es 502, en el
paso2 es 1004 y as sucesivamente) al resultado. Durante la suma no hay que olvidarse del
acarreo, (la suma de R2 a R5 con ADD, la suma de R3 a R6 y R4 a R7 con ADC). Si elbir de
acarreo es un cero, no se hace la suma del multiplicando con el resultado y se pasa el
siguiente paso.
4. Ahora el multiplicando se multiplica por 2, ya que el siguiente bit desplazado con respecto al
nmero de entrada vale tanto como el doble. Se desplaza R2 a la izquierda (mediante la
insercin de un cero en el bit 0) con LSL y el bit 7 se desplaza al acarreo. A continuacin se
rota el acarreo a R3, desplazando su contenido a la izquierda y el bit 7 al acarreo. Lo mismo
con R4.
5. As terminamos con un dgito del nmero de entrada y se procede con el paso 1 de nuevo.
El resultado de la multiplicacin por 502 ahora est en los registros de resultado R7:R6:R5. Si nos
limitamos a pasar por alto el registro R5 (divisin por 256), ya tenemos el resultado deseado. Para
mejorar la precisin, podemos usar el bit 7 de R5 para redondear el resultado. Ahora slo tenemos
que convertir el resultado de su forma binaria a decimal ASC. Si aadimos el punto decimal en el
lugar correcto de la cadena ASC, tenemos una cadena con el voltaje lista para ser mostrada en el
display.
El programa completo, desde el nmero de entrada hasta la cadena ASC resultante, requiere entre
79 y 288 ciclos de reloj, dependiendo del nmero de entrada. Una rutina de punto flotante como sta
en un lenguaje ms sofisticado que ensamblador, conlleva ms tiempo de conversin, ms programa
flash y ms uso de memoria.
Ejemplo 1: Convertidor AD de 8 bits con punto flotante
; Demostracin de conversin de punto flotante en ensamblador, (C) 2003 www.avr-ASM-tutorial.net
; La tarea: Se lee un resultado de 8 bits de un convertidor analgico-digital en un rango que va desde 00 a FF
;hexadecimal y hay que convertirlo en un nmero de punto flotante en el rango de 0,00 a 5,00 voltios.
;Esquema del programa:
;1. Multiplicacin por 502 (01F6 hex). Se multiplica por 500 y por 256 y se divide por 255 en un slo paso.
;2. Redondear el resultado y omitir el ltimo byte (esto ltimo divide por 256). Antes de omitir el ltimo byte
;hay que coger el bit 7 para el redondeo.
;3. Convertir la palabra resultante a ASC y establecer el signo decimal en el lugar correcto. La palabra
;resultante en el rango de 0 a 500 se muestra en caracteres ASC como 0,00 a 5,00.
;Registros utilizados:
;La rutina utiliza los registros R8..R1 sin salvarlos previamente. Tambin se requiere un registro multipropsito
;al que se le llama rmp localizado en la mitad superior de los registros. Hay que tener cuidado de que este
;registro no entre en conflicto con los registros utilizados en el resto del programa.
;Al entrar en la rutina se espera el nmero de 8 bits en el registro R1. La multiplicacin usa los registros
;R4:R3:R2 para mantener el multiplicador 502 (se desplaza a la izquierda mximo 8 veces durante la
;multiplicacin). El resultado de la multiplicacin se calcula en los registros R7:R6:R5. El resultado de la
;llamada a la divisin por 256 ignora R5. R7:R6 se redondea en funcin del bit ms alto de R5 y el resultado se
;copia a R2:R1.
;La conversin a cadena ASC utiliza la entrada en R2:R1, los registros R4:R3 como divisor y coloca el
;resultado en R5:R6:R7:R8 (R6 es la parte decimal)
;Otras convenciones:
;La conversin est estructurada en subrutinas con la utilizacin de la pila. Esta debe funcionar bien para el uso
;en tres niveles (6 bytes de SRAM).
;Tiempos de conversin:
;La rutina completa requiere como mximo 228 ciclos de reloj (conversin $FF) y mnimo 79 (conversin $00).
;A 4 MHz los tiempos son de 56,75 y 17,75 microsegundos respectivamente.
;Definiciones:
;Registros
.DEF rmp = R16 registro multipropsito
9:
;Avr tipo: Probado para el AT90S8515. Slo se requiere establecer la pila. Las rutinas trabajan bien con otros
;AT90S.
.NOLST
.NCLUDE "8515def.inc
.LST
;nicio del programables
;Escribe un nmero en R1 y comienza la rutina de conversin. Slo para propsitos de prueba.
.C9EG
./RG K))))
rJmp m#in
m#in@
ldi rmp14IG45RAMEFD7 ; est#"le*er l# pil#
o!t 9.41rmp
ldi rmp10/85RAMEFD7
o!t 9.01rmp
ldi rmp1KFF ; Convertir KFF
mov R11rmp
r*#ll p*onv8 ; llamada a la rutina de conversin
noGend@ ; bucle sin fin, cuando se hace
rJmp noGend
; Envoltorio de rutina de conversin, llamadas a los diferentes pasos de conversin
p*onv8@
r*#ll p*onv8m ; m!ltipli*#r por 5)2
r*#ll p*onv8r ; redonde# D divide por 256
r*#ll p*onv8# ; convierte a cadena ASC
ldi rmp1T.T ; establecer cadena decimal
mov R61rmp
ret ; todo hecho
; 9!"r!tin# p#r# m!ltipli*#r por 5)2
p*onv8m@
*lr R( ; est#"le*er el m!ltipli*#dor p#r# 5)2
ldi rmp1K)1
mov R;1rmp
ldi rmp1KF6
mov R21rmp
*lr R< ; "orr#r el res!lt#do
*lr R6
*lr R5
p*onv8m1@
or R11R1 ; comprobar si el nmeros es todo ceros
"rne p*onv8m2 ; todava hay unos, ir a convertir
ret ; listo, volver
p*onv8m2@
lsr R1 ; desplazar el nmero a la derecha (dividir por 2)
"r** p*onv8m; ; si el bit ms bajo fue 0, entonces salto a la suma
#dd R51R2 ; s!m#r el nLmero en R6@R5@R(@R; *on el res!lt#do
#d* R61R;
#d* R<1R(
p*onv8m;@
lsl R2 ; m!ltipli*#r R(@R;@R2 por 2
rol R;
rol R(
rJmp p*onv8m1 ; repetir p#r# el si$!iente "it
; Redondeo del v#lor en R<@R6 *on el "it < de R5
p*onv8r@
*lr rmp ; poner# # *ero rmp
lsl R5 ; rrot#r el "it < #l #*#rreo
#d* R61rmp ; s!m#r 09: *on el #*#rreo
#d* R<1rmp ; s!m#r el M9:m *on el #*#rreo
9=
mov R21R< ; Copi#r el v#lor # R2@R1 5dividir por 2567
mov R11R6
ret
; Convertir l# p#l#"r# en R2@R1 # !n# *#den# A9CII en R5@R6@R<@R8
p*onv8#@
*lr R( ; Est#"le*er el v#lor del divisor de*im#l # 1))
ldi rmp11))
mov R;1rmp
r*#ll p*onv8d ; o"tener dB$itos A9CII por s!str#**i+n repetid#
mov R51rmp ; est#"le*er *#den# de *#r#*teres de l# *enten#
ldi rmp11) ; Est#"le*er el v#lor del divisor de*im#l # 1)
mov R;1rmp
r*#ll p*onv8d ; o"tener el si$!iente dB$ito A9CII
mov R<1rmp ; est#"le*er *#den# de *#r#*teres de l# de*en#
ldi rmp1T)T ; *onvertir el resto # !n *#rQ*ter A9CII
#dd rmp1R1
mov R81rmp ; est#"le*er l# *#den# de *#r#*teres
ret
; Convertir l# p#l#"r# "in#ri# en R2@R1 # dB$ito de*im#l rest#ndo el v#lor del divisor en R(@R; 51))1 1)7
p*onv8d@
ldi rmp1T)T ; ComienE# *on el v#lor de*im#l )
p*onv8d1@
*p R11R; ; Comp#r#r l# p#l#"r# *on el v#lor del divisor de*im#l
*p* R21R(
"r** p*onv8d2 ; A*#rreo # *ero. Rest#r el v#lor del divisor
ret ; rest# >e*>#
p*onv8d2@
s!" R11R; ; rest#r el v#lor del divisor
s"* R21R(
in* rmp ; in*rement#r !n dB$ito
rJmp p*onv8d1 ; !n# veE mQs
; Fin de l# r!tin# de pr!e"# de *onversi+n
Ejemplo 2: Convertidor AD de 10 bits con punto flotante
; Demostracin de conversin de punto flotante
; en ensamblador, (C)2003 www.avr-asm-tutorial.net
;
; La tarea: Se lee el resultado de 10 bits de un convertidor analgico-digital. El nmero est en
;el rango de 0000 a 03FF hexadecimal. Hay que convertirlo a un nmero de punto flotante en
;el rango de 0,000 a 5,000 voltios.
;
; Esquema del programa:
; 1. Comprobar que el nmero es menor de $0400, para prevenir desbordamientos no permitidos
; durante la siguiente multiplicacin.
; 2. Multiplicacin por 320313 (04E338 hex). Se multiplica por 5000, por 65536 y se divide por 1023
; en un slo paso.
; 3. Redondear el resultado y cortar los dos ltimos bytes (dividir por 65536). Para redondear se ; ;
; utiliza antes el bit 15.
; 4. Convertir la palabra resultante a ASC y establecer la posicin correcta del punto decimal.
; La palabra resultante en el rango de 0 a 5,000 se muestra en caracteres ASC.
;
; Registros utilizados:
; Las rutinas utilizan los registros R10..R1 sin salvar previamente. Tambin se requiere un registro
;multipropsito al que se le llama rmp localizado en la mitad superior de los registros. Hay que tener
;cuidado de que este ;registro no entre en conflicto con los registros utilizados en el resto del
;programa.
;
; Al entrar en la rutina el nmero de 10 bits se espera en el par de registros R2:R1. Si el nmero es
47
;mayor de $03FF la rutina retorna con el bit de acarreo establecido y la cadena resultante en
;R5:R6:R7:R8:R9:R10 se establece como cadena ASC con terminacin nula "E.EEEE
; La multiplicacin utiliza los registros R6:R5:R4:R3 para contener el multiplicador 320313 (que se
;puede desplazar mximo 10 veces durante la multiplicacin). El resultado de la multiplicacin se
;calcula en los registros R10:R9:R8:R7. El resultado de la llamada a la divisin por 65536 ignora
;R8:R7 y el resultado en R10:R9 se redondea en funcin del bit ms alto de R8. Por ltimo el
;resultado final se copia en R2:R1.
; La conversin a cadena ASC utiliza la entrada en R2:R1 y el par de registros R4:R3 como divisor
;para la conversin y coloca el resultado como cadena ASC en R5:R6:R7:R8:R9:R10
;(null-terminated o terminada en cero)
;Otras convenciones:
;La conversin est estructurada en subrutinas con la utilizacin de la pila. Esta debe funcionar bien
;para el uso en tres niveles (6 bytes de SRAM).
;Tiempos de conversin:
; La rutina completa requiere mximo 326 ciclos de reloj (conversin de $03FF) y mnimo 111
;(conversin de $0000). A 4 MHz los tiempos son de 81,25 y 27,5 microsegundos respectivamente.
;
; Definiciones:
; Registros
.DEF rmp = R16 ; registro multi-propsito
;
;Avr tipo: Probado para el AT90S8515. Slo se requiere establecer la pila. Las rutinas trabajan bien
;con otros AT90S.
.NOLST
.NCLUDE "8515def.inc"
.LST
;
; Comienza el programa
;
; Escribe un nmero en R2:R1 y comienza la rutina de conversin. Slo para propsitos de prueba.
;
.CSEG
.ORG $0000
rjmp main
;
main:
ldi rmp,HGH(RAMEND) ; Set the stack
out SPH,rmp
ldi rmp,LOW(RAMEND)
out SPL,rmp
ldi rmp,$03 ; Convert $03FF
mov R2,rmp
ldi rmp,$FF
mov R1,rmp
rcall fpconv10 ; call the conversion routine
no_end: ; unlimited loop, when done
rjmp no_end
;
; Conversion routine wrapper, calls the different conversion steps
;
fpconv10:
rcall fpconv10c ; Check the input value in R2:R1
brcs fpconv10e ; if carry set, set "E.EEE"
rcall fpconv10m ; multiplicate by 320,313
rcall fpconv10r ; redondear and divide by 65536
43
rcall fpconv10a ; convert to ASC string
rjmp fpconv10f ; set decimal point and null-termination
fpconv10e:
ldi rmp,'E' ; set error condition to result string
mov R5,rmp
mov R7,rmp
mov R8,rmp
mov R9, rmp
fpconv10f:
ldi rmp,'.' ; set decimal point
mov R6,rmp
clr rmp ; null-terminate ASC string
mov R10,rmp
ret ; all done
;
; Subrutina de verificacin de entrada
;
fpconv10c:
ldi rmp,$03 ; compare MSB with 03
cp rmp,R2 ; if R2>$03, set carry on return
ret
;
; Subroutine multiplication by 320,313
;
; Starting conditions:
; +---+---+
; | R2+ R1| nput number
; +---+---+
; +---+---+---+---+
; | R6| R5| R4| R3| Multiplicant 320.313 = $00 04 E3 38
; | 00| 04| E3| 38|
; +---+---+---+---+
; +---+---+---+---+
; |R10| R9| R8| R7| Result
; | 00| 00| 00| 00|
; +---+---+---+---+
;
fpconv10m:
clr R6 ; set the multiplicant to 320.313
ldi rmp,$04
mov R5,rmp
ldi rmp,$E3
mov R4,rmp
ldi rmp,$38
mov R3,rmp
clr R10 ; clear the result
clr R9
clr R8
clr R7
fpconv10m1:
mov rmp,R1 ; check if the number is clear
or rmp,R2 ; any bit of the word a one?
brne fpconv10m2 ; still one's, go on convert
ret ; ready, return back
fpconv10m2:
lsr R2 ; shift MSB to the right (div by 2)
45
ror R1 ; rotate LSB to the right and set bit 7
brcc fpconv10m3 ; if the lowest bit was 0, then skip adding
add R7,R3 ; add the number in R6:R5:R4:R3 to the result
adc R8,R4
adc R9,R5
adc R10,R6
fpconv10m3:
lsl R3 ; multiply R6:R5:R4:R3 by 2
rol R4
rol R5
rol R6
rjmp fpconv10m1 ; repeat for next bit
;
; Round the value in R10:R9 with the value in bit 7 of R8
;
fpconv10r:
clr rmp ; put zero to rmp
lsl R8 ; rotate bit 7 to carry
adc R9,rmp ; add LSB with carry
adc R10,rmp ; add MSB with carry
mov R2,R10 ; copy the value to R2:R1 (divide by 65536)
mov R1,R9
ret
;
; Convert the word in R2:R1 to an ASC string in R5:R6:R7:R8:R9:R10
;
; +----+----+
; + R2| R1| nput value 0..5,000
; +----+----+
; +----+----+
; | R4| R3 | Decimal divider value
; +----+----+
; +----+----+----+----+----+-----+
; | R5 | R6 | R7| R8| R9| R10| Resulting ASC string (for input value 5,000)
; |' 5 ' | ' . ' | '0' | '0' | '0' | $00 | null-terminated
; +----+----+----+----+----+-----+
;
fpconv10a:
ldi rmp,HGH(1000) ; Set the decimal divider value to 1,000
mov R4,rmp
ldi rmp,LOW(1000)
mov R3,rmp
rcall fpconv10d ;obtener dgitos ASC por sustraccin repetida
mov R5,rmp ; establecer la cadena de caracteres del millar
clr R4 ; Set the decimal divider value to 100
ldi rmp,100
mov R3,rmp
rcall fpconv10d ; get the next ASC digit
mov R7,rmp ; establecer la cadena de caracteres de la centena
ldi rmp,10 ; Set the decimal divider value to 10
mov R3,rmp
rcall fpconv10d ; get the next ASC digit
mov R8,rmp ; establecer la cadena de caracteres de la decena
ldi rmp,'0' ; convert the rest to an ASC char
add rmp,R1
mov R9,rmp ; establecer la cadena de la unidad
4@
ret
;
; Convert binary word in R2:R1 to a decimal digit by substracting
; the decimal divider value in R4:R3 (1000, 100, 10)
;
fpconv10d:
ldi rmp,'0' ; start with decimal value 0
fpconv10d1:
cp R1,R3 ; Compare word with decimal divider value
cpc R2,R4
brcc fpconv10d2 ; Carry clear, subtract divider value
ret ; done subtraction
fpconv10d2:
sub R1,R3 ; subtract divider value
sbc R2,R4
inc rmp ; incrementar un dgito
rjmp fpconv10d1 ; una vez ms
;
; End of floating point conversion routines
;
; End of conversion test routine
Plani)icar un pro"ecto en ensamblador *V(
Ahora se vern los conceptos bsicos de como planificar un proyecto simple para programar en
ensamblador. Debido a que lo que ms determina es el componente hardware, primero se ver las
consideraciones de hardware. A continuacin use vern las interrupciones y despus el tema de los
tiempos.
Consideraciones de hardware
Para decidir que tipo de AVR se ajusta mejor a las necesidades hay que tener en cuenta una serie de
consideraciones. He aqu las ms relevantes:
1. Que conexiones de puerto con ubicacin fija se necesitan? Los puertos de /O de los
componentes internos slo estn disponibles en pines determinados y no se pueden cambiar. A
continuacin habra que tener en cuenta:
1. Si el procesador debe ser programable en circuito (interface SP), tienen que asignarse para
este propsito los pines SCK, MOS y MSO. Hay que ver si el perifrico permite que estos
puedan ser utilizados como entradas (por ejemplo SCK y MOS) o como salidas (por
disociacin a travs de resistencias o multiplexores).
2. Si se necesita una interfaz serie, hay que reservar RXD y TXD para tal fin. Si se utiliza el
protocolo de hardware de enlace RTS/CTS, son necesarios dos pines de puerto adicionales
aunque se puede utilizar cualquiera que este libre.
3. Si se necesita un comparador analgico. AN0 y AN1 tendran que ser reservados para ello.
4. Si se necesita seales externas para monitorizar cambios de nivel, hay que reservar NT0 y/o
NT1.
5. Si se van a utilizar convertidores AD, deben emplazarse y reservarse las entradas ADC. Si el
convertidor lleva conexiones AVCC y AREF externas se deben cablear en consecuencia.
6. Si se van a contar pulsos externos, los pines de entrada de temporizador T0, T1 y T2 son fijos
y exclusivos para esto.
7. Si hay que aadir SRAM externa, hay que reservar la respectiva direccin y los puertos de
datos junto con ALE, RD y WR.
8. Si el reloj del procesador debe ser generado a partir de un oscilador de cristal externo, hay
que reservar XTAL1. Si se utiliza un cristal externo o un resonador cermico para controlar la
48
frecuencia de reloj, XTAL1 y XTAL2 han sido fijados para tal fin.
2. Hay componentes externos que requieran ms de un portpin (2, 4 u 8) para ser leidos o escritos?
stos deben definirse de manera adecuada (en el mismo puerto, en el orden correcto).
1. Si para el control de un dispositivo externo se requiere la lectura o escritura de ms de un bit
a la vez, ej. una interfaz de pantalla LCD de cuatro u ocho bits, los bits de puerto necesarios
deben estar en el orden correcto. Si no es posible colocar toda la interfaz en un solo puerto, la
interfaz se puede dividir en dos partes y para el software es ms fcil, si las partes se ajustan
de izquierda a derecha.
2. Si se requieren dos o ms canales ADC, para el software es ms fcil si stos se colocan en
orden, por ejemplo, ADC2+ADC3+ADC4.
3. Al final, todos los componentes externos pueden estar colocados de forma que no requieran pines
fijos.
1. Si por un simple pin hay que seleccionar un dispositivo ms grande, puede considerar utilizar el
pin de RESET para evitarlo. ste puede ser usado si se establece determinado fusible. El ajuste
de este fusible desactiva la programacin SP y el chip slo se puede programar en el modo de
alto voltaje. Esto es aceptable para produccin final pero no para la creacin de un prototipo. En el
caso de crear un prototipo con una interfaz de programacin de alto voltaje, el pin de SP puede
ser utilizado si el componente en el pin de RESET est protegido contra los 12 V durante la
programacin SP, con una resistencia y un diodo zener.
Otras consideraciones para elegir con cul procesador va a trabajar mejor pueden ser:
Que temporizadores son necesarios y que resolucin deben stos proporcionar.
Qu valores/datos hay que preservar cuando se apaga la alimentacin? (Capacidad de
EEPROM)
Cunto espacio de almacenamiento se requiere? (Capacidad de SRAM)
Qu requerimientos de espacio hay en el PCB? Qu procesador encaja mejor y que tipos de
empaquetado hay disponibles?
Voltajes de operacin y requisitos de energa. Si la tensin de alimentacin proviene de una
batera o un acumulador. Las caractersticas de poder pueden jugar un papel importante.
Precio del dispositivo. Es relevante para una gran produccin en serie. No todo depende del
procesador interno y las condiciones del mercado son impredecibles.
Disponibilidad? Si uno comienza un proyecto con un AT90S1200 de un cajn de objetos usados
le puede salir muy barato, pero tal decisin no es muy sostenible. Trasladar un proyecto de un
pequeo a un gran dispositivo o viceversa termina en un completo rediseo de software. Es mejor
tenerlo en cuenta desde el principio porque as se v y se trabaja mejor y es cuestin de una
pequea fraccin de lineas de cdigo.
Consideraciones sobre las interrupciones
Tareas muy simples funcionan bien sin las interrupciones. Si el consumo de energa es un problema,
esto ya no es cierto. Casi todos los proyectos requieren interrupciones y esto debe ser planificado
cuidadosamente.
Requisitos bsicos de operacin por interrupciones
Si no hay que tener en cuenta nada ms he aqu los fundamentos:
- Habilitacin de interrupciones:
Las interrupciones requieren la pila de hardware. As que hay que establecer SPL (y en
dispositivos grandes SPH) al principio de RAMEND y reservar la parte superior de la
49
SRAM para este propsito (por ejemplos los ltimos 8 a x bytes).
Cada componente interno con su respectiva condicin de provocacin de una interrupcin
se habilitan mediante el establecimiento del correspondiente bit de bandera de habilitacin
de interrupcin. Los cambios de estos bits conllevan cierto riesgo por lo que sera mejor
disear el software sin tener que cambiarlos.
La bandera en el registro de estado SREG tiene que establecerse al principio y
permanecer establecida durante la operacin. Si es necesario despejar la bandera
durante una operacin fuera de la rutina de servicio de la interrupcin, agregue la
instruccin de establecimiento de la bandera en unas pocas instrucciones.
- Tabla de vectores de interrupcin:
Cada componente interno con su respectiva condicin de interrupcin corresponden a un
vector especfico de interrupcin situado en una determinada direccin de memoria flash
de programa. La instruccin en esta direccin es la instruccin RJMP de una palabra o en
los procesadores grandes Atmega, la instruccin JMP de dos palabras que salta a la
respectiva rutina de servicio de interrupcin.
Las direcciones de los vectores son especficas del tipo de AVR. Al portar el software a un
tipo diferente se requieren ajustes.
A cada direccin de vector en la tabla que actualmente no es utilizada, se le da una
instruccin RET(en los tipos grandes Atmega, una RET seguida de una NOP). Esto
impide la ejecucin de una interrupcin fantasma por error. El uso de la directiva .ORG
para ajustar las direcciones de vector no ofrece seguridad ante estos posibles eventos.
Si se produce una condicin de interrupcin, se establece la respectiva bandera en el
registro de control del componente interno. sta se pone a cero automticamente si se
ejecuta la interrupcin. En algunos casos excepcionales (por ejemplo el caso de una
condicin de interrupcin de una UART por un buffer TX vaco al que no se le va a enviar
ms caracteres) tiene que ser puesta a cero primero la bandera de habilitacin de
interrupcin del componente y la bandera de condicin de interrupcin despus.
Si se da la condicin de interrupcin en ms de un componente a la vez, la interrupcin
con la direccin ms baja tiene preferencia.
- Rutinas de servicio de interrupcin:
Cada rutina de servicio de interrupcin comienza guardando el registro de estado SREG
en un registro reservado exclusivamente para tal fin, y termina con la restauracin del
registro de estado como estaba al producirse la interrupcin. Debido a que una
interrupcin puede ocurrir en cualquier momento incluso cuando el procesador est
ejecutando las instrucciones del bucle principal del programa, cualquier alteracin del
registro de estado puede causar un funcionamiento impredecible.
Antes de saltar a la rutina de servicio, el procesador lleva el contador de la instruccin en
curso a la pila. La interrupcin y el respectivo salto a la rutina de servicio deshabilita otras
interrupciones temporalmente poniendo a cero la bandera en el registro de estado
SREG. Cada rutina de servicio termina con la instruccin RET que retorna de la pila la
instruccin siguiente a la que se estaba ejecutando cuando ocurri la int. y establece de
nuevo la bandera .
Debido a que durante la ejecucin de una rutina de servicio puede haber nuevas
solicitudes de interrupcin, incluso de mayor prioridad, cada rutina de servicio tiene que
ser lo ms breve posible y realizar las operaciones crticas de la tarea en el mnimo
tiempo. Las operaciones de respuesta demasiado largas deben realizarse fuera de la
rutina de servicio de interrupcin.
Como interrumpir una rutina de servicio de interrupcin no puede suceder, todas las
rutinas de servicio de interrupcin pueden utilizar el mismo registro temporal.
- nterfaz de rutina de servicio de interrupcin y bucle de programa principal:
44
La comunicacin entre la rutina de servicio de int. y el bucle del programa principal se
realiza a travs de banderas individuales, que se establecen dentro de la rutina de
servicio y se ponen a cero en el bucle del programa principal. Esto ltimo se hace con
una simple palabra de instruccin o deshabilitando temporalmente las interrupciones
durante este paso para bloquear sebreescrituras errneas de otras banderas que se han
podido cambiar entre las tres fases de lectura-modificacin-escritura.
Los valores que proporcionan las rutinas de servicio de int. son puestos en los registros
dedicados o en lugares especficos de SRAM. Cada cambio de esos valores (que se
utilizan ms tarde fuera de la rutina de servicio) tiene que ser comprobado por posible
corrupcin si en medio ocurre otra interrupcin. Manejar un slo byte es fcil, pero la
entrega de dos o ms bytes requiere un protocolo de transferencia (desactivar
interrupciones durante la transferencia, establecer la bandera para evitar sobreescrituras,
etc). Por ejemplo, la entrega de un valor del temporizador de 16 bits requiere primero la
desactivacin de las interrupciones, de lo contrario la lectura de un segundo byte no es
correspondiente al primer byte ledo si ha ocurrido una interrupcin de por medio.
- Bucle de programa principal:
En el bucle principal del programa el procesador se enva a dormir seleccionando el modo
de espera "inactivo. Cada interrupcin despierta al procesador que salta a la rutina de
servicio de int. correspondiente y despus del retornar de la interrupcin contina la
operacin en el bucle principal. Tiene sentido comprobar que no se establecieron
banderas dentro de la rutina de servicio y si se da el caso hay que realizar el tratamiento
de la bandera. Despus de realizar todas las operaciones se puede realizar otro chequeo
de la configuracin de las banderas (para rutinas muy largas) y el procesador se puede
enviar de vuelta a dormir.
Ejemplo de un programa ensamblador por interrupciones
A continuacin un programa de ensamblador por interrupciones que utiliza todas las reglas
mencionadas anteriormente:
;
; Definicin de registros
;
.EQU rsreg = R15 ; salvar el estado durante las interrupciones
.EQU rmp = R16 ; registro de las interrupciones temporales externo
.EQU rimp = R17 ; registro de las interrupciones temporales interno
.EQU rflg = R18 ; registro de bandera para la comunicacin
.EQU bint0 = 0 ; bit de bandera para la sealizacin de servicio NT0
.EQU btc0 = 1 ; bit de bandera para la sealizacin de desbordamiento TC0
; ...
; Tabla SR
;
.ORG $0000
rjmp main ; Vector de reset, ejecutado en el arranque
rjmp isr_int0 ;vector NT0, ejecutado en los cambios de nivel en la linea de entrada NT0
reti ; interrupcin sin uso
reti ; interrupcin sin uso
rjmp isr_tc0_Overflow ; vector de desbordamiento TC0
reti ; interrupcin sin uso
reti ; interrupcin sin uso
; ... otros vectores de int.
;
; Rutinas de servicio de interupcin
;
4?
isr_int0: ; Rutina de servicio a para NT0
in rsreg,SREG ; salvar estado
in rimp,PNB ; leer del puerto B el registro de temperatura
out PORTC,rimp ; escribir en el puerto C el registro de temperatura
; ... hacer otras cosas
sbr rflg,1<<bint0 ; sealizacin de NT0 fuera
out SREG,rsreg ; restaurar estado
reti ; retornar y habilitar las interrupciones
isr_tc0_Overflow: ; rutina de servicio de desbordamiento TC0
in rsreg,SREG ; salvar estado
in rimp,PNB ; leer del puerto B el registro de temperatura
out PORTC,rimp ; escribir en elpuerto C el registro de temperatura
; ... hacer otras cosas
sbr rflg,1<<btc0 ; establecer la bandera TC0
out SREG,rsreg ; restaurar estado
reti ; retornar y habilitar las interrupciones
;
; nicio del programa principal
;
main:
ldi rmp,HGH(RAMEND) ; establecer el registro de pila
out SPH,rmp
ldi rmp,LOW(RAMEND)
out SPL,rmp
; ... otras cosas a hacer
; activar interrupcin para desbordamiento TC0
ldi rmp,1<<TOE0 ; habilitacin de interrupcin de desbordamiento del temporizador 0
out TMSK,rmp ; establecer la mascara de desbordamiento del temporizador
ldi rmp,(1<<CS00)|(1<<CS02) ; preescalador en 1024
out TCCR0,rmp ; inicio del temporizador
; habilitar interrupcin en la entrada NT0
ldi rmp,(1<<SE)|(1<<SC00) ; habilitar modo inactivo e interrupcin NT0 en todos los cambios de nivel
out MCUCR,rmp ; al registro de control
ldi rmp,1<<NT0 ; habilitar interrupciones NT0
out GCR,rmp ; al registro de control de interrupcin
; establecer bandera de estado de interrupcin
sei ; establecer bandera de interrupcin
;
; Bucle de programa principal
;
loop:
sleep ; procesador a dormir
nop ; ficitcia para despertar
sbrc rflg,bint0 ; no se establece bandera NT0
rcall mache_int0 ; manejar el evento en NT0
sbrc rflg,btc0 ; no se establece bandera de desbordamiento TC0
rcall mache_tc0 ; manejar desbordamiento TC0
rjmp loop ; volver a dormir
;
; Manejar resultados de evento
;
mache_int0: ; manejar resultado NT0
cbr rflg,1<<bint0 ; despejar bandera NT0
; ... hacer otras cosas
ret ; listo, retornar al bucle
mache_tc0: ; manejar desbordamiento TC0
cbr rflg,1<<btc0 ; despejar bandera TC0
; ... hacer otras cosas
ret ; listo, retornar al bucle
4:
Consideraciones de tiempo
Si un proyecto AVR va ms all de sondear un puerto /O y en funcin de esto hacer algo, es
necesario considerar el tema tiempo, que:
Comienza con la seleccin del tipo de procesador.
Contina con la pregunta de que es lo que ha de ser ejecutado peridicamente y con que
precisin.
Si hay posibilidades de control de sincronizacin y
cmo se pueden combinar las cosas.
Seleccin de la frecuencia de reloj del procesadores
La cuestin principal est en la precisin necesaria del reloj del procesador, aunque en aplicaciones
que permitan un pequeo porcentaje de inexactitud, el oscilador interno RC de la mayora de los AVR
es suficiente. En los tipo tinD y me$# se puede hacer una calibracin del oscilador por lo que se
reduce la diferencia entre la frecuencia nominal y la efectiva. Hay que tener en cuenta que en el byte
de calibracin interna por defecto fue seleccionada una tensin de servicio determinada. Si el voltaje
de operacin se fija en un nivel diferente, volver a escribir el byte de calibracin aporta ms precisin.
Si el voltaje de funcionamiento es fluctuante, el error puede ser demasiado grande.
Si el reloj interno RC es demasiado lento o demasiado rpido, algunos tipos de dispositivo tienen un
preescalador de reloj. Con esta caracterstica pueden ser seleccionadas diferentes frecuencias de
reloj y permite optimizar la frecuencia. Esto se hace de una vez cambiando un fusible de hardware
(el fusible DV8) o por software (por ejemplo para reducir el consumo de energa durante las pausas).
Pero hay que tener en cuenta que algunos dispositivos con una especificacin de reloj limitada (los
de tipo V), no deben establecerse ms all de su lmite o no volvern a funcionar correctamente.
Si el oscilador RC interno es demasiado impreciso, los fusibles se pueden configurar para un
oscilador externo, un cristal (Xtal) o un dispositivo cermico. Dado que una configuracin errnea de
los fusibles puede dar lugar a una catstrofe, una placa de rescate con un oscilador externo podra
ser la ltima oportunidad para recuperar el dispositivo reseteando el fusible de nuevo.
La frecuencia de reloj absoluta debe ser la apropiada para la aplicacin. Se puede utilizar como
indicador la frecuencia que ms a menudo realiza el paquete de trabajo. Si por ejemplo, tiene que ser
consultada una tecla cada 2 ms, y esperar 20 veces este tiempo que debe ser lo suficientemente
largo para que no haya efecto rebote, hay un montn de tiempo si se utiliza un reloj de 1 MHz (2.000
ciclos de reloj entre dos consultas, 20.000 para la ejecucin repetida del comando de teclado).
Si hay que llegar a una frecuencia alta para una seal PWM (modulacin por ancho de pulso) de alta
resolucin, como por ejemplo una frecuencia PWM de 10 KHz y 8 bits de resolucin, 2.56 MHz son
demasiado lentos para una solucin basada en software. Mejor si un contador de tiempo con cierta
sobrecarga de software lo puede asumir.
4=

Вам также может понравиться