Jaipur Geschrieben 10. März 2002 Teilen Geschrieben 10. März 2002 Hi, habe folgende Aufgabe bekommen, ob ich die wohl lösen könne. Ihm fiel leider nichts ein ... Erst ein mal die Aufgabenstellung: Sie haben über eine Karte vier Lampen an Ihren Computer angeschlossen. Zu der Karte gibt es einen Treiber mit folgenden Funktionen: void set( unsigned char w) unsigned char get() Durch diese Funktion wird ein 8-Bit Datenwort zur Karte übertragen bzw. von der Karte gelesen. Das Datenwort hat dabei die folgende Bedeutung: 7 6 5 4 3 2 1 0 - - - - - - - - | | | | | | | | | - - - - - - - - | | | | | | | | | | | | | | | --- Lampe 1 ( 0=aus, 1=ein ) | | | | | | ----- Lampe 2 ( 0=aus, 1=ein ) | | | | | ------- Lampe 3 ( 0=aus, 1=ein ) | | | | --------- Lampe 4 ( 0=aus, 1=ein ) | | | ----------- Lampe 1 ( 0=nicht blinkend, 1=blinkend ) | | ------------- Lampe 2 ( 0=nicht blinkend, 1=blinkend ) | ---------------- Lampe 3 ( 0=nicht blinkend, 1=blinkend ) ----------------- Lampe 4 ( 0=nicht blinkend, 1=blinkend ) Schreiben Sie eine C-Funktion Schnittstelle und Funktionskörper), die eine einzelne Lampe ( 1 - 4 ) blinkend oder nicht blinkend einschaltet, und dabei den Zustand der anderen Lampen unverändert lässt. Hier ist nun mein Vorschlag: # include < stdio.h > # include < stdlib.h > # define AUS 0 # define NICHT_BLINKEN 1 # define BLINKEN 2 unsigned char LAMPE=0; void show( unsigned char w) { int x; for( x=7; x > =0; x--) printf("%d",x); printf("\n"); for( x=7; x > =0; x--) { if(w&(1 < < x)) printf("1"); else printf("0"); } printf("\n\n"); } void set( unsigned char w) { LAMPE = w; } unsigned char get() { return LAMPE; } void funktion( int lampe, int modus) { char w=get(); switch( lampe) { case 1: switch( modus) { case AUS: w = w & ~17; break; case BLINKEN: w = w | 17; break; case NICHT_BLINKEN: w = w | 1; w = w & ~16; break; default: break; } break; case 2: switch( modus) { case AUS: w = w & ~34; break; case BLINKEN: w = w | 34; break; case NICHT_BLINKEN: w = w | 2; w = w & ~32; break; default: break; } break; case 3: switch( modus) { case AUS: w = w & ~68; break; case BLINKEN: w = w | 68; break; case NICHT_BLINKEN: w = w | 4; w = w & ~64; break; default: break; } break; case 4: switch( modus) { case AUS: w = w & ~136; break; case BLINKEN: w = w | 136; break; case NICHT_BLINKEN: w = w | 8; w = w & ~128; break; default: break; } break; default: break; } set( w); } void main() { show( LAMPE); funktion( 4,BLINKEN); show( LAMPE); funktion( 4,AUS); show( LAMPE); funktion( 4,NICHT_BLINKEN); show( LAMPE); } Meine Frage(n): Kann man das so machen? Macht man das so? Ist das O.K. so? Währe für Eure Antworten sehr dankbar. Info's zu Bit-Operationen: - http://www.informatik.fh-wiesbaden.de/~linn/bitoperation.htm - http://www.edv-schaefer.de/c-kurs/bsp-operatoren.html Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
gajUli Geschrieben 11. März 2002 Teilen Geschrieben 11. März 2002 Kommt mir etwas langatmig vor. Vielleicht ist eher sowas gemeint: unsigned char schalte_Lampe_n_ein(int n) { if (n>4 || n<0) return 0; set( get() | (1<<(n-1)) ); return ( get() ); } Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Jaipur Geschrieben 11. März 2002 Autor Teilen Geschrieben 11. März 2002 Hi, was hälst denn hier von: void function( int lampe, int modus) { char w = get(); w = w|(1<<(lampe-1)); w = w|(modus<<(lampe-1+4)); set( w); } Die erste Zeile schaltet die Lampe ein, die zweite Zeile unterscheidet den Blink Modus, macht aber im Grunde genommen nix anderes als auch nur EIN Bit in EINER Stelle zu setzen. Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Jaipur Geschrieben 11. März 2002 Autor Teilen Geschrieben 11. März 2002 Hi, habe mich wohl zu früh gefreut, die zweite Zeile setzt das Bit nicht auf "0" wenn es schon auf "1" gesetzt ist Und außerdem müsste man das auch noch ändern: # define NICHT_BLINKEN 0 # define BLINKEN 1 Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Crush Geschrieben 11. März 2002 Teilen Geschrieben 11. März 2002 Uli´s Ansatz gefällt mir ganz gut. Allerdings ist da nur das Lampensetzen drin, man muß aber den Modus noch ausmaskieren und neu setzen und auch Jaipur hat das übersehen, deshalb klappt das so nicht. unsigned char schalte_Lampe_ein(unsigned char lampe, unsigned char modus) { if (lampe>4 || lampe<1)) return 0; // wenn´s denn sein muß set( get() &~(1<<(lampe+3)) | (1<<(lampe-1)) + (modus<<(lampe+3))); // setzen, löschen, Modus mask & Modus set auf einmal return ( get() ); } Da man jedoch ausgeht, daß die Lampenschaltung nur einmal existiert, könnte man ja auch mit einer static-Variable arbeiten und sich so das get() set() sparen. Bei Hardware-Adressen wird praktisch immer mit statics gearbeitet und wenn es sich nicht nur um Output-Adressen, sondern auch oder nur um Input-Adressen handelt, wird immer mutable bei der (Klassen-)Deklaration dazugefügt. static unsigned char w=0; void schalte_Lampe_ein(unsigned char lampe, unsigned char modus) { w = w&~(1<<(lampe+3)) | (1<<(lampe-1)) + (modus<<(lampe+3)); } Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Crush Geschrieben 11. März 2002 Teilen Geschrieben 11. März 2002 Ist in meinem Fall vielleicht besser die Abfrage so zu machen: if ((lampe-1)&0xfc) return 0; // wenn´s denn sein muß weil die Lampe 1 auch die Zahl 1 darstellt. Nein, ist auch blöd, weil dann 0 nicht abgecheckt wird... bleiben wir lieber doch beim < und > Vergleich... Obwohl man davon ausgeht, daß man nur eine Lampe an oder ausschalten kann, die auch eine Nummer >0 hat... =8-D Aber mit sowas kann man sich ja sonstwie lange die Haare ausraufen, bis man keine mehr hat. Da kommt man sich vor als ob man sich über "Sein - oder nicht Sein?" frägt. Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
gajUli Geschrieben 11. März 2002 Teilen Geschrieben 11. März 2002 Die Aufgabe ist auch nicht eindeutig gestellt. Ich ging davon aus, dass eine Lampe angeschaltet soll in dem Zustand, in dem sie vorher gesetzt war, also blinkend oder dauernd. Crush geht davon aus, dass dies auch noch extra zu setzen waere, usw. Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Crush Geschrieben 11. März 2002 Teilen Geschrieben 11. März 2002 Sagt ja keiner was - Dein set(get())-Vorschlag war doch trotz allem sehr gut! Es stimmt aber, daß gerade bei programmtechnischen Themen die Fragestellung von den Leuten noch ein kleines wenig genauer ausgearbeitet sein könnte. Manchmal lag ich ja auch ziemlich daneben - und hab´s erst später mal mitbekommen. Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Jaipur Geschrieben 11. März 2002 Autor Teilen Geschrieben 11. März 2002 Hi, wie schon erwähnt, es ist eine alte Klausur Aufgabe. Ich denke mal das es dem Prof darauf ankommt, ob und wie man weiß ein Bit zu setzen/löschen/prüfen. Daher würde ich sagen das es so O.K. ist und außerdem steht in der Aufgabenstellung nichts von AUS-Schalten, für Sachen die gelößt werden und nicht gefragt sind, gibt es auch keine Bonus-Punkt .... void funktion( int lampe, int modus) { char w = get(); w = w|(1<<(lampe-1)); switch( modus) { case BLINKEN: w |= (1<<(lampe-1+4)); break; case NICHT_BLINKEN: w = w&~(1<<(lampe-1+4)); break; } set( w); } void main() { funktion( 4,NICHT_BLINKEN); show( LAMPE); funktion( 4,BLINKEN); show( LAMPE); funktion( 4,NICHT_BLINKEN); show( LAMPE); } Meine Lösung mag zwar programmtechnisch nicht 100% ' sein, aber sämtliche Fehlerquellen zu lokalisieren sind/gehören nicht in Klausur Aufgaben. Die funktion alleine, mit Begründung der Schnittstelle dürfte vollkommen ausreichen. Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
maxim_42 Geschrieben 12. März 2002 Teilen Geschrieben 12. März 2002 Hier eine etwas andere Herangehensweise: Wenn es schon unterschiedliche Zustandsgrößen in einem unsigned char gibt, könnte man ihnen auch Namen geben. Etwa so: #include <stdio.h> #define BLINKEN 1 #define NICHT_BLINKEN 0 struct StatusFeld{ unsigned char power :4; /* 4bit fuer die Power */ unsigned char modus :4; /* und 4 fuer den Modus */ }; int anschalten(unsigned char*,int,int); /* Wertebereich fuer lampe 1, 2, 3, 4 ( 0 bis 3 wäre schoener)*/ /* Wertebereich fuer modus 0, 1 */ int anschalten(unsigned char* pAlleLampen,int lampe,int mod){ struct StatusFeld *pbitfeld = (struct StatusFeld*) pAlleLampen; if(lampe <1 || lampe > 4) return 1; if(mod !=1 && mod) return 2; pbitfeld->power |= 1<<(lampe- 1); pbitfeld->modus = (mod == 0) ? pbitfeld->modus & (~(1<<(lampe- 1))) : pbitfeld->modus | (1<<(lampe-1)); return 0; } int main( void ) { unsigned char alleMeineLampen = 0; /* jaaa mach sie an! */ anschalten(&alleMeineLampen, 2, 1); printf("%i\n",(int)alleMeineLampen);/* Ausgabe 34 => 0010 | 0010 */ anschalten(&alleMeineLampen, 3, 1); printf("%i\n",(int)alleMeineLampen);/* Ausgabe 102 => 0110 | 0110 */ anschalten(&alleMeineLampen, 2, 0); printf("%i\n",(int)alleMeineLampen);/* Ausgabe 70 => 0100 | 0110 */ return 0; } Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Crush Geschrieben 12. März 2002 Teilen Geschrieben 12. März 2002 Grundsätzlich kann man das so nach den Konventionen machen. ABER: ... die Bitfelder verwende ich NIE!!! Und zwar aus dem Grund, wie die Compiler das handhaben. 1. sind mehr als 32 Bit nicht möglich (bei M$) ist aber meines Wissens maschinenabhängig. 2. werden die Bitfelder durch Zwischenspeichern, verheriges durch-die-Gegend-Rotieren und erst mal Ausmaskieren extrem langsam und sind auch nicht unbedingt geschickter zu verwenden. (dazu braucht man nur mal so einen Bitfield-Zugriff im Debugger anschauen - absoluter Wahnsinn was Studio da anstellt) 3. Der Einsatz von ganzen Bytes ist wohl kaum langsamer und sogar geschickter, selbst wenn ich dann nachher noch alle Bits zusammenmaskieren müßte um sie dann auf den Port zu legen. Ich bin ein bekennender Verfechter der Bitfield-Befehle - aber nur in C++. In ASM sieht das wieder ganz anders aus! Hier zeigt sich einfach mal wieder wie miserabel Compiler Code übersetzen. Derselbe Spaß findet auch beim Bits Rotieren statt - auch das ist nur umständlich mit unnötigen Zwischenspeicher und Ausmaskieren zu lösen und wird alles andere als maschinennah übersetzt (auch das gibt´s in nur einem ASM Befehl). Das soll jetzt kein Aufruf sein, daß sein zu lassen. Doch es ist einfach schade zu sehen, wie kostbare Rechenzeit von schlechten Compilern verplempert wird. Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
maxim_42 Geschrieben 12. März 2002 Teilen Geschrieben 12. März 2002 Mir gehts da weniger um Schnelligkeit sondern eher um Klarheit. Das alles mag Geschmackssache sein- ich finde einen Namen pro Zustandsgröße einfach klarer und lesbarer.( Und wenns compiliert, who cares?) Ich muß ehrlich zugeben, das ich schon 'ne Weile nicht mehr in reinem C programmiert habe- ich hatte wegen den Unterschieden zu C++ etwas Schwierigkeiten den Code fehlerfrei hinzukriege. Meine Herangehensweise war dann auch schauen wie ichs in c++ machen würde und dann in c zu übersetzen. Tschau Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Empfohlene Beiträge
Dein Kommentar
Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.