Oftmals kommt es vor, dass der PIC auf ein bestimmtes Ereignis sofort reagieren soll. Nun verwendet man hierfür als Anfänger gerne mal das so genannte “Polling”. Der Mikrocontroller soll, sobald an einem bestimmten Eingang eine Zustandsänderung eintrifft (zum Beispiel durch einen betätigten Taster oder Schalter) eine LED eingschalten werden. Hierfür gibt es zwei Lösungsmöglichkeiten: Eine sehr leichte “Quick & Dirty” und eine elegante und Rechenzeit optimierte. In diesem Artikel zeige ich euch die Vorteile von Interrupts und wie ihr sie speziell mit PIC-Mikrocontrollern verwenden könnt um eure Programme wesentlich effizienter zu gestalten.

Das Polling

Beim sogenannten Polling fragt der Mikrocontroller immer wieder eine Bedingung ab, solange bis diese wahr wird und er eine entsprechende Aktion ausführt. An unserem Beispiel würde dies bedeuten, dass der Controller fortwährend den Eingangspegel seines I/O kontrolliert um zu prüfen ob der Taster betätigt wurde, der letztendlich bewirken soll, dass eine LED eingeschaltet wird. Dieser Vorgang ist sehr einfach und dementsprechend auch super simpel zu programmieren. Der nachfolgende Programmablaufplan (PAP) zeigt das Polling-Verfahren:



Dieses Verfahren hat jedoch einen entscheidenden Nachteil: Während der Mikrocontroller immer wieder prüft ob sich der Eingangspegel des I/O geändert hat, kann er stattdessen keine anderen Aufgaben mehr ausführen. Das Pollen ist also einfach aber auch sehr ineffizient, da es eine Menge an Rechenzeit vergeudet. Wie man dieses Problem wesentlich besser lösen kann wollen wir uns im Folgenden anschauen.

Der Interrupt

Mit einem Interrupt wäre dieses Problem deutlich eleganter gelöst. Wir setzten gewisse Steuerbits, welche bewirken, dass sobald sich der Zustand am Eingang ändert, der PIC seinen aktuellen Befehl noch ausführt und im Anschluss sofort zu einer bestimmten Adresse springt und den Code abarbeitet den er dort findet. Es wird also im Prinzip ein Unterprogramm automatisch aufgerufen. Der große Vorteil daran ist, dass wir während wir auf die Zustandsänderung am Eingang warten trotzdem parallel noch weiter arbeiten können! Die nachfolgende Grafik sollte das beschriebene Verhalten verdeutlichen:



Erläuterung des PAP: Wenn ihr euch den letzten PAP zum Interrupt anseht, könnt ihr feststellen, dass der normale Programmablauf durch das Auftreten eines Interrupts unterbrochen wird. An unserem Beispiel hätte ein Druck auf einen Taster den Interrupt ausgelöst und innerhalb der Interrupt-Service-Routine würde nun unsere LED eingeschaltet werden ohne, dass wir ständig überprüfen mussten ob der Taster gedrückt wurde. Im Anschluss wird der normale Programmablauf fortgesetzt.

Interrupt-Quellen

Der PIC kann natürlich nicht nur beim Ändern des Zustandes an einem Eingang einen Interrupt auslösen. Es gibt diverse Möglichkeiten, die einen Interrupt auslösen können. Ihr könnt die Interrupt Quellen des PIC im Kapitel Device Overview oder im Kapitel Interrupts (siehe Interrupt Logic) im Datenblatt nachlesen. Auf der nachfolgenden Grafik sind die Quellen aufgelistet, die einen entsprechenden Interrupt auslösen können:

Interrupt on change

Dieser Interrupt wurde oben schon angesprochen. Er löst aus, sobald an einem Pin ein Zustandswechsel auftritt, dabei unterscheidet man zwischen fallender und steigender Flanke des Signales. Hierbei gilt es schon beim Schaltungsdesign darauf zu achten, dass nur einige wenige Pins für diesen Interrupt geeignet oder besser gesagt vorgesehen sind. Ihr erkennt diese an der Doppelbelegung mit ‘INTx’ – mit x = 0, 1, ….

Timer Interrupt

