mikrocontroller.net

Forum: Compiler & IDEs Problem mit ausgabe über sprintf


Autor: Andreas Herrmann (andy78)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo

typedef struct
{
  uint8_t seconds;
  uint8_t minutes;
  uint8_t hours;

} displ_time;



 displ_time get_time;

uint32_t cantime=0;
cantime=(((message->data[4]<<16)|(message->data[3]<<8)|message->data[2]) 
);

//cantime seconds seit 24uhr.

get_time.hours=(cantime/3600);

sprintf(buffer,"%d#%2x-%2x-%2x\0",get_time.hours,message->data[4],messag 
e->data[3],message->data[2]);

GLCD_chartext(&buffer[0],132,191,26,2,2);



die message->data daten stimmen

feld4=0
feld3=0xc8
feld2=sek z.b 0xd9

ich habe cantime im devcpp ausprobiert dort kommt wenn ich cantime/3600 
teile 14 raus für 14 Uhr.

hier kommt 86 raus

kann mir einer meinen schlauch entfernen auf dem ich gerade stehe.


Viele Dank

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Andreas Herrmann schrieb:

> ich habe cantime im devcpp ausprobiert dort kommt wenn ich cantime/3600
> teile 14 raus für 14 Uhr.

lass dir mal im devcpp die cantime ausgeben und dann vergleich mit dem 
Wert, den du hier hast


  message->data[4]<<16
arbeitest du auf einem AVR?
Wenn ja, dann hast du hier einen Überlauf.
Dieser Ausdruck wird in int gerechnet. int hat 16 Bit. Damit schiebst du 
alle Bits links raus. Der Ausdruck ergibt immer 0.

Autor: Klaus Falser (kfalser)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was ist die Frage und was kommt falsch, aber :

sprintf(buffer,"%d#%2x-%2x-%2x\0",
get_time.hours,message->data[4],message->data[3],message->data[2]);

z.B.: Parameter 1 erwartet integer, du übergibst aber ein uint8_t

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Klaus Falser schrieb:
> Was ist die Frage und was kommt falsch, aber :
>
> sprintf(buffer,"%d#%2x-%2x-%2x\0",
> get_time.hours,message->data[4],message->data[3],message->data[2]);
>
> z.B.: Parameter 1 erwartet integer, du übergibst aber ein uint8_t

Kommt in dem Fall sogar das richtige raus.
der uint8_t wird vor Übergabe automatisch auf int aufgeblasen.

Autor: Andreas Herrmann (andy78)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo

 message->data[4]<<16
arbeitest du auf einem AVR?
Wenn ja, dann hast du hier einen Überlauf.
Dieser Ausdruck wird in int gerechnet. int hat 16 Bit. Damit schiebst du
alle Bits links raus. Der Ausdruck ergibt immer 0.

Also uint32 ahbe zu int gemacht und es geht es kommt 14 raus so was 
blödes ist uint32 nicht ausreichend????

Danke

Gruß
Andy

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Andreas Herrmann schrieb:

> Also uint32 ahbe zu int gemacht und es geht es kommt 14 raus so was
> blödes ist uint32 nicht ausreichend????

das wird mir jetzt zu verwirrend.
Das war
* der falsche fix
* da data[4] sowieso 0 war, hat es sich nicht ausgewirkt

Zeig bitte alles. Die ganze Funktion. Copy&Paste
(So wie sie nicht funktioniert).
Aus dem was du gepostet hattest, ergibt sich nur dieser eine Fehler, der 
sich aber aufgrund der tatsächlichen Daten nicht auswirkt.

Autor: Andreas Herrmann (andy78)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo

stimmt data[4] ist 0 das ist so io.

unsigned int cantime=0;
    cantime=(((message->data[4]<<16)|(message->data[3]<<8)|message->data[2]) 
);
    get_time.hours=(cantime/3600);
    get_time.minutes=((cantime)-(get_time.hours*3600))/60;

    sprintf(buffer,"%02d:%02d\0",get_time.hours,get_time.minutes);
    GLCD_chartext(&buffer[0],130,191,26,2,2);


mit dem funktionierts

ne blöde frage wie bekomme ich auch die sekunden heraus aus cantime???


ich habe vor das Datum in tagen seit 1970 auszugeben oder über den Bus 
zu übermitteln
Mein ansatz

day=16
month=12
year=2010
day=(rtc.date[0]*10)+rtc.date[1];
month=(rtc.date[3]*10)+rtc.date[4];
year=2000+(rtc.date[8]*10)+rtc.date[9];
diff=(year-1970)*12;
diff+=month;
diff=(diff*30.4368499)+day;
diff=tage seit 1970 = 14990 tage.

Gruß

Andy

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Andreas Herrmann schrieb:

> ne blöde frage wie bekomme ich auch die sekunden heraus aus cantime???

Na ja.
Wieviele Minuten und Sekunden sind denn in 234 Sekunden

Das sind 234 / 60 gleich 3 Minuten

d.h. von den 234 Sekunden sind 180 für die 3 Minuten schon verrechnet 
worden und übrig bleiben: 234 - ( 3*60 ) gleich 54 Sekunden.
234 Sekunden sind also 3 Minuten und 54 Sekunden

Oder wie man in der Grundschule schon lernt:
Eine Mutter hat 14 Äpfel und 3 Kinder. Wenn alle Kinder gleich viele 
Äpfel bekommen, wieviele Äpfel bekommt jedes Kind und wieviele bleiben 
der Mutter übrig?
Division mit Rest

/ ist in C die Division.
% ist in C der Rest, der bei einer Ganzzahl-Division bleibt.

Autor: Andreas Herrmann (andy78)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo

Ok ja klar Danke

Hier ist meine Tages berechnung seit 1.1.1970

habe natürlcih jetzt die Schaltjahre drin


uint8_t schaltjahr_berechnen(uint16_t jahr)
{

if ( ( (jahr%4==0) && (jahr%100!=0) ) || (jahr%400==0) ) {
   return 1;
} else {
  return 0;
  }




}



unsigned int daysumm=0;

for (int i=1970;i<year;i++)
{
if(schaltjahr_berechnen(i)==1)
{
daysumm+=366;
}
else
{
daysumm+=365;
}
}
if(month==1 || month>1)daysumm+=31;
if(month==2 || month>2)
{
if(schaltjahr_berechnen(year)==1)
{
daysumm+=(29);
}
else
{
daysumm+=(28);

}
}
if(month==3 || month>3)daysumm+=31;
if(month==4 || month>4)daysumm+=30;
if(month==5 || month>5)daysumm+=31;
if(month==6 || month>6)daysumm+=30;
if(month==7 || month>7)daysumm+=31;
if(month==8 || month>8)daysumm+=31;
if(month==9 || month>9)daysumm+=30;
if(month==10 || month>10)daysumm+=31;
if(month==11 || month>11)daysumm+=30;
if(month==12)daysumm+=day;


Ergebnis =14960 Tage.

Autor: Andreas Herrmann (andy78)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo

jetzt habe ich den salat.
unsigned int cantime=0;
    cantime=(((message->data[4]<<16)|(message->data[3]<<8)|message->data[2]) 
);
    get_time.hours=(cantime/3600);
    get_time.minutes=((cantime)-(get_time.hours*3600))/60;

    sprintf(buffer,"%02d:%02d\0",get_time.hours,get_time.minutes);
    GLCD_chartext(&buffer[0],130,191,26,2,2);



data[4] ist jetzt 1

im devcpp kommt das richtige ergebniss (18Uhr) der AVR liefert 0

cantime=67250.

Danke

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Andreas Herrmann schrieb:

> if(month==1 || month>1)daysumm+=31;

Echt?
Für den 7. Jänner werden wegen des Jänners (month == 1) immer 31 Tage 
gutgeschrieben?

> if(month==12)daysumm+=day;

Das verblüfft mich jetzt ein wenig, dass das Tagesdatum nur dann mit 
eingerechnet wird, wenn der Monat Dezember vorliegt. Eigentlich hätte 
ich das immer erwartet, denn vom Jahresbeginn aus gerechnet ist der 7. 
Jänner der 7. Tag im Jahr, wohingegen der 7. Februar der 38. Tag im Jahr 
ist. 31 für den kompletten Jänner und dann noch 7 im Februar dazu.

Denk nachmal über deine Monatsabfragen nach. Tipp: Du brauchst da kein 
Oder

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Andreas Herrmann schrieb:

> data[4] ist jetzt 1

Das 'Problem' ist nach wie vor, dass

   message->data[4]<<16

in 16 Bit int gerechnet wird, weil message->data[4] nicht größer als ein 
int ist.
Wenn du aber einen 16 Bit int um 16 Stellen nach links verschiebst 
bleibt im Ergebnis, welches nach den C Regeln ebenfalls nur 16 Bit 
umfasst, nichts mehr übrig.
Du hast sozusagen dein Auto zuweit über die Klippen rausgeschoben und 
jetzt ist es weg.

Du musst also message->data[4] zuerst auf einen 32 Bit Typen hochcasten, 
damit du ihn um 16 Bit nich links verschieben kannst UND im Eregbniss 
dann auch noch was übrig bleibt, weil es dann 32 Bit groß ist.

