Hallo, hab da mal wieder ein Rechen Problem das ich nicht gelöst bekomme. Ich habe einen Zähler der in 4 Byte die Betriebsstunden in Sekunden zählt. Die 4 Byte übertrage ich mit dem UART und möchte sie nun in HHHH:MM:SS anzeigen. Der Code ist nur der Anfang, aber das zusammensetzen der 4 Byte zu einer 32-Bit Zahl geht schon nicht und die restliche Berechnung stimmt auch nicht. Ich hoffe Ihr könnt mir helfen, vielen Dank schon mal im Voraus. uint8_t x,z; uint16_t s,t; uint32_t u; if (UART.NEU_BEF) // Neue Daten empfangen { Write_LCD (0xC6,0); // Setze Cursor auf 2.Zeile 5.Stelle u = (UART_BYTE_EIN[5] << 24) | (UART_BYTE_EIN[4] << 16) | \ (UART_BYTE_EIN[3] << 8) | UART_BYTE_EIN[2]; t = u / 3600; x = t / 1000; x = x + 0x30; Write_LCD (x,1); s = t % 1000; x = s / 100; x = x + 0x30; Write_LCD (x,1); z = s % 100; x = z / 10; x = x + 0x30; Write_LCD (x,1); x = z % 10; x = x + 0x30; Write_LCD (x,1); Write_LCD (':',1); }
Bernd wrote: > u = (UART_BYTE_EIN[5] << 24) | (UART_BYTE_EIN[4] << 16) | \ ^ was soll den das hier sein Ein Fortsetzungszeichen in der letzten Spalte braucht man nur bei Makros, sprich: wenn der Präprozessor zum Einsatz hommt. > (UART_BYTE_EIN[3] << 8) | UART_BYTE_EIN[2]; u = ((uint32_t)UART_BYTE_EIN[5] << 24) | ((uint32_t)UART_BYTE_EIN[4] << 16) | ((uint16_t)UART_BYTE_EIN[3] << 8) | UART_BYTE_EIN[2]; Grundregel: In C werden alle Ausdrücke grundsätzlich im Datenbereich int (beim WinAvr also: 16 Bit) ausgeführt, es sei denn einer der beiden Operanden hat einen 'höheren' Datentyp. UART_BYTE_EIN[5] ist (vermutlich) ein Byte, also uint8_t 24 ist definitiv ein int also wird UART_BYTE_EIN[5] als int-Berechnung durchgeführt. Einen 16 Bit um 24 Stellen nach links verschieben, gibt aber auf jeden Fall 0, weil alle relevanten Bits links herausfallen.
Vielen Dank Karl Heinz, hat wunderbar geklappt. Die Definition von Variablen stellt mich immer vor größte Probleme. Habe vorher nur in Assembler Programmiert und das ist doch eine große Umstellung auf C. In meine C-Buch steht halt “Ein Rückstrich (Backslash \) am ende einer Zeile bedeutet eine Fortsetzung der Eingabe auf der nächsten Zeile.“ Also gleich 2 mal dazu gelernt.
Bernd wrote: > ist doch eine große Umstellung auf C. In meine C-Buch steht halt “Ein > Rückstrich (Backslash \) am ende einer Zeile bedeutet eine Fortsetzung > der Eingabe auf der nächsten Zeile.“ Aber nur beim Präprozessor #define MAX(a,b) (a) < (b) \ : \ (b) \ ? \ (a) dort braucht man es um dem Präprozessor mitzuteilen: Die nächste Zeile gehört auch noch dazu. Ansonsten wird in C alles andere, Tabulatoren, mehrere Leerzeichen hintereinander, Zeilenumbruch, Kommentare, wie ein einziges Leerzeichen behandelt: Es dient zum Trennen der einzelnen Schlüsselwörter, sofern sich aus den restlichen Sonderzeichen gemäss Syntax nicht sowieso eine Trennung ergibt. Ob du schreibst:
1 | int main() |
2 | {
|
3 | int i = 5; |
4 | }
|
oder
1 | int
|
2 | main( |
3 | )
|
4 | {
|
5 | int
|
6 | i = /* */ |
7 | 5
|
8 | ;
|
9 | }
|
ist dem Compiler völlig egal. Er sieht nur die Sequenz Schlüsselwort/int Name_der_Funktion/main öffnende_Klammer schliessende_Klammer öffnende_geschweifte_Klammer Schlüsselwort/int Name_einer_Variablen Zuweisungszeichen Zahl/5 Semikolon schliessende_geschweifte_Klammer und baut aus dieser sequenzierten Darstellung seine intern zu übersetzende Programmstruktur zusammen.
>> ist doch eine große Umstellung auf C. In meine C-Buch steht halt “Ein >> Rückstrich (Backslash \) am ende einer Zeile bedeutet eine Fortsetzung >> der Eingabe auf der nächsten Zeile.“ > > Aber nur beim Präprozessor Naja, der Präprozessor ist der Teil, der die Bearbeitung macht, aber gelten tut das überall, nicht nur in #defines. Zum Beispiel geht auch folgendes:
1 | #include <stdio.h> |
2 | int main() |
3 | {
|
4 | puts("Hello \ |
5 | world"); |
6 | return 0; |
7 | }
|
Oder sogar:
1 | #include <stdio.h> |
2 | int testvariable = 5; |
3 | |
4 | int main() |
5 | {
|
6 | printf("%d", test\ |
7 | variable); |
8 | return 0; |
9 | }
|
Rolf Magnus wrote: > Naja, der Präprozessor ist der Teil, der die Bearbeitung macht, aber > gelten tut das überall, nicht nur in #defines. Zum Beispiel geht auch > folgendes: Wow. Das wusste ich wirklich noch nicht! Merci.
> puts("Hello \ > world"); Dafür gibt es eine deutlich elegantere Lösung: puts("Hello " "world"); Zwei Stringkonstanten, die ohne Operator aufeinander folgen werden vom Compiler concateniert. Kommentare dürfen dazwischen stehen, denn die werden vom Preprozessor weggeworfen, bevor der Compiler sie sieht.
Uhu Uhuhu wrote:
> Dafür gibt es eine deutlich elegantere Lösung:
Es ging ja aber um die Demonstration, was die Folge
backslash-newline genau macht.
Jörg Wunsch wrote: > Es ging ja aber um die Demonstration, was die Folge > backslash-newline genau macht. Die Chose mit dem Backslash hat leider erhebliche Tücken: Man sieht ihr nicht so ohne weiteres an, ob das NL escaped wurde, oder nur ein Blank. Ich rate von diesem Klimmzug ab - er ist ein Überbleibsel aus dden ganz frühen C-Zeiten, den man vermutlich aus Kompatibilitätsgründen nicht rausgeschmissen hat. Den Rausschmiß verdient hat er allemal. Nachtrag: Genau genommen ist es eine Funktion des CPP, der escapte NLs einfach wegschmeißt. Beheben könnte man das dadurch, daß man den CPP so ändert, daß er den \ am Zeilenende nur dann bearbeitet, wenn er in einer Preprozessoranweisung steht.
> Die Chose mit dem Backslash hat leider erhebliche Tücken: Man sieht ihr > nicht so ohne weiteres an, ob das NL escaped wurde, oder nur ein Blank. Kommt auf den Editor an. Die, die ich kenne, können überflüssige Blank-Zeichen am Ende einer Zeile optisch markieren, und am Syntaxhighlighting sehe ich in der Regel auch, ob der Zeilenumbruch escaped ist. > Ich rate von diesem Klimmzug ab - er ist ein Überbleibsel aus dden ganz > frühen C-Zeiten, den man vermutlich aus Kompatibilitätsgründen nicht > rausgeschmissen hat. Den Rausschmiß verdient hat er allemal. Wie Jörg schon schrieb: Ich wollte damit nicht sagen, daß man es außerhalb von Makros einsetzen sollte, sondern nur, daß es theoretisch möglich ist. Ich wollte halt auch mal mehr wissen als Karl Heinz ;-) > Beheben könnte man das dadurch, daß man den CPP so ändert, daß er den \ > am Zeilenende nur dann bearbeitet, wenn er in einer > Preprozessoranweisung steht. Beheben? Ich sehe kein Problem, das man beheben müßte. Wenn du es (berechtigterweise) außerhalb von Makro-Definitionen nicht nutzen willst, dann nutze es dort einfach nicht.
Rolf Magnus wrote: >> Die Chose mit dem Backslash hat leider erhebliche Tücken: Man sieht ihr >> nicht so ohne weiteres an, ob das NL escaped wurde, oder nur ein Blank. > Kommt auf den Editor an. Die, die ich kenne, können überflüssige > Blank-Zeichen am Ende einer Zeile optisch markieren, ... Macht meiner auch, und ich bin immer wieder irgendwas zwischen überrascht und entsetzt, wie viele Leute da ihren ,,Datenmüll'' am Zeilenende liegen lassen. Wer natürlich ein Leerzeichen mit einem Backslash versieht, gehört sowieso erschlagen.
Richtig gute Editoren geben dem Benutzer die Möglichkeit zu konfigurieren, was mit Leerzeichen am Zeilenende passieren soll. Einem reinen C/C++-Editor würde ich u.U. noch durchgehen lassen, Blanks am Ende immer automatisch wegzuschmeißen. Für Universal-Editoren ist das nicht sinnvoll. > Wer natürlich ein Leerzeichen mit einem Backslash versieht, gehört > sowieso erschlagen. Sowas passiert zuweilen schneller, als man denkt; copy&paste ist ein sehr gutes Vehikel, solche Effekte mal eben schnell zusammenzuklicken. Aber deswegen den armen Kerl gleich erschlagen?
Der Spruch bei uns auf Arbeit heißt nicht umsonst: "Copy, paste, and die."
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.