eins noch : ich arbeite mit einem Atmega8, und externem 4mhz quartz, von daher bin ich mir bei dieser timing geschichte beim enable impuls nicht sicher...
Hallo, ich habe das myavr board, und habe mich mit dem tutorial von microkontroller.net beschäftigt.
Aber an zwei stellen weiss ich nicht weiter.
Ich habe keine ahnung wie ich das display initalisiere, angepasst an mein Anschlussmuster.
und ich weiss nicht wie ich die delays schreiben muss (5ms und 50us)
In den beiden dateien die ich anhänge (das tesprogramm und die lcd routinen), sollte alles zu finden sein,
ich denke ich bin auf dem richtigen weg, und bis dahin müsste alles stimmen...
Ich könnte natürlich einfach blind aus dem tutorial kopieren, würde aber lieber verstehen was ich da mache.
Ich würde mich sehr freuen, wenn jemand der schon erfahrung damit hat sich dieses kurz ansehen könte.
Danke.
Achso: das Display (16x2) ist HD44780 kompatibel und ich möchte es im 4 bit modus ansteuern.
MfG Georg
eins noch : ich arbeite mit einem Atmega8, und externem 4mhz quartz, von daher bin ich mir bei dieser timing geschichte beim enable impuls nicht sicher...
Hallo,
Zur Initialisierung ...
Lcd_enable mit 5 Nop's bei 4 Mhz ist OK.Code:lcd_init: rcall delay5ms ldi r16, 0b00110000 ;muss 3mal hintereinander gesendet out Portd, r16 ;werden zur Initialisierung rcall lcd_enable ;1 rcall delay5ms rcall lcd_enable ;2 rcall delay5ms rcall lcd_enable ;3 rcall delay5ms ldi r16, 0b00100000 ;4bit-Modus einstellen out Portd, r16 rcall lcd_enable rcall delay5ms ldi r16, 0b00101000 ;2 Zeilen einstellen... rcall lcd_command ldi r16, 0b00001100 ;Display an , Cursor u. Blinken aus rcall lcd_command ldi r16, 0b00000100 ;Increment ohne Display shift rcall lcd_command ret
Bei Lcd_data und Lcd Command, hast du einen Fehler drin.
Andi r16,0b00001111 setzt die oberen 4 Bits auf 0, nicht die unteren.
Die Warteschleifen kannst du entweder selbst ausrechnen oder mal nach
AVRdelayloop googeln. Das Programm erstellt aus der Quarzfrequenz und der Wartezeit den ASM Code.
Für 50µs bei 4 Mhz, mußt du 200 Takte warten. (1/4000000 = 0,25µs)
ldi r16,66
loop: dec r16
brne loop ; der Controller braucht 3 Takte pro Schleifendurchlauf
Danke ! daraus ergibt sich aber schon wieder eine frage :
mit brne lass ich die schleife 3mal durchlaufen ?
und wieso lädst du die 66 in r16 und wiederholst sie 3mal, anstatt direkt 200 hinein zu laden ?
Ich hab jetzt mal die änderungen vorgenommen, und mit dem delay generator eine schleife von 0,005sek (5ms) berechnet, wenn ich das programm brenne und starte passiert garnix...
und wenn ich in AVR studio simuliere scheint der beim lcd init festzustecken (in der ersten delay schleife, sieht so aus als würde der aus der schleife rauskommen und direkt wieder reingehen, wieso tut er das?
[/code]Code:; LCD Routinen ;;;;;;;;;;;;;;;;;; ;4 Bit Interface ;Pinbelegung LCD ; ; RS - portD 2 ; E - portD 3 ; RW - Masse (write = Low) ; DB4 - portD 4 ; DB5 - portD 5 ; DB6 - portD 6 ; DB7 - portD 7 ;soll das display initalisieren ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; lcd_init: rcall delay5ms ldi r16, 0b00110000 ;muss 3mal hintereinander gesendet out Portd, r16 ;werden zur Initialisierung rcall lcd_enable ;1 rcall delay5ms rcall lcd_enable ;2 rcall delay5ms rcall lcd_enable ;3 rcall delay5ms ldi r16, 0b00100000 ;4bit-Modus einstellen out Portd, r16 rcall lcd_enable rcall delay5ms ldi r16, 0b00101000 ;2 Zeilen einstellen... rcall lcd_command ldi r16, 0b00001100 ;Display an , Cursor u. Blinken aus rcall lcd_command ldi r16, 0b00000100 ;Increment ohne Display shift rcall lcd_command ret ;-----------------------------------------> lcd_data: ; soll daten an das LCD senden ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; erstmal das byte "sichern" mov r17, r16 ; dann die unteren bits im register auf 0 setzen andi r16, 0b11110000 ; danach RS (portD 2 auf High setzen) : sbr r16, 0b00000100 ; jetzt r16 nach portD ausgeben out PORTD, r16 ; nun muss nur noch die enable routine zum übergeben des halben bytes ausgeführt werden rcall lcd_enable ; das selbe dann jetzt nochmal nur mit nem swap davor, um jetzt die andere hälfte des bytes zu übertragen ; und vorher aber noch das andere byte aus dem backup register holen mov r16, r17 swap r16 andi r16, 0b11110000 sbr r16, 0b00000100 out PORTD, r16 rcall lcd_enable ;dann muss wohl noch eine delay routine ausgegeben werden, um ein paar millisekunden zu geben, ;damit das lcd die daten übernimmt, da ich ja R/W auf masse gelegt hab rcall delay50us ; und dann zurück zum programm ret ;------------------------------------------------------------> lcd_command: ; soll kommandos an das LCD senden, wie lcd_data, nur ohne rs zu setzen ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; mov r17, r16 andi r16, 0b11110000 out PORTD, r16 rcall lcd_enable ; und die zweite hälfte mov r16, r17 swap r16 andi r16, 0b11110000 out PORTD, r16 rcall lcd_enable rcall delay50us ; und dann zurück ret ;---------------------------------------------> lcd_enable: ;soll den enable impuls erzeugen ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; E auf High setzen (portD 3) sbi PORTD, 3 ; 5 taktzyklen warten nop nop nop nop nop ; E wieder auf low cbi PORTD, 3 ; und zurück ret ;--------------------------------------------------------------> lcd_clear: ;soll das Display löschen ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;DB4 (portD 4 auf 1 setzen, rest auf 0 ldi r16, 0b00010000 ;lcd_command ausführen rcall lcd_command ;5ms warten rcall delay5ms ;und zurück ret ;-------------------------------------------------------------> delay50us: ; um dem lcd dieplay entsprechende reaktinszeiten zu lassen: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; delaying 200 cycles, 50us bei 4mhz ldi R20, $42 WGLOOP0: dec R20 brne WGLOOP0 nop nop ret ;------------------------------------------------------------> delay5ms: ; um dem lcd dieplay entsprechende reaktionszeiten zu lassen: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; delaying 19998 cycles, bein 4mhz 0,005 sek ldi R20, $21 WGLOOP1: ldi R21, $C9 WGLOOP2: dec R21 brne WGLOOP2 dec R20 brne WGLOOP1 nop nop ret ;------------------------------------------------------------>
Hallo, ich nochmal ... hab grad schon mal einen fehler gefunden, ich habe die routinen am anfang eingebunden, so dass er direkt als erstes die routinen verarbeitet hat was ja nicht gehen kann *lichtaufgeh* jetzt gibt er vom programm zumindest schon mal was asu, allerdins immer was er will, mal ein "h", dann beim nächsten programmstart mal ein "L" oder auch mal hallo, aber er beginnt im display unten links und in umgekehrter reihen folge... irgendwas stimmt noch nicht
Die Schleife wird 66 mal durchlaufen.mit brne lass ich die schleife 3mal durchlaufen ?
und wieso lädst du die 66 in r16 und wiederholst sie 3mal, anstatt direkt 200 hinein zu laden ?
brne heißt: Springe zu Loop, solange R16 > 0 ist.
Bei der Initialisierung mußt du wahrscheinlich 1 Zeile einstellen.ldi r16, 0b00101000 ;2 Zeilen einstellen
(Wenn in deinem LCD Datenblatt steht 1.Zeile von $00 bis $0F und 2.Zeile von $10 bis $1F)
Versuch mal ldi r16,0b00100000 ;1 Zeile einstellen
ne, das ist es auch nicht, er gibt jetzt zwar oben links das zeichen aus, aber halt immer nur eins, und kein zweites.
zudem: wenn ich im AVR workpad das programm neustarte scheint das display_clear nicht richtig zu funktionieren, da oben links dann immer noch ein zeichen steht, und das programm dann nach lust und laune irgendwo auf dem display die komplette zeichekette ausgibt, aber nicht unbedingt zusammen, teilweise auch nur nen paar buchstaben...
Das ist auch falsch.Code:lcd_clear: ;soll das Display löschen ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;DB4 (portD 4 auf 1 setzen, rest auf 0 ldi r16, 0b00010000 ;lcd_command ausführen rcall lcd_command
Ldi r16, 0b00000001 ; Bit 0 muß auf "1"
super, danke für deine mühe, super dass es solche leute gibt, da fällt das lernen doch viel leichter... danke nochmal
Lesezeichen