Die Software für ihre bisherigen Mikroelektronik Projekte haben sie höchstwahrscheinlich in der Arduino IDE in der Programmiersprache C geschrieben. Die Befehle der Arduino IDE sind relativ intuitiv und einsteigerfreundlich.
Falls Sie sich schon einmal gefragt haben, wie der Mikrocontroller intern funktioniert, lernen Sie in dieser Blogreihe den Aufbau und die Assembler Sprache kennen. Diese ist eine low level Programmiersprache und somit deutlich Hardware näher als zum Beispiel C++.
Die Assembly Programmiersprache ist nicht nur nützlich, um die Funktionsweise der Prozessoren zu verstehen, sondern bietet auch den Vorteil, dass nur minimal Speicher benötigt wird und die einzelnen Befehle deutlich schneller abgearbeitet werden können.
Deshalb findet die Assemblersprache auch noch heute Verwendung in Zeitkritischen Systemen oder wenn nur wenig Speicherplatz zur Verfügung steht, wie zum Beispiel in Compilern oder Embedded Systems.
Einführung
Die Assemblersprache wurde 1947 von der Britin Kathleen Booth entwickelt. In den 1980er Jahren wurde diese aufgrund leistungsstärkerer Rechnern weitgehend durch hohe Programmiersprachen wie C abgelöst.
In Assembler ist der Aufruf von direkten Prozessorbefehlen möglich, dies umfasst hauptsächlich das Schreiben und Lesen von Speicherregistern, Programmfluss Steuerung und auch logische und mathematische Operationen.
Das Problem dieser Programmiersprache ist aber, dass für die Programmierung vertiefte Kenntnisse wie zum Beispiel über den Speicheraufbau notwendig sind und die Befehle anfangs komplex wirken können.
Aufbau ATmega328P
Am Anfang des Adressraums befinden sich die 32 allgemeinen Register (R0 bis R31). Diese Register sind direkt zugänglich und werden für alle arithmetischen und logischen Operationen sowie für den Datentransfer verwendet.
Unmittelbar danach folgt der I/O-Registerbereich, der alle spezialisierten Steuer- und Statusregister enthält, mit denen Peripherieeinheiten (wie Ports, Timer, UART usw.) konfiguriert und kontrolliert werden.
Anschließend beginnt der SRAM-Bereich (Statischer RAM), der als Datenspeicher dient. In diesem Speicherbereich werden temporäre Variablen und der Stack abgelegt.
Der Flash-Speicher ist ein getrennter Speicherbereich, in dem unter anderem das Programm selbst gespeichert wird. Der ATmega328P verfügt über 32 Kilobyte Flash.
Daneben besitzt der ATmega328P auch 1 Kilobyte EEPROM, einen nichtflüchtigen Speicher, der separat adressiert ist.

Abbildung 1: Blockdiagramm Aufbau ATmega328P
Die Register R0 bis R31, welche in den Beispielen für arithmetische Operationen verwendet werden, befinden sich in der Grafik im "AVR CPU".
Zahlensysteme
Wir benutzen im Alltag Zahlen wie 180 oder 2380. Dabei handelt es sich um sogenannte Dezimalzahlen, was heißt, dass wir Potenzen der Zahl 10 verwenden.

Abbildung 2: Dezimalsystem
Dies hat unter anderem den Hintergrund, dass wir 10 Finger haben.
Binärsystem
Da der Speicher und alle Prozesse im Computer binär ablaufen, ist hierfür das geläufige Dezimalsystem nicht geeignet, da im Speicher nur zwei Zustände (Spannung bzw. keine Spannung) möglich sind. Hierfür wurde das Binärsystem entwickelt. Dieses arbeitet mit Vielfachen der Zahl 2.
Zum Beispiel:

Abbildung 3: Binärsystem
Die Programmschreibweise der Binärzahlen sieht wie folgt aus:
0b10110100
Hexadezimalsystem
Um auch komplexere Operationen verstehen zu können, ist die Kenntnis der verschiedenen Zahlensysteme wichtig. Neben dem Binär- und Dezimalsystem gibt es noch das Hexadezimal- und Oktal-System.
Wie am Namen schon zu erkennen ist, arbeiten das Oktalsystem mit 8er und das Hexadezimalsystem mit 16er Potenzen.
Das relevanteste ist das Hexadezimalsystem, wobei in diesem System Buchstaben für alle zweistelligen Zahlen verwendet werden. Das heißt A=10; B=11; … ; F=15

