Forum: Mikrocontroller und Digitale Elektronik Int-Wert-Ausgabe auf Display ??


von Stephan (Gast)


Lesenswert?

Hallo, ich versuche grad das Ergebnis einer Funktion auf meinem
LCD-Display auszugeben. Wie wandle ich den Int-Wert am einfachsten so
um ,das z.B int x = 52; sendenLCD(x); dann auch 52 auf dem Display
steht und nicht 'r'?
Bei Java war das einfach. Einfach die Variable in die Ausgabe einfügen
und fertig. z.B. "Ergebnis: "+ x +" lautet."
Gibts das auch für C.
Ich verwende einen MSP430, IAR und 2x16 Display.

Danke für eure Tips. Ich komm grad auf keine Lösung.
Gruß Steph

von thkais (Gast)


Lesenswert?

Für den IAR kann ichs leider nicht sagen, aber beim AVR-GCC mach ichs
mit dem sprintf() - Befehl.

Beispiel:

sprintf (text,"+ %d +",x);

text muss als char-array definiert sein. Anschließend "text" mit
einer entsprechenden Subroutine Zeichen für Zeichen auf dem Display
ausgeben.

von Rahul (Gast)


Lesenswert?

itoa könnte auch gehen...

von Stephan (Gast)


Lesenswert?

@thkais
wenn ich das richtig versteh schreibt sprintf die Variable x in den
char-array text. Was bedeutet %d ?? Die Subroutine wäre dann meine
Funktion void sendString(char* Zeichenkette) an die ich nur noch text
übergeben muss. Das werd ich gleich mal testen.

@ Rahul
dein Tip hab ich grad im Kernighan/Ritchie nachgelesen. Ist mir noch
etwas unklar werds aber auch aus probieren. Bin halt noch Anfänger.

Klappt das dann auch mit Long und Double Werten. Die Int ist nur zum
testen. Wenns läuft brauch ich die größeren.

Danke Gruß Steph

von Rahul (Gast)


Lesenswert?

%d ist eine Zahlendarstellungsvariante. Siehe auch "printf".

>hab ich grad im Kernighan/Ritchie nachgelesen
sehr löblich!
Benutzt habe ich itoa auch noch nie, weil ich die Umwandlung des
Zahlenformats bis jetzt immer händisch/zu Fuß gemacht habe.

von Stephan (Gast)


Lesenswert?

@ Rahul

Wie geht das zu Fuß bzw wie machst du das?
Ich hab ja dann das Problem das ich den Wert '143' in 1, 4 und 3
zerlegen muss. 0b10001111. Hab mir erst gedacht durch Bitmaskierung den
Wert quasi in Hunderter, Zehner und Einer zu zerlegen. Hat nicht
geklappt, vielleicht hab ich aber nur einen Fehler gemacht.

von Rahul (Gast)


Lesenswert?

143 / 10 ist 14 da es sich um integer handelt.
143 % 10 ist 3 (der Rest der Division).

143 / 100 ist also?
143 % 100 ist also?

Übrigens findet sich auch im K&R ein Bespiel dazu (zumindest in meiner
Ausgabe).

von Stephan (Gast)


Lesenswert?

@ Rahul

ahh ich verstehe... das gute alte Modulo.

Danke.

Vermutlich steht es dann auch in meiner Ausgabe. Bestimmt hat es sich
nur versteckt, die Sau. ;-). Immer schwierig wenn die Überschriften
nicht so grooß sind wie auf dem Wischpapier mit der hohen Auflage und
dem großen 'B...' vorne drauf.

von Stephan (Gast)


Lesenswert?

klappt nicht, da ist noch der Wurm drin.

char* text;

void sendInt(int a)
{
  LCDcommand(CMD_CLEAR_DISPLAY);
  LCDcommand(CMD_CURSOR_HOME);
  sprintf (text,"+ %d +",a);      // hier passiert nichts !!
  sendString(text);
}

da wird nichts in Text geschrieben ??
Was ist falsch?
Danke

von Stephan (Gast)


Angehängte Dateien:

Lesenswert?

So, kann mir bitte noch mal jemand helfen? Ist jetzt wohl ein reines
C-Problem: wenn ich bei der Initialisierung den char-Arry mit 10
festlege schreibt mir itoa(..) korrekte Werte in s[]. Leider
funkioniert dann meine Funkion sendeString(char* Zeichenkette); nicht
mehr.
Initialisiere ich: char s[]; dann schreibt itoa() nichts in s[].

