Betriebsarten der Portpins

Die Portpins der LPC900-Reihe unterstützen vier verschiedene Betriebsarten. Eine ge­naue Funktionsbeschreibung der Portpins und deren Betriebsarten finden sie im Buch Kapitel 10.6 „Aufbau der Ports“ [3]. Da die Portpins selbst mit unterschiedli­chen Funk­tionen belegt sind, sollte die Umschal­tung 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 Pa­rameter 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 wer­den, 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 Funk­tion „v_PortConfig()“ in ein eigenes Sourcemodul ausgelagert (siehe Listing 18). Die Funktionsde­kla­ra­tion sowie die Aufzählungstypen werden in einem eigenen H-File ab­gespeichert (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

Arbeiten mit der Libraryfunktion „v_PortConfig()“

Soll die Libraryfunktion „v_PortConfig()“ in ein Projekt aufgenommen werden, muss das Sourcemodul „Portconfig.c“ ebenfalls in das Projekt aufgenommen werden. Damit der C51-Com­pi­ler das H-File „PortConfig.h“ findet, muss das Verzeichnis, in dem das H-File abgespeichert ist, im Window „Options for Target“, Reiter „C51“ im Ein­­gabefeld „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 durch­lau­fen. 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 Code­verbrauch größer. Dennoch sollte berücksichtigt werden, dass die Lesbarkeit und die Wartung von Programmen eine entscheidende Rolle bei der Erstellung und Weiter­ent­wicklung spielen. Zudem wird die Fehlermöglichkeit eingeschränkt, da nur noch der Port­pin angegeben wird und die logischen Verknüp­fun­gen in der Funktion passend auf die jeweiligen SFR durch­geführt wer­den.

 

 

P2M1 = 0x00; 

P2M2 = 0x00;

Listing 21  Einstellung der Betriebsart Quasi-Bidir mit Hilfe der direkten Zuweisung