Tabla de contenido:

Tutorial 1 del ensamblador AVR: 5 pasos
Tutorial 1 del ensamblador AVR: 5 pasos

Video: Tutorial 1 del ensamblador AVR: 5 pasos

Video: Tutorial 1 del ensamblador AVR: 5 pasos
Video: 05.1 Curso Programación de AVR en Ensamblador (Como funcionan los registros DDR, PORT y PIN) 2024, Mes de julio
Anonim
Tutorial de ensamblador AVR 1
Tutorial de ensamblador AVR 1

He decidido escribir una serie de tutoriales sobre cómo escribir programas en lenguaje ensamblador para el Atmega328p, que es el microcontrolador utilizado en Arduino. Si la gente sigue interesada, seguiré publicando uno a la semana hasta que se me acabe el tiempo libre o la gente deje de leerlos.

Estoy ejecutando Arch linux y estoy trabajando en un atmega328p-pu configurado en una placa de pruebas. Puede hacerlo de la misma manera que yo o simplemente puede conectar un arduino a su computadora y trabajar en el microcontrolador de esa manera.

Estaremos escribiendo programas para el 328p como el que se encuentra en la mayoría de los arduino, pero debes tener en cuenta que estos mismos programas y técnicas también funcionarán para cualquiera de los microcontroladores Atmel y más adelante (si hay interés) trabajaremos con algunos de los otros también. Los detalles del microcontrolador se pueden encontrar en las hojas de datos de Atmel y en el manual del conjunto de instrucciones. Los adjunto a este instructable.

Esto es lo que necesitará:

1. Una placa de pruebas

2. Un Arduino, o simplemente el microcontrolador

3. Una computadora con Linux

4. El ensamblador avra usando git: git clone https://github.com/Ro5bert/avra.git o si está usando ubuntu o un sistema basado en Debian simplemente escriba "sudo apt install avra" y obtendrá tanto el ensamblador avr y avrdude. SIN EMBARGO, si obtiene la última versión usando github, también obtendrá todos los archivos de inclusión necesarios, en otras palabras, ya tiene los archivos m328Pdef.inc y tn85def.inc.

5. avrdude

El conjunto completo de mis tutoriales de ensamblador AVR se puede encontrar aquí:

Paso 1: construya una placa de prueba

Construye una placa de prueba
Construye una placa de prueba

Simplemente puede usar su arduino y hacer todo en estos tutoriales sobre eso si lo desea. Sin embargo, dado que estamos hablando de codificación en lenguaje ensamblador, nuestra filosofía es inherentemente eliminar todos los periféricos e interactuar directamente con el microcontrolador en sí. Entonces, ¿no crees que sería más divertido hacerlo de esa manera?

Para aquellos de ustedes que estén de acuerdo, pueden sacar el microcontrolador de su arduino y luego comenzar construyendo un "Arduino de tablero" siguiendo las instrucciones aquí:

En la imagen, muestro mi configuración, que consta de dos Atmega328p independientes en una placa de pruebas grande (quiero poder mantener el tutorial anterior cableado y cargado en un microcontrolador mientras trabajo en el siguiente). Tengo la fuente de alimentación configurada para que el riel superior sea de 9 V y todos los demás estén a 5 V del regulador de voltaje. También utilizo una placa de conexión FT232R para programar los chips. Los compré y les puse cargadores de arranque yo mismo, pero si acabas de sacar uno de un Arduino, entonces ya está bien.

Tenga en cuenta que si está probando esto con un ATtiny85, puede obtener el Sparkfun Tiny Programmer aquí: https://www.sparkfun.com/products/11801# y luego simplemente conéctelo al puerto USB de su computadora. Primero deberá instalar un gestor de arranque en el Attiny85 y la forma más fácil es usar el IDE de Arduino. Sin embargo, deberá hacer clic en el archivo y las preferencias, y luego agregar esta URL de nuevos tableros: https://raw.githubusercontent.com/damellis/attiny/ide-1.6.x-boards-manager/package_damellis_attiny_index.json que le permite instalar el gestor de arranque (si su ATtiny85 aún no viene con uno).

Paso 2: Instale el ensamblador y Avrdude

Ahora puede descargar e instalar el ensamblador y avrdude desde los enlaces que se proporcionan en el primer paso de este tutorial. Es probable que si ya ha estado trabajando con Arduino, ya tenga instalado avrdude.

