Hallo,
ich bitte um Hilfe, ich möchte ein 2Byte Datenpaket in Hex von einem
externen Temperatursensor auf Rx Empfangen und als Dezimal
Temperaturwert auf dem myAVR LCD Add-On anzeigen, komme aber auf kein
grünen Zweig. Kann mir vielleicht jemand ein Beispiel zeigen oder mir
sonst wie weiter helfen?
Grüße Lino
Wie Falk schon mit dem Link zeigt, solltest Du dich erstmal mit den
Grundlagen beschäftigen, denn Dein Vorhaben gehört zu den elementarsten
Dingen im Umgang mit Mikrocontrollern....
Wenn Du Hilfe erwartest, dann zeig mal Deine bisherigen Versuche und
Ergebnisse, bzw. sag wo es genau hängt...
Einen Hexwert in ASCII zu wandeln und auf das Display zu schicken sollte
man mit ein wenig Nachdenken auch als Anfänger(?) hinbekommen ;-)
hallo...
das hier: http://www.avr-cpp.de/doku.php?id=ein_kleines_projekt
macht etwas in die richtung die du suchst... durch die Basics musst du
dich natürlich erstmal durcharbeiten dass läßt sich kaum abkürzen :-/
Gruß J.
Funktioniert gut, nur warum kriege ich immer 'Warning: makes Pointer
from integer without a cast' in der itoa Zeile? Wäre nett, wenn mir das
mal jemand erklärt.
Matthias Sch. schrieb:> Funktioniert gut, nur warum kriege ich immer 'Warning: makes Pointer> from integer without a cast' in der itoa Zeile? Wäre nett, wenn mir das> mal jemand erklärt.
weil itoa nun mal keinen char zurückliefert.
Wenn du mit einem Returnwert nichts machst, so wie hier bei dir, dann
musst du ihn auch nicht auffangen.
Die Ausgabeschleife ist zwar in einem gewissen Sinne naheliegend aber
unnötig kompliziert. strlen macht ja auch nichts anderes, als nach dem
'\0' Zeichen im String zu suchen und mitzuzählen wieviele Zeichen es bis
zum '\0' vorgefunden hat. Genau dasselbe kannst du aber auch machen, nur
mit dem einen Unterschied, dass du die Zeichen nicht zählst, sondern
einzeln ausgibst.
1
staticvoidprintnum(int16_tnumber)
2
{
3
charnumAsString[16]="0000000000000000";
4
char*strPtr=numAsString;
5
6
itoa(number,numAsString,10);
7
while(*strPtr!='\0')
8
lcd_putc(*strPtr++);
9
}
oder wenn dir Array-Schreibweise erst mal lieber ist als Pointer
1
staticvoidprintnum(int16_tnumber)
2
{
3
charnumAsString[16]="0000000000000000";
4
inti=0;
5
6
itoa(number,numAsString,10);
7
while(numAsString[i]!='\0')
8
lcd_putc(numAsString[i++]);
9
}
Es gibt keinen Grund warum man den String 2-mal durchgehen muss: Einmal
um seine Länge festzustellen und das andere mal um dann genau diese
Zeichen auszugeben. Einmal durchgehen reicht völlig.
Noch besser ist es allerdings, die Aufgaben zu trennen. Denn in dieser
Funktion stecken eigentlich 2 Funktionalitäten. Die eine soll eine Zahl
ausgeben und das macht sie indem sie für die Zahl eine String
Repräsentierung erzeugt und dann den String ausgibt. Aber einen String
ausgeben ist eine nützliche Funktionalität für sich selber. Daher wird
das vernünftig sein, die Dinge zu trennen
1
staticvoidprintString(constchar*str)
2
{
3
while(*str)
4
lcd_putc(*str++);
5
}
6
7
staticvoidprintnum(int16_tnumber)
8
{
9
charnumAsString[16]="0000000000000000";
10
11
itoa(number,numAsString,10);
12
printString(numAsString);
13
}
Jetzt kenn ich aber zufällig die Fleury Lib und weiß, dass die eine
Funktion hat, um einen String auszugeben. D.h. die Funktion printString
ist für die Katze, denn die Funktion gibt es bereits. Sie heißt
lcd_puts.
Also magert dein Code ab zu
Karl Heinz Buchegger schrieb:> weil itoa nun mal keinen char zurückliefert
Ach, ich Dummerchen zack, ich hab den Fehler immer in den Argumenten
gesucht.
Hier nochmal die korrigierte Version:
1
#include<stdlib.h>
2
#include<string.h>
3
// output a number in decimal style
4
staticvoidprintnum(int16_tnumber){
5
chardectable[16]="0000000000000000";
6
char*a;
7
uint8_tn,i;
8
a=itoa(number,dectable,10);
9
i=strlen(dectable);
10
for(n=0;n<i;n++){
11
lcd_putc(dectable[n]);// Peter Fleurys Library
12
}
13
}
Karl Heinz, ich danke dir!
Karl Heinz Buchegger schrieb:> Jetzt kenn ich aber zufällig die Fleury Lib und weiß, dass die eine> Funktion hat, um einen String auszugeben.
Da hat aber nochmal jemand editiert. Das mit der Stringausgabe ist mir
bekannt, aber die Routine ist deswegen so gehalten, damit ich auch
schnell mal eine UART oder ein anderes Characterdevice anquäken kann.
Das Aufteilen in 2 Routinen schau ich mir mal in Ruhe an.
> Und da kann man doch jetzt nicht mehr meckern.
Doch, kann man schon. Denn die anderen Funktionen, die etwas mit dem LCD
machen oder ausgeben, heißen alle lcd_irgendwas. Nur deine heißt
'printnum'. Abgesehen davon, dass diese Benamung schon mal deswegen
schlecht ist, weil printnum ja eigentlich 2 Wörter sind, die ich aber
auf Anhieb nicht erkennen kann (sieh dir einfach mal an um wieviel
leichter printString zu lesen ist, die Grossschreibung vom S macht einen
gewissen Unterschied in der Lesbarkeit), ist es auch so, dass aus
printnum nicht hervorgeht, wo denn eigentlich die Ausgabe erfolgt. Bei
lcd_puts weiß ich das sofort. Das lcd_ verrät es mir. Bei printnum weiß
ich erst mal gar nichts. Das könnte genausogut die UART sein, oder eine
Ausgabe per SPI oder sonst irgendwie.
Wenn du ein Benamungsschema schon vorgegeben hast, dann bist du gut
beraten, wenn du dich daran hältst. Auch wenn es nicht von dir stammt.
Wenn alle LCD Funktion einen Präfic lcd_ haben, dann kannst du ruhig
diese 'Tradition' fortführen. Der Lesbarkeit, Verstehbarkeit und
Konsistenz deines Code kann sowas nur zu Gute kommen
1
staticvoidlcd_int16(int16_tnumber)
2
{
3
charnumAsString[16]="0000000000000000";
4
5
itoa(number,numAsString,10);
6
lcd_puts(numAsString);
7
}
oder wenn du in der Tradition vom Fleury bleiben willst, bei dem
lcd_putc ein Zeichen ausgeben
lcd_puts einen String ausgeben
bedeutet, dann nenn die Funktion halt lcd_puti (i wie int).
Matthias Sch. schrieb
> Da hat aber nochmal jemand editiert. Das mit der Stringausgabe ist mir> bekannt, aber die Routine ist deswegen so gehalten, damit ich auch> schnell mal eine UART oder ein anderes Characterdevice anquäken kann.> Das Aufteilen in 2 Routinen schau ich mir mal in Ruhe an.
Ach.
Und eine Funktion
1
staticvoiduart_int16(int16_tnumber)
2
{
3
charnumAsString[16]="0000000000000000";
4
5
itoa(number,numAsString,10);
6
uart_puts(numAsString);
7
}
wär dir zu kompliziert?
Du kannst es drehen wie du willst. Ausgabefunktionen haben eine gewisse
Hierarchie. Praktisch immer.
ganz zu unterste steht eine Funktion, die 1 Zeichen ausgibt.
Darauf aufbauend gibt es eine Funktion, die einen String ausgibt
Und auf dieser Stringausgabe wiederrum bauen dann Funktionen auf, die
ihre Ausgabe dergestalt erledigen, dass sie zunächst einen String
erzeugen und mit der Stringausgabe die eigentliche Ausgabe erledigen.
Und das ist immer so!
Willst du auf eine anderes Device ausgeben, dann benutzt du eben eine
andere String Ausgabe. Aber es gibt keinen Grund warum du in all diesen
Funktion die Aufdröselung in einen String selbst vornehmen musst. Denn
eine String Ausgabe ist auf allen Ausgabegeräten immer eine sinnvolle
Funktionalität für sich selber.
Zumal es ja nicht bei einer einzigen Funktion bleibt. Da gibt es 16-Bit
int mit und ohne Vorzeichen. Da gibt es 32 Bit long mit und ohne
Vorzeichen. Da gibt es zum Beispiel ein Datum, welches aus
Tag-Monat-Jahr besteht. Da gibt es .... Willst du in all diesen
Funktionen die Abarbeitung eines Strings immer wieder neu
ausprogrammieren?
Eine weitere 'Kunst' in der Programmierung besteht nicht darin,
möglichst viele Lines of Code zu produzieren, sondern sie besteht darin,
sich einen Baukasten zu machen, in dem die Einzelteile ineinandergreifen
und die universell benutz- und kombinierbar sind. Das ganze Shell
Konzept von Unix beruht darauf, einfache Tools zur Verfügung zu haben,
die aber so gestaltet sind, dass sie wie Bauklötze zusammengesteckt
werden können um sich mit einfachen Basisfunktionalitäten komplexere
Funktionalitäten zu erzeugen. Und die sind dann wieder kombinierbar,
etc. etc.
So Karl Heinz, du kannst dich wieder beruhigen. Ich hatte lediglich eine
kleine Routine gepostet, um dem TE zu helfen und keineswegs vor, eine
Grundsatzdiskussion um Programmierstile zu entfachen. Da du anscheinend
genau das vorhast, klinke ich mich hiermit aus. Viel Spass noch.
Matthias Sch. schrieb:> So Karl Heinz, du kannst dich wieder beruhigen.
Hab ich kein Problem damit :-)
Ich seh ja meine 'Aufgabe' hier nicht nur darin, Code zu korrigieren,
sondern auch Techniken und Verfahren den Leuten näher zu bringen, die
unter dem Stichwort 'gute Coding-Praxis' zusammengefasst werden können.
Und das beginnt durchaus ja auch schon im kleinen.
> Ich hatte lediglich eine> kleine Routine gepostet, um dem TE zu helfen
Ooops. Ich hatte gar nicht gemerkt, dass du nicht der TE bist. Sorry
dafür. Aber enn der TE davon etwas für seine eigene Praxis mitnehmen
kann, dann hab ich das Ziel ja erreicht.