Introducción Aprender a programar microcontroladores significa aprender a usar todos sus recursos para luego aplicarlos en el diseño deseado. Es un proceso continuo, sistemático y que demanda por sobre todo tod o bastante paciencia. En este capítulo empezaremos por conocer el hardware interno de los AVR enfocándonos en losmegaAVR losmegaAVR de las series ATmegaXX8 y ATmegaXX4, que son actualmente los mejores microcontroladores de 8 bits de Atmel disponibles en encapsulados DIP de 28 y 40 pines respectivamente. Las XX indican los kBytes de memoria FLASH que lleva el megaAVR, por ejemplo, el ATmega168A tiene 16 kBytes de FLASH. Entre los miembros de estas familias podemos citar al ATmega48A, ATmega88P, ATmega168PA, ATmega328P, ATmega164A, ATmega324P, ATmega644PA y ATmega1284P. Como se puede notar, al final de cada nombre todavía puede aparecer un sufijo como A, P, V o PA, que identifica una característica adicional del megaAVR como ser de una sub-serie que opera a bajo voltaje (V) o que están fabricados con tecnología picoPower (P) para trabajar consumiendo menos energía. En algunas sub-series se han corregido ciertos bugs encontrados en versiones anteriores del AVR. Esto no necesariamente significa que tengan ser mejor, pues todos los microcontroladores de todas las marcas suelen tener pequeños bugs que en la gran mayoría de aplicaciones se pasan por alto. Quizá el único momento en que nos percatemos de la sub-serie específica de nuestro mega AVR sea cuando lo identifique el software programador, leyendo su código de identificación. Por lo demás no debería preocuparnos la sub-serie del megaAVR. Los programas son compatibles tanto en código fuente como en código máquina. Así que para facilitar la lectura de aquí en adelante nos referiremos a estos megaAVR simplemente como ATmegaXX4 o ATmegaXX8, entendiendo que pueden tener o no el sufijo explicado. Existe mucha compatibilidad entre los microcontroladores de Atmel, por lo que la teoría expuesta es aplicable en gran parte a otras series de AVR como los tinyAVR, los megaAVR con USB o incluso a los AVR antiguos como los clásicos ATmega8535, ATmega8515, ATmega16, ATmega32, etc. A decir verdad, los AVR que estudiaremos son como las versiones mejoradas de los "clásicos" megaAVR citados anteriormente.
Características Comunes de los megaAVR Citaremos las características más notables de los ATmegaXX8 y ATmegaXX4. Quizá muchas de ellas no las comprendas de plano. Puedes tomar eso como referencia para medir tu avance en el dominio del AVR. Tienen un repertorio de 131 instrucciones. Están optimizadas para generar un mejor código con los compiladores de alto nivel, en especial el C. Poseen 32 Registros de Trabajo de 8 bits cada uno. Se denominan desde R0 a R31. Esto en realidad es aplicable a todas las familias de los AVR de bits, incluyendo los XMEGA.
Tienen una velocidad de ejecución de hasta 20 MIPS (20 Millones de Instrucciones Por Segundo), que se alcanzará cuando el reloj del sistema (XTAL) sea de 20 MHz. Aunque como en cualquier otro microcontrolador, en la práctica no será una velocidad sostenida, porque en el programa habrá instrucciones que se demoran 2 ó más ciclos de instrucción. Sin embargo, siguen siendo bastante rápidos si los comparamos por ejemplo con sus contrapartes de Microchip, los PIC18, los cuales tienen un límite de 10 o 12 MIPS. Tienen un Timer0 de 8 bits que puede trabajar como Contador o Temporizador o Generador de hasta dos canales de ondas PWM de 8 bits de resolución. Tienen un Timer1 de 16 bits que opera en modo Contador, Temporizador o como Generador de hasta dos canales de ondas PWM con resolución configurable de hasta 16 bits. Los ATmega1284 tienen adicionalmente un Timer3 idéntico al Timer1. Tienen un Timer2 de 8 bits, parecido al Timer0 pero equipado adicionalmente para operar con un XTAL externo de 32 kHz de modo asíncrono. Tienen un Comparador Analógico. Tienen un módulo TWI (Two Wire Interface) para comunicaciones con el protocolo I2C en modos Maestro y Esclavo. Tienen un módulo SPI programable. Soporta los modos Maestro y Esclavo. Sirve además como la interface de programación prog ramación serial del megaAVR. Tienen un Conversor ADC de 10 bits, con hasta 8 canales de entrada. Tienen un USART0: Puerto serie Transmisor Receptor Síncrono Asíncrono Universal. Los ATmegaXX4 tienen adicionalmente un USART1, con características idénticas a las delUSART0. de lUSART0. Operan con voltajes de alimentación entre 1.8V y 5.5V. Mi entras más alta sea la frecuencia de operación del AVR más alto será el nivel de alimentación requerido, por ejemplo, para trabajar a la máxima frecuencia de 20 MHz, Vcc debe tener un valor muy estable entre 4.5V y 5V. Tienen un Oscilador RC interno configurable como oscilador principal del sistema. Tienen 6 modos Sleep, para una mejor administración del consumo de la energía. Tienen un circuito BOD o detector de bajo voltaje de alimentación. Tienen un temporizador Watchdog, para vigilar que el programa no quede colgado. Los megaAVR de la serie ATmegaXX8 tienen 3 puertos de E/S (con 23 pines en total) y los megaAVR de la serie ATmegaXX4 tienen 4 puertos de E/S (con 32 pines en total). Oscilador del sistema seleccionable, desde el Oscilador RC interno hasta cristales de cuarzo. Tienen un modo de programación paralela de alto voltaje HVPP (a 12V) y un modo de programación serial en bajo voltaje SPI (a 5V). Los ATmegaXX4 pueden adicionalmente ser programados por su interface de depuración JTAG. Por otro lado, la interface debugWIRE de losATmegaXX8 no ofrece la función de programación con la l a misma capacidad.
Tienen una velocidad de ejecución de hasta 20 MIPS (20 Millones de Instrucciones Por Segundo), que se alcanzará cuando el reloj del sistema (XTAL) sea de 20 MHz. Aunque como en cualquier otro microcontrolador, en la práctica no será una velocidad sostenida, porque en el programa habrá instrucciones que se demoran 2 ó más ciclos de instrucción. Sin embargo, siguen siendo bastante rápidos si los comparamos por ejemplo con sus contrapartes de Microchip, los PIC18, los cuales tienen un límite de 10 o 12 MIPS. Tienen un Timer0 de 8 bits que puede trabajar como Contador o Temporizador o Generador de hasta dos canales de ondas PWM de 8 bits de resolución. Tienen un Timer1 de 16 bits que opera en modo Contador, Temporizador o como Generador de hasta dos canales de ondas PWM con resolución configurable de hasta 16 bits. Los ATmega1284 tienen adicionalmente un Timer3 idéntico al Timer1. Tienen un Timer2 de 8 bits, parecido al Timer0 pero equipado adicionalmente para operar con un XTAL externo de 32 kHz de modo asíncrono. Tienen un Comparador Analógico. Tienen un módulo TWI (Two Wire Interface) para comunicaciones con el protocolo I2C en modos Maestro y Esclavo. Tienen un módulo SPI programable. Soporta los modos Maestro y Esclavo. Sirve además como la interface de programación prog ramación serial del megaAVR. Tienen un Conversor ADC de 10 bits, con hasta 8 canales de entrada. Tienen un USART0: Puerto serie Transmisor Receptor Síncrono Asíncrono Universal. Los ATmegaXX4 tienen adicionalmente un USART1, con características idénticas a las delUSART0. de lUSART0. Operan con voltajes de alimentación entre 1.8V y 5.5V. Mi entras más alta sea la frecuencia de operación del AVR más alto será el nivel de alimentación requerido, por ejemplo, para trabajar a la máxima frecuencia de 20 MHz, Vcc debe tener un valor muy estable entre 4.5V y 5V. Tienen un Oscilador RC interno configurable como oscilador principal del sistema. Tienen 6 modos Sleep, para una mejor administración del consumo de la energía. Tienen un circuito BOD o detector de bajo voltaje de alimentación. Tienen un temporizador Watchdog, para vigilar que el programa no quede colgado. Los megaAVR de la serie ATmegaXX8 tienen 3 puertos de E/S (con 23 pines en total) y los megaAVR de la serie ATmegaXX4 tienen 4 puertos de E/S (con 32 pines en total). Oscilador del sistema seleccionable, desde el Oscilador RC interno hasta cristales de cuarzo. Tienen un modo de programación paralela de alto voltaje HVPP (a 12V) y un modo de programación serial en bajo voltaje SPI (a 5V). Los ATmegaXX4 pueden adicionalmente ser programados por su interface de depuración JTAG. Por otro lado, la interface debugWIRE de losATmegaXX8 no ofrece la función de programación con la l a misma capacidad.
Tienen un sistema de depuración OCD con interface JTAG en el caso de los ATmegaXX4 y con interface debugWIRE en el caso de los ATmegaXX8. En general, la interface JTAG (compuesta por 4 pines) está disponible en todos los megaAVR de 40 pines o más y la interface debugWIRE(conformada por una sola línea) está presente en los megaAVR con menos de 40 pines. pi nes. Su memoria de programa FLASH tiene una sección de Boot Loader para albergar un programa cargador del mismo nombre. De los megaAVR estudiados en este curso (entre los ATmegaXX4 yATmegaXX8) el único que no ofrece esta funcionalidad es el ATmega48. El programa de Boot Loader le permite al microcontrolador auto-programarse sin necesidad de usar un programador externo como el USBasp o AVR ISP MkII. Es así como trabajan los módulos Arduino, por ejemplo.
Empaques de los megaAVR
Diagrama de pines de los ATmegaXX8 en encapsulado PDIP.
Diagrama de pines de los ATmegaXX4 en encapsulado PDIP.
Diagrama de bloques de los megaAVR El siguiente diagrama muestra los principales elementos de un AVR y que tarde o temprano los tendrás que memorizar.
Diagrama de bloques simplificado de los megaAVR ATmegaXX4 / ATmegaXX8 ATmegaXX8.. Ahora una somera descripción de lo que representan estos bloques. El CPU es el circuito encargado de leer, decodificar y ejecutar las instrucciones del programa. Dispone de 32 registros de trabajo y un ALU (Unidad Aritmético Lógica) con el que realiza las operaciones de suma, resta, AND lógica, OR lógica, etc. La Memoria FLASH de Programa almacena las instrucciones del programa del AVR. Es una memoria permanente pero que se puede reprogramar para cambiar de tarea. La Memoria RAM de Datos aloja las variables que procesa el CPU. El Contador de Programa es un registro que evoluciona para indicar cuál será la siguiente instrucción que debe ejecutar el CPU. La Pila o Stack es un segmento de la memoria RAM para guardar el valor del Contador de Programa y también variables temporales del programa cuando sea necesario. Los periféricos del AVR son elementos que se pueden usar para una determinada tarea; por ejemplo, el Timer0 sirve para temporizaciones. El USART para comunicaciones seriales RS232 RS232,, etc. Casi todos ellos serán estudiados en un capítulo aparte. Los puertos de E/S, PORTA PORTA,..., ,..., PORTD, son las líneas hacia/desde el exterior donde se pueden conectar los dispositivos a controlar, como diodos LED, transistores, LCDs, etc. Los megaAVR de 40 pines tienen los 4 puertos completos, mientras que a los megaAVR de 28 pines les falta PORTA y algunos pines en los otros puertos.
,
,
Hay más recursos presentes dentro de un AVR que también son imprescindibles pero cuyo trabajo queda en segundo plano. Algunos de ellos serán abordados en otro momento.
La Memoria de Programa Es de tipo FLASH. Aquí es donde se aloja el programa que el CPU ejecutará. Se puede modificar por completo mediante un dispositivo programador por hasta 10 000 veces. Pero tampoco deberíamos tanto. No conozco a nadie que haya llegado a ese límite con un solo microcontrolador. Lo más probable es que, por más cuidado que tengas, llegues a freír tu AVR antes de tiempo en algún accidente. Eso es algo muy “normal”. En los AVR las instrucciones de programa son de 16 ó de 32 bits. Pero siendo la gran mayoría de 16 bits, podemos decir que un AVR de N bytes de memoria FLASH puede almacenar hasta N/2 instrucciones de código ensamblador. Antiguamente parecía sencillo reconocer la cantidad de memoria FLASH que tenían algunos AVR. Por ejemplo, un ATmega32 tiene 32 k-bytes, un ATmega8L tiene 8 kbytes. Los megaAVR de ahora todavía conservan esa correspondencia entre el número que aparece en su nombre y la cantidad de k-bytes de FLASH, solo que las nuevas series también llevan un número que puede entrar a confundir un poco. En la siguiente tabla apreciamos los AVR de las series ATmegaXX8, ATmegaXX4, ATmegaXX5 yATmegaXX50. Las XX representan la cantidad de FLASH de megaAVR. Al final de cada nombre aparece el sufijo yy representando a las letras P, V, A o PA. Personalmente, creo que al haber varias series, es más fácil separar primero los números que representan la capacidad de FLASH porque deben ser números redondos (digitalmente hablando), es decir, deben ser potencias de 2, como 4, 8, 16, 32, 64 ó 128. Por ejemplo, ¿cuánta memoria FLASH tendrá un ATmega3290P?, ¿3290 kbytes, 329 kbytes, 32 kbytes o 3 kbytes? Como el único número redondo es 32, la respuesta es 32 kbytes y deducimos que este megaAVR es de la serie 90P. Se llega más rápido a la respuesta si leemos las opciones empezando por la izquierda. Tabla AVR
AVR
Memoria FLASHMemoria RAMMemoria EEPROMPines de E/S
ATmega48yy
4K
512
256
23
ATmega88yy
8K
1K
512
23
ATmega168yy
16 K
1K
512
23
ATmega328yy
32 K
2K
1K
23
-
-
-
-
ATmega164yy
16 K
1K
512
32
ATmega324yy
32 K
2K
1K
32
-
Tabla AVR
AVR
Memoria FLASHMemoria RAMMemoria EEPROMPines de E/S
ATmega644yy
64 K
4K
2K
32
ATmega1284yy
128 K
16 K
4K
32
-
-
-
-
ATmega165yy
16 K
1K
512
54/69
ATmega325yy
32 K
2K
1K
54/69
ATmega3250yy
32 K
2K
1K
54/69
ATmega645yy
64 K
4K
2K
54/69
ATmega6450yy
64 K
4K
2K
54/69
-
Secciones de Aplicación y de Boot Loader Los AVR ofrecen la posibilidad de escribir en su memoria de programa FLASH incluso en tiempo de ejecución. Esta función puede ser aprovechada para almacenar datos procesados por el usuario o para permitir la auto-programación del AVR. Para facilitar y robustecer el proceso de auto-programación los AVR dividen su memoria FLASH en dos segmentos lógicos, de Aplicación y de Boot Loader. La Sección de Aplicación está destinada a almacenar el programa que el AVR ejecuta habitualmente, como leer sensores, controlar motores, etc. La Sección de Boot Loader está diseñada para almacenar el código del Boot loader, que es un pequeño programa para cargar el programa del AVR en la Sección de Aplicación, así como Windows carga en la RAM de la PC el programa que vamos a utilizar. Un Boot Loader no es precisamente un mini S.O. porque ya hay S.O. para microcontroladores conocidos como RTOS (Real Time Operating System). Además, a diferencia de un S.O. para PC, un Boot Loader debe ser el programa más pequeño posible y se debe ubicar al final de la memoria FLASH. No todos los megaAVR tienen Sección de Boot Loader, como el ATmega48.
Secciones de Aplicación y de Boot Loader de la memoria de programa del AVR. La Sección de Boot Loader siempre se ubica al final de la memoria FLAH pero su tamaño varía de acuerdo con el AVR y con la configuración establecida por los fuses BOOTSZ1 y BOOTSZ0. Por ejemplo, el ATmega644PA puede tener una Sección de Boot Loader entre 512 palabras y 4096 palabras, según la siguiente tabla. Tabla BOOTSZ1
BOOTSZ1BOOTSZ0Tamaño del Boot LoaderDirección del Boot Loader 1
1
512 palabras
0x7E00 - 0x7FFF
1
0
1024 palabras
0x7C00 - 0x7FFF
0
1
2048 palabras
0x7800 - 0x7FFF
0
0
1096 palabras
0x7000 - 0x7FFF
Los fuses BOOTSZ1 y BOOTSZ0 solo se pueden modificar al grabar el AVR. Su configuración por defecto siempre establece el tamaño mayor elegible de la Sección de Boot Loader. El hecho de que la Sección de Boot Loader esté diseñada para alojar el programa cargador no significa que esté limitada a esa tarea. Si no la vamos a usar para su
propósito primigenio, podemos emplearla como si fuera parte de la Sección de Aplicación, o sea, como si no existiera la división entre estas dos Secciones y por ende no tendrá importancia el valor que pongamos en los fuses BOOTSZ1 y BOOTSZ0.
Configuración de los Fuses de Boot loader en el programa grabador. A propósito, la configuración de los fuses BOOTSZ1 y BOOTSZ0 en Proteus no tiene ningún efecto porque Proteus aún no soporta simulaciones con Boot Loader. Así que están como decorativos.
Configuración de los Fuses de Boot Loader en Proteus.
La Memoria de Datos SRAM Actualmente suena redundante especificar memoriaSRAM (Static RAM) porque casi todas las RAM de los microcontroladores son estáticas. Decimos simplemente RAM, a la memoria cuya función “tradicional” es alojar temporalmente los datos que se procesan en el programa. La cantidad de RAM disponible internamente depende del modelo de AVR y, a diferencia de la memoria FLASH, no tiene una directa correspondencia con el nombre del dispositivo. Aun así, podemos observar en la siguiente tabla que en muchos modelos existe una relación que se repite (los ATmega128nn rompen la relación, y pueden no ser los únicos). Los megaAVR con 4K de FLASH tienen 512 bytes de RAM, los megaAVR con 8 K y 16 K de FLASH tienen 1 K de RAM, y así, tal como se ve en la tabla. Tabla AVR
AVR
Memoria FLASHMemoria RAM
ATmegaNNN
4K
512
ATmegaNNN
8K
1K
Algunos Modelos ATmega48A, ATmega48PA, ATmega48P/V, ATmega48/V ATmega88A, ATmega88PA, ATmega88P/V, ATmega88/V ATmega168A, ATmega168PA, ATmega168P/V, ATmega168/V
ATmegaNNN
16 K
1K
ATmega164A, ATmega164PA ATmega165A, ATmega165PA ATmega169, ATmega169P ATmega328, ATmega328P ATmega324A, ATmega324PA
ATmegaNNN
32 K
2K
ATmega325A, ATmega325PA ATmega3250A, ATmega3250PA ATmega329P, ATmega3290P ATmega644A, ATmega644PA
ATmegaNNN
64 K
4K
ATmega645A, ATmega645P ATmega6450A, ATmega6450P
ATmegaNNN
128 K
4K, 8K o 16K
ATmega128, ATmega1281 ATmega1284, ATmega1284P
En los modelos listados y en general en todos los megaAVR de las series más recientes el espacio de la memoria RAM (entendida en su concepto tradicional) empieza en la dirección 0x0100 y termina en 0x02FF, 0x04FF, 0x08FF, 0x10FF, 0x20FF o 0x40FF, según el modelo. La verdad, no importa mucho saber dónde termina como la cantidad misma. La dirección de inicio sí es de consideración pero cuando se programa en lenguaje ensamblador. Quizá alguien pudiera preguntar por qué la dirección de inicio no es 0x0000, como en otros microcontroladores. Porque las primeras direcciones, desde 0x0000 hasta 0x00FF, están reservadas para acceder a los Registros de Trabajo y a los Registros de E/S del AVR en „modo de memoria‟. Normalmente los 32 Registros de Trabajo se acceden directamente con instrucciones como LDI o MOV. Pero también se les puede acceder direccionándolos como si fueran parte de la memoria RAM, con instrucciones como LD o ST y con las direcciones presentadas. En ocasiones esto facilitará mover bloques de datos entre la RAM y los registros de trabajo aprovechando la potencia de los pu nteros. Del mismo modo, los Registros de E/S, que tampoco ocupan posiciones reales en la RAM, pueden ser accedidos como si en verdad fueran RAM con las instrucciones como LD y ST, para lo cual emplean las direcciones mostradas en la figura.
Los Registros de E/S y los Registros de E/S extendidos son hermanos, por decirlo de algún modo, y tienen funciones análogas. Están separados solo por tener diferente modo de acceso, pero eso se explicará mejor en su sección respectiva. El direccionamiento y distinción de los espacios de la RAM solo son de preocupación al trabajar en ensamblador. Al programar en lenguajes de alto nivel los compiladores se encargan de toda la administración de la RAM, salvo que reciban directivas avanzadas.
Espacio de la Memoria RAM del megaAVR.
El Contador de Programa, PC El PC es un registro que indica la siguiente instrucción que debe ejecutar el CPU. Si vale 0x0000, ejecutará la primera instrucción de la memoria; si vale 0x0002 ejecutará la tercera instrucción, y así... Al arrancar microcontrolador, elPC vale 0x0000 y se va incrementando automáticamente, con lo que el AVR debería ejecutar una a una desde la primera hasta la última instrucción del programa. En realidad, en el código habrá instrucciones que modifiquen el valor del PCde modo que el programa nunca termine.
La Pila y el Puntero de Pila La Pila o STACK es una memoria que almacena temporalmente el valor del PC (Program Counter) cuando el programa llama a una subrutina o cuando salta a un Vector de Interrupción. También sirve para guardar datos temporalmente cuando los 32 Registros de Trabajo no sean suficientes. Al igual que en una PC, la Pila forma parte de RAM Interna. No es un pedazo de RAM con características especiales, es una simple área cuya dirección de inicio la puede establecer el usuario y cuyo tamaño es indefinido porque crece y decrece en tiempo de ejecución. Las que sí son especiales son las instrucciones que trabajan con la Pila, como PUSH y POP. Estas instrucciones no necesitan conocer la locación en la Pila a/de donde guardarán/recuperarán los datos. Aprovechan, en cambio, su acceso de tipo LIFO (Last In First Out), que s ignifica “el último dato en entrar será el primero en Salir”. Es por eso que siempre se recurre a la analogía con una pila de platos de donde no podemos tomar un plato que se encuentra en el fondo o en la mitad. Para llegar a él primero tendríamos que quitar los platos que están encima. Pero hasta ahí llega la analogía porque a diferencia de las pilas de platos, las pilas en RAM crecen de arriba abajo, es decir, cada dato que se va depositando en la Pila ocupa una dirección inferior a la anterior. Esta dirección la va marcando el Puntero de Pila, el cual se decrementa cada vez que se coloca un dato en la Pila y se incrementa cada vez que se toma un dato de ella. La Pila trabaja de cabeza para evitar que sus datos colisionen (se solapen) con las variables accedidas aleatoriamente, las cuales se van mapeando en la RAM normalmente de abajo arriba. Registro SPH
SPH
SP15
SP14
SP13
SP12
SP11
SP10
SP9
SP8
SP3
SP2
SP1
SP0
Registro SPL
SPL
SP7
SP6
SP5
SP4
El Puntero de Pila está representado por los registros de E/S SPH y SPL, que concatenados actúan como un registro de 16 bits. Como se dijo anteriormente, este registro tiene un comportamiento de auto-incremento y auto-decremento. La única intervención por parte del usuario debería ser su inicialización, esto es, cargarle la última dirección de la RAM. Pero esta operación solo es indispensable al programar en ensamblador. Los compiladores como el C inicializan la Pila automáticamente. Sin embargo, incluso en C es importante conocer estos conceptos para entender por ejemplo por qué un programa para un ATmega328P nunca funcionará en un ATmega168P, incluso si el tamaño del código es pequeño y le puede caber sobradamente.
Los Registros de Trabajo y los Punteros X, Y y Z
Todos los AVR de 8 bits, desde los tinyAVR hasta losXMEGA cuentan con 32 Registros de Trabajonombrados desde R0 hasta R31. Los Registros de Trabajo tienen la función de alojar los datos más inmediatos que el CPU procesa. ¿Acaso ésa no era tarea de la RAM?. Bueno, sucede que en todos los microcontroladores inspirados en la arquitectura de los procesadores de Intel (como los AVR, ARM y Freescale entre otros) el acceso a la memoria RAM toma más ciclos que el acceso a los Registros de Trabajo. En los AVR de 8 bits, por ejemplo, se puede acceder a los Registros de Trabajo en un solo ciclo, puesto que todos están directamente conectados al CPU, o mejor dicho, son parte del CPU. En cambio, la mayoría de las instrucciones ensamblador que acceden a la RAM consumen 2 ciclos de instrucción. No es posible cargar datos en la RAM directamente ni moverlos entre locaciones diferentes de la RAM (a menos que tengan DMA, como los AVR32). Para esas operaciones los Registros de Trabajo actúan como in termediarios. Pero quizá la participación más notable de Los Registros de Trabajo sea en el ALU (Unidad Aritmético Lógica) para computar las operaciones aritméticas y lógicas. Por ejemplo imaginemos que deseamos obtener la raíz cuadrada de un número de punto flotante ubicado en la RAM y almacenar el resultado de nuevo en la RAM. En lenguaje C bastaría con escribir una sola sentencia, pero el código máquina generado involucra una tarea más compleja: al inicio el CPU mueve los 4 bytes del número desde la RAM a los Registros de Trabajo, luego viene el trabajo pesado, que implica el procesamiento de varios datos intermedios. En lo posible todos estos datos también estarán en los registros de trabajo para aprovechar su velocidad y eficacia. Solo al terminar el cómputo el CPU depositará el resultado en la RAM. Los compiladores de alto nivel también suelen emplear los Registros de Trabajo para pasar los argumentos de sus funciones. Creo que con esos ejemplos debe quedar clara la razón de ser de los Registros de Trabajo. En la siguiente figura podemos notar que los Registros de Trabajo se parten por la mitad. La diferencia está en que los primeros 16 registros (R0 a R15) no admiten la instrucción LDI, que sirve para cargar constantes al registro (otro aspecto primordial de la programación en ensamblador9. Los registros R26a R31 tienen la capacidad adicional de funcionar como punteros de 16 bi ts cada uno.
Los Registros de Trabajo de los AVR. El par de registros R27-R26 forma el Puntero X, el par R29-R28 forma el Puntero Y, y el par R31-R30forma el Puntero Z. Los punteros pueden apuntar a (contener la dirección de) cualquier locación del espacio de RAM. Esto junto con las instrucciones adecuadas conforman el direccionamiento indirecto más potente, muy útil por ejemplo para mover grandes bloques de datos.
Terminamos esta sección explicando las direcciones que figuran en el mapa de los Registros de Trabajo. En principio a los Registros de Trabajo no les debería hacer falta tener direcciones porque están directamente unidos al CPU. Hay instrucciones adecuadas como LDI y MOV para acceder a ellos. Sin embargo, los AVR les brindan direcciones para adicionalmente poder ser accedidos como si fueran parte de la RAM, es decir, con instrucciones que están diseñadas para la RAM, como LD y ST. De esta manera se hacen más flexibles las operaciones de transferencias de datos entre los diferentes espacios de memoria. Cuando manipulamos los Registros de Trabajo utilizando sus direcciones podemos decir que los estamos accediendo “en modo RAM”, pero sin perder de vista que los Registros de Trabajo no pertenecen a la RAM porque no están implementadas físicamente allí.
Los Registros de E/S Anteriormente se dijo que para programar el AVR primero había que conocer sus recursos. Pues bien, todos ellos se pueden controlar mediante losRegistros de E/S. por ejemplo, si queremos manejar el puerto B, debemos conocer los registros PORTB, DDRB y PINB. Si queremos programar el USART0, debemos conocer los registros UDR0, UCSR0A,UCSR0B, UCSR0C, UBRR0L y UBRR0H. Si queremos… En tiempo de ejecución los registros de E/S (Entrada Salida) lo controlan todo, no solo las operaciones de los módulos periféricos, como se podría inferir a partir de la denominación E/S, sino que también controlan la performance del mismo CPU. En este caso los registros a conocer serían MCUCR, MCUSRo SMCR. Entenderás que no tiene caso seguir mencionando las funciones de otros Registros de E/S. es por eso que cada módulo se trata por separado estudiando con detenimiento cada registro y cada uno de los bits que lo componen. Espero que los mapas de memoria de los Registros de E/S que presento no te hagan pensar que están divididos en una suerte de bancos, como en los PICmicro. No, señor, nada de eso. Todos los espacios de memoria en los AVR son lineales. Yo los quise subdividir para una mejor presentación.