Hallo erstmal,
bin ein Neuling in Sachen uC-Progarmmierung und habe C im ersten
Semester vor 2 Jahren "gelernt". Meine erste Frage mag deshalb für die
erfahrenen unter uns sehr einfach klingen, ich scheitere jedoch bereits
hieran.
Ich verwende einen AT90CAN128. Es geht um folgendes C-Problem.
AN PORTB sind alle Pins auf Eingang geschalten. PIN G0 dient ebenfalls
als Eingang. Aufgrund von schaltungsspezifischen Vorgaben ist nur
jeweils ein PORT high. Wäre z.B. Port B2 High sollte ich folgendes
Bitmuster bekommen.
PB0 PB1 PB2 PB3 PB4 PB5 PB6 PB7 PG0
0 0 1 0 0 0 0 0 0
Nun möchte ich diese Information in eine dezimale Zahl umwandeln und
zwar folgendermassen,
PB0 PB1 PB2 PB3 PB4 PB5 PB6 PB7 PG0
0 0 1 0 0 0 0 0 0
1 2 3 4 5 6 7 8 9
und in diesem Fall würde die unsigned char Variable "openport" den Wert
3 bekommen. Ist kein Port High, dann soll die Variable den Wert 0
erhalten. Diese Variable steht für den PORT der High ist. Nun mache ich
das derzeit mit einer "hässlichen" For-Schleife und ich glaube das man
das wesentlich schöner hinkriegt.
Vielen Dank erstmal für die schnelle Hilfe,
leider kann ich in meinen C-Büchern und im Web nichts über die Funktion
finden (Deklaration etc.). Vielleicht könntest du mir eine gute
Internetseite nennen, wo ich mehr über die Funktion bzw. die Bibliothek
dazu erfahre.
Vielen Dank
! Nachtrag:
Habe gerade diese Seite gefunden:
http://www.opengroup.org/onlinepubs/009695399/functions/ffs.html
meinst du diese Funktion ?
Finde ich eine sehr gelungene Darstellung.
Allerdings habe ich mal gehört, dass Operationen mit "goto()" und
"break" alte Programmierweise ist und aufgrund des harten Eingriffs in
den Ablauf des Programms nicht mehr eingesetzt werden. Die Funktion
müsste aber doch auch ohne dem break funktionieren.
Die nun vorläufige Funktion habe ich nochmal ein bisschen abgeändert.
Habe nun nur noch 7 Eingänge. Und der alte Wert, steht im EEPROM und
wird gegebenenfalls aktualisiert. Müsste doch so funktioieren oder ?
Matthias Nagel wrote:
> Allerdings habe ich mal gehört, dass Operationen mit "goto()" und> "break" alte Programmierweise ist und aufgrund des harten Eingriffs> in den Ablauf des Programms nicht mehr eingesetzt werden.
Kokolorus.
Donald E. Knuth hat in der Zeit, in der die sogenannte ,,strukturierte
Programmierung'' ihre politische Hochkonjunktur hatte, mal ein Buch
geschrieben, das heißt: ``Structured Programming with GOTO''. Darin
hat er sehr detailliert beide Seiten der (eher politischen) Diskussion
beleuchtet und begründet, warum absolutistisch vertretene Meinungen
nicht automatisch zu einem gesunden Programmierstil führen.
> Die Funktion müsste aber doch auch ohne dem break funktionieren.
Nein, du hast die Funktion der switch-Anweisung von C noch nicht
verstanden.
> Donald E. Knuth hat in der Zeit, in der die sogenannte ,,strukturierte> Programmierung'' ihre politische Hochkonjunktur hatte, mal ein Buch> geschrieben, das heißt: ``Structured Programming with GOTO''. Darin> hat er sehr detailliert beide Seiten der (eher politischen) Diskussion> beleuchtet und begründet, warum absolutistisch vertretene Meinungen> nicht automatisch zu einem gesunden Programmierstil führen.
Interessant, so habe ich das noch nie gehört. Jetzt kenn ich wenigstens
mal den Background dahinter.
>> Die Funktion müsste aber doch auch ohne dem break funktionieren.>> Nein, du hast die Funktion der switch-Anweisung von C noch nicht> verstanden.
Richtig, habe ich verwechselt. SRY
Ich hätte eine Frage zu UART. Wäre wahrscheinlich besser einen neuen
Beitrag aufzumachen oder ?
Gruß an Meister "Matthias Nagel":
Wenn Du das brak bei einer Switch case Anweisung weglässt, dann erlebst
du
dein blaues Wunder.
Die switch(value) Anweisung sollte vom Compiler in eine Sprungtabelle
übersetzt werden. Dabei wird der Wert value so ausgewertet, dass daraus
ein
Sprungoffset berechnet wird.
Beispiel:
1
// PC = Aktuelle Position in der Befehlsverarbeitung
2
// Wird entweder als "Instruction Pointer" (IP) od. auch als
3
// "Program counter" (PC) bezeichnet.
4
5
AdressePseudocode
6
7
00SpringezuPC+x;// switch (value) - value ist hier 2; x = 0;
8
01
9
02TueProzedur1;// wird bei value = 2 angesprungen
10
03springezu07;
11
04TueProzedur2;// wird bei value = 4 angesprungen
12
05springezu07;
13
06....
14
07Tuewasanderes;// ist das Ende der Switch case.
Ich garantiere hier nicht für Fehlerfreiheit, aber das Prinzip dürfte
klar sein.
Eine stapel if-Anweisung erzeugt einen etwas komplexeren und dadurch
langsameren code. Währen die switch-Anweisung schnelleren code
produziert.
(Intelligente OPtimierungen eines Compilers mal vernachlässigt!)
Zusatz:
Hab ne Kleinigkeit vergessen:
Das "break" übersetzt der Compiler dabei in die Anweisungen an Adresse
03 und 05. Wenn man die weglässt läuft das Programm linear durch!
REM ** Wer lesen kann ist klar im Vorteil ***
Sorry, hab wohl den Thread zu schnell überflogen.
Ich hab noch einen Tip für "Matthias Nagel":
>Und der alte Wert, steht im EEPROM und>wird gegebenenfalls aktualisiert. Müsste doch so funktioieren oder ?
Wie oft ändert sich der Wert? BEdenke dass das EEPROM nur eine begrenzte
Anzahl an Schreibzyklen hat! Ausserdem ist die read_eeprom() Funktion
relativ langsam. Ich empfehle eine Kombination aus Hardware- und
Softwarelösung.
IN die Schaltung einen "dicken" Elko einbauen, der dem Controller noch
für einige hundert Milisekunden Strom liefern kann.
Den alten Wert einmal in eine globale VAriable laden und dann bei jeder
Änderung nur diese Aktualisieren. Wenn die Spannungsversorgung ausfllt
sollte der Controller einen INterrupt bekommen, die globale Variable ins
EEPROM sichern und dann solang in einer Schleife (bitte mit Zähler,
falls wieder Strom kommt) warten, bis der Elko entladen ist!
Das spart Rechenzeit und eeprom-Zyklen ;)