Después de haber instalado avra, notará que hay un subdirectorio que viene con él llamado "fuentes" y dentro de ese directorio hay un montón de archivos de inclusión. Estos son todos los microcontroladores que puede programar con avra. Notará de inmediato que no hay ningún archivo para el 328p que estamos usando aquí. He adjuntado uno. El archivo debe llamarse m328Pdef.inc y debe colocarlo dentro del directorio incluye o en cualquier otro lugar que desee. Lo incluiremos en nuestros programas de lenguaje ensamblador. Todo esto hace es dar a cada uno de los registros en el microcontrolador los nombres de la hoja de datos para que no tengamos que usar sus nombres hexadecimales. El archivo de inclusión anterior contiene "directivas pragma" ya que fue diseñado para programación C y C ++. Si se cansa de ver al ensamblador escupir quejas de "ignorando la directiva pragma", simplemente ingrese al archivo y elimine o comente todas las líneas que comienzan con #pragma

Bien, ahora que tiene su microcontrolador listo, su ensamblador listo y su programador listo, podemos escribir nuestro primer programa.

Nota: Si está utilizando ATtiny85 en lugar de ATmega328P, entonces necesita un archivo de inclusión diferente llamado tn85def.inc. Lo adjuntaré también (tenga en cuenta que tuve que llamarlo tn85def.inc.txt para que Instructables me permitiera cargarlo). SIN EMBARGO, si obtuvo el ensamblador avra de github, entonces ya tiene ambos archivos con él. Así que recomiendo obtenerlo y compilarlo usted mismo: git clone

Paso 3: Hola mundo

El objetivo de este primer tutorial es construir el primer programa estándar que uno escribe cuando aprende un nuevo idioma o explora una nueva plataforma electrónica. "¡Hola Mundo!." En nuestro caso, simplemente queremos escribir un programa en lenguaje ensamblador, ensamblarlo y subirlo a nuestro microcontrolador. El programa hará que se encienda un LED. Hacer que un LED "parpadee" como lo hace para el programa normal de Arduino hello world es en realidad un programa mucho más complicado en lenguaje ensamblador, por lo que no lo haremos todavía. Vamos a escribir el código "básico" más simple con un mínimo de cosas innecesarias.

Primero conecte un LED de PB5 (vea el diagrama de pines) que también se llama Digital Out 13 en un arduino, a una resistencia de 220 ohmios, luego a GND. Es decir.

PB5 - LED - R (220 ohmios) - TIERRA

Ahora a escribir el programa. Abra su editor de texto favorito y cree un archivo llamado "hello.asm"

; hola.asm

; enciende un LED que está conectado a PB5 (salida digital 13).incluye "./m328Pdef.inc" ldi r16, 0b00100000 out DDRB, r16 out PortB, r16 Start: rjmp Start

Lo de arriba es el código. Lo revisaremos línea por línea en un minuto, pero primero asegurémonos de que podemos hacerlo funcionar en su dispositivo.

Después de haber creado el archivo, luego en una terminal lo ensambla de la siguiente manera:

avra hello.asm

esto ensamblará su código y creará un archivo llamado hello.hex que podemos cargar de la siguiente manera:

avrdude -p m328p -c stk500v1 -b 57600 -P / dev / ttyUSB0 -U flash: w: hello.hex

Si está utilizando un arduino de tablero, tendrá que presionar el botón de reinicio en el arduino de tablero justo antes de ejecutar el comando anterior. Tenga en cuenta que también puede tener que agregar un sudo al frente o ejecutarlo como root. También tenga en cuenta que en algunos arduino (como el Arduino UNO) probablemente tendrá que cambiar la tasa de bits a -b 115200 y el puerto -P / dev / ttyACM0 (si recibe un error de avrdude sobre una firma de dispositivo no válida, simplemente agregue un - F al comando)

Si todo ha funcionado como debería, ahora tendrá un LED encendido … "¡Hola mundo!"

Si está utilizando ATtiny85, el comando avrdude será:

avrdude -p attiny85 -c usbtiny -U flash: w: hola.hex

Paso 4: Hello.asm línea por línea

Para finalizar este tutorial introductorio, revisaremos el programa hello.asm línea por línea para ver cómo funciona.

; hola.asm

; enciende un LED que está conectado a PB5 (salida digital 13)

El ensamblador ignora todo lo que aparece después de un punto y coma y, por lo tanto, estas dos primeras líneas son simplemente "comentarios" que explican lo que hace el programa.

.incluir "./m328Pdef.inc"

Esta línea le dice al ensamblador que incluya el archivo m328Pdef.inc que descargó. Es posible que desee poner esto en un directorio de archivos de inclusión similares y luego cambiar la línea anterior para que apunte allí.

