Sommario:

Tutorial Assembler AVR 1: 5 passaggi
Tutorial Assembler AVR 1: 5 passaggi

Video: Tutorial Assembler AVR 1: 5 passaggi

Video: Tutorial Assembler AVR 1: 5 passaggi
Video: AVR Ассемблер. Урок 1. Вводный. AVR Assembler. Lesson 1. Promo. 2024, Dicembre
Anonim
Tutorial assemblatore AVR 1
Tutorial assemblatore AVR 1

Ho deciso di scrivere una serie di tutorial su come scrivere programmi in linguaggio assembly per l'Atmega328p che è il microcontrollore utilizzato in Arduino. Se le persone rimangono interessate, continuerò a pubblicarne una alla settimana o giù di lì fino a quando non finirò il tempo libero, altrimenti la gente smetterà di leggerle.

Sto eseguendo Arch linux e sto lavorando su un atmega328p-pu configurato su una breadboard. Puoi farlo allo stesso modo di me o puoi semplicemente collegare un arduino al tuo computer e lavorare in questo modo sul microcontrollore.

Scriveremo programmi per 328p come quello che è nella maggior parte degli arduino, ma dovresti notare che questi stessi programmi e tecniche funzioneranno anche per qualsiasi microcontrollore Atmel e in seguito (se c'è interesse) lavoreremo con alcuni di anche gli altri. I dettagli del microcontrollore possono essere trovati nelle schede tecniche Atmel e nel Manuale del set di istruzioni. Li allego a questo istruibile.

Ecco di cosa avrai bisogno:

1. Una breadboard

2. Un Arduino, o solo il microcontrollore

3. Un computer con Linux

4. L'assembler avra che usa git: git clone https://github.com/Ro5bert/avra.git o se stai usando Ubuntu o un sistema basato su Debian, digita semplicemente "sudo apt install avra" e otterrai entrambi l'assembler avr e avventuroso. TUTTAVIA, se ottieni l'ultima versione usando github, otterrai anche tutti i file include necessari, in altre parole ha già i file m328Pdef.inc e tn85def.inc.

5. avrdude

Il set completo dei miei tutorial sull'assemblatore AVR può essere trovato qui:

Passaggio 1: costruire una scheda di test

Costruisci una tavola di prova
Costruisci una tavola di prova

Puoi semplicemente usare il tuo arduino e fare tutto in questi tutorial su questo, se lo desideri. Tuttavia, poiché stiamo parlando di codifica in linguaggio assembly, la nostra filosofia è intrinsecamente quella di eliminare tutte le periferiche e interagire direttamente con il microcontrollore stesso. Quindi non pensi che sarebbe più divertente farlo in questo modo?

Per quelli di voi che sono d'accordo, è possibile estrarre il microcontrollore dal proprio arduino e quindi iniziare a costruire un "Breadboard Arduino" seguendo le istruzioni qui:

Nella foto mostro la mia configurazione che consiste in due Atmega328p standalone su una grande breadboard (voglio essere in grado di mantenere il tutorial precedente cablato e caricato su un microcontrollore mentre si lavora su quello successivo). Ho impostato l'alimentatore in modo che il binario più in alto sia a 9 V e tutti gli altri siano a 5 V dal regolatore di tensione. Uso anche una scheda breakout FT232R per programmare i chip. Li ho comprati e ho messo i bootloader su di loro da solo, ma se ne hai appena estratto uno da un Arduino, allora va già bene.

Nota che se stai provando questo con un ATtiny85, puoi semplicemente ottenere il programmatore Sparkfun Tiny qui: https://www.sparkfun.com/products/11801# e quindi collegarlo semplicemente alla porta USB del tuo computer. Dovrai prima installare un bootloader su Attiny85 e il modo più semplice è usare l'IDE Arduino. Tuttavia, dovrai fare clic su file e preferenze, quindi aggiungere questo URL di New Boards: https://raw.githubusercontent.com/damellis/attiny/ide-1.6.x-boards-manager/package_damellis_attiny_index.json che ti consente di installare il bootloader (se il tuo ATtiny85 non ne è già stato fornito uno.)

Passaggio 2: installa l'Assembler e Avrdude

Ora puoi scaricare e installare l'assemblatore e avrdude dai collegamenti forniti nel primo passaggio di questo tutorial. È probabile che se hai già lavorato con Arduino, hai già installato avrdude.

Dopo aver installato avra noterai che c'è una sottodirectory chiamata "sources" e all'interno di quella directory ci sono un mucchio di file di inclusione. Questi sono tutti i microcontrollori che puoi programmare con avra. Noterai subito che non c'è nessun file per il 328p che stiamo usando qui. ne ho allegato uno. Il file dovrebbe essere chiamato m328Pdef.inc e dovresti metterlo all'interno della directory include o in qualsiasi altro posto tu voglia. Lo includeremo nei nostri programmi in linguaggio assembly. Tutto questo è dare a ciascuno dei registri nei nomi del microcontrollore dal foglio dati in modo che non dobbiamo usare i loro nomi esadecimali. Il file include sopra contiene "direttive pragma" poiché è stato progettato per la programmazione C e C++. Se sei stanco di vedere l'assemblatore sputare reclami "ignoring pragma direction" basta entrare nel file ed eliminare o commentare tutte le righe che iniziano con #pragma

Ok, ora che hai il tuo microcontrollore pronto, il tuo assembler pronto e il tuo programmatore pronto, possiamo scrivere il nostro primo programma.

Nota: se si utilizza ATtiny85 invece di ATmega328P, è necessario un file di inclusione diverso chiamato tn85def.inc. Lo allegherò anche (nota che dovevo chiamarlo tn85def.inc.txt in modo che Instructables mi permettesse di caricarlo.) TUTTAVIA, se hai ottenuto l'assemblatore avra da github, hai già entrambi questi file con esso. Quindi consiglio di ottenerlo e compilarlo da solo: git clone

Passaggio 3: Ciao mondo

L'obiettivo di questo primo tutorial è costruire il primo programma standard che si scrive quando si impara una nuova lingua o si esplora una nuova piattaforma elettronica. "Ciao mondo!." Nel nostro caso vogliamo semplicemente scrivere un programma in linguaggio assembly, assemblarlo e caricarlo sul nostro microcontrollore. Il programma farà accendere un LED. Far "lampeggiare" un LED come fanno per il normale programma Arduino Hello World è in realtà un programma molto più complicato in linguaggio assembly e quindi non lo faremo ancora. Scriveremo il codice "bare bone" più semplice con un minimo di inutili fronzoli.

Prima collega un LED da PB5 (vedi lo schema dei piedini) che è anche chiamato Digital Out 13 su un arduino, a un resistore da 220 ohm, quindi a GND. Cioè.

PB5 -- LED -- R (220 ohm) -- GND

Ora per scrivere il programma. Apri il tuo editor di testo preferito e crea un file chiamato "hello.asm"

;ciao.asm

; accende un LED collegato a PB5 (digital out 13).include "./m328Pdef.inc" ldi r16, 0b00100000 out DDRB, r16 out PortB, r16 Start: rjmp Start

Quello sopra è il codice. Lo esamineremo riga per riga in un minuto, ma prima assicuriamoci di farlo funzionare sul tuo dispositivo.

Dopo aver creato il file, in un terminale lo assembli come segue:

avra ciao.asm

questo assemblerà il tuo codice e creerà un file chiamato hello.hex che possiamo caricare come segue:

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

se stai usando una breadboard arduino dovrai premere il pulsante di ripristino sulla breadboard arduino appena prima di eseguire il comando sopra. Nota che potresti anche dover aggiungere un sudo davanti o eseguirlo come root. Nota anche che su alcuni arduino (come Arduino UNO) dovrai probabilmente cambiare il bitrate in -b 115200 e la porta -P /dev/ttyACM0 (se ricevi un errore da avrdude su una firma del dispositivo non valida basta aggiungere un - F al comando)

Se tutto ha funzionato come dovrebbe ora avrai un LED acceso….. "Hello World!"

Se stai usando ATtiny85, il comando avrdude sarà:

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

Passaggio 4: Hello.asm riga per riga

Per finire questo tutorial introduttivo, esamineremo il programma hello.asm riga per riga per vedere come funziona.

;ciao.asm

; accende un LED collegato a PB5 (uscita digitale 13)

Tutto ciò che segue un punto e virgola viene ignorato dall'assemblatore e quindi queste prime due righe sono semplicemente "commenti" che spiegano cosa fa il programma.

.include "./m328Pdef.inc"

Questa riga dice all'assemblatore di includere il file m328Pdef.inc che hai scaricato. Potresti volerlo inserire in una directory di file di inclusione simili e quindi modificare la riga sopra in modo che punti lì.

ldi r16, 0b0010000

ldi sta per "load immediate" e dice all'assemblatore di prendere un registro funzionante, r16 in questo caso, e caricarci un numero binario, 0b0010000 in questo caso. Lo 0b davanti dice che il nostro numero è binario. Se avessimo voluto avremmo potuto scegliere un'altra base, come l'esadecimale. In tal caso il nostro numero sarebbe stato 0x20 che è esadecimale per 0b0010000. Oppure avremmo potuto usare 32 che è la base 10 decimale per lo stesso numero.

Esercizio 1: Prova a cambiare il numero nella riga sopra in esadecimale e poi in decimale nel tuo codice e verifica che funzioni ancora in ogni caso.

L'uso del binario è però più semplice a causa del modo in cui funzionano le porte e i registri. Discuteremo le porte e i registri di atmega328p in modo più dettagliato nei tutorial futuri, ma per ora dirò solo che stiamo usando r16 come nostro "registro di lavoro", il che significa che lo useremo solo come variabile che memorizziamo numeri in. Un "registro" è un insieme di 8 bit. Significa 8 punti che possono essere 0 o 1 ("off" o "on"). Quando carichiamo il numero binario 0b0010000 nel registro utilizzando la riga sopra, abbiamo semplicemente memorizzato quel numero nel registro r16.

fuori DDRB, r16

Questa riga dice al compilatore di copiare il contenuto del registro r16 nel registro DDRB. DDRB sta per "Data Direction Register B" e imposta i "pin" su PortB. Sulla mappa di pinout per il 328p puoi vedere che ci sono 8 pin etichettati PB0, PB1, …, PB7. Questi pin rappresentano i "bit" di "PortB" e quando carichiamo il numero binario 00100000 nel registro DDRB stiamo dicendo che vogliamo PB0, PB1, PB2, PB3, PB4, PB6 e PB7 impostati come pin di INPUT poiché hanno Ci sono 0 e PB5 è impostato come pin OUTPUT poiché abbiamo inserito un 1 in quel punto.

fuori PortaB, r16

Ora che abbiamo fissato le direzioni dei pin, possiamo ora impostare le tensioni su di essi. La riga sopra copia lo stesso numero binario dal nostro registro di archiviazione r16 a PortB. Questo imposta tutti i pin su 0 volt tranne il pin PB5 su HIGH che è 5 volt.

Esercizio 2: Prendi un multimetro digitale, collega il cavo nero a massa (GND) e poi testa ciascuno dei pin da PB0 a PB7 con il cavo rosso. Le tensioni su ciascuno dei pin sono esattamente quelle corrispondenti a mettere 0b0010000 in PortB? Se ce ne sono altri che non lo sono, perché pensi che lo sia? (vedi la mappa dei pin)

Cominciare:

rjmp Start

Infine, la prima riga sopra è una "etichetta" che etichetta un punto nel codice. In questo caso etichettare quel punto come "Start". La seconda riga dice "salto relativo all'etichetta Start". Il risultato netto è che il computer viene inserito in un ciclo infinito che continua a tornare indietro all'inizio. Ne abbiamo bisogno perché non possiamo fare in modo che il programma finisca o cada da un dirupo, il programma deve semplicemente continuare a funzionare affinché la luce rimanga accesa.

Esercizio 3: Rimuovi le due righe precedenti dal tuo codice in modo che il programma cada da un dirupo. Che succede? Dovresti vedere qualcosa che assomiglia al tradizionale programma "blink" usato da Arduino come "ciao mondo!". Perché pensi che agisca in questo modo? (Pensa a cosa deve succedere quando il programma cade da un dirupo…)

Passaggio 5: conclusione

Se sei arrivato fin qui, congratulazioni! Ora puoi scrivere il codice assembly, assemblarlo e caricarlo sul tuo microcontrollore.

In questo tutorial hai imparato a utilizzare i seguenti comandi:

ldi hregister, numero carica un numero (0-255) in un mezzo registro superiore (16-31)

out ioregister, register copia un numero da un registro funzionante a un registro I/O

rjmp label salta alla riga del programma etichettata da "label" (che non può essere più lontana di 204 istruzioni - cioè salto relativo)

Ora che queste nozioni di base sono state eliminate, possiamo continuare a scrivere codice più interessante e circuiti e dispositivi più interessanti senza dover discutere i meccanismi di compilazione e caricamento.

Spero che questo tutorial introduttivo ti sia piaciuto. Nel prossimo tutorial aggiungeremo un altro componente del circuito (un pulsante) ed espanderemo il nostro codice per includere porte di input e decisioni.

Consigliato: