© prettyboy80/Shutterstock.com
Teil 2: Programmierung der Mikrocontroller mit Assembler und C

Die Welt regeln und steuern


Im ersten Artikel dieser Serie haben Sie eine Entwicklungsumgebung eingerichtet, ein Testbeispiel auf dem Steckbrett aufgebaut und eine LED einmal mit einem Assembler- und einmal mit einem C-Programm zum Blinken gebracht. In diesem Teil schauen wir uns diese Programme genauer an.

Der PIC18F25K50-Mikrocontroller aus unserem Testaufbau aus dem letzten Artikel gehört zu einer proprietären 8-Bit-Mikrocontroller-Reihe der Firma Microchip Technology Inc. Hierbei handelt es sich nach der Übernahme der Firma Atmel um den drittgrößten Hersteller von Mikrocontrollern weltweit – und sicherlich um den bei Hobbyentwicklern und Kleinunternehmen am verbreitetsten Hersteller. Neben den proprietären 8-Bit-Mikrocontrollern der kleineren PIC-Reihen bietet das Unternehmen auch größere Mikrocontroller mit z. B. 32 Bit Busbreite auf Basis der MIPS-Architektur an. Außerdem gehören mittlerweile die beliebten Atmel AVR Mikrocontroller der ATtiny- und ATmega-Serien sowie die größeren auf der ARM-Architektur basierenden Atmel-Mikrocontroller zum Portfolio. Wir schauen uns hier weiterhin die PIC16F- und PIC18F-Familie detailliert an, die für die meisten Projekte sehr gut geeignet ist und einfach beschaltet und programmiert werden kann.

Assembler

Listing 1 zeigt noch einmal das Hello-World-Programm aus dem vorherigen Artikel, mit dem eine LED zum Blinken gebracht werden kann. Wie versprochen, soll nun aufgeklärt werden, was da eigentlich passiert und wie das Programm funktioniert.

# list p=18F25K50
include p18f25k50.inc
config WDTEN=OFF, BOREN=OFF, FOSC = INTOSCIO, MCLRE = ON, LVP = OFF

org 0x00
goto start

org 0x04

start
clrf TRISC
clrf PORTC

main
btg PORTC, RC0

wait
movlw 0x70
movf counter
wait1
movlw 0x70

wait2
addlw 0xff ; w = w-1
btfss STATUS, Z
goto wait2

decfsz counter, 1
goto wait1

goto main

counter db 1

end

Listing 1

In einem Assemblerprogramm sind praktisch alle Zeilen eingerückt. Am Anfang kommen immer einige Whitespaces als Tabulatoren oder Leerzeichen. In einigen Zeilen aber nicht, dort steht etwas direkt am Zeilenanfang. In Listing 1 sind das beispielsweise start, main, wait etc. Hierbei handelt es sich um Labels. Ein Label ist einfach nur ein Name für die Programmstelle, an der das Label steht. Es kann im Code einfach referenziert werden, beispielsweise um den Sprung an eine bestimmte Stelle zu realisieren. Kurz vor dem Ende des Programms gibt es die Anweisung goto main. Das ist ein solcher Sprung an die Stelle des Labels main.

Ein Assembler-Listing endet immer mit der Anweisung end; am Anfang des Programms finden Sie eine Präambel bestehend aus einigen wenigen Zeilen. Die Statements in diesen Zeilen geben dem Assembler einige Hinweise darauf, was er bei der Übersetzung beachten soll. Kommentare beginnen mit einem Semikolon und gehen immer bis zum Zeilenende.

Die ersten paar Zeilen konfigurieren den Assembler und bereiten einiges vor. Gleich in der allerersten Zeile teilen wir dem Assembler mit, für welchen konkreten Mikrocontroller er Code generieren soll. Dazu dient die Direktive list p=18F25K50. Dieser Schritt ist eigentlich nicht erforderlich, da man heutzutage den Typ des Mikrocontrollers ja bereits in der Entwicklungsumgebung einstellt; beispielsweise direkt beim Anlegen des Projekts. Ich schreibe diese Zeile dennoch immer noch zusätzlich in den Code, einfach weil es mir ein Stück weit als Dokumentation dient. Falls man später mal die Build-Umgebung wechseln und beispielsweise einen Assemblerlauf außerhalb der MPLAB X IDE ausführen möchte, kann das sogar sehr nützlich sein, da dann die Angaben, die nur innerhalb der Umgebung definiert wurden, fehlen. Mit der list-Direktive können noch einige andere Dinge eingestellt werden, in der Praxis verwendet man diese Möglichkeiten jedoch kaum.

Die nächste Zeile bindet die Datei p18f25k50.inc in das Programm ein. Der Mechanismus funktioniert so, wie Sie es vielleicht von C-Programmen her kennen: Der Inhalt der Datei wird gelesen und so ausgewertet, als würde er an der Stelle der include-Direktive im Quelltext stehen. In der inkludierten Datei p18f25k50.inc befindet sich demnach gültiger und übersetzbarer Assemblercode. Genaugenommen befinden sich darin allerdings lediglich weitere Direktiven, die sehr viele Voreinstellungen treffen, damit der Mikrocontroller PIC18F25K50 leichter verwendet werden kann.

Insbesondere werden hier solch schöne Namen wie PORTC definiert. Er wird weiter unten im Programm verwendet, um auf die Pins des Mikrocontrollers zuzugreifen – jedenfalls auf einige davon. Aber dazu später mehr.

Konfiguration des Mikrocontrollers

Mithilfe der config-Direktive wird beschrieben, in welcher Konfiguration wir den Mikrocontroller verwenden und welche Features wir benutzen möchten. Wir werden uns die vielen Möglichkeiten, die es hier gibt, Schritt für Schritt in späteren Artikeln dieser Serie anschauen. Das für dieses Beispiel wichtigste Feature, das wir hier konfigurieren, ist die Art des Oszillators, den wir verwenden möchten. Da wir keinen externen Quarz oder sonstigen Taktgeber in die Schaltung gebaut haben, möchten wir den internen Oszillator des Mikrocontrollers nutzen. Dazu dient die Einstellung FOSC = INTOSCIO.

Diese Konfigurationsmöglichkeiten entsprechen in etwa dem, was man bei AVR-Mikrocontrollern über di...

Neugierig geworden? Wir haben diese Angebote für dich:

Angebote für Gewinner-Teams

Wir bieten Lizenz-Lösungen für Teams jeder Größe: Finden Sie heraus, welche Lösung am besten zu Ihnen passt.

Das Library-Modell:
IP-Zugang

Das Company-Modell:
Domain-Zugang