ein Kapitel zurück                                           ein Kapitel weiter

Ich möchte dieses Kapitel nur kurz anschneiden da uns dazu noch einige Grundlagen der Systemprogrammierung fehlen. Nehmen wir mal an sie sollen einen Roboter zur Fließbandproduktion programmieren. Machen wir es mal ganz einfach. Der Roboter soll ein Produkt von A nach B. Hier die einzelnen Arbeitsabläufe....

1. Produkt zum befördern vorhanden (Sensor 1) wenn ja -br

Das ganze soll natürlich auch überprüft werden und bei Fehler ein sogenannter Fehlercode ausgegeben werden. Also benötigen wir noch eine Anzeige. Wir gehen einfach mal davon aus das unser Roboter mit unserem PC schon verbunden ist. Also benötigen wir eine Struktur für unseren Roboter......

struct robo {
                  unsigned char sensor1;
                  unsigned char sensor2;
                  unsigned char sensor3;
                  unsigned char schalter;
                  int Ausgabe;
                 }Roboter1;

Nun benötigt unser Roboter hier 48 Bits also 6 Bytes. Nun wenn sie noch mehrere Roboter so steuern müssen ist das ein rechte Platzverschwendung und meist haben sie nicht unbegrenzt Speicherplatz bei sogenannten Embeeded Systems. Bei unseren Sensoren und bei dem Schalter benötigen wir eigentlich nur 2 Schaltstellung. 1 für betätigt oder ein und 0 für unbetätigt bzw. aus. Nun gibt es in C die Möglichkeit auch einzelne Bits anzusprechen. Hier unsere Struktur dazu....

struct robo {
                  unsigned sensor1:1;
                  unsigned sensor2:1;
                  unsigned sensor3:1;
                  unsigned schalter:1;
                  unsigned Ausgabe:4;
                }Roboter1;

Nun benötigt unsere Struktur nur noch sage und schreibe 8 Bits also 1 Byte. Der Trick ist eigentlich ganz einfach wir benutzen hier das Schlüsselwort unsigned das intern im Prozessor auf 0 gesetzt ist falls mit + und - arbeiten. Also signed. Oder das Bit ist auf 1 gesetzt falls sie mit unsigned Arbeiten also ohne Vorzeichen. Aber das ist jetzt in dem Kapitel nicht so wichtig. Es geht lediglich darum das unsigned 1 Bit benötigt und 1 Bit eben nur 1 oder 0 als Wert erhalten kann. Unsere Variable Ausgabe erhält dagegen 4 Bits womit wir eine Zahl bis 16 darstellen können(2*2*2*2). Hier nun das Beispiel dazu....

/*Download:bit1.c*/
#include <stdio.h> struct robo { unsigned Sensor1:1; unsigned Sensor2:1; unsigned Sensor3:1; unsigned Schalter:1; unsigned Ausgabe:4; }Roboter1; char *msg[7] = {"Kein Signal an Sensor 1!\n", "Kein Signal an Sensor 2!\n", "Kein Signal an Sensor 3!\n", "Schalter 1 nicht betätigt!\n", "Notaus betätigt!\n", "Kein Strom!\n" }; int main() { int anzahl; do{ printf("Wieviele Produkte soll der Roboter von A->B heben: "); scanf("%d",&anzahl); fflush(stdin); while((anzahl>0) && (anzahl--)) { Roboter1.Sensor1=1; if(Roboter1.Sensor1) printf("Produkt wird aufgenommen und zum Fließband transportiert\n"); else { Roboter1.Ausgabe=0; puts(msg[Roboter1.Ausgabe]); } Roboter1.Sensor2=1; if(Roboter1.Sensor2) { printf("Produkt ist auf dem Fließband\n"); printf("Schalter wird eingeschaltet!\n"); Roboter1.Schalter=1; } else { Roboter1.Ausgabe=1; puts(msg[Roboter1.Ausgabe]); Roboter1.Ausgabe=3; puts(msg[Roboter1.Ausgabe]); } Roboter1.Sensor3=1; if(Roboter1.Sensor3) { printf("Produkt am Ziel angekommen!\n"); printf("Schalter für Fließband wieder auf aus.\n"); Roboter1.Schalter=0; } else { Roboter1.Ausgabe=2; puts(msg[Roboter1.Ausgabe]); } } }while(anzahl>0); Roboter1.Sensor1=0; Roboter1.Sensor2=0; Roboter1.Sensor3=0; Roboter1.Ausgabe=0; puts(msg[Roboter1.Ausgabe]); return 0; }

