Kurz gesagt — ein programmierbarer I
C. Man entwickelt am Computer ein Programm und spielt es über ein Kabel auf den Microcontroller (kurz: µC), der dieses dann bei 5V Spannung ausführt. Somit kann man zum Beispiel komplizierte Ansteuerungen von LCD-Displays realisieren, die ohne µC oder passenden I
C fast unmöglich wären. Außerdem lässt sich bei geänderten Anforderungen leicht eine neue Version aufspielen, ohne dass an der Hardware etwas modifiziert werden muss.
Ein Microcontroller hat immer drei festgelegte Anschlüsse: Betriebsspannung (VCC), Masse (GND) und Reset. Alle restlichen Pins (die „Beinchen” des µCs) sind immer maximal zu acht in Ports organisiert. Die Ports werden mit Buchstaben benannt, die Pins mit Zahlen; beispielsweise wird der zweite Pin im PortD mit PORTD1 angesprochen (weil das Zählen in den meisten Programmiersprachen mit Null anfängt).
Wenn an einem Pin die Betriebsspannung anliegt, ist er high, ansonsten low. Für Microcontroller gibt es nichts dazwischen, da im Binärsystem nur mit Nullen und Einsen gerechnet wird.
Die folgenden Pakete werden (zusätzlich zu einem Texteditor) benötigt:
Für Debian und dessen Derivate (z.B. Ubuntu, Kubuntu und Xubuntu) gilt somit folgender Code:
$ sudo apt-get install avrdude avr-libc gcc-avr avra
Danach müssen noch die Berechtigungen angepasst werden:
$ sudo chmod a+rw /dev/ttyS0
Wir werden hauptsächlich den ATtiny13, den ATtiny2313 den ATmega8 und den ATmega16 verwenden, von Atmel gibt es aber eine ganze Reihe von Microcontrollern:
(Die Bedeutung der hervorgehobenen Teile wird im nächsten Abschnitt beschrieben.)
avrdude -p 1200
avrdude -p 2313
avrdude -p 2333
avrdude -p 2343
avrdude -p 4414
avrdude -p 4433
avrdude -p 4434
avrdude -p 8515
avrdude -p 8535
avrdude -p c128
avrdude -p c32
avrdude -p c64
avrdude -p m103
avrdude -p m128
avrdude -p m1280
avrdude -p m1281
avrdude -p m1284p
avrdude -p m128rfa1
avrdude -p m16
avrdude -p m161
avrdude -p m162
avrdude -p m163
avrdude -p m164
avrdude -p m164p
avrdude -p m168
avrdude -p m169
avrdude -p m2560
avrdude -p m2561
avrdude -p m32
avrdude -p m324p
avrdude -p m325
avrdude -p m3250
avrdude -p m328p
avrdude -p m329
avrdude -p m3290
avrdude -p m329p
avrdude -p m3290p
avrdude -p m32u4
avrdude -p m48
avrdude -p m64
avrdude -p m640
avrdude -p m644p
avrdude -p m644
avrdude -p m645
avrdude -p m6450
avrdude -p m649
avrdude -p m6490
avrdude -p m8
avrdude -p m8515
avrdude -p m8535
avrdude -p m88
avrdude -p pwm2
avrdude -p pwm2b
avrdude -p pwm3
avrdude -p pwm3b
avrdude -p t10
avrdude -p t12
avrdude -p t13
avrdude -p t15
avrdude -p t2313
avrdude -p t25
avrdude -p t26
avrdude -p t261
avrdude -p t4
avrdude -p t44
avrdude -p t45
avrdude -p t461
avrdude -p t5
avrdude -p t84
avrdude -p t85
avrdude -p t861
avrdude -p t88
avrdude -p t9
avrdude -p ucr2
avrdude -p usb1286
avrdude -p usb1287
avrdude -p usb162
avrdude -p usb646
avrdude -p usb647
avrdude -p usb82
avrdude -p x128a1
avrdude -p x128a1d
avrdude -p x128a3
avrdude -p x128a4
avrdude -p x16a4
avrdude -p x192a1
avrdude -p x192a3
avrdude -p x256a1
avrdude -p x256a3
avrdude -p x256a3b
avrdude -p x32a4
avrdude -p x64a1
avrdude -p x64a3
avrdude -p x64a4
Um vom Computer aus Dateien auf den µC spielen zu können, benötigt man eine Programmierplatine. Dabei gibt es Einsteigerboards wie das Pollinboard (Bausatz oder fertige Schaltung), das bereits einige Hardware zum Üben mitbringt. Eine andere Möglichkeit sind sogenannte ISP-Adapter, die über ein entsprechendes Kabel mit der Zielschaltung verbunden werden, ohne dort den µC aus dem Sockel nehmen zu müssen. Diese haben den Vorteil, dass man sie für mehrere Zielschaltungen verwenden kann. Beispiele sind der AVR-ISP-Adapter (Selbstbau) oder USBasp (Bausatz).
Das Programm, das die gewünschte Funktionalität bereitstellt, wird natürlich auf dem Computer mit einem beliebigen Texteditor geschrieben. Um es zu übertragen, wird eine hex-Datei benötigt, die erst durch das Kompilieren (bei C) oder Assemblieren (bei Assembler) entsteht. Diese generierte Datei kann dann über eine Programmierplatine auf den µC programmiert werden. Dazu ist das Programm avrdude da:
$ avrdude -p m8 -c ponyser -P /dev/ttyS0 -v -U flash:w:datei.hex
avrdude: AVR device initialized and ready to accept instructions
Reading | ################################################## | 100% 0.00s
avrdude: Device signature = 0x1e9309
avrdude: NOTE: FLASH memory has been specified, an erase cycle will be performed
To disable this feature, specify the -D option.
avrdude: erasing chip
avrdude: reading input file "datei.hex"
avrdude: writing flash (5462 bytes):
Writing | ################################################## | 100% 3.18s
avrdude: 5462 bytes of flash written
avrdude: verifying flash memory against datei.hex:
avrdude: load data flash data from input file datei.hex:
avrdude: input file datei.hex contains 5462 bytes
avrdude: reading on-chip flash data:
Reading | ################################################## | 100% 2.08s
avrdude: verifying ...
avrdude: 5462 bytes of flash verified
avrdude: safemode: Fuses OK
avrdude done. Thank you.
$ avrdude -p m8 -c ponyser -P /dev/ttyS0 -v -U eeprom:w:datei.eep.hex
Dieser Befehl überträgt die Datei datei.hex (-U) über die serielle Schnittstelle (-P) auf einen ATmega8 (-p m8). Der Parameter -c gibt das Interface an, -v schaltet mehr Ausgabeinformationen ein. Eine Übersicht aller verwendbaren Parameter und möglicher Interfaces gibt es im Manual.
Vor allem später, wenn man Fuses setzen will, wird einem aber die Kommandozeile doch zu umständlich. Torsten Brischalle hat eine GUI geschrieben, die intuitiv zu bedienen ist: AVR8 Burn-O-Mat
Für die Programmierung ist es evtl. wichtig oder praktischer, eine Zahl in einem speziellen Format darzustellen. Wichtig ist dabei, dass alle Darstellungen dieselbe Zahl bedeuten.
Bit Nr. | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | ||
---|---|---|---|---|---|---|---|---|---|---|
dezimaler Wert | 128 | 64 | 32 | 16 | 8 | 4 | 2 | 1 | ||
hexadezimaler Wert | 8 | 4 | 2 | 1 | 8 | 4 | 2 | 1 | ||
Beispiele: | ||||||||||
dezimal | hexadezimal | binär | ||||||||
17 | 0x11 | 0b00010001 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 1 |
60 | 0x3c | 0b00111100 | 0 | 0 | 1 | 1 | 1 | 1 | 0 | 0 |
103 | 0x67 | 0b01100111 | 0 | 1 | 1 | 0 | 0 | 1 | 1 | 1 |
41 | 0x29 | 0b00101001 | 0 | 0 | 1 | 0 | 1 | 0 | 0 | 1 |
238 | 0xf3 | 0b11110011 | 1 | 1 | 1 | 1 | 0 | 0 | 1 | 1 |
165 | 0xa5 | 0b10100101 | 1 | 0 | 1 | 0 | 0 | 1 | 0 | 1 |
Um aus einer binären Zahl eine (hexa)dezimale Zahl zu errechnen, addiert man nun die dezimalen bzw. hexadezimalen Werte aller Bits, die auf high gesetzt sind, also den Wert 1 haben. Bei der hexadezimalen Darstellung stehen die Buchstaben A bis F (Groß- / Kleinschreibung egal) für die Zahlen 10 bis 15.
Nach der ganzen Theorie kommen wir natürlich endlich zu den Projekten: Als erstes beschäftigen wir uns mit dem Pollinboard.
Allen, die schon etwas Erfahrung haben, empfehle ich die eigene Würfelplatine.
Wer nach einer Programmieralternative für den USB-Port sucht, wird mit USBasp sicher glücklich.
Bei jedem Microcontroller-Projekt müssen mehrere Befehle vom Kompilieren / Assemblieren zum Übertragen ausgeführt werden. Das wird natürlich sehr schnell sehr lästig. Deshalb gibt es eine schöne kleine Programmiersprache namens make. In dem entsprechenden makefile
wird bei einem Aufruf von make
für jede Zieldatei geprüft, ob sich etwas an den zugehörigen Quelldateien geändert hat. Dann werden die Befehle ausgeführt, die zum Erstellen der Zieldatei nötig sind.
Für C-Dateien:
# Datei, die übertragen werden soll
file = mein-projekt.hex
all: $(file)
avrdude -p m8 -c ponyser -P /dev/ttyS0 -v -U flash:w:$(file)
# Befehl wird jedes Mal ausgeführt
%.hex: %.c
avr-gcc -mmcu=atmega8 -I. -Wall -Wstrict-prototypes -Wundef -std=gnu99 $*.c -o $*.o
# -mmcu muss natürlich an den jeweiligen µC angepasst werden
avr-objcopy -O ihex -R .eeprom $*.o $*.hex
# $* wird durch Dateinamen ohne Endung (mein-projekt) ersetzt
Für Assembler-Dateien:
# Datei, die übertragen werden soll
file = mein-projekt.hex
all: $(file)
avrdude -p m8 -c ponyser -P /dev/ttyS0 -v -U flash:w:$(file)
# Befehl wird jedes Mal ausgeführt
%.hex: %.asm
avra -I "/usr/share/avra" $*.asm
$ make