Tutorial de ensamblador AVR 4 (6 / 9 paso)

Paso 6: Punteros y tablas de búsqueda

Alguno de ustedes que tienen experiencia usando C o C++ ya tiene experiencia con punteros. Vamos a usar lo mismo aquí en el contexto de "tablas de búsqueda".

Tablas de búsqueda son otra forma de compactifying nuestro código para hacerlo más corto, más elegante y más fácil de entender.

En primer lugar permite escribir el código y luego vamos a explicar lo que está sucediendo. En primer lugar, en la parte superior de nuestro programa tenemos una sección denominada "números:" seguido de algunas directivas del ensamblador ".db". Estas directivas "definen bytes" y lo que hacen es que esos bytes secuencialmente en una sección de "Memoria de programa", definido por el número de etiqueta. Para que cuando se carga el código hex en el microcontrolador, un cierto segmento de la memoria flash que almacena todas las instrucciones del programa contendrá los bytes uno tras otro en orden.

Entonces realmente podemos conseguir estos números en cualquier momento queremos puesto que siempre se encuentra en ciertos lugares de la memoria de programa especificado. ¿Recuerdas cómo nos ocupamos de interrupciones? Colocamos una instrucción en exactamente 0x0020 en memoria de programa. Sabíamos que si una interrupción de desbordamiento del temporizador se produjo la cpu Compruebe exacta ubicación y ejecutar cualquier comando ponemos allí. Bien tablas de búsqueda funcionan de una manera muy similar.

Vamos a volver a escribir nuestro "dice:" etiquetado como subrutina, que es la que cuenta el microcontrolador que alfileres para encender para conseguir que el número en un dado, para que en lugar de una sección larga y fea de código, puede utilizar un bucle y hacer las cosas más simplemente. Aquí está el nuevo código:

Verás que es mucho más corto. De hecho, cada vez que te encuentras repitiendo el mismo conjunto de instrucciones una y otra vez dentro de una subrutina y el unico diferente cada vez que es que un número particular es diferente, es el momento perfecto utilizar una tabla de búsqueda. En los casos donde se utilizaría un "loop" o una rutina de "switch-case" en C o algún otro idioma, que es un buen momento para utilizar una tabla de búsqueda en ensamblador.

Tablas de búsqueda tienen fama de ser complicado pero no creo que se merecía. Voy a intentar explicar de forma sencilla.

Empecemos con el mapa de memoria atmega328p. Hay tres tipos diferentes de memoria disponible para almacenar cosas. La "memoria de programa" que almacena nuestro programa, la "memoria de datos SRAM" que contiene todos los registros que utilizamos como el objetivo general de trabajo registros, los puertos de entrada salida y todos los registros que utilizamos para cambiar poco y control se hacen las cosas y finalmente la memoria "EEPROM", que vamos a introducir en un tutorial posterior (si me pasado ese largo) y se utiliza para almacenar información que no desaparecerá cuando nos volvemos de la energía. Muy útil si usted está haciendo un juego y desea almacenar forma puntuación hasta la próxima vez que juegan!

Sabemos que cada byte de un determinado tipo de memoria tiene una dirección. Por ejemplo, el primer byte del código que ejecutamos está en 0 x 0000 y el manejador de interrupción desbordamiento de contador de tiempo es en 0x0020, etc.. Te darás cuenta que ya que tenemos más de 256 bytes de memoria en nuestro espacio de memoria de programa sólo no podemos usar direcciones de 0 x 00 a 0xFF. De hecho, contamos con 32k de memoria flash en el espacio de memoria de programa. Esto significa que necesitamos direcciones de 0 x 0000 hasta 0x7FFF.

¿Ahora, supongamos que queremos leer lo que está en una dirección específica en la memoria? Por ejemplo, cuando la cpu recibe una interrupción desbordamiento va a 0x0020 y ejecuta la instrucción que colocó allí. ¿Qué pasa si queremos poner las instrucciones o datos o lo que sea en alguna dirección específica en la memoria de programa y en nuestro programa? Nosotros podemos, salvo que nuestro propósito general se registra sólo puede contener 8 bits (1 byte) entre 0 x 00 y 0xFF, y como hemos visto, una dirección ocupa 2 bytes a escribir (entre 0 x 0000 y 0x7FFF). Así que no hay espacio suficiente en un registro de propósito general (es decir, una variable como r16) para mantener una dirección de memoria de programa. No podemos decir "ldi r16, 0b0000000000000010" por ejemplo, ya R16 no es lo suficientemente grande. ¿Así que si hemos no hay manera de almacenar la dirección completa de cómo podemos ir allí durante el programa? Podemos simplemente levantar el teléfono, llame a la cpu y decir "puede usted ir a ejecutar lo que almacena en 0x2a7f por favor" tienes que tener esa dirección en un r16 o algo y entonces "mov" él o "hacia fuera" a partir de ahí.

