Forum: Mikrocontroller und Digitale Elektronik Darstellungproblem


von Max F. (Gast)


Lesenswert?

Ich sende über die UART vom ATMEGA8535 Temperatur und Luftdruckwerte
sowie Datum. Das alles geht ja schon mal. Nur ich bekomme nicht die
Daten so an wie hier:

2006 12. 16. 1 1014 23
2006 12. 16. 2 1014 23
2006 12. 16. 3 1014 23
2006 12. 16. 4 1014 23
2006 12. 16. 5 1014 23
2006 12. 16. 6 1014 23
2006 12. 16. 7 1014 23
2006 12. 16. 8 1014 23
2006 12. 16. 9 1014 23
2006 12. 16. 1 1014 23
2006 12. 16. 1 1014 23
2006 12. 16. 1 1014 23
2006 12. 16. 1 1014 23
2006 12. 16. 1 1014 23
2006 12. 16. 1 1014 23
2006 12. 16. 1 1014 23
2006 12. 16. 1 1014 23
2006 12. 16. 1 1014 23
2006 12. 16. 1 1014 23
2006 12. 16. 2 1014 23
2006 12. 16. 2 1014 23
2006 12. 16. 2 1014 23
2006 12. 16. 2 1014 23

Mit dem Terminalprogramm empfange ich immer dies hier:
Da sind immer Leerzeichen die da nicht hin sollen, sowie nach 16.
sollte eigentlich die Zahl von 1 bis 23 dargestellt werden. Hier sieht
man nur immer ein Zeichen.

 2006 12. 16. 1 1014 23
 2006 12. 16. 2 1014 23
 2006 12. 16. 3 1014 23
 2006 12. 16. 4 1014 23
 2006 12. 16. 5 1014 23
 2006 12. 16. 6 1014 23
 2006 12. 16. 7 1014 23
 2006 12. 16. 8 1014 23
 2006 12. 16. 9 1014 23
 2006 12. 16. 1 1014 23
 2006 12. 16. 1 1014 23
 2006 12. 16. 1 1014 23
 2006 12. 16. 1 1014 23
 2006 12. 16. 1 1014 23
 2006 12. 16. 1 1014 23
 2006 12. 16. 1 1014 23
 2006 12. 16. 1 1014 23
 2006 12. 16. 1 1014 23
 2006 12. 16. 1 1014 23
 2006 12. 16. 2 1014 23
 2006 12. 16. 2 1014 23
 2006 12. 16. 2 1014 23
 2006 12. 16. 2 1014 23

Meine Funktion sieht so aus:

void tagesprofil (void)
{
 unsigned char n, m;
 for (n=0; n<24; ++n)
    {
     if (n == 0)
      {
       putchar('T');
      }
     sprintf (printbuf,"%4i%2i.%2i.%2i
",2006,(int)12,(int)16,(int)n);
     sprintf (printbuf+15,"%4i%3i",1014,23);
     *(printbuf+24) = 0x0d;
     *(printbuf+25) = 0x0a;
     for (m=0; m<26; ++m)
        {
          putchar(*(printbuf + m));
        }
     {unsigned int i; for (i=1000; i>0; --i);}
    }
 putchar('E');
}

von Max F. (Gast)


Lesenswert?

Mist ich muss mich wieder korrigieren:

Ich möchte diese Darstellung haben:

2006 12.16.01 1014 23
2006 12.16.02 1014 23
2006 12.16.03 1014 23
2006 12.16.04 1014 23
2006 12.16.05 1014 23
2006 12.16.06 1014 23
2006 12.16.07 1014 23
2006 12.16.08 1014 23
2006 12.16.09 1014 23
2006 12.16.10 1014 23
2006 12.16.11 1014 23
2006 12.16.12 1014 23
2006 12.16.13 1014 23
2006 12.16.14 1014 23
2006 12.16.15 1014 23
2006 12.16.16 1014 23
2006 12.16.17 1014 23
2006 12.16.18 1014 23
2006 12.16.19 1014 23
2006 12.16.20 1014 23
2006 12.16.21 1014 23
2006 12.16.22 1014 23
2006 12.16.23 1014 23

Also ganz oben das ist falsch.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Warum so umständlich?

     sprintf (printbuf,"%4i%2i.%2i.%2i
",2006,(int)12,(int)16,(int)n);
     sprintf (printbuf+15,"%4i%3i",1014,23);
     *(printbuf+24) = 0x0d;
     *(printbuf+25) = 0x0a;

a) Die typecasts nach int kannst Du weglassen, die Konstanten sind
sowieseo vom Typ int.

Leerzeichen sollten auch im Formatstring angegeben sein.

b) Ein Aufruf von sprintf genügt völlig:


  sprintf(printbuf, "%04d %02d.%02d.%02d %04d %02d\r\n",
    2006, 12. 16, n, 1014, 23);



