Hallo in die Runde,
ich habe sicherlich ein Anfängerproblem.
Ich wollte einen Zähler rückwärts laufen lassen und den Wert auf einem
LCD-Display darstellen.
Das initialisieren des Displays klappt,
die beiden Werte 'Timer' und '3 Min' erscheinen richtig,
nur die Ausgabe des Wertes leider nicht. Da stehen nur asiatische
Zeichen.
Ich habe verschiedene Displays getestet HD44780 oder 1602.
Selbe Problematik.
Danke für eure Unterstützung.
aus dem Makefile:
MCU = attiny2313
F_CPU = 1000000
Meine Source:
1
#include<avr/io.h>
2
#include<stdlib.h>
3
#include"lcd-routines.h"
4
#include<avr/interrupt.h>
5
#include<util/delay.h>
6
7
8
volatileintzeit1=180;
9
volatileintzeit;
10
11
voidsetup_global(void)
12
{
13
DDRD=0xff;
14
}
15
16
voidsetup_timer(void)
17
{
18
// Timer1
19
TCCR1A=(1<<COM1A0);// CTC mode, toggle OC1A on compare match
20
TCCR1B=(1<<CS12)// Start Timer1 with prescaler 256
21
|(1<<WGM12);
22
OCR1A=3906;// F_Timer = F_clk/Prescaler
23
// Compare Interrupt erlauben
24
TIMSK|=(1<<OCIE1A);
25
}
26
voidDispl_def(void)
27
{
28
lcd_clear();
29
lcd_string("Timer ");
30
lcd_setcursor(0,2);
31
lcd_string("3 Min");
32
return;
33
}
34
35
voiddisplay_time(intx)
36
{
37
lcd_setcursor(15,2);
38
charBuffer[5];// in diesem {} lokal
39
itoa(zeit,Buffer,10);
40
lcd_string(Buffer);
41
}
42
43
intmain(void)
44
{
45
setup_global();
46
lcd_init();
47
Displ_def();
48
setup_timer();
49
sei();
50
while(1)
51
{
52
display_time(zeit);
53
_delay_ms(100);
54
PORTD^=(1<<PD1);
55
}
56
57
}
58
ISR(TIMER1_COMPA_vect)
59
{
60
zeit1--;
61
zeit=zeit1;
62
}
--
Bitte die Formatierungstags verwenden, die das Forum bietet. So ist
Dein Quelltext gleich lesbarer.
-rufus
Das beschriebene Verhalten passt wohl zu einer nicht korrekt gesetzten
Variablen.
Auffälligkeiten:
1.) Die Variable zeit wird zu Beginn auf keinen vernünftigen Wert
initialisiert.
2.) In dieser Funktion hier:
void display_time(int x)
wird der Parameter x nirgendwo verwendet. Wozu existiert er dann?
3.) Bist Du sicher, dass die Interrupt Service Routine korrekt
konfiguriert ist und auch ausgeführt wird? Das ist die einzige Stelle im
Code, an der die Variable zeit beschrieben wird.
4.) Die Variable zeit1 wird irgendwann negativ (so die ISR immer wieder
ausgeführt wird). Dann hätte auch die Variable zeit einen negativen
Wert. Das ist vermutlich nicht was Du willst.
>Dann hätte auch die Variable zeit einen negativen Wert.
Und passt dann nicht mehr in den Buffer.
Der müsste mit abschliessender Null schon
mal 7 Bytes aufnehmen können.
holger schrieb:> Und passt dann nicht mehr in den Buffer.> Der müsste mit abschliessender Null schon> mal 7 Bytes aufnehmen können.
Das wäre dann Punkt 5, den ich vergessen habe. ;-)
Hallo und Danke.
1. verständlich, ich hatte die Variable zu Testzwecken noch im Source,
das entschuldigt es nicht. Sie wird richtig gefüllt und
weiterverarbeitet.
2. stimmt auch, wurde korrigiert.
3. Ja, wurde mit >>PORTD ^= ( 1 << PD2 );<< in der ISR getestet
4. im Moment stehe ich vor dem Problem das die Ausgabe im Display nicht
funktioniert, der Rest wurde noch nicht implementiert.
(5.) ist richtig, erklärt 4.
Anbei das Bild vom Display.
Ich kenne deine lcd-rotuines.h nicht, aber ich gehe stark davon aus,
dass
lcd_string
als Parameter einen String aus dem Progmem erwartet, du aber mit
lcd_string( Buffer );
einen Array übergibst. Hier wundert es mich, dass der Compiler nicht
meckert, denn normalerweise hätte zumindest ein Zeiger übergeben werden
müssen ...
Du brauchst also fuer die Ausgabe eines Strings im Ram eine
entstprechende Funktion !
Wenn es in lcd-routines.h etwas in der Art wie:
void lcd_putchar(char ch)
gibt (so in der Art halt), dann lässt sich eine Ausgaberoutine leicht
selbst implementieren.
void lcd_ramstring(char *c)
{
while (*c)
{
lcd_putchar(*c++);
}
}
Der Aufruf in deinem Programm würde dann erfolgen mit:
lcd_ramstring(&Buffer[0]);
Im übrigen:
Du reservierst füf <Buffer> 5 Bytes. Ein Integer kann maximal den Wert
65535 annehmen (und ist somit 5 stellig). Ein abschließendes Zero Byte
(als Endekennung des Strings) wird bei <itoa> automatisch mit angehängt,
sodass ein Ergebnis im schlimmen Fall 6 Bytes Speicher benötigt !
Gruß am Morgen,
Ralph
Ralph S. schrieb:> im schlimmen Fall 6 Bytes Speicher benötigt !
Ah, wurde oben schon erwähnt, sorry: 6 Bytes natürlich für ein
unsigned integer (vorzeichenlos)
ansonsten 7.
Hallo,
Ralph S. schrieb:> Ich kenne deine lcd-rotuines.h nicht, aber ich gehe stark davon aus,> dass>> lcd_string>> als Parameter einen String aus dem Progmem erwartet, du aber mit>> lcd_string( Buffer );>> einen Array übergibst. Hier wundert es mich, dass der Compiler nicht> meckert, denn normalerweise hätte zumindest ein Zeiger übergeben werden> müssen ...
ich bin nicht der sonderliche C-Spezi, aber wie ich es verstanden habe,
wird in C in diesem Fall immer der Zeiger auf das Array übergeben.
Ich lasse mich da aber gern korrigieren.
Gruß aus Berlin
Michael
Hallo und Danke,
ich habe erst hier im Forum gelesen wie so was angesteuert wird.
https://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/LCD-Ansteuerung
dort findet sich auch folgendes Beispiel:
// Ausgabe der Variable als Text in dezimaler Schreibweise
{
// ... umwandeln siehe FAQ Artikel bei
http://www.mikrocontroller.net/articles/FAQ
// WinAVR hat eine itoa()-Funktion, das erfordert obiges #include
<stdlib.h>
char Buffer[20]; // in diesem {} lokal
itoa( variable, Buffer, 10 );
// ... ausgeben
lcd_string( Buffer );
}
Gruß Klaus.