Durch das 4-Byte-Alignment (Linux) benötigt in diesem Beispiel die Struktur robo auch 4-Bytes-Speicher, obwohl drei davon nicht verwendet werden. Auch hier können sie den Speicherplatz auf 1 Byte Größe mit dem Keyword attribute zusammenpacken.......

struct robo {
                  unsigned Sensor1:1;
                  unsigned Sensor2:1;
                  unsigned Sensor3:1;
                  unsigned Schalter:1;
                  unsigned Ausgabe:4;
                 } __attribute__ ((packed)) Roboter1;

...und voiala, unser Roboter1 benötigt wirklich nur noch 1 Byte. Hier das ganze nochmals Bildlich.......



Das dämlich an diesem Beispiel ist eigentlich das es gar nichts taugt da wir ja keine Verbindung mit einem Roboter haben. Die Zeilen z.B. wie .....

Roboter1.Sensor1=0;
Roboter1.Sensor2=0;
.......................
........................

...müssen wir alle von selber eingeben. Diese eben sind mit der Schnittstelle von Rechner und Roboter verbunden und müssen normalerweise nicht von Hand eingegeben werden.

Nun gut ich werde mal ein Funktionierendes Beispiel bringen was ich mit Schnittstelle bzw. Adresse meine damit sie das Beispiel mit dem Roboter besser verstehen. Wir überprüfen unseren Druckerstatus am LPT 1 - Anschluss (das Programm läuft leider nur unter MS-DOS)...

/*Download:printer.c*/
#include <stdio.h> #include <stdlib.h> #include <dos.h> #define LPT1_PORT 0x378 /*0x378 ist die Adresse der Schnittstelle von LPT1*/ struct status { unsigned :3; /*Bit 0-2 nicht verwendet*/ unsigned fehler :1; /*0=Druckerfehler*/ unsigned online :1; /*1=Drucker online*/ unsigned papier :1; /*1=kein Papier*/ unsigned empfang:1; /*Emfangsbestätigung*/ unsigned busy :1; /*Drucker bereit*/ }LPT1_status; /*Status am LPT1-Port auslesen*/ void druckerstatus(char *statuszeiger) { *statuszeiger = inp( LPT1_PORT+1 ) & 0xF8; } int main() { druckerstatus( (char *) &LPT1_status); if(LPT1_status.busy && LPT1_status.online) { printf("Drucker Betriebsbereit!\n"); exit (0); } else if(!LPT1_status.online) printf("Drucker nicht online!\n"); else if(LPT1_status.papier) printf("Kein Papier vorhanden!\n"); else printf("Drucker nicht Betriebsbereit!\n"); return 0; }

Dies Programm läuft leider nur unter Dos bzw. MSWin-Systemen und nicht unter Linux. Die Adresse 0x378 stellt die Adresse des Portes LPT1 dar. Der Statusregister den wir hier überprüfen sieht intern folgendermaßen aus.....

Bit7 Bit6 Bit5 Bit4 Bit3 Bit2 Bit1 Bit0
busy Empf. Papier online fehler - - -


Hier sehen sie nichts anderes wie unsere Struktur die wir oben definiert haben. Die Bits 0-2 werden nicht verwendet. Die Bits 3-7 geben uns anschließend den Status des Druckers zurück je nachdem welche Bits gesetzt sind oder welche nicht. Unsere Funktion druckerstatus() liefert uns dann denn Status zurück. Das Programm selber braucht sie jetzt momentan nicht zu interessieren. Ich komme später beim Systemprogrammieren darauf zurück. Wichtig ist hier nur das sie den Sinn und Zweck von Bit-Feldern verstanden haben. Neu ist bei diesem Programm.....

unsigned:3;

Hiermit definieren wir 3 Bits ohne einen Namen. In unserem Fall sind es die ersten 3 Bits die wie sie in der Tabelle sehen können nicht verwendet werden. Folglich können sie mit diesen auch nichts (falsch) machen bzw. darauf zugreifen. Man sagt dazu auch anonyme Bitfelder.

ein Kapitel zurück          nach oben           ein Kapitel weiter


© 2001,2002 Jürgen Wolf