(Anstelle von %i kann auch das üblichere %d verwendet werden)

Natürlich könntest Du, wenn fast alle Parameter eh Konstanten sind,
auch sprintf wie folgt verwenden:

  sprintf(printbuf, "2006 12.16.%02d 1014 23\r\n", n);

aber das wäre vermutlich zu einfach.

Desweiteren kannst Du auf Dein Abzählen von Zeichen bei der Ausgabe des
Inhaltes von printbuf verzichten; printbuf enthält einen
nullterminierten String, und das kann man ausnutzen:

  char* p;  // Hilfspointer

  p = printbuf;

  while (*p)
  {
    putchar(*p++);
  }

Du musst nur sicherstellen, daß printbuf ausreichend groß ist, um einen
Deiner Strings aufnehmen zu können - und auch Platz für die
abschließende \0 hat, die von sprintf als Kennzeichnung des
Stringendes angehängt wird.

Im übrigen hätten zur Demonstration des gewünschten Formates zwei bis
drei Beispiele vollends genügt; 23 ist eindeutig übertrieben.

Ansonsten solltest Du die "BACK"-Funktion Deines Browsers nicht
verwenden, sonst passiert Dir diese Beitragsinkontinenz wie oben.

von Hannes L. (hannes)


Lesenswert?

> Beitragsinkontinenz

Der war gut!

;-)

...

von Max F. (Gast)


Lesenswert?

Hab meinen Code abgeändert.
Jetzt erhalte ich vom Controller über die UART folgendes:

T 2006 12. 16. 0 1024 23
<0> 2006 12. 16. 1 1024 23
<0> 2006 12. 16. 2 1024 23
<0> 2006 12. 16. 3 1024 23
<0> 2006 12. 16. 4 1024 23
<0> 2006 12. 16. 5 1024 23
<0> 2006 12. 16. 6 1024 23
<0> 2006 12. 16. 7 1024 23
<0> 2006 12. 16. 8 1024 23
<0> 2006 12. 16. 9 1024 23
<0> 2006 12. 16. 10 1024 23
 2006 12. 16. 11 1024 23
 2006 12. 16. 12 1024 23
 2006 12. 16. 13 1024 23
 2006 12. 16. 14 1024 23
 2006 12. 16. 15 1024 23
 2006 12. 16. 16 1024 23
 2006 12. 16. 17 1024 23
 2006 12. 16. 18 1024 23
 2006 12. 16. 19 1024 23
 2006 12. 16. 20 1024 23
 2006 12. 16. 21 1024 23
 2006 12. 16. 22 1024 23
 2006 12. 16. 23 1024 23
E

Woher kommt da das Zeichen <0>? Ich möchte dass das Zeichen <0> nicht
erscheint bzw vorhanden ist.Desweiteren sollte nach 12. und nach 16.
kein Leerzeichen vorhanden sein. Ich weiss nun nicht wo ich da meinen
Code abändern muss.

Der Code sieht so jetzt aus:

void tagesprofil (void)
{
 unsigned char n, m;
 for (n=0; n<24; ++n)
    {
     if (n == 0)
      {
       putchar('T');
      }
     sprintf
(printbuf,"%4d%2d.%2d.%2d%4d%3d\r\n",2006,(int)12,(int)16,(int)n,1024,23 
);
     for (m=0; m<26; ++m)
        {
          putchar(*(printbuf + m));
        }
     {unsigned int i; for (i=1000; i>0; --i);}
    }
 putchar('E');
}

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Du solltest Dir mal die Bedeutung des Formatstrings von printf() und
Konsorten näher ansehen.

Der von Dir gepostete Formatstring kann jedenfalls die von Dir
gepostete  Ausgabe nicht erzeugen:

  "%4d%2d"

  mit den Argumenten 2006 und 12 (lass den Typecast weg!)

  ergibt

  "200612"

Ohne dazwischengesetztes Leerzeichen und auch ohne Leerzeichen oder
sonstwas vor 2006.

Mir scheint, Code und Ausgabe"beispiel" passen nicht zusammen.

Hast Du eigentlich wirklich gelesen, was ich vor drei Tagen schrieb?

von Profi (Gast)


Lesenswert?

vielleicht sendest Du zu schnell und das Terminal bringt etwas
durcheinander:
     for (m=0; m<26; ++m)
        {
          putchar(*(printbuf + m));
        }
     {unsigned int i; for (i=1000; i>0; --i);}

teste mit Pause nach jedem Zeichen statt nur vor dem E:
     for (m=0; m<26; ++m)
        {
          putchar(*(printbuf + m));
          {unsigned int i; for (i=1000; i>0; --i);}
        }
und pass auf, ob der Compiler die Warteschleife nicht wegoptimiert.

oder Dein Compiler hält sich nicht an die Konventionen und hält vor
jeder integer-Zahl ein Zeichen für das Vorzeichen frei.
caste mal mit (unsigned int)
aber das kann ich mir gar nicht vorstellen.

Versuche mal rauszufinden, ob der Fehler in der sprintf-Zeile passiert
oder in der Ausgabeschleife.

von Max F. (Gast)


Lesenswert?

Tja, ich hab alles mögliche versucht. Ohne Erfolg.Ich in verschiedenen
stellen delays eingebaut.

unsigned char printbuf [96];

void tagesprofil (void)
{
 unsigned char n, m;
 for (n=0; n<24; ++n)
    {
     if (n == 0)
      {
       uart_transmit('T');
      }
     sprintf
(printbuf,"%4d%2d.%2d.%2d%4d%3d\r\n",2006,(int)12,(int)16,(int)n,1024,(i 
nt)23);
     for (m=0; m<25; ++m)
        {
          uart_transmit(*(printbuf + m));
        }
     delay_ms(20);
    }
 uart_transmit('E');
}

Also beim Empfangen sieht es mal schon besser aus.
Leider ist es aber noch immer so, dass zwischen den Punkten (Datum)
immer noch ein Leerzeichen vorhanden ist.
Ich hab soger mal nur ein paar Zeichen gesendet da sieht es auch nicht
besser aus.
ich finde das echt komisch!

von peter dannegger (Gast)


Lesenswert?

RC-Oszillator ?


Peter

von Max F. (Gast)


Lesenswert?

Hi peter,

du denkst dass es am Oszillator liegt. Warum dass denn?

von Hannes L. (hannes)


Lesenswert?

Ich denke, dass Peter dich gefragt hat, ob du mit dem internen
RC-Oszillator arbeitest. Eine Antwort wäre hilfreicher als eine
Gegenfrage.

...

von Max F. (Gast)


Lesenswert?

Ach so, entschuldige.
Ich verwende bei mir einen externen 8Mhz Resonator.

von Hannes L. (hannes)


Lesenswert?

Naja, ein Baudratenquarz wäre vermutlich besser gewesen.

Die Frage sollte wohl klären, ob die Möglichkeit besteht, dass Zeichen
verloren gehen weil die Baudrate nicht genau eingehalten wird.

...

von Max F. (Gast)


Lesenswert?

Ok das könnte vielleicht sein, aber diesen String
"2006 12. 16. 11 1024 23" empfange ich 24 mal korrekt.
Da sind wie gesagt nach den Punkten immer ein Leerzeichen. Die sollen
da nicht vorkommen.

sprintf
(printbuf,"%4d%2d.%2d.%2d%4d%3d\r\n",2006,12,)16,n,1024,23);

Genau so verwende ich den Code bei mir.

von Max F. (Gast)


Lesenswert?

sprintf
(printbuf,"%4d%2d.%2d.%2d%4d%3d\r\n",2006,12,16,n,1024,23);

hab mich vertippt. So müsste es stimmen.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Hast Du mal in einem Debugger den Inhalt von printbuf näher angesehen?

Hast Du mal ausprobiert,

sprintf(printbuf, "200612.16.%2d1024 23\r\n", n);

aufzurufen?

Oder einfach nur

sprintf(printbuf, "#%2d#\r\n", n);

aufzurufen?

Warum gibst Du den Wert 23 mit dem Formatspezifizierer %3d aus?

von Max F. (Gast)


Lesenswert?

Ok ich werds mal so testen.

von Karl H. (kbuchegg)


Lesenswert?

Das ist in der Tat seltsam.
Das sollte nicht so sein.

Sag. Welchen Compiler in welcher Version benutzt du?
Vielleicht klingelts da bei irgendjemandem.

Hmm.

sprintf
(printbuf,"%4d%2d.%2d.%2d%4d%3d\r\n",2006,(int)12,(int)16,(int)n,1024,(i 
nt)23);
     for (m=0; m<25; ++m)
        {
          uart_transmit(*(printbuf + m));
        }

Hmm. Beim sprintf sollte eigentlich gar kein String der
Laenge 25 entstehen. Wenn ich den Format-String durchgehe,
komme ich auf 21 Zeichen

PS:
Die int-casts im Aufruf kannst Du Dir sparen, die bewirken
gar nichts. Kannst Du Dir die Laenge des entstandenen Strings
in printbuf mal ausgeben lassen. Ziel ist es abzuklaeren ob
die zusaetzlichen Zeichen im sprintf entstehen oder ob die
irgendwie waehrend der Datenuebertragung hineingeschmuggelt
werden.

von Hannes L. (hannes)


Lesenswert?

> Da sind wie gesagt nach den Punkten immer ein Leerzeichen. Die
> sollen da nicht vorkommen.

Hmmm...
Sind die Leerzeichen nun nach den Punkten oder vor den Zahlen?

Denn in VB muss ich die Zahlen über TRIM(zahl) ausgeben, wenn ich die
Leerzeichen davor vermeiden will.

Von C habe ich aber keine Ahnung, AVRs programmiere ich in ASM.

...

von Max F. (Gast)


Lesenswert?

Jeweils ein Leerzeichen nach einem Punkt!

von Karl H. (kbuchegg)


Lesenswert?

@Hannes

Das passt schon so.
In C kann man die Ausgabe sehr genau und feinfuehlig
ueber den Format-String steuern. Er hat fuer jede
Ausgabe exakt angegeben, wieviele Stellen sie umfassen
soll. Eigentlich sollte sich der sprintf daran halten.

von Profi (Gast)


Lesenswert?

Nicht nach einem Punkt, sondern vor einer 2-stelligen Zahl (beachte:
vor dem 12 ist auch ein falsches Leerzeichen).

Versuche mal, statt %2d nur %d  und auch mal %2u  und %u zu verwenden.
Bitte teile uns auch die Ausgaben von  %02d und %02u  mit.

Ich vermute, er reserviert vor einer 2-stelligen Zahl ein Zeichen für
das (bei positiven Zahlen nicht vorhandene) Vorzeichen. Sind Zahlen
länger als angegeben, werden sie auch länger ausgegeben. Bei der Angabe
handelt es sich um eine Mindestbreite.

Welchen Compiler / Version verwendest Du?

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.