Así que aquí está lo que ha hecho la gente de ATmel para resolver este dilema. Tienen doble propuso algunos de nuestros registros de propósito general. En particular, si nos fijamos en la tabla 7-2 en la página 12 de la hoja de datos, puede ver cómo se organizan los registros de propósito general. Los registros r26, r27, r28, r29, r30 y r31 puede también combinarse en pares llamados X, Y y Z. Eso X es r26 r27 juntos, Y es el r28 y r29 juntos, y Z es r30 r31 juntos. De esta manera si tomamos Z por ejemplo, la primera mitad es r30 y la segunda mitad de su r31. Así que si queremos almacenar una dirección de memoria de programa almacenamos sólo la mitad de ella en r30 y la otra mitad de él en r31 y luego le decimos a la cpu para ver Z si queremos hablar sobre toda la cosa. Han implementado dos instrucciones que hacen esto. La primera es spm que está parado para el "Almacén de memoria de programa" y el otro es lpm que está parado para la "Carga de memoria de programa". Ahora si queremos conseguir lo que instrucción o dato se almacena en la dirección de memoria 0x24c8 por ejemplo, poner la dirección en r30 y r31 y luego cuando queremos obtener los datos le lpm sólo que un variable haciendo

que ir a la dirección de memoria Z, tomar cualquier datos ponemos allí y pegarlo en r16. Lo cool de esto es que si le sumamos 1 al uso de la Z

entonces Z ahora será "punto a" la próxima dirección de memoria después del primero. Así que eso si pegamos toda una lista de números en memoria uno tras otro que nos podemos ciclo de incremento de Z.

¿¿Usamos esto en nuestro programa?

Bueno, ya que cada número en el dado aparece girando y desactivar varios puertos como PC2 y PB5 sólo almacenamos el número que hace que para cada número en el dado. Por ejemplo si estamos "out" 0b11010010 a PortC establecerá PC0 0, PB1 a 1, etc. y encender los LEDs correspondientes que nos den nuestro número en el dado. En este caso el número 4.

Así que vamos a utilizar una "tabla de búsqueda" llamada "números:" para guardar todas estas configuraciones de tintas diferentes y simplificar nuestro código.

Creo que si lees el código anterior y ver las diferentes instrucciones en el manual de instrucciones, usted fácilmente puede averiguar cómo funciona. La parte sólo rara es el primer bit donde inicializamos el indicador Z.

Lo que esto hace es inicializa el puntero Z para que apunte a la lista con la etiqueta "números". La razón de 2 veces en el frente es que queremos que la dirección de "números" cambió de puesto a la izquierda y un espacio (que es lo que el tiempo por dos hace a números binarios). Esto deja libre al derecho bit (el bit menos significativo) que se utiliza para decidir qué bytes de memoria de programa nos referimos a. Esto es porque la memoria de programa es 2 bytes (16 bits) de ancho. Por ejemplo, en nuestra tabla de búsqueda tenemos dos números como
.dB 0b01111111, 0b11011110

Puesto que el espacio de memoria de programa es de 16 bits de ancho ambos de estos números estará realmente sentado en la misma dirección de memoria de programa para la forma en que agarra el primer o el segundo es por ello que necesitamos los "tiempos por 2" o cambio izquierda de los bits. Cuando el "bit menos significativo" de Z es 0 apuntará al primero de la lista: 0b01111111, y cuando el bit menos significativo de Z es un 1 apuntará a la segunda de la lista: 0b11011110.

Como se puede ver, agregar 1 a Z cambia el menos significativo del pedacito de 0 a 1 y luego agregando 1 a Z aumenta otra vez la dirección de memoria de programa y el LSB se remonta a un cero. Así que verás que funciona muy bien para nuestra lista completa de números almacenados en una selección a la vez incrementando simplemente Z.

Aviso que cuando cambio la dirección de «números» dejó al multiplicar por 2 para liberar el bit menos significativo a utilizar para seleccionar el primer o segundo byte almacenado en esa dirección se está perdiendo el "pedacito más significativo" de la dirección. Esto significa que sólo podemos almacenar nuestros datos de la tabla de búsqueda de direcciones donde no importa el pedacito más significativo - es decir, todos nuestros datos nombre tendrá el mismo pedacito más significativo. Esto significa que nuestra dirección es efectivamente 15 pedacitos largos. 2 ^ 15 es 32768 direcciones diferentes para nuestros datos almacenados. Vamos a mirar esto en más detalle en el siguiente tutorial para que no te preocupes si es un poco confuso en este punto.

Ahora ya sabes cómo utilizar tablas de búsqueda y los punteros X, Y y Z para simplificar la escritura de código.

Demos ahora el programa completo con estas innovaciones incluidas.

Artículos Relacionados

Tutorial de ensamblador AVR 11

Tutorial de ensamblador AVR 11

