Betriebssunden Zähler

Gast #681933
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);
  }
#681949
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.
Gast #682599
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.
#682957
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.
Gast #683027
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
}
#683136
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.
#683252
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.
Gast #683673
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.
Moderator Persönliche Seite #683706
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.
#683952
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?

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren