Forum: Mikrocontroller und Digitale Elektronik Ausgabeprobleme LCD 4Bit


von Klaus H. (Firma: privat) (klaus777)


Lesenswert?

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
volatile int zeit1 = 180;
9
volatile int zeit ;
10
11
void setup_global(void)
12
{
13
DDRD= 0xff;
14
}
15
16
void setup_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
void Displ_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
void display_time(int x)
36
{
37
  lcd_setcursor( 15, 2 );
38
  char Buffer[5]; // in diesem {} lokal
39
  itoa( zeit, Buffer, 10 ); 
40
  lcd_string( Buffer );
41
}
42
 
43
int main(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

von Mark B. (markbrandis)


Lesenswert?

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.

von holger (Gast)


Lesenswert?

>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.

von Mark B. (markbrandis)


Lesenswert?

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. ;-)

von Klaus H. (Firma: privat) (klaus777)


Angehängte Dateien:

Lesenswert?

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.

von Ralph S. (jjflash)


Lesenswert?

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

von Ralph S. (jjflash)


Lesenswert?

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.

von Michael U. (amiga)


Lesenswert?

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

von Klaus H. (Firma: privat) (klaus777)


Lesenswert?

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.

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.