Forum: Mikrocontroller und Digitale Elektronik mal wieder ein LCD am Atmega8


You were forwarded to this site from EmbDev.net. Back to EmbDev.net
von Adi A. (mateit)


Lesenswert?

Hallo Leute,

es tut mir leid, dass ich einen Thread zum Thema LCD am Atmega8 
schreiben muss, aber leider konnte mir bisher kein Thread aus dem Forum 
hier helfen.

Ich besitze ein LCD-Modul BATRON BTHQ22005VSS-13 von Pollin 
(http://www.pollin.de/shop/dt/MjgzOTc4OTk-/Bauelemente/Aktiv/Displays/LCD_Modul_BATRON_BTHQ22005VSS_13.html), 
auf dem Modul ist ein KS0070BP-00CC Controller.

Folgendermaßen habe ich das LCD angeschlossen:
VSS          gnd
VDD          5V
V0           an einem Poti
Ich möchte das LCD im 4bit Modus ansteuern.
Daher:
DB4          PC0
DB5          PC1
DB6          PC2
DB7          PC3
EN           PC4
RS           PC5
R/W          auf gnd gezogen

Die lcd.h und lcd.c habe ich von Peter Fleury. Die lcd.h habe ich 
folgendermaßen angepasst:
1
#define XTAL 125000  
2
           
3
#define LCD_CONTROLLER_KS0073 0  
4
#define LCD_LINES           2     
5
#define LCD_DISP_LENGTH    20    
6
#define LCD_LINE_LENGTH  0x40    
7
#define LCD_START_LINE1  0x00    
8
#define LCD_START_LINE2  0x40    
9
#define LCD_START_LINE3  0x14     
10
#define LCD_START_LINE4  0x54     
11
#define LCD_WRAP_LINES      0     
12
13
#define LCD_IO_MODE      1         
14
15
#if LCD_IO_MODE
16
17
#define LCD_PORT         PORTC       
18
#define LCD_DATA0_PORT   LCD_PORT     
19
#define LCD_DATA1_PORT   LCD_PORT     
20
#define LCD_DATA2_PORT   LCD_PORT     
21
#define LCD_DATA3_PORT   LCD_PORT     
22
#define LCD_DATA0_PIN    0            
23
#define LCD_DATA1_PIN    1            
24
#define LCD_DATA2_PIN    2           
25
#define LCD_DATA3_PIN    3            
26
#define LCD_RS_PORT      LCD_PORT     
27
#define LCD_RS_PIN       5            
28
#define LCD_RW_PORT      PORTB   
29
#define LCD_RW_PIN       6            
30
#define LCD_E_PORT       LCD_PORT      
31
#define LCD_E_PIN        4

Da ich R/W auf gnd gezogen habe, habe ich hier einen Pin gewählt der 
ebenfalls auf 0V liegt.

Ich programmiere mit dem AVR Studio und als Programmer nutze ich USBProg 
mit einem vorinstalliertem AVRISP MKII Klon.


Nun zum Programm:
1
#include <stdlib.h>
2
#include <avr/io.h>
3
#include "lcd.h"
4
#include <util/delay.h>
5
6
int main(void)
7
{
8
  DDRD = 0xFF;
9
  PORTD = ( 1 << DDD0 | 1 << DDD1 | 1 << DDD2 | 1 << DDD3);
10
  
11
  DDRC = 0xFF;
12
13
14
    /* initialize display, cursor off */
15
    lcd_init(LCD_DISP_ON);
16
17
  _delay_ms(50);
18
19
    for (;;) {                           /* loop forever */
20
 
21
    /* loesche das LCD Display und Cursor auf 1 Zeile, 1 Spalte */
22
    lcd_clrscr();
23
        
24
    /* String auf Display anzeigen */
25
    lcd_puts("Hello world.");
26
             
27
    }
28
}
(An PORTD liegen LEDs - ich wollte nur sehen, ob sich überhaupt was tut)

Kombilieren funktioniert genauso wie das Flashen ohne Probleme.
Allerdings sehe ich nix auf dem LCD..

Was mache ich falsch?
Wäre schön wenn jemand über diesen Roman drüber schauen würde ;)


