8051 & Seiko L2432 mit HD44780A00 Chip

OP #1578640
Lesenswert?

Hallo,

ich habe einen 8051 Mikrocontroller und einen Seiko L2432 LC-Display mit 
dem HD44780 Chip (2*24).
Ich bin nicht der beste Programmierer :/. Ich bin gerade dabei in 
Assembler ein Programm zu schreiben.
Richtig angeschlossen habe ich ihn, er zeigt zunächst nur schwarze 
Balken in der 1. Zeile an.
Könnte mir jemand eine kleine Stütze geben. Das bisherige Programm habe 
ich mal beigefügt. Bitte Hilfe. Obwohl ich keine Ahnung habe ob dieses 
richtig ist.

#include <REG552.h>

CSEG at 8000h
Ljmp WRITE_DATA

DB4     EQU   P1.0
DB5     EQU   P1.1
DB6     EQU   P1.2
DB7     EQU   P1.3
RS      EQU   P1.4
RW      EQU   P1.5
EN      EQU   P1.6

;Um Daten zu schreiben
WRITE_DATA:
SETB RS            ; Rs auf 1
CLR RW          ; Rw auf 0
SETB EN          ; EN auf 1
SETB P1.0           ; P1.0 auf 1
SETB P1.1           ; P1.0 auf 1
SETB P1.2            ; P1.0 auf 1
SETB P1.3            ; P1.0 auf 1
CLR EN

;Init LCD
INIT_LCD:
CLR RS          ; Rs auf 0
CLR RW          ; Rw auf 0
CLR EN          ; En auf 0
SETB EN          ; En auf 1
MOV P1,#28h          ;
CLR EN           ; En auf 0
LCALL WAIT_LCD      ; Wait_lcd aufrufen
MOV A,#28h        ;
LCALL WAIT_LCD      ; Wait_lcd aufrufen
MOV A,#0Eh        ;
LCALL WAIT_LCD      ; Wait_lcd aufrufen
MOV A,#06h        ;
LCALL WAIT_LCD      ; Wait_lcd aufrufen
RET

;Warten
WAIT_LCD:
CLR RS           ; Rs auf 0
SETB RW         ; Rw auf 1
CLR RW          ; Rw auf 0
RET               ; reset

;LCD löschen
CLEAR_LCD:
CLR RS            ; Rs auf 0
MOV A,#00h          ; Zeile löschen
RET            ; reset

END
Persönliche Seite #1578648
Lesenswert?

Hier mal ein paar Denkanstösse:
1
WAIT_LCD:
2
CLR RS           ; Rs auf 0
3
SETB RW         ; Rw auf 1
4
CLR RW          ; Rw auf 0
5
RET               ; reset
Hier wartest du nicht, du änderst einfach nur ein paar Pins.
1
;LCD löschen
2
CLEAR_LCD:
3
CLR RS            ; Rs auf 0
4
MOV A,#00h          ; Zeile löschen
5
RET            ; reset
Hier setzt du einzig RS auf 0 und löschst den Akku, macht am Display gar 
nichts.

Google doch einfach mal nach 8051 LCD oder 8051 HD44780, auf 8051.com 
gibts einen super ASM-Code.
Gast #1579892
Lesenswert?

@justin


hiermal meine Variante!

;LCD_Port                     DATA     P2
;LCD_EN                       BIT      LCD_Port.4
;LCD_RW                       BIT      LCD_Port.5
;LCD_RS                       BIT      LCD_Port.6
;LCD_Backlight                BIT      LCD_Port.7
;LCD_D4                       BIT      LCD_Port.3
;LCD_D5                       BIT      LCD_Port.2
;LCD_D6                       BIT      LCD_Port.1
;LCD_D7                       BIT      LCD_Port.0
;LCD_buffer                   DATA     30h
;Offsets für 4x20 Zeilliges Display
;Zeilen_Offset0               EQU      0h
;Zeilen_Offset1               EQU      40h
;Zeilen_Offset2               EQU      14h
;Zeilen_Offset3               EQU      54h

