Ich hab ein Problem, ich möchte eine 16 Bit Binärzahl, die in zwei
Registern ist, auf das LCD ausgeben und zwar als Integer Dezimalzahl
habe aber noch keinen Plan wie ich das am besten realisieren soll.
Wenn ich z.B. 1111'1111'1111'1111 habe soll auf dem Display -32768
erscheinen, habe ich 111'1111'1111'1111 soll 32767 erscheinen.
Hat jemand eine Idee wie man das realisieren könnte?
Hi Felix,
kennst Du http://www.atmel.com/atmel/acrobat/doc0938.pdf ?
Vorher würde ich das höchstwertigste Bit (Vorzeichen) testen, ggfls.
Minuszeichen generieren und dann im MSB löschen.
Grüsse
Ralf
Hallo
Danke, ich habe es unterdessen geschafft!
Wer genaueres wissen möchte soll sich die Doku anschauen, die ich
geschrieben habe (atached).
MfG
Felix
Hallo,
kann jemand den oberen Code einmal in C für einen Mega8 umschreiben ?
Die 16Bit Zahl soll aus dem Zählregister des Timer1 gelesen werden und
dann auf einem LCD-Display mit einer 4-Bit-Ansteuerung angezeigt werden.
Das wäre sehr nett.
Gruß
D.
dunial schrieb:
> Hallo,>> kann jemand den oberen Code einmal in C für einen Mega8 umschreiben ?> Die 16Bit Zahl soll aus dem Zählregister des Timer1 gelesen werden und> dann auf einem LCD-Display mit einer 4-Bit-Ansteuerung angezeigt werden.> Das wäre sehr nett.>
1
charBuffer[8];
2
uint16_tWert;
3
4
Wert=TCCR1;
5
utoa(Wert,Buffer,10);
6
lcd_string(Wert);
Wobei lcd_string eine Funktion ist, die einen Textstring auf einem LCD
ausgeben können muss.
Hallo,
bei "Wert = TCCR1;" bringt der Compiler eine Fehlermeldung.
Ich dachte immer, es wird das TCNT1-Register ausgelesen und nicht das
TCCR1.
Beim Test erscheinen keine Zahlen, sondern zusammenhangslose Buchstaben
und Zeichen...
Der Zähler wird mit einem externen Signal gespeist, wobei die steigenden
Flanken erkannt werden (TCCR1B=0x07;). Bei jedem Impuls zählt der Timer
logischerweise immer 1 aufwärts, und das eine Minute lang (dafür
verwende ich in einer Schleife den Timer0). Der aktuelle Wert soll, wie
ich schon sagte, auf dem LCD erscheinen.
Ist es auch möglich, ein Komma an folgende Stelle zu setzen ("xxxxxx" zu
"xxxx,xx") und wenn das vorletzte oder das letzte "x" = 0 ist, die leere
Stelle hinter dem Komma und die Stelle vor dem Komma mit einer Null
aufzufüllen (z.B. 0,54 (bei Zählstand 54) oder 0,09 (bei Zählstand 9) ?
Gruß
D.
dunial schrieb:
> Hallo,>> bei "Wert = TCCR1;" bringt der Compiler eine Fehlermeldung.> Ich dachte immer, es wird das TCNT1-Register ausgelesen und nicht das> TCCR1.
Du hast recht.
Ich hab nicht im Datenblatt nachgesehen und offensichtlich hat mir mein
Gedächtnis beim schnellen Tippen einen Streich gespielt.
> Beim Test erscheinen keine Zahlen, sondern zusammenhangslose Buchstaben> und Zeichen...
Dann zeig den möglichst kompletten Code.
Meine Kristallkugel tippt auf einen Array-Überlauf, weil du den
Ausgabebuffer zu klein dimensioniert hast.
> Ist es auch möglich, ein Komma an folgende Stelle zu setzen ("xxxxxx" zu> "xxxx,xx") und wenn das vorletzte oder das letzte "x" = 0 ist, die leere> Stelle hinter dem Komma und die Stelle vor dem Komma mit einer Null> aufzufüllen (z.B. 0,54 (bei Zählstand 54) oder 0,09 (bei Zählstand 9) ?
Alles ist möglich.
In dem Fall, wenn die Laufzeit bzw. Programmgröße nicht dagegen spricht,
würde ich zu sprintf greifen
http://www.mikrocontroller.net/articles/FAQ#Wie_kann_ich_Zahlen_auf_LCD.2FUART_ausgeben.3F
Hallo dunial,
ich hatte mal das selbe Problem und nicht ausreichend Platz für
sprintf(). Habe mir dann folgende Funktion geschrieben welche sicher
noch nicht das Optimun ist, aber für meine Zwecke ausreichend war.
1
// Funktion Int to String (Zahl, länge des fertigen String, Komma)
2
// Komma = 2 -> Zahl / 100, Komma = 0 für kein Komma
Karl heinz Buchegger schrieb:
>> Beim Test erscheinen keine Zahlen, sondern zusammenhangslose Buchstaben>> und Zeichen...>> Dann zeig den möglichst kompletten Code.> Meine Kristallkugel tippt auf einen Array-Überlauf, weil du den> Ausgabebuffer zu klein dimensioniert hast.
Meine Kristallkugel tippt eher darauf, dass du wenigstens den Puffer zum
LCD schicken solltest und nicht den Int ;)
Anstelle
Philipp Burch schrieb:
> Karl heinz Buchegger schrieb:>>> Beim Test erscheinen keine Zahlen, sondern zusammenhangslose Buchstaben>>> und Zeichen...>>>> Dann zeig den möglichst kompletten Code.>> Meine Kristallkugel tippt auf einen Array-Überlauf, weil du den>> Ausgabebuffer zu klein dimensioniert hast.>> Meine Kristallkugel tippt eher darauf, dass du wenigstens den Puffer zum> LCD schicken solltest und nicht den Int ;)
Mist.
Mea culpa.
Danke für die Korrektur.
Hallo,
vielen Dank erst einmal für die vielen Antworten :-) !!
Den Code habe ich beigefügt. Evtl. ist es noch wichtig zu sagen, dass
ich mit AVR Studio 4 und mit dem Compiler WinAVR arbeite.
Die Variante von Steffen werde ich morgen einmal ausprobieren.
Einmal zur Erläuterung meines Projektes:
Es soll eine Zähleinheit für einen selbstgebauten Geigerzähler werden.
Der Impuls kommt von einem NE555, der die Impulse des Zählrohrs für den
Mega8 aufbereitet.
Das Programm besteht aus 3 Unterprogrammen:
-Programm A: eine Minute lang die ankommenden Impulse zählen (soll auch
schon auf LCD ausgegben werden). Nach der Minute soll das Ergebnis 15
Sekunden lang angezeigt werden. Wenn keine andere Programmwahl durch
einen Taster erfolgt, läuft das Programm A erneut durch. Durch einen
Reset-Impuls (nicht der Reset des Controllers an Pin PC6 !) kann man zur
main-Schleife zurückkehren.
-Programm B: 30 Sekunden lang messen. Danach das Ergebnis in der 2.
Zeile anzeigen ('xxxx,xx 30sec.') und den Wert in µSv/h in der 1. Zeile
berechnen und ausgeben.
-Programm C: 10 Sekunden messen. Sonst genau so wie B.
Das schwierige war nun, einen geeigneten Zähler zu programmieren. Der
einfache 8Bit-Timer0 zählt ja nur bis 255. Da hätte man dann bei jedem
Überlauf Variabeln setzen müssen und Gleichungen bearbeiten, damit der
Gesamtzählwert angezeigt wird. Also dachte ich mir, nehme ich den Timer1
der bis ca. 65.500 zählen kann. Da aber bei stark strahlenden Mineralien
das noch nicht ausreicht, habe ich mit der Formel ZA=Z1+ZG gearbeitet.
ZA ist der Ausgabewert auf dem LCD-Display. Z1 ist der momentane
Zählwert des Timer1. Wenn Z1 größer gleich 50.000 ist, dann wird Z1=ZG
gesetzt und der Timer1 wieder auf null gesetzt. Somit kann man insgesamt
bis ca. 115.500 zählen. Das entspricht dann 1155,00µSv/h
Die strings für das LCD wollte ich in den EEPROM schreiben. Das
Schreiben an sich hat auch funktioniert, aber beim Test war dann die
ganze Anzeige schwarz ??? Deshalb habe ich die strings direkt in main
eingegeben.
Gruß
Daniel
TCNT1=0x00; //Z�hlregister Timer1 wird auf null gesetzt
TCNT1H=0x00; //High-Byte Timer1 wird auf null gesetzt
TCNT1L=0x00; //Low-Byte Timer1 wird auf null gesetzt
TCNT1 ist das 16-Bit Zählregister!
Bestehend aus TCNT1H und TCNT1L.
Obiges ist also doppelt gemoppelt.
if (TCNT1>=0xc350) //ist Timer1 >= 50.000 ?
Warum schreibst du nicht gleich
if (TCNT1 >= 50000) //ist Timer1 >= 50.000 ?
Jetzt steht im Kommentar dasselbe wie im Code: -> Kommentar kann
entfallen und braucht daher auch nicht weiter gepflegt werden. Und vor
allen Dingen: Ein nicht vorhandener Kommentar kann auch nicht falsch
sein, wenn der Code mal geändert wird.
"Die dringlichste Kritik:
Du solltest den Befehl 'goto' schleunigst aus dem C-Wortschatz
streichen."
...es funktioniert aber ;-)
Das werde ich natürlich in Zukunft anders lösen. Das ist mein erstes
C-Programm, welches ich entwerfe. Da fällt einem selbst so ein 'Fehler'
gar nicht auf.
Gruß
Daniel
Hallo,
hier einmal ein Ausschnitt aus dem Quelltext. Der Sekundentimer und der
eigentliche Programmablauf funktionieren einwandfrei (das "goto" habe
ich erst einmal so gelassen (schäm*)). Nur das Anzeigen der Zahl
funktioniert noch nicht. Die Variable 'za' soll angezeigt werden. Die
Schleife "retmin1" dauert eine Minute und hier soll der laufende
Zählstand des Timer1 auf dem LCD-Display ausgegeben werden.
Kann sich jemand einmal den Code ansehen und diesen berichtigen, damit
das angezeigt wird, was ich will ?
Das wäre sehr nett.
Gruß
Daniel
dunial schrieb:
> Kann sich jemand einmal den Code ansehen und diesen berichtigen, damit> das angezeigt wird, was ich will ?
Du brauchst dringend ein C-Buch
Der Teil hier
Warum hast du eigentlich die ursprüngliche Lösung nicht dem Prinzip nach
beibehalten.
Ursprünglich war das
1
retmin1:
2
za=z1+zg;
3
z1=TCNT1;//Variable z1 nimmt den Wert des Z�hlregisters TCNT1 von Timer1 an
4
5
6
/*Wert, der in "lcd_string" steht, wird aus den 16 Bits des Timer1 ausgelesen. */
7
//za Anzeige auf LCD (noch nicht erf�llt)
8
charBuffer[8];
9
utoa(z1,Buffer,10);
10
set_cursor(0,1);
11
lcd_string(Buffer);
Jetzt willst du za ausgeben. za ist ein unsigned long und die
korrspondierende Funktion zur Wandlung dafür heisst ultoa
1
retmin1:
2
za=z1+zg;
3
z1=TCNT1;//Variable z1 nimmt den Wert des Z�hlregisters TCNT1 von Timer1 an
4
5
6
/*Wert, der in "lcd_string" steht, wird aus den 16 Bits des Timer1 ausgelesen. */
7
//za Anzeige auf LCD (noch nicht erf�llt)
8
charBuffer[12];/* 7 benutzbare Zeichen könnte bei einem ulong knapp werden -> größer gehen */
9
ultoa(za,Buffer,10);
10
set_cursor(0,1);
11
lcd_string(Buffer);
Die Funktionsnamen sind nach einem Schema aufgebaut. In der Mitte steht
jeweils 'to' um anzuzeigen, dass etwas konvertiert wird. Das 'a' hinten
bedeutet ASCII, also Text. Und vorne steht ein Kürzel für den Datentyp
itoa integer to ascii
utoa unsigned integer to ascii
ltoa long to ascii
ultoa unsigned long to ascii
Wie gesagt, du brauchst dringend ein Buch!
Hallo,
ich darf verkünden: es klappt !!
Vielen Dank noch einmal für eure Bemühungen.
Nach einem Buch werde ich mich einmal umsehen. Ich habe nur momentan
eines, dass im Speziellen die Controller der Atmel-Mega-Serie behandelt.
Da gibt es auch Codebeispiele und Anwendungen, aber eben nicht für so
einen Zähler.
Viele Grüße
Daniel
dunial schrieb:
> Hallo,>> ich darf verkünden: es klappt !!>> Vielen Dank noch einmal für eure Bemühungen.> Nach einem Buch werde ich mich einmal umsehen. Ich habe nur momentan> eines, dass im Speziellen die Controller der Atmel-Mega-Serie behandelt.> Da gibt es auch Codebeispiele und Anwendungen, aber eben nicht für so> einen Zähler.
Du brauchst ein Grundlagenbuch für C!
Ein Buch über die speziellen Formgebungen des Brennraums und dessen
Auswirkungen auf den Wirkungsgrad hilft dir nichts oder nur wenig, wenn
dein Problem darin besteht, wie so ein Ottomotor eigentlich
funktioniert. Klar kann man sich das eine oder andere aus dem
Spezialbuch zusammenreimen. Aber es wird immer ein Zusammenreimen
bleiben und nie etwas Handfestes werden!
Ich hab dein Programm mal etwas bearbeitet.
Es entspricht der Funktionalität nicht ganz deinem Programm. ABer es
soll dir zeigen, wie man sich durch die Einführung von Funktionen den
Code in kleinere überschaubarere Einheiten zergliedern kann.