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
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.
Danke für die schneller Antwort, aber da war ich schon und ich verstehe das nicht.
>Danke für die schneller Antwort, aber da war ich schon und ich verstehe >das nicht. Dann lern es zu verstehen!
Lad dir mal von http://www.c51.de/c51.de/Dateien/software.php?UIN= den Link "Buch_PraxisTeil2_Kap7.ZIP" herunter. Da ist eine funktionierende und dokumentierte Library drin, welche in Assembler geschrieben wurde (LCD_Lib_4BitPort.a51). Ciao, Rainer
Die Beispielroutine aus diesem Tutorial ist erprobt, funktioniert zuverlässig und schnell: http://www.8052.com/tutlcd
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?
@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
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.
Ist denn die Portbelegung richtig? keine Datenleitungen vertauscht?
Die Portbelegung ist richtig, ich habe alle durchgetestet.
moin moin, im Anhang meine LCD-Ansteuerung. Bitte die Anschlußbelegung beachten. MfG Pieter
Danke danke, für die Mühe, dennoch versteh ich leider gar nicht was du da programmiert hast. Kann ich das Programm von der Seite "http://8052.com/tut2lcd" nicht nehmen und einfach die Ports ändern? Bzw. Ich habe es schon versucht, jedoch ohne Erfolg.
moin moin, >>Mein Display funktioniert, da er die schwarzen Balken anzeigt. Falsch, da funktioniert gar nichts! Nur die Betriebsspannung liegt richtig an. Welcher 8051 mit welcher Taktfrequenz? MfG Pieter
>Kann ich das Programm von der Seite "http://8052.com/tut2lcd" nicht >nehmen und einfach die Ports ändern? Das ist am besten, da jeder Schritt genau erklärt ist. Aber für den Anfang würde ich Dir die 8-Bit Ansteuerung empfehlen.
Auf meiner CPU steht 80C552. Ich weiß nicht genau, ob das derselbe ist, wie der 8051 und die Taktfrequenz kenn ich auch nicht, wie finde ich diese heraus?
Taktfrequenz? Quarz anschauen. Ein normaler 8051 braucht allerdings 12 Takte für einen einfachen Befehl und ggf. mehr für einen komplexen, siehe Datenblatt.
Falls nicht schon bekannt, hier ist es: http://www.nxp.com/documents/data_sheet/80C552_83C552.pdf Ganz schön fettes Teil übrigens, für einen 8051er zumindest.
moin moin, also 80C552 habe ich auch ( 11,xxx und 22,xxx MHz Takt) mit diesem Code betrieben. MfG Pieter
>Ganz schön fettes Teil übrigens, für einen 8051er zumindest. ?? Ein 8051 mit 256 Byte RAM, 8k Rom, I2C, PWM, ... ist mittlerer Durchschnitt. Mein "Lieblingschip" aus den 8051ern ist der AT89C51AC3, der ist Oberklasse und kostet auch nur ~8-10$ (64k Flash, Bootloader ab Werk, EEProm, ...,...,...)
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
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
Hallo, welches der Programme muss ich denn von der "c51.de" seite nehmen? Buch_PraxisTeil2_Kap7.ZIP ??
#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
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=
@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.
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
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
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.
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.
Kann man das mit einem Port überhaupt realisieren oder benötige zwei Ports? Da auf der 8052 Seite zwei Ports angegeben werden, Port 1 und Port 3?!
>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.
Ich hatte noch vor einen Temperaturfühler zu bauen, aber ich danke dir erstmal Georg ich denke daran liegt es. Ich werde das mal ändern und mich nochmal melden. Wenn ich die 4 Bit Ansteuerung nehme geht es dann über einen Port?
>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.
@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.
Hallo, ich habe nun einen blinkenden Cursor angezeigt bekommen, ist er nun richtig initialisiert??
>ich habe nun einen blinkenden Cursor angezeigt bekommen, ist er nun >richtig initialisiert?? Ja. Schreib doch mal was rein.
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
@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
Ich habe es so ähnlich. Wenn ich deins nehme übernimmt er aber nicht push A & pop A ? -> Fehlermeldung Woran liegt das?
manche mögens heiss...ähh, Dein Assembler will eventuell ein ACC haben??
Alternativ kannst auch den Akkuinhalt in ein Register sichern oder Variable Variable Data 30h oder eines der Register R0 bis R7. Welchen Compiler verwendest Du eigentlich?
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.