Bienvenido a Tutorial 11!En este breve tutorial, finalmente vamos a construir la primera parte de nuestro proyecto final.Lo primero que debes hacer es ir al último paso de este tutorial y ver el video. Luego vienen aquí. [pausa mientras haces eso...]
Tutorial de ensamblador AVR 1

Tutorial de ensamblador AVR 1

He decidido escribir una serie de tutoriales sobre cómo escribir programas del lenguaje ensamblador para el Atmega328p que es el microcontrolador utilizado en el Arduino. Si la gente sigue interesada voy a seguir poner a uno una semana o así hasta qu
Tutorial de ensamblador AVR 6

Tutorial de ensamblador AVR 6

Bienvenido a Tutorial 6!Tutorial de hoy será corto donde desarrollamos un método sencillo para comunicar datos entre uno atmega328p y otro con dos puertos conectan. Luego tomar los dados rodillo del Tutorial 4 y el analizador de registro de 5 Tutoria
Tutorial de ensamblador AVR 8

Tutorial de ensamblador AVR 8

Bienvenido a Tutorial 8!En este breve tutorial vamos a tomar un poco de diversión de introducir nuevos aspectos de la programación de lenguaje ensamblador para mostrar cómo mover nuestros componentes prototipos a un separado "" del circuito impr
Tutorial de ensamblador AVR 9

Tutorial de ensamblador AVR 9

Bienvenido a Tutorial 9.Hoy nos muestra cómo controlar un display de 7 segmentos y un display de 4 dígitos utilizando nuestro código de lenguaje ensamblador ATmega328P y AVR. En el curso de hacer esto que tendremos que hacer desvíos cómo utilizar la
Tutorial de ensamblador AVR 7

Tutorial de ensamblador AVR 7

Bienvenido a Tutorial 7!Hoy vamos a ver primero cómo limpiar un teclado y luego se muestra cómo utilizar los puertos de entrada analógicos para comunicarse con el teclado.Esto lo haremos utilizando como entrada de interrupciones y un solo cable. Se a
Tutorial de ensamblador AVR 10

Tutorial de ensamblador AVR 10

Bienvenido al Tutorial de 10!Lo siento que tomó tanto tiempo para salir esta próxima entrega, pero esta es una época bastante ajetreada del año. En cualquier caso, aquí está!Hemos recorrido un largo camino y probablemente ya eres lo suficientemente c
Tutorial de ensamblador AVR 5

Tutorial de ensamblador AVR 5

Hoy vamos a tomar un vistazo a los distintos lugares de la memoria en el microcontrolador Atmega328p y ver si podemos comprender mejor cómo se almacenan las cosas, donde se almacenan y cómo funcionan los punteros y tablas de búsqueda.El tutorial se s
Tutorial de ensamblador AVR 2

Tutorial de ensamblador AVR 2

Este tutorial es una continuación de "AVR Assembler Tutorial 1"Si no has ido por 1 Tutorial debe parar ahora y hacer que uno primero.En este tutorial vamos a continuar nuestro estudio de programación del lenguaje ensamblador de la atmega328p en
Tutorial de ensamblador AVR 3

Tutorial de ensamblador AVR 3

Bienvenido a tutorial número 3!Antes de empezar quiero hacer un punto filosófico. No tenga miedo de experimentar con los circuitos y el código que estamos construyendo en estos tutoriales. Cambiar los cables alrededor de añadir nuevos componentes, sa
Un enfoque avanzado de programación de Arduino y AVR

Un enfoque avanzado de programación de Arduino y AVR

Este instructable es obligada lectura para todo aquel que esté familiarizado con núcleo AVR virutas y Arduino.Bien, para ser más específicos, al leer el instructivo, usted será capaz de:1) saber la diferencia correcta entre el AVR y Arduino.2) progra
Placa de desarrollo para microcontrolador Attiny84

Placa de desarrollo para microcontrolador Attiny84

Se trata de una placa de desarrollo para microcontrolador Attiny84. Tha Attiny84 chip tiene 11 pines direccionables con el IDE de Arduino, 8k de memoria flash para el almacenamiento de programa y 512 bytes de RAM disponible para las variables de pila
La tortura de Raven, aguda

La tortura de Raven, aguda

este es un pequeño dispositivo que diseñé para el sencillo propósito de ser discretamente molesta. Espera una cantidad predeterminada de tiempo, y luego empieza a emitir pitidos agudos. Yo he programado mina para tomar ventaja de una propiedad intere
Cariño, encogi lo Arduino: pasar de Arduino a ATtiny y escribir el código en C de AVR puro

Cariño, encogi lo Arduino: pasar de Arduino a ATtiny y escribir el código en C de AVR puro

Arduino es una plataforma de software y de gran dura - pero con todas sus características también está un poco hinchado y a menudo necesita sólo una pequeña parte de todas las funciones. A veces el proyecto requiere dispositivos más pequeños y más ba