Die Portpins der LPC900-Reihe unterstützen vier verschiedene Betriebsarten. Eine genaue Funktionsbeschreibung der Portpins und deren Betriebsarten finden sie im Buch Kapitel 10.6 „Aufbau der Ports“ [3]. Da die Portpins selbst mit unterschiedlichen Funktionen belegt sind, sollte die Umschaltung auf die jeweilige Betriebsart immer nur auf das benötigte Portpin und nicht auf den gesamten Port durchgeführt werden. Die Funktion „v_PortConfig()“ ermöglicht eine Konfiguration der Portpins. Im ersten Parameter wird der Port, im zweiten der Pin und im dritten die einzustellende Betriebsart übergeben (siehe Listing 17, ). Damit die Übergabeparameter besser gelesen werden können, wurde der Aufzählungstyp enum für die einzelnen Parameter verwendet (siehe ‚). Aufbau und Funktionsweise des Aufzählungstyps enum können sie im Kapitel 13.4 [1] nachlesen. Sollen alle Portpins eines Ports auf eine Betriebsart gesetzt werden, wird die Definition „AllPins“ verwendet (siehe ƒ). Sollen mehrere Portpins auf eine Betriebsart gesetzt werden, kann dies mit einer Oder-Verknüpfung bei der Übergabe erfolgen (siehe „). Erstellen sie das Projekt aus Tabelle 35 und fügen das Programm aus Listing 17 in das Sourcemodul ein.
|
Projektname |
Verzeichnis |
Verwendete Sourcemodule |
|
PortConfig |
Test_PortConfig |
TestPortConfig.c |
Tabelle 35 Projekt PortConfig
|
‚
‚ ‚
ƒ „ |
#include <REG932.H> enum enPinADDR{Pin0 = 0x01, Pin1 = 0x02, Pin2 = 0x04, Pin3 = 0x08, Pin4 = 0x10, Pin5 = 0x20, Pin6 = 0x40, Pin7 = 0x80, AllPins = 0xFF}; enum enPort {Port0 = 0, Port1, Port2, Port3}; enum enConfig {BiDir = 0, PushPull, InpOnly, OpenDrain};
void v_PortConfig(unsigned char ucPortAddr, unsigned char ucPin, unsigned char Config) { if (Config == BiDir) { ucPin ^= 0xFF; switch(ucPortAddr) { case Port0: P0M1 = P0M1 & ucPin; P0M2 = P0M2 & ucPin; break; case Port1: P1M1 = P1M1 & ucPin; P1M2 = P1M2 & ucPin; break; case Port2: P2M1 = P2M1 & ucPin; P2M2 = P2M2 & ucPin; break; case Port3: P3M1 = P3M1 & ucPin; P3M2 = P3M2 & ucPin; break; default: break; } } else if (Config == PushPull) { switch(ucPortAddr) { case Port0: P0M1 = P0M1 & (ucPin ^ 0xFF); P0M2 = P0M2 | ucPin; break; case Port1: P1M1 = P1M1 & (ucPin ^ 0xFF); P1M2 = P1M2 | ucPin; break; case Port2: P2M1 = P2M1 & (ucPin ^ 0xFF); P2M2 = P2M2 | ucPin; break; case Port3: P3M1 = P3M1 & (ucPin ^ 0xFF); P3M2 = P3M2 | ucPin; break; default: break; } } else if (Config == InpOnly) { switch(ucPortAddr) { case Port0: P0M1 = P0M1 | ucPin; P0M2 = P0M2 & (ucPin ^ 0xFF); break; case Port1: P1M1 = P1M1 | ucPin; P1M2 = P1M2 & (ucPin ^ 0xFF); break; case Port2: P2M1 = P2M1 | ucPin; P2M2 = P2M2 & (ucPin ^ 0xFF); break; case Port3: P3M1 = P3M1 | ucPin; P3M2 = P3M2 & (ucPin ^ 0xFF); break; default: break; } } else // Open-Drain { switch(ucPortAddr) { case Port0: P0M1 = P0M1 | ucPin; P0M2 = P0M2 | ucPin; break; case Port1: P1M1 = P1M1 | ucPin; P1M2 = P1M2 | ucPin; break; case Port2: P2M1 = P2M1 | ucPin; P2M2 = P2M2 | ucPin; break; case Port3: P3M1 = P3M1 | ucPin; P3M2 = P3M2 | ucPin; break; default: break; } } }
void main(void) { v_PortConfig (Port0, AllPins, BiDir); v_PortConfig (Port2, Pin4 | Pin 7, PushPull); v_PortConfig (Port0, Pin2, InpOnly); v_PortConfig (Port2, Pin5, OpenDrain); while(1); } |
Listing 17 Inhalt von TestPortConfig.c
Da die Konfiguration der Portpins bei jedem Projekt wieder benötigt wird, wird die Funktion „v_PortConfig()“ in ein eigenes Sourcemodul ausgelagert (siehe Listing 18). Die Funktionsdeklaration sowie die Aufzählungstypen werden in einem eigenen H-File abgespeichert (siehe Listing 19). Damit die Aufzählungstypen im Sourcemodul PortConfig.c für den C51-Compiler bekannt sind, muss das H-File mit eingefügt werden (siehe Listing 18, ). Speichern sie diese beiden Dateien im Verzeichnis Library ab.
|
Projektname |
Verzeichnis |
Verwendete Sourcemodule |
|
- |
Library |
PortConfig.c |
Tabelle 36 Projekt -
|
|
#include <REG932.H> #include <PortConfig.H>
void v_PortConfig(unsigned char ucPortAddr, unsigned char ucPin, unsigned char Config) { if (Config == BiDir) { ucPin ^= 0xFF; switch(ucPortAddr) { case Port0: P0M1 = P0M1 & ucPin; P0M2 = P0M2 & ucPin; break; case Port1: P1M1 = P1M1 & ucPin; P1M2 = P1M2 & ucPin; break; case Port2: P2M1 = P2M1 & ucPin; P2M2 = P2M2 & ucPin; break; case Port3: P3M1 = P3M1 & ucPin; P3M2 = P3M2 & ucPin; break; default: break; } } else if (Config == PushPull) { switch(ucPortAddr) { case Port0: P0M1 = P0M1 & (ucPin ^ 0xFF); P0M2 = P0M2 | ucPin; break; case Port1: P1M1 = P1M1 & (ucPin ^ 0xFF); P1M2 = P1M2 | ucPin; break; case Port2: P2M1 = P2M1 & (ucPin ^ 0xFF); P2M2 = P2M2 | ucPin; break; case Port3: P3M1 = P3M1 & (ucPin ^ 0xFF); P3M2 = P3M2 | ucPin; break; default: break; } } else if (Config == InpOnly) { switch(ucPortAddr) { case Port0: P0M1 = P0M1 | ucPin; P0M2 = P0M2 & (ucPin ^ 0xFF); break; case Port1: P1M1 = P1M1 | ucPin; P1M2 = P1M2 & (ucPin ^ 0xFF); break; case Port2: P2M1 = P2M1 | ucPin; P2M2 = P2M2 & (ucPin ^ 0xFF); break; case Port3: P3M1 = P3M1 | ucPin; P3M2 = P3M2 & (ucPin ^ 0xFF); break; default: break; } } else // Open-Drain { switch(ucPortAddr) { case Port0: P0M1 = P0M1 | ucPin; P0M2 = P0M2 | ucPin; break; case Port1: P1M1 = P1M1 | ucPin; P1M2 = P1M2 | ucPin; break; case Port2: P2M1 = P2M1 | ucPin; P2M2 = P2M2 | ucPin; break; case Port3: P3M1 = P3M1 | ucPin; P3M2 = P3M2 | ucPin; break; default: break; } } } |
Listing 18 Inhalt von PortConfig.c
|
|
enum enPinADDR{Pin0 = 0x01, Pin1 = 0x02, Pin2 = 0x04, Pin3 = 0x08, Pin4 = 0x10, Pin5 = 0x20, Pin6 = 0x40, Pin7 = 0x80, AllPins = 0xFF}; enum enPort {Port0 = 0, Port1, Port2, Port3}; enum enConfig {BiDir = 0, PushPull, InpOnly, OpenDrain};
extern void v_PortConfig(unsigned char ucPortAddr, unsigned char ucPin, unsigned char Config); |
Listing 19 Inhalt von PortConfig.h
Soll die Libraryfunktion „v_PortConfig()“ in ein Projekt aufgenommen werden, muss das Sourcemodul „Portconfig.c“ ebenfalls in das Projekt aufgenommen werden. Damit der C51-Compiler das H-File „PortConfig.h“ findet, muss das Verzeichnis, in dem das H-File abgespeichert ist, im Window „Options for Target“, Reiter „C51“ im Eingabefeld „Include Paths“ angegeben werden (siehe Abbildung 43). Erstellen sie das Projekt aus Tabelle 57. Der C51-Compiler sowie der BL51-Linker müssen ohne Fehler durchlaufen. Wenn sie das Projekt anschließend durchsteppen, müssen die LEDs an Port 2 den Zustand wechseln.
|
|
Abbildung 43 Window Options for Target, Reiter C51
|
Projektname |
Verzeichnis |
Verwendete Sourcemodule |
|
Test_ConfigLib |
Test_PortConfigLib |
TestPortConfigLib.c |
|
|
..\Library |
PortConfig.c |
Tabelle 37 Projekt Test_ConfigLib
|
|
#include <REG932.H> #include <PortConfig.h>
void main(void) { v_PortConfig(Port2, AllPins, BiDir); while(1) { P2 = 0x00; P2 = 0xFF; } } |
Listing 20 Inhalt von TestPortConfigLib.c
Die Funktion „v_PortConfig()“ ist gegenüber einer Zuweisung (siehe Listing 21) im Codeverbrauch größer. Dennoch sollte berücksichtigt werden, dass die Lesbarkeit und die Wartung von Programmen eine entscheidende Rolle bei der Erstellung und Weiterentwicklung spielen. Zudem wird die Fehlermöglichkeit eingeschränkt, da nur noch der Portpin angegeben wird und die logischen Verknüpfungen in der Funktion passend auf die jeweiligen SFR durchgeführt werden.
|
|
P2M1 = 0x00; P2M2 = 0x00; |
Listing 21 Einstellung der Betriebsart Quasi-Bidir mit Hilfe der direkten Zuweisung