;Konstanten
;_LCD_DDRAM                   EQU      80h
;_LCD_CGRAM                   EQU      40H
;_LCD_AUS                     EQU      08h
;_LCD_EIN                     EQU      0Ch   ;Display an, Cursor 
unsichtbar
;_LCD_Loeschen                EQU      01h
;_LCD_ReturnHome              EQU      02h   ;Der Cursor wird an die 
erste Position im Display gesetzt
;_LCD_Betriebsart             EQU      06h   ;Entry Mode Set
;_LCD_DSP_RechtsBewegen       EQU      1Ch   ;Display Shift
;_LCD_DSP_LinksBewegen        EQU      18h   ;Display Shift
;_LCD_Cursor_RechtsBewegen    EQU      14h   ;Cursor  Shift
;_LCD_Cursor_LinksBewegen     EQU      10h   ;Cursor  Shift
;_LCD_Schnitstellenbreite     EQU      14h   ;Function-Set 4 Bit 
Interface, 2 Zeilen, Font 5 x 8 Dots


LCD_INIT:

   CALL  LCD_Pause_15ms
   MOV   A,#30h
   CALL  LCD_Intialisieren
   CALL  LCD_Pause_4ms
   MOV   A,#30h
   CALL  LCD_Intialisieren
   CALL  LCD_Pause_4ms
   MOV   A,#30h
   CALL  LCD_Intialisieren
   CALL  LCD_Pause_4ms
   MOV   A,#20h
   CALL  LCD_Intialisieren
   CALL  LCD_Pause_4ms
   MOV   A,#_LCD_Schnitstellenbreite
   CALL  LCD_Komando
   MOV   A,#_LCD_AUS
   CALL  LCD_Komando
   MOV   A,#_LCD_Loeschen
   CALL  LCD_Komando
   LCALL LCD_Pause_15ms
   MOV   A,#_LCD_ReturnHome
   CALL  LCD_Komando
   MOV   A,#_LCD_Betriebsart
   CALL  LCD_Komando
   MOV   A,#_LCD_EIN
   CALL  LCD_Komando
RET
OP #1579904
Lesenswert?

Hallo Klaus,
danke für die schnelle Antwort.
Ich habe das Display an dem P1 angeschlossen und ihn so angeschlossen:

DB4     EQU   P1.0
DB5     EQU   P1.1
DB6     EQU   P1.2
DB7     EQU   P1.3
RS      EQU   P1.4
RW      EQU   P1.5
EN      EQU   P1.6

So steht das in meiner 4-Bit Datenbus Anleitung:

1. ³15ms warten, nachdem Betriebsspannung min.
+4,5V erreicht hat.

2. 3?h1 ins Steuerregister (RS=0) schreiben

3.  ³4,1ms warten

4. 3?h ins Steuerregister (RS=0) schreiben

5. ³100μs warten

6. 3?h ins Steuerregister (RS=0) schreiben

7. ab hier vor jedem Zugriff das Busy-Flag prüfen

8. auf 4-Bit Datenbus umstellen: 2?h ins Steuerregister
(RS=0) schreiben. Ab hier erfordert jeder Zugriff
zwei Schreib- bzw. Lesezyklen, zuerst für die Bits
7…4, danach für die Bits 3…0 eines jeden Bytes.

9.  Befehl System Set (s.u.) ins Steuerregister schreiben:
bei einzeiligen Displays im allgemeinen [2?h, 0?h],
bei mehrzeiligen [2?h, 8?h]

10. Die Befehle Display on/off, Clear display, Cursor
home und Entry mode set (s.u.) mit den
gewünschten Einstellungen schreiben

Das ist wie auf der 8052.com Seite, dennoch funktioniert das nicht. Ich 
möchte ja lediglich erstmal ein A, B, oder C anzeigen lassen, der Rest 
kommt dann denke ich von alleine.
Gast #1580270
Lesenswert?

moin moin,

das ist nun aber eine andere Baustelle, ich benutze den Silabs 
C8051F340...
zuviele Leckerbissen um sie hier aufzuzählen...

@Justin,

böse Frage: Hast Du schon mal mit dem 80C552 eine LED blinken lassen?


MfG
Pieter
#1580271
Lesenswert?

Justin B. schrieb:
> Hallo,
> danke für die Hilfe, allerdings habe ich das schon getestet und das
> funktioniert nicht wirklich. Mein Display funktioniert, da er die
> schwarzen Balken anzeigt. Kann mir da nicht jemand weiterhelfen?

Hast du die Version von www.c51.de mal getestet?
Ich benutze die schon seit etlichen Jahren in diversen Projekten und die 
funktioniert völlig fehlerfrei. Dort kannst du einfach den Port angeben, 
an welchem das LCD dranhängt.
Also wenn du das LCD damit nicht zum laufen bekommst, dann liegt es aber 
definitiv nicht an der der Lib.

