Forum: Mikrocontroller und Digitale Elektronik LCD 1602A an ATmega8


von L. F. (ping)


Angehängte Dateien:

Lesenswert?

Guten Abend.
Ich versuche seit geraumer Zeit ein LCD zum laufen zu bekommen, leider 
scheint es mit der Initialisierung nicht zu klappen.

Habe die LCD-routines aus dem Tutorial genommen.
XTAL = 3686400
Display an PortC
R/W = GND
RS = PC4
E = PC5

nach dem Einschalten zeigt das LCD sofort eine Zeile schwarz.
Kontrastspannung kann ich einstellen.

LCD ist ein 1602A vorr. von Chrystalfontz.
vielleicht sieht jemand gleich einen Fehler.
Die Init-Routine (lcd_init) ist im angehängten Datenblatt als 
Flussdiagramm beschrieben. Soweit ich das verstanden habe, wird das so 
umgesetzt.

Vielleicht sieht ja jemand gleich einen Fehler oder hat einen guten 
Hinweis für mich. Danke.

main.c:
1
// LCD_Init
2
  lcd_init();
3
  lcd_data( 'T' );

lcd-routines.h:     (Auzug)
1
#ifndef F_CPU
2
#define F_CPU 3686400
3
#endif
4
 
5
////////////////////////////////////////////////////////////////////////////////
6
// Pinbelegung für das LCD, an verwendete Pins anpassen
7
// Alle LCD Pins müssen an einem Port angeschlossen sein und die 4
8
// Datenleitungen müssen auf aufeinanderfolgenden Pins liegen
9
 
10
//  LCD DB4-DB7 <-->  PORTD Bit PD0-PD3
11
#define LCD_PORT      PORTC
12
#define LCD_DDR       DDRC
13
#define LCD_DB        PC0
14
 
15
//  LCD RS      <-->  PORTD Bit PD4     (RS: 0=Data, 1=Command)
16
#define LCD_RS        PC4
17
 
18
//  LCD EN      <-->  PORTD Bit PD5     (EN: 1-Impuls für Daten)
19
#define LCD_EN        PC5
20
 
21
////////////////////////////////////////////////////////////////////////////////
22
// LCD Ausführungszeiten (MS=Millisekunden, US=Mikrosekunden)
23
 
24
#define LCD_BOOTUP_MS           16
25
#define LCD_ENABLE_US           1
26
#define LCD_WRITEDATA_US        46
27
#define LCD_COMMAND_US          42
28
 
29
#define LCD_SOFT_RESET_MS1      5
30
#define LCD_SOFT_RESET_MS2      1
31
#define LCD_SOFT_RESET_MS3      1
32
#define LCD_SET_4BITMODE_MS     5
33
 
34
#define LCD_CLEAR_DISPLAY_MS    2
35
#define LCD_CURSOR_HOME_MS      2
36
 
37
////////////////////////////////////////////////////////////////////////////////
38
// Zeilendefinitionen des verwendeten LCD
39
// Die Einträge hier sollten für ein LCD mit einer Zeilenlänge von 16 Zeichen passen
40
// Bei anderen Zeilenlängen müssen diese Einträge angepasst werden
41
 
42
#define LCD_DDADR_LINE1         0x00
43
#define LCD_DDADR_LINE2         0x40
44
#define LCD_DDADR_LINE3         0x10
45
#define LCD_DDADR_LINE4         0x50
46
.
47
.
48
.
49
// LCD Befehle und Argumente.
50
// Zur Verwendung in lcd_command
51
 
52
// Clear Display -------------- 0b00000001
53
#define LCD_CLEAR_DISPLAY       0x01
54
 
55
// Cursor Home ---------------- 0b0000001x
56
#define LCD_CURSOR_HOME         0x02
57
 
58
// Set Entry Mode ------------- 0b000001xx
59
#define LCD_SET_ENTRY           0x04
60
 
61
#define LCD_ENTRY_DECREASE      0x00
62
#define LCD_ENTRY_INCREASE      0x02
63
#define LCD_ENTRY_NOSHIFT       0x00
64
#define LCD_ENTRY_SHIFT         0x01
65
 
66
// Set Display ---------------- 0b00001xxx
67
#define LCD_SET_DISPLAY         0x08
68
 
69
#define LCD_DISPLAY_OFF         0x00
70
#define LCD_DISPLAY_ON          0x04
71
#define LCD_CURSOR_OFF          0x00
72
#define LCD_CURSOR_ON           0x02
73
#define LCD_BLINKING_OFF        0x00
74
#define LCD_BLINKING_ON         0x01
75
 
76
// Set Shift ------------------ 0b0001xxxx
77
#define LCD_SET_SHIFT           0x10
78
 
79
#define LCD_CURSOR_MOVE         0x00
80
#define LCD_DISPLAY_SHIFT       0x08
81
#define LCD_SHIFT_LEFT          0x00
82
#define LCD_SHIFT_RIGHT         0x04
83
 
84
// Set Function --------------- 0b001xxxxx
85
#define LCD_SET_FUNCTION        0x20
86
 
87
#define LCD_FUNCTION_4BIT       0x00
88
#define LCD_FUNCTION_8BIT       0x10
89
#define LCD_FUNCTION_1LINE      0x00
90
#define LCD_FUNCTION_2LINE      0x08
91
#define LCD_FUNCTION_5X7        0x00
92
#define LCD_FUNCTION_5X10       0x04
93
 
94
#define LCD_SOFT_RESET          0x30
95
.
96
.
97
.

lcd-routines.c:      (Auszug: die init-Funktion)
1
void lcd_init( void )
2
{
3
    // verwendete Pins auf Ausgang schalten
4
    uint8_t pins = (0x0F << LCD_DB) |           // 4 Datenleitungen
5
                   (1<<LCD_RS) |                // R/S Leitung
6
                   (1<<LCD_EN);                 // Enable Leitung
7
    LCD_DDR |= pins;
8
 
9
    // initial alle Ausgänge auf Null
10
    LCD_PORT &= ~pins;
11
 
12
    // warten auf die Bereitschaft des LCD
13
    _delay_ms( LCD_BOOTUP_MS );
14
    
15
    // Soft-Reset muss 3mal hintereinander gesendet werden zur Initialisierung
16
    lcd_out( LCD_SOFT_RESET );
17
    _delay_ms( LCD_SOFT_RESET_MS1 );
18
 
19
    lcd_enable();
20
    _delay_ms( LCD_SOFT_RESET_MS2 );
21
 
22
    lcd_enable();
23
    _delay_ms( LCD_SOFT_RESET_MS3 );
24
 
25
    // 4-bit Modus aktivieren 
26
    lcd_out( LCD_SET_FUNCTION |
27
             LCD_FUNCTION_4BIT );
28
    _delay_ms( LCD_SET_4BITMODE_MS );
29
 
30
    // 4-bit Modus / 2 Zeilen / 5x7
31
    lcd_command( LCD_SET_FUNCTION |
32
                 LCD_FUNCTION_4BIT |
33
                 LCD_FUNCTION_2LINE |
34
                 LCD_FUNCTION_5X7 );
35
 
36
    // Display ein / Cursor aus / Blinken aus
37
    lcd_command( LCD_SET_DISPLAY |
38
                 LCD_DISPLAY_ON |
39
                 LCD_CURSOR_OFF |
40
                 LCD_BLINKING_OFF); 
41
 
42
    // Cursor inkrement / kein Scrollen
43
    lcd_command( LCD_SET_ENTRY |
44
                 LCD_ENTRY_INCREASE |
45
                 LCD_ENTRY_NOSHIFT );
46
 
47
    lcd_clear();
48
}

von holger (Gast)


Lesenswert?

>Vielleicht sieht ja jemand gleich einen Fehler oder hat einen guten
>Hinweis für mich. Danke.

Unvollständiger Code wird hier natürlich immer
gerne genommen. Da bleibt genug Spielraum zum RATEN.

Ohne Schaltplan wird das hier auch nix.

von Tobi L. (derarzt)


Lesenswert?

#define F_CPU 3686400



XTAL = 3686400


ist das nur ein post fehler oder fehlt die 6 auch im code?(hab mir den 
code nicht weiter angeschaut)


wieviel spalten hat denn das lCD display weil das aus dem tut hatte 2*16

von L. F. (ping)


Angehängte Dateien:

Lesenswert?

@Tobi: Wo fehlt die 6?, ich stehe auf dem Schlauch.

Display hat 2*16, ja.

@holger:

Pins des Displays sind wie folgt angeschlossen:

16 = GND
15 = +5V
14 = PC3
13 = PC2
12 = PC1
11 = PC0
10 bis 7 = GND
6 = PC5
5 = GND
4 = PC4
3 = V_DD = Potiabgriff
2 = +5V
1 = GND

am Controller ist sonst noch die der externe Quartz (PB6+PB7) 
angeschlossen, dieser ist auch aktiviert. (ext. 16k +ck 4ms).

Zum programmieren benutze ich mySmartUSBlight von myavr.de, 
Angeschlossen ist sonst noch am Atmega:

PC6 = Reset-Taster
PB5 = SCK
PB4 = MISO
PB3 = MOSI

Details sieje Schaltunh.png.

main.c
1
// --- main.c ---
2
3
#include <avr/interrupt.h>
4
#include <inttypes.h>
5
#include "main.h"
6
#include "lcd-routines.h"
7
8
9
int main(void)
10
{
11
12
// LCD_Init
13
  lcd_init();
14
  lcd_setcursor(1,1);
15
  lcd_string("Hallo Welt!");
16
17
    return 0;
18
}

main.h
1
// ---- main.h ----
2
3
#ifndef F_CPU
4
/* wenn F_CPU nicht bereits vorher definiert (z.B. durch
5
   Übergabe als Parameter zum Compiler innerhalb des Makefiles) */
6
//#define F_CPU 7372800L     /* Quarz mit 3.6864 Mhz */
7
#define F_CPU 3686400
8
#endif
9
10
#include <avr/io.h>
11
#include <util/delay.h>

von holger (Gast)


Lesenswert?

>Pins des Displays sind wie folgt angeschlossen:

>16 = GND
>15 = +5V

Oh, oh. Das ist die Hintergrundbeleuchtung (falls vorhanden).
Da braucht man einen Vorwiderstand für die LEDs.
Am besten erstmal die +5V da wegnehmen.

>14 = PC3
>13 = PC2
>12 = PC1
>11 = PC0
>10 bis 7 = GND

Lass 10-7 offen. Nirgendwo anschliessen.

Das hier drunter ist ok.

>6 = PC5
>5 = GND
>4 = PC4
>3 = V_DD = Potiabgriff
>2 = +5V
>1 = GND

von L. F. (ping)


Lesenswert?

PIN 7-10 am Display = NC    (GND entfernt)
PIN 15 = NC      (kein 5V angeschlossen, Hintergrundbeleuchtung aus)

keine Veränderung sichtbar.  Eine Zeile des Displays wird komplett 
schwarz angezeigt. (wie vorher auch)

von Helfer (Gast)


Lesenswert?

Zeig mal deine lcd_out()!

von L. F. (ping)


Lesenswert?

kompletter Code ist weiter oben mit angehängt.
1
// Sendet eine 4-bit Ausgabeoperation an das LCD
2
static void lcd_out( uint8_t data )
3
{
4
    data &= 0xF0;                       // obere 4 Bit maskieren
5
 
6
    LCD_PORT &= ~(0xF0>>(4-LCD_DB));    // Maske löschen
7
    LCD_PORT |= (data>>(4-LCD_DB));     // Bits setzen
8
    lcd_enable();
9
}

von holger (Gast)


Angehängte Dateien:

Lesenswert?

>keine Veränderung sichtbar.  Eine Zeile des Displays wird komplett
>schwarz angezeigt. (wie vorher auch)

Dann wird das Display nicht richtig initialisiert.
Irgenwo eine Leitung falsch angeschlossen?
Kurzschlüsse? Offene Leitungen?

Funktioniert die HEX Datei im Anhang?

von L. F. (ping)


Lesenswert?

funktioniert leider auch nicht. Habe nochmal die Verdrahtung überprüft 
und die Kontakte Drähte durchgemessen. soweit alles ok. Kurzschlüsse 
soweit keine messbar. was meinst du mit offenen Leitungen?

von Felix N. (Gast)


Lesenswert?

Ich wollte mal fragen, ob Du das Problem lösen konntest?

Ich stehe jetzt genau vor dem gleichen Fehler, nur die obere Zeile 
funktioniert. Habe genau den selben Aufbau wie Du.

Auch die LCD_Test_MEGA8.hex von holger habe ich schon geflasht, mit dem 
gleichen Ergebnis wie Du.

Jemand eine Idee, wie sich der Fehler beheben lässt?

P.S.: Alte Threads soll man ja nicht ausgraben, sagt mir also bitte wenn 
ich einen neuen aufmachen soll.

von Hubert G. (hubertg)


Angehängte Dateien:

Lesenswert?

Ich nehme mal an das das die Lib von Peter Dannegger ist.
Dein *.hex funktioniert bei mir nicht.
Die von mir kompilierte schon. Allerdings PortD nicht PortC.

von Hubert G. (hubertg)


Lesenswert?

ICh habe mein LCD umgebaut, jetzt funktioniert die LCD_Test_MEGA8.hex 
von Holger auch.
Falls du das Pollin Addon-Board benutzt, PortC des Mega8 kommt dort als 
PortA an.

von Felix N. (Gast)


Lesenswert?

"Hallo Peter" - LCD funktioniert! Danke Hubert :)!

Habe es jetzt auch mal mit dem Code aus dem Wiki getestet, läuft soweit 
auch.

Nur sehe ich leichte "Streifen" auf dem Display, d.h. die Anzeige ist 
nicht so klar, wie man es als auf den Beispielbildern sieht.

Hast Du mir da auch einen Rat?

Kann auch gerne mal ein Bild anhängen.

von Hubert G. (hubertg)


Lesenswert?

Könnte am Kontrast liegen, schon mal am Regler gedreht?

von Felix N. (Gast)


Lesenswert?

Ja, habe wir im Tutorial einen 10k Poti dran und auch schon daran 
gedreht.

Aber so richtig "klar" ist die Anzeige leider nicht. Die Frage ist 
jetzt, ob es an der Ansteuerung oder am LCD liegt?

von spess53 (Gast)


Lesenswert?

Hi

>Aber so richtig "klar" ist die Anzeige leider nicht. Die Frage ist
>jetzt, ob es an der Ansteuerung oder am LCD liegt?

Wie schnell hinter einander beschreibst du das Display?

MfG Spess

von Hubert G. (hubertg)


Lesenswert?

Also mein Display ist ganz sauber, das mit beiden Versionen die hier 
gepostet wurden, es könnte daher auch defekt sein.

von Felix N. (Gast)


Angehängte Dateien:

Lesenswert?

Ich verstehe die Frage nicht ganz, das Display wird doch, wenn wir von 
dem Code aus dem Tutorial ausgehen, nur einmal beschrieben und dann wird 
die CPU mit der While-Schleife beschäftigt:

  lcd_string("Hello World!");

  while(1)
  {
  }

Habe mal zwei Bilder angehängt, die das Problem verdeutlichen. Bei einem 
habe ich den Kontrast mal ganz hoch gedreht.

Gruß

von spess53 (Gast)


Lesenswert?

Hi

>Ich verstehe die Frage nicht ganz...

Welche?

Dein geposteter Code passt aber nicht zu der Ausgabe auf dem Display.

MfG Spess

von Felix N. (Gast)


Lesenswert?

Die Frage, wie schnell ich das Display hintereinander beschreibe?

Ich habe sowohl die LCD_Danni.hex ausporbiert (Bilder von oben), als 
auch den Code aus dem Tutorial.

Bei beiden treten die Streifen im Display auf. Jetzt versteh ich nicht, 
wie Du es meinst, wie schnell ich das Display hintereinander beschreibe, 
da ich den Code aus dem Tutorial so verstehe, dass dort die Anzeige nur 
einmal beschrieben wird und dann nichts mehr gemacht wird (Codeschnipsel 
von oben).

von Karl H. (kbuchegg)


Lesenswert?

Felix N. schrieb:
> Die Frage, wie schnell ich das Display hintereinander beschreibe?

Dein Code hätte ja auch so aussehen können
1
  ...
2
  while(1)
3
  {
4
    lcd_clear();
5
    lcd_string("Hello Peter");
6
  }

in dem Fall wäre es nicht ungewöhnlich, wenn das LCD 'nicht klar' 
aussieht.

> Ich habe sowohl die LCD_Danni.hex ausporbiert (Bilder von oben), als
> auch den Code aus dem Tutorial.

zeig doch bitte immer DEINEN Code und verweise nicht auf irgendwas 
anderes. Wenn du Code Stückchen postest, in denen "Hello World" 
ausgegeben wird und auf deinem Photo sieht man ein LCD auf dem 
offensichtlich "Hello Peter" und eine Zahl drunter steht, dann ist das 
eben nicht exakt der Code auf den du verwiesen hast oder der Code von 
dem du ein Stückchen gepostet hast. Und dann werden viele Leute hier 
stutzig. (Und wenn man sowas oft genug macht, dann sinkt die 
Bereitschaft der anderen sich da Gedanken darüber zu machen ganz 
gewaltig)

von Hubert G. (hubertg)


Lesenswert?

In dem oben geposteten Bild wird "Hello Peter" nur einmal geschrieben. 
Die Zahl darunter wird laufend erhöht.
Da in der zweiten Zeile eine ganze Reihe an Pixel zu fehlen scheint, 
würde ich sagen das das Display defekt ist.
Es sei denn du hast eine extrem unsaubere Versorgungsspannung. Dann 
würde sich der Fehler allerdings am Display bewegen.

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.