Abbildung 4: Hexadezimalsystem
Die Programmschreibweise der Hexadezimalzahlen sieht wie folgt aus:
0xB4
Dennoch bieten im Alltag Hilfsmittel wie ein Wissenschaftlicher Taschenrechner oder eine Umrechnungswebsite den Vorteil einer schnelleren Umrechnung von dem uns bekannten Dezimalsystem in die anderen Systeme.
16bit
Da der ATmega 328P ein 8 bit Prozessor ist, hat ein Speicher Register nur eine Länge von 8 bit, was einem Zahlenraum von 0-255 entspricht.
Dieser Zahlenraum ist nicht immer ausreichend. Wenn Sie zum Beispiel einen Pointer auf eine Speicheradresse speichern wollen, würde dies bereits zu Problemen führen, da die Adressen einer Länge von 16 bit entsprechen.
Um diese trotzdem speichern zu können, ist es möglich, die oberen beziehungsweise unteren 8 bit in zwei separate Registern zu speichern.
Somit kann eine Zahl
0000111111110000
auf die Register wie folgt aufgeteilt werden:
00001111 (high)
und
11110000 (low)
Programme
Software Tools Download:
Es werden zwei Software-Tools benötigt. Zum einen ein Assembler, um den Code in eine kompilierte Datei umzuwandeln und ein Programmer, um die kompilierte Hex- Datei auf das Board zu übertragen.
Assembler
Als Assembler empfiehlt sich die Software avra welche manuell auf ihrem Computer kompiliert werden muss.
Linux:
Unter Linux ist die Installation einfach, da die meisten Betriebssysteme, wie Ubuntu; Fedora; Manjaro, den make Befehl bereitstellen.
Erstellen Sie zuerst ein Abbild der Dateien des GitHub Repository auf Ihrem Computer. Hierfür können Sie den Git-Clone- Befehl benutzen.
cd Downloads
git clone https://github.com/Ro5bert/avra.git
Alternativ können Sie die Dateien auch direkt vom Github Repository herunterladen.
Nachdem sich die Dateien auf ihrem Computer befindet, wechseln Sie in den Ordner über das Terminal, wie folgt:
cd Downloads/avra
Führen Sie im Anschluss den Behl
make
aus.
Zuletzt muss die kompilierte Datei noch installiert werden. Hierfür kann einfach der
sudo make install
Befehl ausgeführt werden.
Jetzt ist die Kompiler Software erfolgreich auf ihrem Rechner installiert. Das weitere Vorgehen finden Sie im Abschnitt Anwendung
Windows:
Natürlich können Sie das Programm auch unter Windows installieren, hierfür muss aber wie auch unter Linux das Programm erst kompiliert werden. Hierfür wird die MS Visual Studio 2019 IDE empfohlen, welche in der Community Version kostenlos verfügbar ist.
Eine detaillierte Beschreibung der Schritte ist in einer Anleitung auf dem GitHub Repository verfügbar.
AVRDUDE
Für das Übertragen der kompilierten Dateien auf den Mikrocontroller eignet sich die Software AVRDUDE.
Diese wird normalerweise mit der Arduino IDE bereits installiert, da diese die Software ebenfalls zur Datenübertragung benutzt.
Sollten Sie die Software trotzdem selbst installieren wollen, ist dies natürlich auch möglich.
Linux
Führen Sie folgenden Befehl im Terminal aus:
sudo apt-get install avrdude
Windows
Im GitHub repository können Sie die aktuelle Software für Ihren Prozessor herunterladen.
Anwendung
Nach erfolgreicher Installation können Sie mit einem Texteditor oder Code Editor eine Datei mit Dateiendung .asm erstellen. Zum kompilieren führen Sie im Terminal folgenden Befehl im Verzeichnis der Datei aus:
avra Programmname.asm
Nun wurde ein Programmname.hex Datei erzeugt. Diese Binärdatei kann nun auf das Board geladen werden.
Dies kann mit folgendem Befehl ausgeführt werden:
avrdude -c arduino -p m328p -P <Port> -b 115200 -U flash:w:"Path/File.hex":a
Passen Sie hier den Seriellen Port und den Dateipfad entsprechend an.
Den Seriellen Port können Sie entweder in Windows im Gerätemanager ermitteln und unter Linux mit dmesg | grep tty oder alternativ in der Arduino IDE.
Alternativ können Sie hierfür auch die grafische Benutzeroberfläche AVRDUDESS benutzen. Diese verwendet denselben Befehl wie die Kommandozeilenversion, aber die Konfiguration und Auswahl der Parameter ist deutlich intuitiver und dadurch auch angenehmer.

Abbildung 5: Grafische Benutzeroberfläche AVRDUDESS
Fazit
Nachdem in diesem Blogbeitrag die ersten Grundlagen geschaffen wurden, geht es im nächsten Teil um die Anwendung in einem kurzen Beispielprojekt.
Viel Spass beim Nachbauen :)
Referenzen der Blog Reihe:
2 commentaires
Leopold Gann
Bezugnehmend auf ihr Umrechnungsbeispiel binär/dezimal – 10110100=180 ist zwar richtig, aber die 2er-Potenzen sind jedoch verkehrt rum angegeben …
Roman
Vielen Dank für diesen anschaulichen Einstieg in die Assembler‑Programmierung mit dem ATmega328P.
Ich freue mich sehr auf die nächsten Teile des Kurses!
Eine kleine Rückmeldung zum Blockdiagramm:
Beim ersten Lesen war ich irritiert, weil ich die 32 allgemeinen Register (R0–R31) und den I/O‑Registerbereich nicht direkt im Bild verortet habe. Mir wurde erst später klar, dass beide Registerarten fest im AVR‑CPU‑Block stecken und deshalb nicht als eigene Kästchen auftauchen. Vielleicht hilft künftigen Leserinnen und Lesern ein kurzer Hinweis im Text (oder eine kleine Markierung im Diagramm), dass das Register‑File und der I/O‑Registerraum „im Inneren“ der CPU bzw. entlang des Datenbusses liegen.
Ansonsten gefällt mir der Kurs bislang sehr gut – weiter so!