Danke schon im Voraus.


beste Grüße

von Ulf R. (roolf)


Lesenswert?

M. Q. schrieb:
> #define XTAL 125000

sehr niedrige Frequenz!?

von Adi A. (mateit)


Lesenswert?

Huch das ging aber schnell ;)

Ulf Rolf schrieb:
> M. Q. schrieb:
>> #define XTAL 125000
>
> sehr niedrige Frequenz!?

Habe die Frequenz mal hochgestellt.
1
#define XTAL 8000000
funktioniert aber dennoch nicht.

Gruß

von Ulf R. (roolf)


Lesenswert?

M. Q. schrieb:

> R/W          auf gnd gezogen

Das geht mit der originalen Fleury-Lib nicht, weil die das Busy-Bit 
auswerten möchte.

von Wayne M. (vibra)


Lesenswert?

moin

Ich kenn die lib von fleury leider nicht :( und hab auch keine Lust mir 
das reinzuziehen ,aber ich kann dir nur den Tip geben das 
Initialisierungsschema mal mit folgendem Ablauf zu vergleichen.
1
LCD_init:     
2
;**** for the most LCD you must write 3times a dummy command before you change to 4Bit***
3
4
  
5
  ldi  temp, 0b00001110  ;control lines are output, rest is input
6
  out  DDRD, temp
7
  
8
  rcall  LCD_delay    ;first, we'll tell the LCD that we want to use it
9
  ldi  arg, 0x20      ;in 4-bit mode.
10
  rcall  LCD_command8    ;LCD is still in 8-BIT MODE while writing this command!!!
11
12
  rcall  LCD_delay
13
  ldi  arg, 0x20    ;NOW: 2 lines, 5*7 font, 4-BIT MODE!     ** DUMMY ***
14
  rcall  LCD_command    ;
15
  
16
  rcall  LCD_wait
17
  ldi  arg, 0x20    ;NOW: 2 lines, 5*7 font, 4-BIT MODE!     ** DUMMY ***
18
  rcall  LCD_command    ;
19
20
  rcall  LCD_wait
21
  ldi  arg, 0x28    ;NOW: 2 lines, 5*7 font, 4-BIT MODE!     ** this change to 4bit 2 lines **
22
  rcall  LCD_command    ;after this point you don't can change anything 'show HD44780 Datasheet'

von Adi A. (mateit)


Lesenswert?

Hallo vibra,

Wayne Monga schrieb:
> moin
>
> Ich kenn die lib von fleury leider nicht :( und hab auch keine Lust mir
> das reinzuziehen

kann ich gut verstehen ;)


Ich kann zwar kein ASM, aber ich kann Kommentare lesen ;)
In Peter Fleury's lcd.c steht dazu folgendes:
1
 /* initial write to lcd is 8bit */
2
    LCD_DATA1_PORT |= _BV(LCD_DATA1_PIN);  // _BV(LCD_FUNCTION)>>4;
3
    LCD_DATA0_PORT |= _BV(LCD_DATA0_PIN);  // _BV(LCD_FUNCTION_8BIT)>>4;
4
    lcd_e_toggle();
5
    delay(4992);         /* delay, busy flag can't be checked here */
6
   
7
    /* repeat last command */ 
8
    lcd_e_toggle();      
9
    delay(64);           /* delay, busy flag can't be checked here */
10
    
11
    /* repeat last command a third time */
12
    lcd_e_toggle();      
13
    delay(64);           /* delay, busy flag can't be checked here */
14
15
    /* now configure for 4bit mode */
16
    LCD_DATA0_PORT &= ~_BV(LCD_DATA0_PIN);   // LCD_FUNCTION_4BIT_1LINE>>4
17
    lcd_e_toggle();
18
    delay(64);           /* some displays need this additional delay */

das sollte dem obigen ASM Befehlen entsprechen.


Gruß

von Ulf R. (roolf)


Lesenswert?

Wayne Monga schrieb:

> ;**** for the most LCD you must write 3times a dummy command before you
> change to 4Bit***

Es ist extrem verwunderlich, welche Blüten diese Initialisierungsroutine 
und ihre Begründung trägt. Man könnte den Eindruck gewinnen, LCDs seien 
irgendwie schwerhörig und lassen sich erst mit mehreren Tritten in den 
Hintern zu einem Interfacewechsel bewegen.

Dem ist überhaupt nicht so. Es geht hier um eine 
100%-Foolproof-Initialisierung, die auch bei beliebiger Vorgeschichte 
(zufällige Eingaben auf dem Bus) das LCD in einen definierten Zustand 
versetzt.

Ein LCD mit 4 Drähten kann zu jedem Zeitpunkt in einem der folgenden 
vier Zustände sein:

* 8BIT: Es ist im 8-Bit-Modus

* 4BIT_HI: Es ist im 4-Bit-Modus und wartet auf das Hi-Nibble

* 4BIT_LO8: Es ist im 4-Bit-Modus, wartet auf das Lo-Nibble, hat aber im 
gerade empfangenen Hi-Nibble den Umschaltbefehl auf 8-Bit-Modus erhalten

* 4BIT_LO: Es ist im 4-Bit-Modus, wartet auf das Lo-Nibble, und das 
gerade empfangene Hi-Nibble enthält nicht diesen Umschaltebefehl

Jetzt malt man einfach ein Zustandsdiagramm
1
Zustand    Folgezustand bei 0x02    Folgezustand bei 0x03
2
-----------------------------------------------------------
3
8BIT           4BIT_HI                  8BIT
4
4BIT_HI        4BIT_LO                  4BIT_LO8
5
4BIT_LO        4BIT_HI                  4BIT_HI
6
4BIT_LO8       8BIT                     8BIT

Wenn man nun nur den Befehl 0x02 (auch wiederholt) schicken würde, 
könnte man auch nach 29 Wiederholungen nicht mit Sicherheit sagen, ob 
das Display im Zustand 4BIT_LO oder 4BIT_HI ist, und eine zuverlässige 
Initialisierung ist nicht möglich.

Man muss also zwingend zwischenzeitlich in den 8BIT-Modus schalten. 
Damit dies sicher passiert, muss dreimal 0x03 geschickt werden: Falls 
das Display zufällig im Zustand 4BIT_LO war, durchläuft es dabei die 
Zustände 4BIT_HI, 4BIT_LO8 und erreicht schließlich 8BIT. In allen 
anderen Fällen wird der Zustand 8BIT schon früher erreicht und bei 0x03 
dann beibehalten.

Nun ist man also definitiv im Zustand 8BIT und kann mit 0x02 in den 
4-Bit-Modus wechseln.

Wenn man der Stromversorgung traut, dann kann man sich den ganzen Kram 
auch sparen, weil das Display von selbst in den 8-Bit-Modus hochfährt.

von Adi A. (mateit)


Lesenswert?

Ulf Rolf schrieb:
> M. Q. schrieb:
>
>> R/W          auf gnd gezogen
>
> Das geht mit der originalen Fleury-Lib nicht, weil die das Busy-Bit
> auswerten möchte.


Entschuldige Ulf. Das habe ich gerade eben erst entdeckt.
Welche Alternative/n kann ich nutzen?

Danke bis hier hin schon mal!


Gruß

von Ulf R. (roolf)


Lesenswert?

M. Q. schrieb:

> Entschuldige Ulf. Das habe ich gerade eben erst entdeckt.
> Welche Alternative/n kann ich nutzen?

RW anschließen.

Oder andere Lib verwenden.

Oder selber schreiben.

Oder aber für ein erstes Weiterkommen "Speichern als..." > "mqlcd.c" und 
beherzt geändert. Die Routine, welche das Busy-Bit auswertet, kann auch 
einfach 60us warten. Es gibt nur zwei Befehle, die deutlich längere 
maximale Verarbeitungszeit (2ms) haben: CLEAR und HOME; dafür musst Du 
halt auch noch ein Delay einbasteln.

von Hubert G. (hubertg)


Angehängte Dateien:

Lesenswert?

Es macht nicht sehr viel Sinn, R/W auf einen Pin zu legen der 0V hat. Es 
wäre es besser diesen gleich zu aktivieren.
Ich lege R/W immer auf GND, der Geschwindigkeitsunterschied ist nicht 
erkennbar und ich spare diesen Pin für anderes.
Du solltest auch #define LCD_CONTROLLER_KS0073 0  auf 1 geben.
In der lib im Anhang kannst du einstellen ob mit oder ohne R/W.

von Adi A. (mateit)


Lesenswert?

Hubert G. schrieb:
> Es macht nicht sehr viel Sinn, R/W auf einen Pin zu legen der 0V hat. Es
> wäre es besser diesen gleich zu aktivieren.
> Ich lege R/W immer auf GND, der Geschwindigkeitsunterschied ist nicht
> erkennbar und ich spare diesen Pin für anderes.
> Du solltest auch #define LCD_CONTROLLER_KS0073 0  auf 1 geben.
> In der lib im Anhang kannst du einstellen ob mit oder ohne R/W.

Hallo Hubert,

genauso mache ich es auch! Ich lege R/W auf meiner Platine direkt auf 
GND.
Da ich in der alten lcd.h allerdings einen Pin angeben musste, an dem 
R/W liegt, habe ich einen ausgewählt, der auf 0V liegt.

Ich muss feststellen, dass das "Hello World." auf dem Display sehr gut 
aussieht! Soll heißen: ES FUNKTIONIERT.

Vielen Dank an alle, die mir meinem Nachmittag doch noch gerettet haben!



Mit besten Grüßen

mateit

von Paul (Gast)


Lesenswert?

Hallo,

ich hab mal gerade den Display angeschlossen. Sehe ich das Richtig:

Bezogen auf: lcd_new.c & lcd_new.h

VSS          gnd
VDD          5V
V0           Poti

DB0          NC
DB1          NC
DB2          NC
DB3          NC

DB4          PC2
DB5          PC3
DB6          PC4
DB7          PC5
EN           PC0
RS           PC1
R/W          GND

#define F_CPU 8000000L

#define LCD_CONTROLLER_KS0073  1
#define LCD_LINES              2
#define LCD_DISP_LENGTH       20

int main(void)
{
    DDRC = 0xFF;


    lcd_init(LCD_DISP_ON);

    _delay_ms(50);

    for (;;) {

    lcd_clrscr();
    lcd_puts("Hello");

    }
}


Ich bekomme nur einen weißen Balken in der ersten Zeile.

Was mach ich Falsch / Was habe ich vergessen?

von Karl H. (kbuchegg)


Lesenswert?

Paul schrieb:

> #define F_CPU 8000000L
>
> #define LCD_CONTROLLER_KS0073  1
> #define LCD_LINES              2
> #define LCD_DISP_LENGTH       20


Was hast du mit
LCD_READ_REQUIRED
gemacht?

von Paul (Gast)


Lesenswert?

Ist auch auf 0 gesetzt.

von Hubert G. (hubertg)


Lesenswert?

Was hast du für einen Kontroller und wie ist die ganze Beschaltung. 
Vielleicht kannst du die ganze Schaltung posten.

von Paul (Gast)


Lesenswert?

Ja ist ein Atemga8 auf einem STK500. Die beschalteten Pins stehen im 
Beitrag oben. Mehr ist da an sich nicht.

Die +5V und GND kommen von einer externen Quelle, die durch einen 
5V-Spannungsregler geregelt wird.

Kann es vielleicht was damit zu tun haben, dass ich die +5V von STK500 
holen muss?

von spess53 (Gast)


Lesenswert?

Hi

Nein, aber die Masse.

MfG Spess

von Paul (Gast)


Lesenswert?

Könnte mal jemand einen funktionierenden bsp. Code und ein Schaltplan 
posten.

Ich weiß echt nicht mehr weiter. Beschaltung müsste stimmen, und am Code 
muss man doch nur paar Zeilen ändern und die Main Funktion einfügen.

Meine lautet zurzeit:

int main(void)
{
  DDRC = 0xFF;


    /* initialize display, cursor off */
    lcd_init(LCD_DISP_ON_CURSOR);

    //_delay_ms(50);



    for (;;) {                           /* loop forever */

    /* loesche das LCD Display und Cursor auf 1 Zeile, 1 Spalte */
    //lcd_clrscr();

    /* String auf Display anzeigen */
    lcd_puts("Hello");

    }
}

von holger (Gast)


Lesenswert?

>#define LCD_CONTROLLER_KS0073  1
>#define LCD_LINES              2
>#define LCD_DISP_LENGTH       20

Ich glaube kaum das ein 2x20 Display einen KS0073 hat.

#define LCD_CONTROLLER_KS0073  0

Was für ein Diplay benutzt du?

von Timo S. (kaffeetas)


Angehängte Dateien:

Lesenswert?

mal so nebenbei, bei dem Display stimmt (zumindest bei meinen 
Exemplaren) der angegebene Typ nicht mit dem bei Pollin verfügbaren 
Datenblatt überein!

Auf meinen Displays werkelt ein ‘NOVATEK’ NT3881DH-02/AI Controller. Man 
muss sich nur mal die Zeichen über 128 ansehen, dann merkt man schnell 
dass es kein KS0070BP-00CC ist sondern was anderes.

Bei mir funktioniern die Displays mit den Routinen von Peter Dannegger 
ohne Probleme.

Grüße
 Timo

von Paul (Gast)


Lesenswert?

Kann vielleicht jemand die Routinen hier rein stellen oder verlinken?

von Hubert G. (hubertg)


Lesenswert?

Du schreibst so schnell in das Display das es sein kann das du nichts 
siehst. Füge mal ein _delay_ms(200); ein.
Oder besser, schreibe dein Hello gleich nach der Initialisierung.

von Karsten (Gast)


Angehängte Dateien:

Lesenswert?

Hi Leute,

ich habe auch das BTHQ Display von Pollin mit 2x20Zeichen. Benutze auch 
die oben gepostete lcd-new library, lese aber das busy-flag aus. Ich 
habe das Display auch bereits in Betrieb gehabt, auf einer 
Streifenrasterplatine, aber die neu geätzte Platine ist genauso und das 
Display zeigt nichts mehr an. Nach der Initialisierung ist das Display 
einfach dunkel und ich kann keine Zeichen anzeigen lassen. Die 
Beschaltung ist:

DB0-DB7 : PC0-PC3
RS : PD6
E  : PD7
RW : PB2

Wie gesagt, vorher hat es wunderbar funktioniert, aber seit dem Aufbau 
auf eine neue Platine nicht mehr. Habe alle Verbindungen durchgemessen, 
keine Kurzschlüsse und kalte Lötstellen. Habe auch ein anderes Display 
angeschlossen, das zeigt nur einen Balken an. Irgendwas ist in der 
Initialisierung nicht vollständig, aber ich weiß nicht was.

Ich hoffe auf eure Unterstützung.
Viele Grüße,
Karsten
PS: Ich benutze AVR-gcc und AVR-Studio.

von Hubert G. (hubertg)


Lesenswert?

Wenn es schon mal funktioniert hat, dann sollte die SW in Ordnung sein.
Wohin geht der Kontrast, sieht man in der Schaltung nicht. Wenn beide 
Zeilen dunkel sind, ist das wohl eher der Fehler.

von Karsten (Gast)


Lesenswert?

Hallo Hubert,

danke, habe das Display auf meiner Streifenraster wieder in Betrieb 
nehmen können. Werde jetzt nach Leiterbahnenfehlern suchen müssen. 
Software scheint wirklich i.O. zu sein.

Kontrast ist soweit ok, kann man normal über ein Potentiometer 
einstellen, fehlt nur im Plan, ist rechts oben das übrig gebliebene 
R8... :)

Danke schonmal für die Antwort.

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.