Eventuell solltest du dich erst mal etwas mehr mit den Basics des 
Controllers beschäftigen, um sicher zu gehen, dass du auch die 
Arbeitsweise richtig verstanden hast. ;)

Ciao,
     Rainer
OP #1580322
Lesenswert?

#define USED_LCDPORT  P2
sbit LCD_D0 = USED_LCDPORT ^4;
sbit LCD_D1 = USED_LCDPORT ^5;
sbit LCD_D2 = USED_LCDPORT ^6;
sbit LCD_D3 = USED_LCDPORT ^7;

sbit LCD_EN = USED_LCDPORT ^0;
sbit LCD_R_W= USED_LCDPORT ^1;
sbit LCD_RS = USED_LCDPORT ^2;

So steht das in der Datei und bei mir sind sie so belegt:

DB4     EQU   P1.0
DB5     EQU   P1.1
DB6     EQU   P1.2
DB7     EQU   P1.3
RS      EQU   P1.4
RW      EQU   P1.5
EN      EQU   P1.6

*************************************************************

Ist das dann so korrekt?

#define USED_LCDPORT  P1
sbit LCD_D0 = USED_LCDPORT ^0;
sbit LCD_D1 = USED_LCDPORT ^1;
sbit LCD_D2 = USED_LCDPORT ^2;
sbit LCD_D3 = USED_LCDPORT ^3;

sbit LCD_EN = USED_LCDPORT ^6;
sbit LCD_R_W= USED_LCDPORT ^5;
sbit LCD_RS = USED_LCDPORT ^4;


Und wo müsste ich noch etwas ändern? Danke
#1580362
Lesenswert?

Das ist leider die einzige Einschränkung in dieser LCD Lib, dass du nur 
den Port einstellen kannst. Die Zuordnung der Pins ist leider nicht 
veränderbar. Die Pindefinitionen zu Beginn sind nur dazu da um im Code 
die Bits ansprechen zu können. Aber teilweise wird auch der gesamte Port 
direkt angesprochen, was eine feste Pinzuordnung vorraussetzt. Ich 
benutze eben immer genau diese Pinzuordnung, wie sie auch am Anfang der 
Assemblerdatei definiert wird. Falls sich die Pinzuordnung in deiner 
Hardware nicht mehr ändern lässt, dann wird dir diese Lib, ohne sie 
umzuschreiben, leider nicht viel nützen. :/

Aber insofern du Keil µVision als Entwicklungsumgebung benutzt kannst du 
unter [1] dir das Plugin "lcd.zip" herunterladen. Damit kannst du 
sämtliche HD44780 LCDs direkt in µVision simulieren und somit deinen 
Code testen ohne ihn erst auf die Hardware aufspielen zu müssen. Die 
Pinzuordnung bei diesem Plugin ist frei wählbar und es wird auch das 
Timing korrekt simuliert. In der Demo Version ist die Simulations-DLL 
zwar eingeschränkt auf den 4Bit Modus, aber das reicht für deinen Zweck 
ja auch aus. Und in "lcd_demo.zip" auf der gleichen Seite gibt es sogar 
komplett fertige Beispielprojekte dafür.

Ciao,
     Rainer

[1] http://www.c51.de/c51.de/Dateien/LCD.php?UIN=
Gast #1580739
Lesenswert?

@Justin
Ich hoffe dir ist schon klar das man pro Datenbyte/Befehl das High und 
Low- nibble senden musst. Also im 4-Bit-Modus.
Und jweils dann das Enable setzen und wieder rücksetzen.
Das Busyflag würd ich jetzt als Anfänger noch nicht abfragen, weil wenn 
die Busyflagabfrage nicht richtig funzt bleibt der µC in dieser Routine 
hängen. Mach lieber ein paar Delays rein.
Als erstes musst Du die Initalisierung hinbekommen.

Zeig mal deine Routine wie du Befehle bzw. Daten sendest. Also dein 
selbst geschriebener Code.
OP #1581528
Lesenswert?

So muss ich das initialisieren:

1. ³15ms warten, nachdem Betriebsspannung min.
+4,5V erreicht hat.

2. 3?h1 ins Steuerregister (RS=0) schreiben

3.  ³4,1ms warten

4. 3?h ins Steuerregister (RS=0) schreiben

5. ³100µs warten

6. 3?h ins Steuerregister (RS=0) schreiben

7. ab hier vor jedem Zugriff das Busy-Flag prüfen

8. auf 4-Bit Datenbus umstellen: 2?h ins Steuerregister
(RS=0) schreiben. Ab hier erfordert jeder Zugriff
zwei Schreib- bzw. Lesezyklen, zuerst für die Bits
7…4, danach für die Bits 3…0 eines jeden Bytes.

9.  Befehl System Set (s.u.) ins Steuerregister schreiben:
bei einzeiligen Displays im allgemeinen [2?h, 0?h],
bei mehrzeiligen [2?h, 8?h]

10. Die Befehle Display on/off, Clear display, Cursor
home und Entry mode set (s.u.) mit den
gewünschten Einstellungen schreiben


Das ist meine Initialisierung, ist die richtig?:

DB4     EQU   P1.0
DB5     EQU   P1.1
DB6     EQU   P1.2
DB7     EQU   P1.3
RS      EQU   P1.4
RW      EQU   P1.5
EN      EQU   P1.6

INIT_LCD:
 CLR   RS
 CLR   RW
 CLR   EN
 SETB  EN
 MOV   P1,#28h
 CLR   EN
 lcall warten
 MOV   A,#28h
 lcall warten
 MOV   A,#0Eh
 lcall warten
 MOV   A,#06h
 lcall warten
 RET

warten:
  CLR RS
  SETB RW
  JB ACC.7, warten
  CLR RW
  RET

Gruß jusbu
OP #1581546
Lesenswert?

Danke für die Antwort!

Hier her:

LESE_2_NIBBLE:
 ORL   P1,#0F0h        ; "oder"
 SETB  EN
 MOV  A,P1    ;schreibe P1 in A
 CLR   EN
 ANL  A,#0F0h
 PUSH  ACC    ;speicher wird um 1 erhoeht und abgelegt
 SETB  EN
 MOV   A,P1
 CLR   EN
 ANL   A,#0F0h       ; "UND"
 SWAP  A             ; vertauschen
 MOV   R7,A
 POP   ACC            ;uebertrage inhalt durch speicher und -1
 ORL   A,R7
 RET

SCHREIBE_2_NIBBLE:
 PUSH  ACC
 ORL   P1,#0F0h
 ORL   A,#0Fh
 ANL   P1,A
 SETB  EN
 CLR   EN
 POP   ACC
 SWAP  A            ; vertauschen
 ORL   P1,#0F0h    ; 4 - 7
 ORL   A,#0Fh       ; 0 bis 3
 ANL   P1,A
 SETB  EN
 CLR   EN
 RET
Gast #1581551
Lesenswert?

Du weißt anscheinend gar nicht, was Du tust.
z.B.:

> MOV   A,#28h
> lcall warten

Du schreibst #28h in den Akku und dann? Wie kommt der Inhalt des Akkus 
zum
LCD?

Weiter oben hat Dir schon einer das Tutorial auf 8052.com empfohlen.
Ich rate Dir dringend, genau danach vorzugehen.
Alles andere hat keinen Zweck. Und informier Dich vor allem über
den µC selbst, Du hast leider absolut keine Ahnung, was da überhaupt 
passiert.
Gast #1581557
Lesenswert?

Ich habe Deine Antwort erst gelesen, nachdem ich meinen Beitrag 
abgeschickt
habe.

Viel zu kompliziert. Nimm einfach den 8-Bit-Mode, dann kannst Du Dir
die ganze Swapperei sparen. Dein Programm sollte am Anfang so einfach 
wie möglich sein.
Gast #1581621
Lesenswert?

>Kann man das mit einem Port überhaupt realisieren oder benötige zwei 2
>Ports?
>Da auf der 8052 Seite zwei Ports angegeben werden Port 1 und Port 3?!

Klar, Du brauchst einen ganzen Port für die Daten und noch 3 Portpins
für die Steuersignale. Ist das denn ein Problem? Der 552 hat doch 
genügend
Ports; Du willst ja nur das LCD ansteuern.
Gast #1581640
Lesenswert?

>Wenn ich die 4 Bit Ansteuerung nehme geht es dann über einen Port?

Natürlich. Ich verstehe aber nicht, warum Du bei so einem Port-Monster
wie dem 552 so knauserig mit den Ausgängen sein willst.

Die ganze Ausgaberoutine, die Du für Deine 4 Bit geschrieben hast
reduziert sich beim 8-Bit-Modus auf wenige Zeilen.
Gast #1581666
Lesenswert?

@Justin
>INIT_LCD:
> CLR   RS
> CLR   RW
>CLR   EN
>SETB  EN
> MOV   P1,#28h
> CLR   EN
> lcall warten
> MOV   A,#28h
> lcall warten
> MOV   A,#0Eh
> lcall warten
> MOV   A,#06h
> lcall warten
> RET