ldi r16, 0b00100000

ldi significa "carga inmediata" y le dice al ensamblador que tome un registro de trabajo, r16 en este caso, y cargue un número binario en él, 0b00100000 en este caso. El 0b al frente dice que nuestro número está en binario. Si quisiéramos, podríamos haber elegido otra base, como hexadecimal. En ese caso, nuestro número habría sido 0x20, que es hexadecimal para 0b00100000. O podríamos haber usado 32, que es un decimal en base 10 para el mismo número.

Ejercicio 1: intente cambiar el número en la línea anterior a hexadecimal y luego a decimal en su código y verifique que todavía funciona en cada caso.

Sin embargo, el uso de binarios es más simple debido a la forma en que funcionan los puertos y registros. Discutiremos los puertos y registros de atmega328p con más detalle en futuros tutoriales, pero por ahora solo declararé que estamos usando r16 como nuestro "registro de trabajo", lo que significa que solo lo usaremos como una variable que almacenamos. números en. Un "registro" es un conjunto de 8 bits. Es decir, 8 puntos que pueden ser 0 o 1 ("desactivado" o "activado"). Cuando cargamos el número binario 0b00100000 en el registro usando la línea anterior, simplemente hemos almacenado ese número en el registro r16.

fuera DDRB, r16

Esta línea le dice al compilador que copie el contenido del registro r16 en el registro DDRB. DDRB significa "Registro de dirección de datos B" y configura los "pines" en el PuertoB. En el mapa de distribución de pines del 328p puede ver que hay 8 pines etiquetados como PB0, PB1,…, PB7. Estos pines representan los "bits" de "PortB" y cuando cargamos el número binario 00100000 en el registro DDRB estamos diciendo que queremos PB0, PB1, PB2, PB3, PB4, PB6 y PB7 configurados como pines de ENTRADA ya que tienen 0 en ellos, y PB5 se establece como un pin de SALIDA ya que ponemos un 1 en ese lugar.

hacia fuera PortB, r16

Ahora que hemos fijado las direcciones de los pines, ahora podemos establecer los voltajes en ellos. La línea anterior copia el mismo número binario de nuestro registro de almacenamiento r16 a PortB. Esto establece todos los pines en 0 voltios, excepto el pin PB5 en ALTO, que es de 5 voltios.

Ejercicio 2: Tome un multímetro digital, conecte el cable negro a tierra (GND) y luego pruebe cada uno de los pines PB0 a PB7 con el cable rojo. ¿Son los voltajes en cada uno de los pines exactamente los correspondientes a poner 0b00100000 en PortB? Si hay alguno que no lo sea, ¿por qué cree que es así? (ver el mapa de pines)

Comienzo:

Inicio rjmp

Finalmente, la primera línea de arriba es una "etiqueta" que etiqueta un lugar en el código. En este caso, etiquetar ese lugar como "Inicio". La segunda línea dice "salto relativo a la etiqueta Inicio". El resultado neto es que la computadora se coloca en un bucle infinito que sigue volviendo al inicio. Necesitamos esto porque no podemos hacer que el programa termine o se caiga por un precipicio, el programa tiene que seguir funcionando para que la luz permanezca encendida.

Ejercicio 3: Elimine las dos líneas anteriores de su código para que el programa se caiga por un precipicio. ¿Lo que sucede? Debería ver algo que se parezca al programa tradicional de "parpadeo" utilizado por Arduino como su "¡hola mundo!". ¿Por qué crees que actúa de esta manera? (Piense en lo que debe suceder cuando el programa se cae por un precipicio …)

Paso 5: Conclusión

Si has llegado tan lejos, ¡felicidades! Ahora puede escribir código ensamblador, ensamblarlo y cargarlo en su microcontrolador.

En este tutorial ha aprendido a utilizar los siguientes comandos:

ldi hregister, number carga un número (0-255) en un registro de la mitad superior (16-31)

out ioregister, register copia un número de un registro de trabajo a un registro de E / S

rjmp label salta a la línea del programa etiquetado por "label" (que no puede estar más allá de 204 instrucciones, es decir, salto relativo)

Ahora que estos conceptos básicos están fuera del camino, podemos continuar escribiendo código más interesante y circuitos y dispositivos más interesantes sin tener que discutir la mecánica de compilación y carga.

Espero que hayas disfrutado de este tutorial introductorio. En el siguiente tutorial agregaremos otro componente de circuito (un botón) y expandiremos nuestro código para incluir puertos de entrada y decisiones.

Recomendado: