PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : LCD & myavr weiss beim programmieren nicht weiter



schroejahr
26.09.2005, 21:38
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

schroejahr
26.09.2005, 21:42
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...

albundy
27.09.2005, 10:30
Hallo,

Zur Initialisierung ...

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_enable mit 5 Nop's bei 4 Mhz ist OK.

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

schroejahr
27.09.2005, 11:58
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 ?

schroejahr
27.09.2005, 12:28
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?



; 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

;------------------------------------------------------------>

[/code]

schroejahr
27.09.2005, 13:49
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

albundy
27.09.2005, 15:01
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 ?

Die Schleife wird 66 mal durchlaufen.
brne heißt: Springe zu Loop, solange R16 > 0 ist.


ldi r16, 0b00101000 ;2 Zeilen einstellen

Bei der Initialisierung mußt du wahrscheinlich 1 Zeile 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

schroejahr
27.09.2005, 18:01
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...

albundy
27.09.2005, 19:47
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


Das ist auch falsch.
Ldi r16, 0b00000001 ; Bit 0 muß auf "1"

schroejahr
27.09.2005, 21:37
super, danke für deine mühe, super dass es solche leute gibt, da fällt das lernen doch viel leichter... danke nochmal