Autor: Andreas Herrmann (andy78)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo

Das hier geht nicht

long cantime=0;
cantime=(((long)message->data[4])<<16)|(message->data[3]<<8)|message->da 
ta[2];


als stunde kommt eins raus statt 19.


Danke

Gruß


Andy

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wie hast du eigentlich data definiert.

Ansonsten: Schau dir deine Werte an, rechne nach und finde raus, wo das 
Programm etwas anderes machst als du erwartest.

Geht nicht anders. Du musst das lernen, wie du selber Fehler auf die 
Schliche kommen kannst.

(D.h. das stimmt nicht ganz. Ein C-Buch wäre deine erste Anlaufstelle)

Autor: Andreas Herrmann (andy78)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo

hast Du vieleicht ein Tip für ein gutes Buch???


Danke

Habeübrigends den Fehler gefunden

Natürlch sollte man die Gegenstelle auch so definieren das wenn es über 
die 65xxx grenze geht auch zu long wandeln.

danke

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Andreas Herrmann schrieb:
> Hallo
>
> hast Du vieleicht ein Tip für ein gutes Buch???

Der Klassiker

Kernighan&Ritchie
Programmieren in C

> Habeübrigends den Fehler gefunden
>
> Natürlch sollte man die Gegenstelle auch so definieren das wenn es über
> die 65xxx grenze geht auch zu long wandeln.

gut.

Übrigens:
Wenn du auf Byte-Ebene arbeitest, dann willst du immer haben, dass dir 
ein eventuelles Vorzeichenbit nicht in die Quere kommt.
Das heißt du arbeitest IMMER mit unsigned Datentypen!
Sei das jetzt unsigned char, oder unsigned int oder unsigned long.
Hauptsache unsigned.

Autor: Andreas Herrmann (andy78)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo

Danke

Klappt jetzt alles wunderbar

GPS CAN Modul sendet Datm(tage seit 1.1.1970) Uhrzeit(sekunden seit 
00:00)

Display empfängt über CAN und rechnet zurück



Das Buch werde ich mir als erstes morgen betsellen.

Für heute ist feierabend

Danke


Gruß

Andy

Autor: Andreas Herrmann (andy78)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo

Buch bestellt bei Amazon neu.

Noch eine dringende frage habe jetzt das Problem das wenn Data[4]=0 ist 
die Uhrzeit nicht mehr stimmt.

Ist es möglich wenn Data[4]==0 dann unsigned int cantime
wenn data[4]==1 dann unsigned long cantime.

Wenn ich jetzt wo data4[0] ist unsigned int nehme haut es wieder hin.

Danke

Autor: Rolf Magnus (rmagnus)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Andreas Herrmann schrieb:
> Ist es möglich wenn Data[4]==0 dann unsigned int cantime wenn data[4]==1
> dann unsigned long cantime.

Wozu sollte das gut sein? Wo ist denn das Problem, wenn cantime immer 
unsigned long ist?

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Andreas Herrmann schrieb:

> Ist es möglich wenn Data[4]==0 dann unsigned int cantime
> wenn data[4]==1 dann unsigned long cantime.
>
> Wenn ich jetzt wo data4[0] ist unsigned int nehme haut es wieder hin.

Dann muss man das Problem analysieren.
Diese "Ich probiere so lange rum bis es funktioniert"-Technik 
funktioniert nicht auf Dauer.

Autor: Andreas Herrmann (andy78)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo

Ich schon wieder


Jetzt bin ich an die magische zahl 14965 angelangt für datum seit 
1.1.1970.

wäre 21.12.2010.

long candate=14965;


dabei erhalte ich für tag=246 monat=12 year=2011

wenn ich 14964 setze dann 20.12.2010;

ich kann das ganze doch auch in ein uint32_t packen.

Habe mal den quellcode angehangen nur der Formatierung wegen.

Danke

Gruß

ANdy

Autor: Andreas Herrmann (andy78)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo

habe durch zufall entdeckt das 14965/365=41 Jahre sind dann hat es ja 
nicht hin.

dies betrifft alles was ende dezember ist egal welches jahr

rechne ich gestern 14964 +1 Jahr drauf 365 und teile durch 365 kommen 41 
Jahre wieder raus für 2011.

Wie kompensiere ich den Dezember????


Danke

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Andreas Herrmann schrieb:
> Hallo
>
> habe durch zufall entdeckt das 14965/365=41 Jahre sind dann hat es ja
> nicht hin.
>
> dies betrifft alles was ende dezember ist egal welches jahr
>
> rechne ich gestern 14964 +1 Jahr drauf 365 und teile durch 365 kommen 41
> Jahre wieder raus für 2011.
>
> Wie kompensiere ich den Dezember????


Was um alles in der Wet machst du da bloss
    uint16_t s=0,jahr=1970;
    s=(int)day/365;
    for(int i=0;i<s;i++)
    {
    if(schaltjahr(jahr)==1)
    {
      day-=366;
    }
    else
    {
      day-=365;
        }
    jahr++;                       
    }                        

Es gibt doch nicht nur for-Schleifen.
Sinn der Sache ist es offenbar das Jahr festzustellen und wieviele Tage 
dann im nicht vollständig angerechneten Jahr noch übrig bleiben. Du 
kannst dir doch nicht im Vorfeld mit day/365 ausrechnen, wieviele Jahre 
das sind. Wenn du das könntest, dann bräuchtest du nicht so kompliziert 
runterzählen sondern könntest ganz einfach:  day = day - 365*s  machen 
und hast richtig reduziert. Da du das (aus naheliegenden Gründen) nicht 
tun kannst, kannst du auch nicht in der Umkehrung dividieren. Wenn nicht 
sicher gestellt ist, dass in 10 Jahren genau 3650 Tage vorkommen, dann 
gilt logischerweise auch die Umkehrung nicht, dass 3650 Tage genau 10 
Jahre sind.


   uint16_t jahr = 1970;

   while( day > 365 ) {
     if( schaltjahr(jahr) )
       day -= 366;
     else
       day -= 365;

     jahr++;
   }

die Abbruchbedingung der while Schleife muss ich noch überlegen. Da muss 
noch was rein je nachdem ob man sich in einem Schaltjahr befindet oder 
nicht, ist der 366.te Tag manchmal der 12.Dezember und manchmal der 
1.Jänner

Schnellschuss
   uint16_t jahr = 1970;

   while( day > 365 || ( day > 366 && schaltjahr(jahr+1) ) {
     if( schaltjahr(jahr) )
       day -= 366;
     else
       day -= 365;

     jahr++;
   }

Ich habs nicht ausprobiert, ich denke es ist nicht so weit daneben.
Man könnte auch sowas machen
   uint16_t jahr = 1970;

   while( day > 366 ) {
     if( schaltjahr(jahr) )
       day -= 366;
     else
       day -= 365;

     jahr++;
   }

   if( day == 366 && schaltjahr(jahr) ) {
     day -= 366;

     jahr++;
   }

Also bis auf 366 Tage reduzieren und hinterher entscheiden, ob man noch 
1 Jahr gutschreiben muss oder nicht.


Ein bischen besser systematisch testen und die richtigen Schlüsse 
ziehen!

Autor: sven (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wie wärs wenn Du ab 1.1.2010 +(const Tage_1.1.1970-31.12.2009 = 14609) 
zählst ? Dann kommt das Problem mit dem Schaltjahr später :-)

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Eben. Das Problem lässt sich tabellenorientiert lösen. Die Betrachtung 
von Jahren vor 2010 ist irrelevant, und die Schaltjahrbestimmung kann 
auch über eine einfache Tabelle gelöst werden.

Die Tabelle enthält für die nächsten 15..20 Jahre die Nummer des ersten 
Tages im Jahr. Damit sind gerade mal 15..20 uint16_t-Werte erforderlich.

(wie wahrscheinlich ist denn eine Nutzung des Programmes im Jahr 2030?)

Zur Jahresbestimmung wird also diese Jahrestabelle durchlaufen, bis der 
Tage-seit-1970-Wert ins gefundene Jahr passt.

Der gefundene Jahresanfangswert wird abgezogen, und das Resultat ist der 
Tag im Jahr.

Anhand der Differenz Jahresanfangswert[aktuelles Jahr] und 
Jahresanfangswert[aktuelles Jahr + 1] kann festgestellt werden, ob ein 
Schaltjahr vorliegt.

Dann gibt es eine zweite Tabelle, die die Nummer des ersten Tages im 
Monat enthält, diese enthält 12 uint16_t-Werte und kann der Einfachheit 
halber doppelt ausgeführt werden (mit entsprechender Verschiebung bei 
Schaltjahren).

Jan Feb Mär Apr Mai  Jun  Jul  Aug  Sep  Okt  Nov  Dez
 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335

Die Bestimmung des Monats erfolgt analog zur Bestimmung des Jahres, es 
wird solange die Monatsanfangstabelle durchlaufen, bis der Tag im Jahr 
in den gefundenen Monat passt.

Damit sind Monat und Tag im Monat bestimmt.

Nötig sind dazu drei Tabellen und zwei Schleifen.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.