Liegt das daran das mit char s[10] keine richtige Zeichenkette mehr
vorliegt. Jedenfalls zeigt der Debuger es als Array an[1][2] und nicht
mehr als Zeichenkette {"..."}

Danke für Eure Hilfe. C-File angehängt.

char s[10];
void itoa(int n, char s[])  // n in Ziffernkette s umwandeln
{
    int i, sign;
    if((sign = n) < 0) // Vorzeichen notieren
    n =-n;
    i =0;
    do{
        s[i] = n % 10;
        i++;
    }while ((n /= 10 ) > 0);
    if(sign < 0)
        s[i++] = '-';
    s[i]= '\0';
    reverse(s);
}

void(main){
  itoa(12345,char* s)
  sendeString(char* zeichenkette)
}

von thkais (Gast)


Lesenswert?

Mit char* text wird nur ein Pointer auf einen Speicherbereich gesetzt.
Aber wohin?

char* text = {"              "};

sollte einen Leerstring initialisieren, sprich: Auch den benötigten
Speicher reservieren. Evtl. liegts schon daran.

von Stefan (Gast)


Lesenswert?

Woher soll dein Programm wissen, dass s und zeichenkette auf den
gleichen Speicherbereich zeigen?

Die Implementation von s z.B. mit char s[10]; ist OK. Es wird ein
Speicherbereich von 10 Zeichen angelegt. Anders geht es auch s. unten
1
void main()
2
{
3
  char s[] = "hier soll genug Platz für eine zahl reserviert
4
werden";
5
  char * zeichenkette;
6
7
  itoa(12345, s);
8
  zeichenkette = s;
9
  sendeString(zeichenkette);
10
}
11
[C]
12
13
Der Name *itoa* für die eigene Funktion ist unglücklich gewählt. Es
14
gibt eine Bibliotheksfunktion, die leicht damit verwechselt werden
15
kann, weil sie genauso heisst. 
16
17
http://www.mkssoftware.com/docs/man3/itoa.3.asp
18
19
Der Unterschied ist: Es kann ein beliebiger Radix angegeben werden (bei
20
dir ist 10 fest eingestellt) und es wird s zurückgegeben (bei dir keine
21
Rückgabe)
22
23
Mit der Bibliotheksfunktion könnte man schreiben:
24
25
[C]
26
void main()
27
{
28
  char s[] = "hier soll genug Platz für eine zahl reserviert
29
werden";
30
  sendeString(  itoa(12345, s, 10);
31
}

von Stefan (Gast)


Lesenswert?

Woher soll dein Programm wissen, dass s und zeichenkette auf den
gleichen Speicherbereich zeigen?

Die Implementation von s z.B. mit char s[10]; ist OK. Es wird ein
Speicherbereich von 10 Zeichen angelegt. Anders geht es auch s.
unten
1
void main()
2
{  
3
  char s[] = "hier soll genug Platz für eine zahl reserviert werden";
4
   
5
  char * zeichenkette;   
6
7
  itoa(12345, s);  
8
  zeichenkette = s;  
9
  sendeString(zeichenkette);
10
}

Der Name itoa für die eigene Funktion ist unglücklich gewählt. Es
gibt eine Bibliotheksfunktion, die leicht damit verwechselt werden
kann, weil sie genauso heisst.

http://www.mkssoftware.com/docs/man3/itoa.3.asp

Der Unterschied ist: Es kann ein beliebiger Radix angegeben werden (bei
dir ist 10 fest eingestellt) und es wird s zurückgegeben (bei dir keine
Rückgabe)

Mit der Bibliotheksfunktion könnte man schreiben:
1
void main()
2
{  
3
  char s[] = "hier soll genug Platz für eine zahl reserviert werden";
4
  
5
  sendeString(itoa(12345, s, 10);
6
}

von Stefan (Gast)


Lesenswert?

... , 10); => , 10));

von Karl heinz B. (kbucheg)


Lesenswert?

@thakis

Aeh nein.
Dein Pointer zeigt zwar auf einen char-String, aber diese
character sind const!
Das das überhaupt vom Compiler akzeptiert wird, hat historische
Gründe, die zähneknirschend akzeptiert werden (mussten).

Eigentlich sollte das heissen:

const char* test = "          ";

und alles andere (also: ohne const) einen Fehler ergeben.

@Stephan
Sag mal: Warum schreibst du eigentlich Funktionen wie strlen()
und itoa() selbst? Die hast du bereits in Deiner Libarary drinnen.
Alles was du tun musst, ist sie zu verwenden:
Fuer alle str... Funktionen (streln, strcat, strcpy) inkludierst
du
#include <string.h>
und itoa() findet sich meist in stdlib.h
#include <stdlib.h>
(itoa ist keine Standard-C Funktion. d.h. der Compiler muss sie
nicht anbieten. Viele tun es aber. Die Funktion heisst dann
auch oft _itoa(), mit einem führenden '_' am anzuzeigen, dass es
sich hier um eine Nicht-Standardfunktion handelt.

von Stephan (Gast)


Lesenswert?

Ich bin davon ausgegangen das iota(int x, s[]){...} das s quasi als
Rückgabewert liefert und wenn ich dann meine Funkion
   sendeString(s);
ausführe s als Übergabewert angenommen wird, auch wenn die Funktion
eigentlich
   void sendeString(char* zeichenkette){...} lautet

Mein iota(,) ist aus Kernighan/Ritchie abgeschrieben weil ich nichts
anderes gefunden hab.
Werd mal versuchen zu verstehen was du mir geschrieben hast. Danke

Gruß Steph

von Karl heinz B. (kbucheg)


Lesenswert?

> char* text;
> ...
> void sendInt(int a)
> {
>   LCDcommand(CMD_CLEAR_DISPLAY);
>   LCDcommand(CMD_CURSOR_HOME);
>   sprintf (text,"+ %d +",a);
>   sendString(text);
> }

das kann nichts werden.
Wie thakis richtig sagt: Wohin zeigt text?

Das Problem ist:
'text' ist ein Pointer. Als solcher ist 'text' daher eine
Variable, die eine Speicheradresse aufnehmen kann. In diesem
konkreten Fall liegt dort die Adresse im Speicher an
der beginnend eine Reihe von Character abgelegt werden kann.
Aber: Nur weil du einen Pointer hast, heist das noch lange nicht,
dass du auch den entsprechenden Speicher für die Character hast.
Den Speicher musst du schon selbst anlegen, der Compiler hat nur
den Speicher zur Speicherung der Adresse angelegt.

char* text;

ist also ein Pointer, der (wie alle globalen Variablen) mit 0
vorinitialisiert wird, d.h. der Pointer zeigt auf die Speicher
Adresse 0. Wenn nun
sprintf( text, ... );
den String dort ablegt, tja, dann überschreibt er sich damit
eine Menge andere Variablen, da ja nirgendwo definiert wurde, dass
ab Speicheradresse 0 beginnend ein paar character abgelegt werden.

Machst du aber

  char text[20];

dann könnten theoretisch die 20 character auch bei Adresse 0
abgelegt werden, allerdings: jetzt weiss der Compiler, dass die
ersten 20 Speicherzellen zur Speicherung von charactern reserviert
sind und legt keine anderen Variablen dorthin.

Auch wichtig: Auch wenn sich Pointer und Arrays bei ihrer Verwendung
in der Syntax ähneln bzw. über weite Strecken identisch verwendet
werden, so sind sie doch verschiedene Dinge. Ein Pointer ist
kein Array und ein Array ist kein Pointer. Um einen String zu
speichern brauchst du ein charcater-Array, dass gross genug ist
um alle Zeichen plus das abschliessende '\0'-Zeichen speichern
zu können. Alles andere geht zwar oft syntaktisch durch den
Compiler durch, ist aber trotzdem falsch. Letztendlich musst du dich
immer fragen: Wo existiert den nun der Speicher, in den ich grade
schreibe? Und wenn du nur einen Pointer hast, lautet die nächste
logische Frage: WOhin zeigt denn der Pointer?

von Stephan (Gast)


Lesenswert?

o.k die Pointer-Problematik, irgendwann holt sie mich ein. Ich habs
geahnt.

@ Karl-Heinz
die obere Methode sendInt() verwende ich nicht mehr, weil mein Compiler
sprintf() nicht leiden kann? Daher hab ich's dann mit itoa() versucht.
Der IAR hat in der stdlib.h das itoa() nicht stehen nur atoi. Aber vom
Prinzip würde meine sendInt() wegen dem Pointer auch nicht laufen.
Also mal sehen wie ich das zum laufen bekomm mit itoa() und co.

Gruß Steph

von Karl heinz B. (kbucheg)


Lesenswert?

Probier mal _itoa()

Falls alle Stricke reissen: Probier mal in der Hilfe
zum Compiler, ob er so eine Funktion hat.

> die obere Methode sendInt() verwende ich nicht mehr, weil mein
> Compiler sprintf() nicht leiden kann?

Was soll das heissen?
Ein Compiler kann nicht irgendetwas leiden oder nicht leiden.
Du kannst aber durch Unwissenheit einen oder mehrere schwerwiegende
Fehler in ein Program einbauen, sodass das Pgm im schlimmsten
Fall die komplette Laufzeitumgebung zerschiesst und nichts
mehr funktioniert. Wenn du das als: mein Compiler mag mich nicht
ansiehst, ....

Wenn du schon einen K&R hast, dann solltest du den auch
durcharbeiten. Nach Möglichkeit nicht auf einem AVR, sondern
auf einem Desktop-System. Ein µC öffnet dem gegenüber nur
einen zusätzlichen Sack an Fehlermöglichkeiten.

von Stephan (Gast)


Lesenswert?

int i = 25;
int* p = &i; // p zeigt auf i
*p = 10; // jetzt ist i = 10 !!

wie funktioniert das bei char arrays??

meine Werte stehen jetzt in char s[10].

Wie baue ich einen Zeiger der darauf zeigt und den ich an die Funktion
übergeben kann. Oder ist es besser die Funkton umzuschreiben und ihr
statt char* ein char s[] zu übergeben? oder geht das auch nicht?
Es tut mir leid, aber ich komm nicht drauf.
Bin zu doof- sollte wohl besser Metzger werden(die armen Tiere).

@stefan : so gehts nicht.
char * zeichenkette;
itoa(12345, s);
zeichenkette = s;
sendeString(zeichenkette);

@karl heinz: kein itoa beim IAR-Compiler

// allso Inhalt von char s[] muss da rein verdammt...
void sendString(char* Zeichenkette)
{
  int i;
  char zeile=0;
  char spalte=0;
  LCDcommand(CMD_CLEAR_DISPLAY);
  LCDcommand(CMD_CURSOR_HOME);
  for (i=0;Zeichenkette[i]!='\0';i++)
  {
    sendChar(Zeichenkette[i]);
    spalte++;
    wait(70000);
    if((Zeichenkette[i]==' ')&&(spalte>12)&&(zeile==0)){
      LCDcommand(CMD_2nd_LINE_2x16);
      zeile++;
    }
        }

von Karl heinz B. (kbucheg)


Lesenswert?

> Wie baue ich einen Zeiger der darauf zeigt und den ich an die
> Funktion übergeben kann.

Du brauchst keinen expliziten Zeiger.
Benutze einfach das Array:


char text[20];

...

  sprintf( text, "%d", i );


Arraysa werden in C immer so an Funktionen übergeben, indem
ein Zeiger auf das erste Array Element übergeben wird.
Das einzige worauf du achten musst ist, dass der String den
sprintf erzeugt nicht länger wird als (in diesem Fall) 20
Zeichen. Ist das der Fall, kann gar nichts mehr schief gehen.
OK. sprintf ist ein Resourcenfresser. Dafür bietet er aber
auch einiges. Mit den FOrmatierungen kann man so manch tolle
Dinge ganz einfach machen:
zb.

  %4d      der Integer wird in ein Feld der Größe 4 rechtsbündig
           eingepasst. Gut für Tabellen

  %04d     selbiges wie oben. Nur werden jetzt noch führende
           Nullen eingebaut. Eine Zahl 25 in i wird als 0025
           ausgegeben.

  ...      Noch viel mehr.

von Stephan (Gast)


Lesenswert?

Danke für die Hilfe, aber hab ich jetzt nicht mein Ziel verlohren?
Du sagst:

char text[20];
...
  sprintf( text, "%d", i );

Mein anfänglicher Wunsch war es ein Ergebnis einer Berechnung
vorliegend als Int,Long oder Double umzuwandeln in eine char*
Zeichenkette die ich an mein LCD-Display schicken kann(Funktion
vorhanden).
printf und sprintf schicken ihre Rückgabewerte an die Standartausgabe.
Das ist aber der Bildschirm bzw. die Konsole. Ich müsste also putchar()
welches von printf() verwendet wird, umleiten auf mein kleines 2 Zeilen
LCD-Modul. Stimmt das? Das klappt bei meinem Kenntnisstand nicht in
vertretbarer Zeit. Ich hab dafür auch schon mal ein Beispiel gesehen.
Leider hat es nicht funktioniert.
Deshalb fand ich itoa eigentlich ganz passend.
Gruß Steph

von Karl heinz B. (kbucheg)


Lesenswert?

Oh Mann.

> als Int,Long oder Double umzuwandeln in eine char*
> Zeichenkette

Was bitte ist eine char* Zeichenkette :-)

Sowas gibt es nicht in C. Du solltest schleunigst im
K&R noch mal über Stringbehandlung nachlesen. Und wenn
du schon dabei bist, informier dich auch noch über den
Array-Pointer Zusammenhang. Es ist genau dieses Nichtwissen,
das dich jetzt straucheln laesst.

In C werden Zeichenketten immer in einem char-Array
gespeichert. Punkt.

Wenn du also schreibst:

  char Test[20] = "Hallo";

dann wird ein Array der Laenge 20 aufgesetzt, dass mit
den Buchstaben 'H', 'a', 'l', 'l', 'o', '\0' gefüllt
wird.

Test
+---+---+---+---+---+---+- ...-+---+---+
| H | a | l | l | o | \0|      |   |   |
+---+---+---+---+---+---+- ... +---+---+

Soweit so gut.
Was passiert bei:

char* Test = "Hallo";

Auch hier wird ein Array aufgesetzt. Nur hat dieses Array keinen
Namen. Zusätzlich wird noch eine Pointer Variable erzeugt, und
das ganze so eingerichtet, dass dieser Pointer auf das Array
zeigt.

Test
+-----+
|  o--------------------+
+-----+                 |
                        |
                        v
                        +---+---+---+---+---+---+
                        | H | a | l | l | o | \0|
                        +---+---+---+---+---+---+

Beachte auch: Das Array hat genau die Größe die notwendig
ist, um den String "Hallo" aufzunehmen. Weiters darf der
Compiler dieses Array im ROM ablegen. D.h. das Array ist
für dich als Progammierer unveränderlich. Du kannst dort
zwar lesen, kannst aber nicht schreiben.

Wenn du einen String beschreiben willst, und sprintf will genau
das tun, dann muss das Array zwangsweise irgendwo im RAM-Speicher
liegen. d.h. mittels

char* Test = "Hallo";

kannst du das nicht erreichen.

Also musst du für das Ergebnis selbst ein Array definieren:

char Test[20];

Weiters: Wenn ein Array an eine Funktion übergeben wird, so
erfolgt dies in C immer in der Form, dass ein Pointer auf
das erste Array-Element übergeben wird.
Deine Funktion SendString (oder wie die heist) möchte einen
Pointer auf den auszugebenden String haben. Dann übergib
doch das Array! Arrays werden immer per 'Pointer auf das
erste Element' übergeben und genau das will doch deine Funktion:
Einen Pointer auf den Beginn des Strings (auf das erste Element).

> printf und sprintf schicken ihre Rückgabewerte an die
> Standartausgabe.

Unsinn
Die Rückgabewerte der Funktionen printf und sprintf sind Zahlen.
Diese Zahlen geben an, wieviele Konvertierungen durchgeführt
werden konnten.
printf gibt den durch die Konvertierungen und Ersetzungen
entstandenen String nach stdout aus. sprintf schreibt den
entstandenen String in den bei sprintf() angegebenen Buffer.
Die Verantwortung dafür, dass der Buffer bei sprintf() gross
genug ist, trägt der Programmierer.

char Text[20];

  sprintf( Text, "%d", i );
  SendString( Text );

und fertig. Wenn sendString richtig funktioniert, und davon
gehe ich mal aus; wenn der Typ im Formatstring (%d) zum Datentyp
des Arguments (i) passt; wenn der sprintf()-Buffer (in diesem
Fall 'Text') gross genug ist (nun ja: eine einzelne Zahl in einer
16 Bit Variable kann unmöglich 19 dezimale Ziffern haben), dann
kann da gar nichts schief gehen.

K&R studieren! Das ist alles C-Basiswissen.

von Stephan (Gast)


Lesenswert?

oh Mann, danke, vielen Dank.
Kannst die Mail gleich ins WIKI setzen.
Werde mich gleich heut Abend damit beschäftigen.
Falls es nicht klappt werd ich mich jetzt auch nicht mehr melden.
Irgendwann ist halt dann genug.
Danke, Gruß Steph

von Wolfgang (Gast)


Angehängte Dateien:

Lesenswert?

Von der Programmiertechnik, die Karl Heinz offensichtlich beherrscht,
bin ich natürlich weit entfernt. Falls es aber trotzdem noch
interessiert:
 Im Anhang einige  Ausschnitte aus einem bei mir funktionierenden
Programm für die Ausgabe eines Zahlenwertes mit einem MSP430  auf einer
Flüssigkristallanzeige unter Verwendung des IAR Compilers. (keine neuen
Lösungsansätze)
Vielleicht hilft es zur Lösung des Problems.
MfG
Wolfgang

von Karl heinz B. (kbucheg)


Lesenswert?

@Wolfgang

Danke für die Blumen. Aber das bis jetzt geschilderte
ist eigentlich noch sehr einfaches C-Basiswissen.

Zu Dienem Code: Ich hoffe du nimmst es mir
nicht übel wenn ich da was zu meckern habe.

Ein schwerwiegender Punkt ist folgendes:

> void Puls1(void)
> {
>   int z,b,c;
>   char txt[5];

Beachte: txt hat Platz für exakt 5 Zeichen!

>  WriteData(33);                      33 legt fest, wo erstes
>                                      Zeichen auf  FKL erscheint
>  WriteData(0);
>  WriteCtrl(0x24);    0x24 = Kommando
>  sprintf(txt,"%5d",Puls_A );  Puls_A ist der anzuzeigende
Puls-Wert

Hier: der sprintf erzeugt aber 6 Zeichen!
Wie kommts?
%5d  ist die Anforderung den int in ein Ausgabefeld bestehend
aus 5 Zeichen einzupassen. Der int wird dazu rechtsbündig
eingepasst und führende Stellen werden mit einem ' ' gemacht.
Die Zahl 123  wird also so "  123" in das Ausgebfeld eingepasst.
So weit so gut.
Aber: sprintf erzeugt auch einen String! Und so wie jeder andere
String in C, ist auch dieser mit einem '\0' Zeichen abgeschlossen.
Wird dieser String in txt aufgebaut, so werden tatsächlich 6 Zeichen
geschrieben, nicht 5!:

  txt[0]  <-   ' '
  txt[1]  <-   ' '
  txt[2]  <-   '1'
  txt[3]  <-   '2'
  txt[4]  <-   '3'
  txt[5]  <-   '\0'

Das würde aber ein Array der Größe 6 erfordern, txt ist aber
nur ein Array der Größe 5! d.h. das letzte Zeichen überschreibt
im Speicher irgendetwas anderes (eine andere Variable oder
wenns gar böse kommt, eine Returnadresse, oder ...). Wie die
Auswirkungen konkret sind, hängt immer vom Einzelfall (und
vom verwendeten Compiler) ab, das kann niemand voerhersagen.
Es kann auch sein, dass man den Fehler gar nicht bemerkt,
es kann aber auch sein, dass die Maschine abschmiert. Wie
auch immer: Fehler ist Fehler. Auch wenn man den Fehler zunächst
nicht bemerkt, ist er trotzdem vorhanden.
Und Fehler dieser Art sind sehr schwer zu finden.
Daher hab ich mir zur Regel gemacht: bei sprintf() und
Konsorten nicht kleckern und kleinlich sein. Das Array lieber
großzügig dimensionieren als in das Risiko hineinzulaufen,
dass ich das Array überlaufe (Im Englischen heist dieser
Fehler, ein 'Out of Bounds Access' - 'Ausserhalb der Grenzen
Zugriff'). Wenn ich keine Obergrenze habe, dann muss schlimmsten-
falls eine andere Technik benutzt werden. Oder eine andere
Programmiersprache. In C++ zb. ist es extrem einfach diesen Fehler
nicht zu machen :-)

von Wegstabenverbuchsler (Gast)


Lesenswert?

@Wolfgang

neben C-Kenntnissen solltest du dir auch noch weitere Kenntnisse
anlernen:

Ein *.txt Dokument (deines Codes) belegt garde mal 1836 Bytes.

Man (du) kannst das auch als Word-Dokument abspeichern und als Anhang
einstellen, das belegt dann locker mal 20 Kbytes.

Alternativ kannst du das auch noch auf Postscript oder pdf Format
aufblasen, da sind locker über 30 Kbytes drin ....

von Wolfgang (Gast)


Lesenswert?

Das stimmt, da habe ich echt gepennt. Zumeist komprimiere ich größere
Dateien mit Winzip. Werde mich in Zukunft bessern.
@ Karl Heinz,
>Ich hoffe du nimmst es mir nicht übel wenn ich da was zu meckern
habe.<
niemals, im Gegenteil. Ich freue mich, wenn ich Tipps erhalte, wie ich
es besser machen könnte.
Aber das ist mal eine Stelle in meinem Programm, die ich bewusst so
gestaltet habe. Da der Puls eines Menschen niemals über 3 Stellen
ansteigen wird, habe ich hier so wenig Zeichen gewählt.
MfG
Wolfgang

von Karl H. (kbuchegg)


Lesenswert?

> die ich bewusst so gestaltet habe.

Bei allem Respekt. Aber das ist dem sprintg() völlig egal.
Du forderst ihn auf 6 Zeichen in einen 5 character-breiten
Buffer zu schreiben. Und das ist nun mal ein Fehler.

   char txt[5];

   sprintf(txt,"%5d",Puls_A );  Puls_A ist der anzuzeigende
                ***

Egal was deine Absichten waren: 6 Zeichen passen nun mal
nicht in ein Array der Länge 5.

von Wolfgang (Gast)


Lesenswert?

Habe ich es jetzt richtig verstanden?

  char txt[5];
  sprintf(txt,"%4d",Puls_A );


Obwohl wir hier nicht in einem C-Programmierkurs sind, aber Karl Heinz
aus meiner Sicht immer fundierte und  ausführliche  Antworten gibt, mal
eine Frage zu einer wahrscheinlich einfachen Sache: return  soll ja bei
einer Funktion den in der Klammer stehenden Wert zurückgeben.
aus einem Demoprogramm von TI zur Kopplung einer MMC/SD -Speicherkarte
an einen MSP430:

unsigned char spiSendByte(const unsigned char data)
{
  while ((IFG1&UTXIFG0) ==0);   // wait while not ready / for RX
  TXBUF0 = data;                            // write
  while ((IFG1 & URXIFG0)==0);  // wait for RX buffer (full)
  return (RXBUF0);
}

meine Fragen: - wie komme ich zu dem im Empfangsregister RXBUF
                stehenden Wert?
              -  wann wird RXBUF geleert?
Vielleicht kann Karl Heinz eine Antwort an meine oben stehende
e-mail Adresse senden.
MfG
Wolfgang

von Rahul (Gast)


Lesenswert?

x = spiSendByte(d);

und schon steht RXBUF in x.

IMHO wird erst RXBUF gelesen (und damit vermutlich auch gelöscht) und
dann auf den Stack geschrieben, wo ihn die aufrufende Funktion abholen
kann.

von Karl heinz B. (kbucheg)


Lesenswert?

> Habe ich es jetzt richtig verstanden?
>
>   char txt[5];
>   sprintf(txt,"%4d",Puls_A );

Jetzt hast du's. Der Grund warum ich darauf so rumreite
ist der, dass
* solche Fehler häufig passieren
* solche Fehler gern übersehen werden
* die Auswirkungen des Fehlers nicht abschätzbar sind
  (dein Programm verhält sich dann morgen u.U anders als
   heute. Stichwort unter Programmierern: 'Das lief aber
   schon mal.'
* solche Fehler immer im ungünstigsten Moment zuschlagen
* solche banale Fehler enorme Kosten in der Behebung verursachen,
  da sie in einem größeren Projekt praktisch nicht zu finden sind.
  Um sowas zu finden, braucht man normalerweise auch immer etwas
  Glück.

> return  soll ja bei einer Funktion den in der Klammer stehenden
> Wert zurückgeben.

Letzteres ist ein Irrtum: Der zurückzugebende Wert muss keineswegs
in Klammern stehen. 'return' ist ja kein Funktionsaufruf sondern
ein ganz normales C-Schlüsselwort.

> wie komme ich zu dem im Empfangsregister RXBUF
> stehenden Wert?

Wenn du RXBUF0 lesend benutzt, wird das entsprechende
Hardware-Register ausgelesen und der darin enthaltene
Wert geliefert. Er ist dann Returnwert der Funktion.
Den Wert kriegt dann der Aufrufer der Funktion zur Verfügung
gestellt. Zb. so

  unsigned char Received;

  ...

  Received = spiSendByte( 'a' );

'a' ist das zu sendende Zeichen. spiSendByte sendet dieses,
wartet danach auf Antwort (die 2.te while-Schleife), holt
die Antwort aus RXBUF0 ab und returniert diese an den Aufrufer.
Der Aufrufer seinerseits speichert, das was spiSendByte liefert
(nämlich den Inhalt von RXBUF0) in einer Variablen 'Received' ab.

> wann wird RXBUF geleert?
Ich würde mal sagen, gar nicht. Aber wenn wieder was neues
über die Schnittstelle reinkommt, dann wird RXBUF0 überschrieben.

> oben stehende e-mail Adresse senden.
Normalerweise heist es in Newsgroups immer:
 You post here, you read here

Ausserdem mache ich auch Fehler. Und da ist es schon gut wenn
Andere auch noch korrekturlesen.

von Wolfgang (Gast)


Lesenswert?

<warum ich darauf so rumreite>
das hast du richtig gemacht, denn aus meinen Argumenten war für dich
erkennbar, dass ich noch gar nicht verstanden hatte, worum es wirklich
geht.
Was du zu return  geschrieben hast, werde ich mir nun genauer ansehen.
Danke
Auf e-mail kam ich, weil mein Frage eigentlich nicht unmittelbar zum
Thema gehört.
MfG
Wolfgang

von Karl heinz B. (kbucheg)


Lesenswert?

> Was du zu return  geschrieben hast, werde ich mir nun genauer
> ansehen.

Ist im Grunde ganz simpel.
Die C-Syntax verlangt nicht, dass der Ausdruck nach dem
return, sofern einer vorhanden ist, in Klammern geschrieben
wird. Das ist einfach nur ein Ausdruck, der einen Wert
liefern muss. Mehr nicht.

Das ist genauso, wie du bei einer Zuweisung auch nicht den
rechts vom '=' stehenden Teil in Klammern schreiben musst.
Das ist genaus einfach nur ein Ausdruck, der einen Wert
liefert.

Du schreibst ja auch nicht
   i = ( 5 );

sondern
   i = 5;

Obwohl: wenn du unbedingt willst, kannst du natuerlich
die Klammern schreiben.

Genauso hier

   return 5;

Wenn du unbedingt willst, kannst du natuerlich schreiben

   return ( 5 );

Ist aber genauso nicht notwendig, wie im Beispiel mit der
Zuweisung. In beiden Fällen wird nur verlangt, dass da ein
Ausdruck steht, der zu einem Wert führt. Syntaktisch gesehen
ist es in beiden Fällen sogar das selbe Sprachelement, das hier
verlangt wird. D.h. du kannst bei einem return alles machen,
was du auch auf der rechten Seite einer Zuweisung machen kannst
und natürlich umgekehrt.

von Stephan (Gast)


Lesenswert?

Hallo, hab jetzt noch mal ne Frage zur Formatierung der Ausgabe nachdem
meine Ausgabe jetzt funktioniert.

void sendDouble(double a){
    int z,b;
    char txtDouble[33];
  sprintf (txtDouble,"%.02E",a);
  for (z=0; z<9;z++){
           b=txtDouble[z];
           sendChar(b);
        }
}
sendDouble(0.000044); erzeugt eine Ausgbabe: 4.40E-05[]
Das [] ist ein schwarzes Kästchen. O.k. das Kästchen bekomm ich weg mit
z<8 oder ich sende eine neg.Zahl. Wie kann ich das dynamisch anpassen?
Der Wert kann ja auch mal kleiner oder größer sein, oder muss ich mich
auf eine bestimmte Zahl an Nachkommastellen festlegen mit +/-
Vorzeichen.
Zu dem würde es mir besser gefallen die Ausgabe würde so aus sehen:
440E-03.
Das hab ich leider nicht heraus gefunden wie das geht.
Gruß Steph

von Karl heinz B. (kbucheg)


Lesenswert?

Alle C Funktionen, die mit Strings arbeiten, befolgen
eine Konvention: jeder String wird mit einem 0-Byte
(in C-speak: ein '\0'-character) abgeschlossen.

D.h. anstatt einer fixen Laufweite, gibst du einfach
Zeichen aus, bis du auf den abschliessenden '\0' stoest:


  z = 0;
  while( txtDouble[z] != '\0' )
    sendChar( txtDouble[z++] );

oder etwas kürzer:

  z = 0;
  while( txtDouble[z] )
    sendChar( txtDouble[z++] );


irgendwann bist du dann die Array-Syntax leid und wandelst
das ganze in Pointer-Syntax um:

void sendDouble( double a )
{
  char txtDouble[33];
  char* tmp = txtDouble;

  sprintf( txtDouble, "%.02E", a );

  while( *tmp )
    sendChar( *tmp++ );
}

von Karl heinz B. (kbucheg)


Lesenswert?

> Zu dem würde es mir besser gefallen die Ausgabe würde so aus sehen:
> 440E-03.

Ich denke nicht, dass das mit printf nur durch die Formatierung
möglich ist. Da müsste man selbst Hand anlegen.

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.