Dieser Interrupt wird ausgelöst, sobald ein Timer überläuft. Sprich, sobald der Zähler wieder bei 0 anfängt zu zählen, wird dieser Interrupt ausgelöst. Dies kann sehr nützlich sein um beispielsweise Warteschleifen zu erzeugen, bei denen der Controller nicht stillsteht, sondern anderweitige Aufgaben durchführen kann.

EUSART

Auch das serielle Interface kann einen Interrupt auslösen. Wenn das Modul ein Datenpaket empfängt und dieses in den Buffer lädt, kann ein Interrupt ausgelöst werden, so dass der Controller die empfangenen Daten sofort auslesen kann.

Konfiguration von Interrupts

Natürlich funktionieren die Interrupts nicht “einfach so” ohne jegliches Zutun. Interrupts sind im Normalfall deaktiviert bzw. verboten. Damit man einen Interrupt benutzen kann, muss man das entsprechende Enable-Bit setzten, welches den Interrupt zulässt. Außerdem muss maneine globale Freigabe für Interrupts freigeben, man muss das GIE Bit setzten. Dieses Bit ist das Global-Interrupt-Enable-Bit und verbietet beim Zustand ‘0’ alle Interrupts. Das bedeutet jedoch nicht, dass im Umkehrschluss, wenn dieses Bit gesetzt ist, dass alle Interrupts erlaubt sind. Jeder Interrupt hat ein weiteres Kontrollbit (Enable Bit).

Außerdem hat jeder Interrupt ein eigenes Flag, welches das Auftreten eines Interrupts signalisiert. Zum Beispiel wird bei einem Timer0 überlauf das Bit T0IF Bit gesetzt, somit weiß der PIC, dass der Timer0 einen Interrupt auslösen möchte, dieses wird aber nur passieren, wenn das zugehörige Enable Bit T0IE (Timer0 Interrupt Enable) Bit ebenfalls “1” ist und zusätzlich das GIE Bit die Interrupts überhaupt zulässt.

Bei den PIC18F-Typen werden verschiedene Interrupt Prioritäten unterschieden (Low & High). Diese haben auch zwei unterschiedliche Interrupt-Vektoren. Daher gibt es bei den PIC18F-Typen auch zwei globale Enable-Bits. Einmal das GIEL und das GIEH Bit. Ist das GIEL Bit auf disable, so können keine Interrupts, welche als “Low priority” deklariert sind ausgeführt werden – “high priority” Interrupts hingegen schon, sofern das GIEH Bit auf enable steht. Ist hingegen das GIEH Bit aus disable, können weder Low noch High- priorisierte Interrupts ausgeführt werden. Wir stellen also fest, dass das GIEH Bit übergreifend auch die niedrig priorisierten Interrupts sperren kann aber nicht umgekehrt! Für verschiedene Interrupt Prioritäten müsst Ihr das Bit IPEN im Register RCON setzten.

Die Priorität eines Interrupts wird mit dem zugehörigen Priority-Bit eingestellt. Diese sind auf verschiedene Register verteilt. Man findet jedoch mit Hilfe des Datenblatts sehr schnell heraus, wo das entsprechende Bit zu finden ist. Wird ein Priority-Bit gesetzt, so hat der zugehörige Interrupt eine hohe Priorität. Wird das Bit hingegen gelöscht, so ist die Priorität niedrig. Ein Interrupt mit einer niedrigen Priorität kann von einem Interrupt mit hoher Priorität unterbrochen werden! Umgekehrt st das logischerweise nicht möglich.

Programmieren eines Interrupts

Hier muss noch Inhalt entstehen..

Das Konfigurationswort

Das Konfigurationswort eines PIC gibt spezielle Einstellungen an, welche für den PIC zum Arbeiten unabdingbar sind. Das entscheidende hierbei ist, dass der PIC dieses Wort (auch als Fuses bezeichnet) nicht selber verändern kann. Wenn die Fuses einmal beim Brennen gesetzt sind bleiben sie so. Man legt durch die Fuses grundlegende Hardware Einstellungen fest, welche angegeben werden müssen. Man kann das Konfigurationswort entweder manuell in den Programmcode eingeben, oder aber setzt die gewünschten Option in der IDE.

Erklärungen des Codes

Hier sind einmal die für den Einstieg in die PIC µC Welt wichtigsten Einstellungsmöglichkeiten in einer Tabelle aufgelistet:

FUNKTION KURZBESCHREIBUNG
Taktgenerator Gibt an mit welcher Frequenzkategorie der PIC arbeitet
Power up Timer Kann einen verzögerten Start des PIC hervorrufen (sinnvoll)
Watchdog Timer Kann einen Reset auslösen, wenn der PIC abstürzt
Code protection Wer seinen Code vor Spionage schützen möchte
MCLR Hier kann die Reset Funktion deaktiviert werden (bringt einen I (Input) Pin mehr
LV Programming Kann eine Programmierung mit 5V ermöglichen (kostet einen IO-Pin)
Brown out Reset Kann einen Reset auslösen, wenn die Betriebsspannung einbricht

Taktgenerator

Bei dieser Option müssen Sie den richtigen Taktbereich auswählen, damit der PIC weiß, mit welcher Frequenz gearbeitet wird. Sie finden die Entsprechende Einstellung im Datenblatt. Hier ein Überblick:

LP 32 kHz – 200 kHz Quarz, Keramikresonator, Extern
XT 100 kHz – 4 MHz Quarz, Keramikresonator, Extern
HS 4 MHz – 20 MHz Quarz, Keramikresonator, Extern
RC 30 kHz – 4 MHz Widerstand – Kondensator Kombi

Power up Timer

Durch das aktivieren dieser Funktion startet der µC mit 72 ms Verspätung. Diese Option ist eigentlich immer Sinnvoll!

Watchdog Timer

Der Watchdog Timer ist ein weiterer Hardwaretimer, welcher den PIC resetet sobald der Timer überläuft. Ist diese Funktion aktiviert, muss der Timer in regelmäßigen Abständen gelöscht werden!

Code protection

Diese Funktion schützt Euren Programmcode vor Diebstahl. Wenn Ihr ein Programm geschrieben habt, welches Ihr nicht veröffentlichen möchtet, könnt Ihr mit dieser Funktion den Code schützen.

MCLR (Master clear reset)

Oftmals ist es ja überhaupt nicht notwendig, dass ein PIC per Tastendruck resetet werden kann. Daher kann der MCLR Pin (RA5) auch als Eingang (nur als Eingang) benutzt werden.

LV Programming

Diese Funktion ist für Einsteiger weniger Interessant. Sie ermöglicht das Brennen mit 5 anstatt 12V Programmierspannung. Geht aber auf Kosten von einem IO Pin!

Brown out Reset

Der Brown out Reset schützt den PIC davor fehlerhaft zu arbeiten, wenn ein Spannungseinbruch passiert ist. Der Brown out Reset überprüft ständig die Betriebsspannung des PIC. Sobald diese für mindestens 0,1 ms unter 4V fällt, wird ein Reset ausgelöst sobald die Spannung wieder im sicheren Bereich ist und 72 ms vergangen sind. Bei PIC18F ist die Schwelle einstellbar!

Gut zu wissen

Hier entsteht eine kleine Sammlung mit Dingen die immer wieder falsch gemacht werden bzw. zu Problemen führen. Für Hinweise per Mail oder als Kommentar unter diesem Tutorial bin ich immer dankbar.

Was ist Fosc, Tosc und Tcy

\text{F}_{\text{osc}} ist die Taktfrequenz der Signalquelle, die wir an unseren PIC anschließen (zum Beispiel ein Quarz). \text{T}_{\text{osc}} ist dementsprechend die Periodendauer der Frequenz \text{F}_{\text{osc}}. Man errechnet \text{T}_{\text{osc}} mit 1 / \text{F}_{\text{osc}}. Da ein PIC zum Bearbeiten eines Befehls 4 Taktzyklen (  4 \cdot \text{T}_{\text{osc}} = \text{T}_{\text{cy}} ) benötigt, errechnet sich \text{T}_{\text{cy}} (also die Zeit zum Bearbeiten eines Befehls) durch \frac{1}{ \text{F}_{\text{osc}} \text{/} 4} = 4 \cdot \text{T}_{\text{osc}}.

Beispiel: An einem PIC ist ein 4 MHz Quarz angeschlossen.

\text{F}_{osc} = 4\,\text{MHz}

\text{T}_{\text{osc}} =\frac{1}{\text{f}_{\text{osc}}} = \frac{1}{4\,\text{MHz}} = 250\,\text{ns}

Durch die Tatsache, dass der PIC vier Taktzyklen zum Abarbeiten eines Befehls benötigt, ist der interne Befehlstakt 4\,\text{MHz} \text{/} 4 =1\,\text{MHz}. Also benötigt der PIC zum abarbeiten eines Befehls:

\text{T}_{\text{cy}} = 4 \cdot \text{T}_{\text{osc}} = 4 \cdot 250\,\text{ns} = 1\,\mu\text{s}

Offene Pins am Controller

Wenn es vorkommt, dass Ihr nicht alle Pins des Mikrocontrollers braucht, dann habt ihr zwei Möglichkeiten: Ihr schaltet die Pins in der Software auf Ausgang und weist Ihnen idealerweise den Wert ‘0’ zu (in diesem Fall keine externe Beschaltung vorsehen um die Gefahr eines Kurzschlusses zu vermeiden) oder Ihr legt die nicht verwendeten Pins (Eingänge) über entweder externe oder interne (falls vorhanden) Pull-up/down-Widerstände auf ein definiertes Potential. Nicht verwendete Eingänge sollten niemals offen gelassen werden. Sie können zum Schwingen führen und verursachen unter Umständen einen erhöhten Stromverbrauch. Siehe hierzu auch folgende Artikel [1], [2 siehe Unused Port Pins] und [3 siehe 2.3.2 Dynamische Verluste…]

Achtung bei RA4

Immer wenn Ihr den PIN RA4 eines PIC als Ausgang benutzen wollt müssen bei Euch die Alarmglocken angehen (dies bezieht sich lediglich auf PIC16F), denn dieser Pin ist bei vielen PIC16F Typen nur ein Open Drain Pin und ist somit nicht in der Lage, ohne einen extra Pull up Widerstand, sein Potential allein auf 5V zu ziehen!

In circuit serial programming

Wer kennt das nicht: Für die Entwicklung einer Software muss der PIC mehrmals geflasht und anschließend die Software in der Schaltung getestet werden. Es ist nervtötend andauernd den PIC immer wieder aus der Fassung der Schaltung zu entnehmen, dann in die Fassung des Brenners zu stecken und dann wieder anders herum. Es gibt hierfür eine Lösung und die nennt sich In Cuircuit Serial Programming oder kurz ICSP. Das bedeutet der PIC wird in seiner fertigen Schaltung gebrannt ohne ihn entnehmen zu müssen. Damit die ICSP Funktion benutzt werden kann müssen ein paar Vorkerungen getroffen werden:

Es werden folgende Leitungen benötigt:

  • \text{V}_{\text{PP}}, Leitung mit der Programmierspannung
  • \text{V}_{\text{DD}} , Leitung mit der Versorgungsspannung für PIC
  • \text{V}_{\text{SS}} , Leitung für Masse
  • \text{PGD}, die Datenleitung zum Programmieren
  • \text{PGC} , die Taktleitung zum Programmieren

Die Leitungen werden wie folgt angeschlossen:

ICSP LEITUNG ANSCHLUSS AM PIC
Programmierspannung [ \text{V}_{\text{PP}} ] an den PIN MCLRE
Versorgungsspannung [ \text{V}_{\text{DD}} ] an den/die Pin(s) \text{V}_{\text{DD}}
Masseleitung [ \text{V}_{\text{SS}} ] an den/die Pin(s) \text{V}_{\text{SS}}
Taktleitung [ \text{PGC} ] an den Pin RB6
Datenleitung [ \text{PGD} ] an den Pin RB7

Hier seht Ihr die ICSP-Beschaltung am Beispiel des PICKit3 von Microchip:


Schlusswort

Ich hoffe, dass ich Euch mit diesem kleinen Tutorial den Einstieg in die PIC-Mikrocontroller-Welt etwas versüßen konnte. Gerne könnt Ihr eure Meinung und Kritik als E-Mail oder als Kommentar im Forum abladen. Oder schreibt direkt einen Kommentar hier unter diesen Artikel. Ich freue mich über jede Rückmeldung.

Siehe auch

Leave a Comment