Forum: Compiler & IDEs Betriebssunden Zähler


von Bernd (Gast)


Lesenswert?

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);
  }

von Karl H. (kbuchegg)


Lesenswert?

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.

von Bernd (Gast)


Lesenswert?

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.

von Karl H. (kbuchegg)


Lesenswert?

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.

von Rolf Magnus (Gast)


Lesenswert?

>> 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
}

von Karl H. (kbuchegg)


Lesenswert?

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.

von Uhu U. (uhu)


Lesenswert?

>     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.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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.

von Uhu U. (uhu)


Lesenswert?

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.

von Rolf Magnus (Gast)


Lesenswert?

> 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.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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.

von Uhu U. (uhu)


Lesenswert?

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?

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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
Noch kein Account? Hier anmelden.