>warten:
> CLR RS
> SETB RW
> JB ACC.7, warten
> CLR RW
> RET

Was soll das?  Das entspricht nicht was du schriftlich niedergelegt 
hast.
Also am Anfang musst 3 mal hintereinander 30h senden.
das mach ich mit der Routine.
LCD_Intialisieren:
   CLR   LCD_RS
   CLR   LCD_RW
   SWAP  A
   ANL   A,#0Fh
   MOV   C,A.0
   MOV   LCD_D4,C
   MOV   C,A.1
   MOV   LCD_D5,C
   MOV   C,A.2
   MOV   LCD_D6,C
   MOV   C,A.3
   MOV   LCD_D7,C
   SETB  LCD_EN
   NOP
   CLR   LCD_EN
RET

und für den Rest mach ich das über die Routine
LCD_Komando:
   PUSH  PSW
   PUSH  A
   PUSH  B
   LCALL LCD_Busy
   MOV   B,A
   SWAP  A
   ANL   A,#0Fh
   MOV   C,A.0
   MOV   LCD_D4,C
   MOV   C,A.1
   MOV   LCD_D5,C
   MOV   C,A.2
   MOV   LCD_D6,C
   MOV   C,A.3
   MOV   LCD_D7,C
   CLR   LCD_RS
   CLR   LCD_RW
   NOP
   SETB  LCD_EN
   NOP
   CLR   LCD_EN
   LCALL LCD_Busy
   MOV   A,B
   ANL   A,#0Fh
   MOV   C,A.0
   MOV   LCD_D4,C
   MOV   C,A.1
   MOV   LCD_D5,C
   MOV   C,A.2
   MOV   LCD_D6,C
   MOV   C,A.3
   MOV   LCD_D7,C
   CLR   LCD_RS
   CLR   LCD_RW
   NOP
   SETB  LCD_EN
   NOP
   CLR   LCD_EN

   POP   B
   POP   A
   POP   PSW
RET

und die Busyflagabfrage die da!
LCD_Busy:
      ORL   LCD_Port,#00001111b  ;Port auf Eingang schalten ausser EN 
etc. sonst gehts nicht
      CLR   LCD_RS               ;Wollen Busy Flag abfragen keine 
Zeichen
      SETB  LCD_RW
    _LCD_busy:
      SETB  LCD_EN               ;Zum einlesen setzen
      MOV   C,LCD_D7             ;Busy Flag einlesen
      CLR   LCD_EN               ;Übernahme
      SETB  LCD_EN               ;Enable nochmal toggeln
      CLR   LCD_EN
      JC   _LCD_busy             ;Wenn BF <> 0 nochmal abfragen
      ANL   LCD_Port,#11110000b  ;LCD_Port wieder als Augang schalten
      CLR LCD_RW
    $END IF
RET

So im Prinzip hast jetzt alles damit du dein LCD initialisieren kannst.
#1581857
Lesenswert?

Also nichts für Ungut, aber du solltest dich wirklich erst mal etwas 
mehr mit dem Controller, seiner Programmierung und dem internen Aufbau 
des Displays auseinandersetzen, bevor du diese programmieren willst. Bei 
deinen diversen Assembler Codebeispielen sieht man deutlich, dass es dir 
am Verständnis der Programmiersprache fehlt. Und ohne passende 
Vorkenntnisse bleibt deine gesamte Programmierung ein Try&Error 
Verfahren anstatt auf Wissen zu basieren. Es gibt viele Tutorials zu 
8051ern anhand derer man die Programmiersprache schnell erlernen kann.

Ciao,
     Rainer
Gast #1581883
Lesenswert?

@Justin
Wie sieht dein Code zum senden eines Zeichen denn aus?

Vorschlag!
Zeichen_senden:
clr RS
clr RW
clr EN
mov A,#"G"       ; Zeichen G soll am Dsplay ausgegeben werden
push A           ; erst mal sichern
swap A           ; high-lowbyte vertauschen
anl  A,#0Fh      ; Higbyte isolieren
mov  P1,A        ; an Port ausgeben
setb RS          ; setzen! willst ja Zeichen senden
nop
setb EN
nop
clr  EN
pop  A
anl  A,#0Fh     ; lowbyte isolieren
mov  P1,A       ; an Port ausgeben
nop
setb EN
nop
clr  EN
clr  RS
ret

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren