PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Atmega 8 verzögerungsschleifen?



Mr Bean
27.07.2006, 10:44
Hallo wie ihr seht bin ich neu hier, will zuerst kurz was über mich sagen. ich habe eine Ausbildung zum Elektromechaniker gemacht und hab als Servicetechniker gearbeitet. Nun habe ich gerade angefangen in Konstanz Wirtschaftsingenieurwesen Elektrotechnik zu studieren.

So nun zu meiner eigentlichen Frage:

Ich beschäftige mich schon einige Zeit mit dem Atmega8 und bin über das LED lauflicht Stadium hinaus... :-) Jetzt will ich ein LCD Display ansteuern. Ich habe mir dazu die LCD Routines von www.mikrocontroller.net besorgt. Dort sind die Schleifen für die Verzögerung aber auf ein 4 MHz Takt ausgelegt. Ich habe auf meinem Board aber ein 12 MHZ Quarz. wie kann ich die Werte die in das Register geladen werden nun umrechen? Ich häng die Schleifen einfach mal an damit ihr das seht. Außerdem würde ich gerne wissen was das "$" Zeichen bedeutet. Ich hab bis jetzt nämlich einfach immer Binäre Werte oder eben Dezimale Werte in die Register geladen.

Vielen Dank schonmal im Voraus!!!

MFG

Mr Bean

delay50us: ;50us Pause

ldi temp1, $42
delay50us_: dec temp1
brne delay50us_
ret ;wieder zurück

delay 5ms: ;5ms Pause

ldi temp1, $21
WGLOOP0: ldi temp2, $C9
WGLOOP1: dec temp2
brne WGLOOP1
dec temp1
brne WGLOOP0
ret ;wieder zurück

PicNick
27.07.2006, 11:20
"$" das ist hexadezimal. $42 ==> 4*16^^1 + 2*16^^0 ==> dez. 66

Bei solchen Schleifen werden Maschinenzyklen verbraten.
Bei 4 MHZ sollten es für 50 µS also 50*4 --> 200 Zyklen sein.
Und dazu mußt du du Zyklen jedes Befehls in der schleife zusammenrechnen

LDI temp1, $42 ---> 1 Zyk.
delay50uS:
DEC temp1 ---> 1 Zyk.
BRNE delay50uS springen 2 Zyk, nicht springen 1 Zyk
d.h. 1 * 2 + (temp1-1) * 3

insgesamt also
1 + 2 + 65 * 3 --> 197 Zyklen

FÜr 12 MHZ brauchst du offenbar 3-mal soviele Zyklen. Also, Bleistift raus und rechnen :-)

27.07.2006, 13:28
Vielen Dank erstnal für die Antwort! Hab meine Schleifen jetzt um gemodelt. Das sollte nun eigentlich ncihtmehr das Problem sein. Trotzdem bin ich so langsam am verzweifeln. Versuche den ganzen Tag schon dieses Display zum laufen zu bekommen. Aber es will nicht wie ich will. Ich hab jetzt mal meinen Code angehängt. Wie das Display an den Controller angeschlossen ist steht auch da drin. Vielleicht kann mir ja jemand weiterhelfen. Würde mich sehr freuen.

MFG

Mr Bean


.include "m8def.inc"

.def temp1 = r16
.def temp2 = r17
.def temp3 = r18

ldi temp1, LOW(RAMEND) ;LOW-Byte der obersten RAM-Adresse
out SPL, temp1
ldi temp1, HIGH(RAMEND) ;High-Byte der obersten Ram-Adresse
out SPH, temp1

ldi temp1, 0xFF ;PortB=Ausgang
out DDRB, temp1

rcall lcd_init ;Display initialisieren
rcall lcd_clear ;Display löschen

ldi temp1, 'T' ;Zeichen anzeigen
rcall lcd_data

ldi temp1, 'e'
rcall lcd_data

ldi temp1, 's'
rcall lcd_data

ldi temp1, 't'
rcall lcd_data

loop:
rjmp loop



; LCD Routinen

;4-Bit Interface
;BDB4-BDB7: PB0 - Pb3
;RS: PB4
;E: PB7

;sendet ein DAtenbyte an das LCD

lcd_data:
mov temp2, temp1 ;"Sicherungskopie" für die Übertragung des zweiten Nibbles
swap temp1 ;vertauschen
andi temp1, 0b00001111 ;oberes Nibble auf 0 setzen
sbr temp1, 1<<4 ;entspricht 0b00010000
out PORTB, temp1 ;ausgeben
rcall lcd_enable ;Enable-Routine aufrufen


andi temp1, 0b00001111 ;obere Hälfte auf null setzen
sbr temp2, 1<<4 ;entspricht 0b00010000
out PORTB, temp2 ;ausgeben
rcall lcd_enable ;enable routine aufrufen
rcall delay50us ;Delay routine aufrufen
ret ;zurück zum Hauptprogramm

;sendet einen Befehl an das LCD

lcd_command: ;wie lcd_data, nur ohne RS zu setzen

mov temp2, temp1
swap temp1
andi temp1, 0b00001111
out PORTB, temp1
rcall lcd_enable
andi temp2, 0b0001111
out PORTB, temp2
rcall lcd_enable
rcall delay50us
ret

;erzeugt den Enable-Puls

lcd_enable:

sbi PORTB, 7 ;Enable high
nop ;6 Taktzyklen warten
nop
nop
nop
nop
nop
nop
nop
nop
cbi PORTB, 7 ;Enable wieder low
ret ;wieder zurück

;Pause nach jeder Übertragung

delay50us: ;50us Pause

ldi temp1, $E9
WGLOOP0: dec temp1
brne WGLOOP0
ret ;wieder zurück

;Längere Pause für manche Befehle

delay5ms: ;5ms Pause

ldi temp1, $8F
WGLOOP2: ldi temp2, $E7
WGLOOP3: dec temp2
brne WGLOOP3
dec temp1
brne WGLOOP2

ldi temp1, $01
WGLOOP4: dec temp1
brne WGLOOP4

ret ;wieder zurück

;Initialisierung: muss ganz am Anfang des Programms aufgerufen werden

lcd_init:
ldi temp3,50
powerupwait:
rcall delay5ms
dec temp3
brne powerupwait
ldi temp1, 0b00000011 ;muss 3 mal hintereinander gesendet werden zur Initialisierung
out PORTB, temp1 ;1
rcall lcd_enable
rcall delay5ms
rcall lcd_enable ;2
rcall delay5ms
rcall lcd_enable ;3
rcall delay5ms
ldi temp1, 0b00000010 ;4Bit Modus einstellen
out PORTB, temp1
rcall lcd_enable
rcall delay5ms
ldi temp1, 0b00101000
rcall lcd_command
ldi temp1, 0b00001100
rcall lcd_command
ldi temp1, 0b00000100
rcall lcd_command
ret

;sendet einen Befehl zur Löschung des Displays

lcd_clear:

ldi temp1, 0b00000001 ;Display Löschen
rcall lcd_command
rcall delay5ms
ret

Lektor
27.07.2006, 18:45
Also LCD's bringen mich eigentlich auch immer zum verzweifeln. Habe es zwar über die parallele Schnittstelle und einen PC-Programm geschafft Schrift auszugeben, aber mit dem µC noch nicht.

Schreib mal bitte welches LC-Display du hast, weil manche mit der Routine von Mikrocontroller.net nicht funktionieren. Das Problem hatte ich nämlich auch und habe mich sehr lange daran versucht.

Aber dieses Problem, welches hier angesprochen wurde, muß doch irgendwie zu beheben sein. Meistens hat man ja nicht ausreichend Timerinterrupts und Schleifen sind auch eher unschön. Gibt es keine bessere Möglichkeit?

Wäre es möglich mit einem Programm die Timerzeiten immer neu zu berechnen und den Timer neu einzustellen.
Beispiel:
Aufgabe 1: Interrupt soll nach zwei Minuten auslösen
neue Aufgabe 2 kommt nach einer Minute hinzu und soll nach 30sek den Interrupt auslösen.

Dadurch muß der Timerwert nach einer Minute von einer Minute Restzeit auf 30sek gestellt werden und nach Ablauf von Aufgabe 2 die letzten 30sek wieder in den Timerwert geschrieben werden, damit die Zeit für Aufgabe 1 weiterläuft.
Vielleicht geht es eleganter, indem man einen externen Takt zählt, der halt nicht 12MHz beträgt.

Dieses Schleifenproblem wird mit steigender Frequenz immer größer und deswegen sollte man hierfür vielleicht eine Lösung finden. ;)

uwegw
27.07.2006, 18:47
Ein kleines Programm, um die Verzögerungsschleifen zu berechnen:
http://www.elektronik-projekt.de/include.php?path=content/download.php&contentid=183

Hanni
27.07.2006, 23:15
Der sauberste Weg Leerlaufzeiten zu überbrücken ist übrigens über einen Timer .....

Lektor
28.07.2006, 10:33
das denke ich auch, aber davon hat man leider nicht unbegrenzt viele und wenn man den Takt nicht in Form von ca. 1KHz extern bereitstellt, dann wird man leider auch bei Zeiten von einigen Sekunden auf Registerinkrementieren zurückgreifen müssen, wodurch der Timerinterrupt mehrmals auslöst. Das ist auch nicht gerade optimal. Vielleicht gibt es ja Timer-IC's die 30 Timer beinhalten und die man über I2C beschreiben kann, damit der µC seine Rechenkapazität an Schleifen verschwenden muß. ;)

Mr Bean
28.07.2006, 11:50
Hallo

Vielen Dank nochmal für die Antworten. Zuersteinmal es ist ein 2 Zeilen Display mit 16 Zeichen. Ich hab es bei Reichelt gekauft und es scheint von Displaytech zu sein. Als IC ist ein KS0070B.PCC drauf. Denke aber eher nicht daß das Problem beim Display liegt. Wohl eher an der Software... 8-[ Naja Die Diskusion um die Schleifen ist ja nicht schlecht. Ich weiß auch, daß das nicht gerade die sauberste Art ist zu programmieren. aber im Moment will ich eigentlich nur mal soweit kommen daß ich ein paar Zeichen auf dem Display erscheinen lassen kann. Und das sollt sich doch eigentlich so machen lassen. Ich weiß so langsam aber echt nichtmehr wo der Fehler noch liegen könnte... Gibt es eine Möglichkeit zu Testen Ob die Hardware (Display) defekt ist? Wenn ich das Display an µC anschließe, dann erscheint ein schwarzer Balken in der ersten Zeile. Ich hoffe da immernoch etwas auf euch... 8-[

MFG

Bean

Lektor
28.07.2006, 12:33
Also ich habe ein LCD von Electronic Assembly. EA DIP204-4NLED (Reichelt: LCD 204 DIP) mit einem KS0073 Kontroller drauf und bei dem funktioniert die Mikrocontroller.net-Ansteuerung NICHT. Bei dem muß ich andere Timings verwenden oder andere Befehle benutzen.
Habe mir dann von Pollin noch ein anderes günstiges Display geholt; WDC2704M und bei dem soll angeblich die Ansteuerung funktionieren.
Das dein Display schwarze Zeilen anzeigt ist ein gutes Zeichen, denn das tut er, wenn er nicht richtig initialisiert wurde.
Also am besten mal deinen Code mit dem Datenblatt des Displays vergleichen und schauen, ob die Warteschleifen richtig sind und die Befehle auch richtig sind.

Durchmessen kann man eher schlecht. Könntes den Stromverbrauch messen. Wenn der zu hoch ist, dann ist das Display wohl defekt (Größenordnung 1A wurde mir von EA gesagt). Aber das schliesse ich eher aus.
Was ich nicht ganz verstehe ist, warum ich wenn ich nur Spannung und Kontrastspannung anlege, auf unterschiedlichen Leitungen etwas messe. Die Leitungen muß ich ja mit dem µC ansteuern und wie soll das gehen, wenn auf einigen Leitungen schon Spannung vorhanden ist. Das verwundert mich bei beiden Displays.
Habe die Displays erstmal in die Kiste geworfen weil ich mir nicht länger die Zähne daran ausbeissen möchte. Wenn du eine funktionierende Routine hast, dann poste mal bitte den Code. Vielleicht läuft er ja auch auf meinen LCDs
Man weiss ja dummerweise auch nie, an welcher Stelle der Fehler ist.

Mr Bean
28.07.2006, 13:25
Hallo

Ich glaube mir ist gerade etwas eingafallen wo der Fehler liegen könnte. Und zwar betreibe ich das LCD ja im 4-Bit Modus. dann muss ich doch bei der Initialisierungs routine die nibbles (4Bit) der Datenwörter auch erst vertauschen? (siehe oben in meinem Code) Hab jetzt grad leider keine Zeit zum das zu probieren, werd am Wochenende hoffentlich dazu kommen. Wenn mir jemand diesen Fehler bestätigen könnte wäre das natürlich auch klasse...

MFG

Bean

29.07.2006, 02:46
Zitat:
"Wenn ich das Display an µC anschließe, dann erscheint ein schwarzer Balken in der ersten Zeile".
Die Kontrastspannung, meist VEE genannt, darf nicht direkt mit der Versorgungsspannung oder GND verbunden werden. Meist hängt ein Poti
10 kOhm zwischen der Versorgungsspannung und GND und der Abgriff an VEE. Damit stellt man den Kontrast erst mal so ein, das die Display Zeile gerade beginnt dunkel zu werden.
Des Weiteren kann dein Programm einfach zu schnell sein.( Code nicht gecheckt). Man kann den display controller abfragen ob er "Busy" ist indem man seine Daten liest und prüft ob das "Busy Flag" gesetzt ist (Bit 7).
Wenn Daten / Commands kommen wärend der Controller beschäftigt ist, dann gibt es meistens Mist.

Mr Bean
29.07.2006, 11:43
Hallo

Der Kontrast kann nicht das Problem sein, habe schon von Anfang an ein Poti drin und habe auch nach jedem neuen Programm versucht ob es am Kontrast liegt.

Wie kann ich jetzt herausbekommen ob mein Programm zu schnell ist?

Kann es sein daß die Taktfrequenz von 12 MHz einfach zu hoch ist? Wenn ja wie kann ich das ändern? Ich meine auf die schnelle, hab grad leider kein langsameres Quarz da... Werd mir aber mal ein 4 Mhz Quarz besorgen.

MFG

Bean

Lektor
29.07.2006, 16:28
du hast doch die ganzen Warteschleifen auf 12MHz angepasst, weil sie wohl für 4MHz gedacht waren, oder? Sonst kann es auch nicht funktionieren.
Ich habe mir auch mal wieder die Mühe gemacht, nachdem mein UART jetzt mit dem externen Quarz läuft, mein LCD in Gang zu bekommen.
Habe den gleichen Code von Mikrocontroller.net genommen und den Port auf C umgeschrieben, weil der noch frei war.
Hat leider nicht funktioniert, also habe ich mit obigem Programm sämtliche Schleifen neu berechnet und eingefügt. Hat aber auch nichts gebracht.
Ich schätze, dass ich irgendwelche Störungen in der Schaltung habe und es deswegen nicht funktioniert. Muß mal die Mikrocontroller.net Checkliste durchgehen und überall wo nötig Pullup-down Widerstände reinsetzen und das mit den Entstörkondensatoren sollte ich auch mal machen.
Kann ich irgendwie nicht wahrhaben, dass jeder Hans und Franz so ein dummes LCD zum laufen kriegt und ich nicht. Aber ich benutze auch nicht das RN Board oder ähnliches sondern Marke-Eigenbau, weil mir das mehr Spaß macht, als irgendwelche Dinge nachzubauen. Dafür fehlt mir jetzt auch die Erfahrung und der Support von den Leuten, die schon länger mit diesen fertigen Boards arbeiten. Naja, aus Fehlern lernt man. (hoffentllich) ;)



.include "m8def.inc"

.def temp1 = r16
.def temp2 = r17
.def temp3 = r18


ldi temp1, LOW(RAMEND) ; LOW-Byte der obersten RAM-Adresse
out SPL, temp1
ldi temp1, HIGH(RAMEND) ; HIGH-Byte der obersten RAM-Adresse
out SPH, temp1

ldi temp1, 0xFF ;Port C = Ausgang
out DDRC, temp1

rcall lcd_init ;Display initialisieren
rcall lcd_clear ;Display löschen

ldi temp1, 'T' ;Zeichen anzeigen
rcall lcd_data

ldi temp1, 'e' ;Zeichen anzeigen
rcall lcd_data

ldi temp1, 's' ;Zeichen anzeigen
rcall lcd_data

ldi temp1, 't' ;Zeichen anzeigen
rcall lcd_data

loop:
rjmp loop

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; LCD-Routinen ;;
;; ============ ;;
;; (c)andreas-s@web.de ;;
;; ;;
;; 4bit-Interface ;;
;; DB4-DB7: PC0-PC3 ;;
;; RS: PC4 ;;
;; E: PC5 ;;
;; für 4MHz Quarz ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;



;sendet ein Datenbyte an das LCD
lcd_data:
mov temp2, temp1 ;"Sicherungskopie" für
;die Übertragung des 2.Nibbles
swap temp1 ;Vertauschen
andi temp1, 0b00001111 ;oberes Nibble auf Null setzen
sbr temp1, 1<<4 ;entspricht 0b00010000
out PORTC, temp1 ;ausgeben
rcall lcd_enable ;Enable-Routine aufrufen
;2. Nibble, kein swap da es schon
;an der richtigen stelle ist
andi temp2, 0b00001111 ;obere Hälfte auf Null setzen
sbr temp2, 1<<4 ;entspricht 0b00010000
out PORTC, temp2 ;ausgeben
rcall lcd_enable ;Enable-Routine aufrufen
rcall delay50us ;Delay-Routine aufrufen
ret ;zurück zum Hauptprogramm

;sendet einen Befehl an das LCD
lcd_command: ;wie lcd_data, nur ohne RS zu setzen
mov temp2, temp1
swap temp1
andi temp1, 0b00001111
out PORTC, temp1
rcall lcd_enable
andi temp2, 0b00001111
out PORTC, temp2
rcall lcd_enable
rcall delay50us
ret

;erzeugt den Enable-Puls
lcd_enable:
sbi PORTC, 5 ;Enable high
nop ;3 Taktzyklen warten
nop
nop
cbi PORTC, 5 ;Enable wieder low
ret ;Und wieder zurück

;Pause nach jeder Übertragung
delay50us: ;50us Pause
; =============================
; delay loop generator
; 200 cycles:
; -----------------------------
; delaying 198 cycles:
ldi R16, $42
WGLOOP0: dec R16
brne WGLOOP0
; -----------------------------
; delaying 2 cycles:
nop
nop
ret
; =============================
; ldi temp1, $42
;delay50us_:dec temp1
; brne delay50us_
; ret ;wieder zurück

;Längere Pause für manche Befehle
delay5ms: ;5ms Pause
; ldi temp1, $21
;WGLOOP0: ldi temp2, $C9
;WGLOOP1: dec temp2
; brne WGLOOP1
; dec temp1
; brne WGLOOP0
; =============================
; delay loop generator
; 20000 cycles:
; -----------------------------
; delaying 19998 cycles:
ldi R16, $21
WGLOOP1: ldi R17, $C9
WGLOOP2: dec R17
brne WGLOOP1
dec R16
brne WGLOOP0
; -----------------------------
; delaying 2 cycles:
nop
nop
; =============================
ret ;wieder zurück

;Initialisierung: muss ganz am Anfang des Programms aufgerufen werden
lcd_init:
ldi temp3,50
powerupwait:
rcall delay5ms
dec temp3
brne powerupwait
ldi temp1, 0b00000011 ;muss 3mal hintereinander gesendet
out PORTC, temp1 ;werden zur Initialisierung
rcall lcd_enable ;1
rcall delay5ms
rcall lcd_enable ;2
rcall delay5ms
rcall lcd_enable ;und 3!
rcall delay5ms
ldi temp1, 0b00000010 ;4bit-Modus einstellen
out PORTC, temp1
rcall lcd_enable
rcall delay5ms
ldi temp1, 0b00101000 ;noch was einstellen...
rcall lcd_command
ldi temp1, 0b00001100 ;...nochwas...
rcall lcd_command
ldi temp1, 0b00000100 ;endlich fertig
rcall lcd_command
ret

;Sendet den Befehl zur Löschung des Displays
lcd_clear:
ldi temp1, 0b00000001 ;Display löschen
rcall lcd_command
rcall delay5ms
ret

Mr Bean
30.07.2006, 11:37
Hallo

Also so langsam versteh ich das ganze echt nichtmehr. Weiß nichtmehr was ich noch probieren soll. Ich hab mir jetzt mal ein 4 MHz Quarz bestellt und stütze mich auf die Hoffunung daß es damit funktioniert. Habe nämlich die Vermutung daß die Datenwörter einfach zu kurz am Display anliegen und dieses die Befehle gar nicht "mitbekommt" Ich hab jetzt nochmal meine letzte Codevariante angehängt... Kann ja eigentlich auch nicht sein daß hier eigentlich jeder diese Displays zum laufen bekommt nur ich nicht... ](*,) Falls irgendjemand doch einen Fehler findet bitte melden...

Vielen Dank im Voraus!!!!

MFG

Bean


.include "m8def.inc"

.def temp1 = r16
.def temp2 = r17
.def temp3 = r18

ldi temp1, LOW(Ramend)
out SPL, temp1
ldi temp1, High(Ramend)
out SPH, temp1

ldi temp1, 0xFF
out DDRB, temp1

rcall delay5ms
rcall lcd_init
rcall lcd_clear

loop:

rjmp loop

; LCD Routinen

;4-Bit Interface
;BDB4-BDB7: PB0 - Pb3
;RS: PB4
;E: PB7


;sendet ein Datenbyte an das LCD

lcd_data:
mov temp2, temp1 ;"Sicherungskopie" für die Übertragung des zweiten Nibbles
swap temp1 ;vertauschen
andi temp1, 0b00001111 ;oberes Nibble auf 0 setzen
sbr temp1, 1<<4 ;entspricht 0b00010000
out PORTB, temp1 ;ausgeben
rcall lcd_enable ;Enable-Routine aufrufen


andi temp1, 0b00001111 ;obere Hälfte auf null setzen
sbr temp2, 1<<4 ;entspricht 0b00010000
out PORTB, temp2 ;ausgeben
rcall lcd_enable ;enable routine aufrufen
rcall delay50us ;Delay routine aufrufen
ret ;zurück zum Hauptprogramm

;sendet einen Befehl an das LCD

lcd_command: ;wie lcd_data, nur ohne RS zu setzen

mov temp2, temp1
swap temp1
andi temp1, 0b00001111
out PORTB, temp1
rcall lcd_enable
rcall delay50us
andi temp2, 0b00001111
out PORTB, temp2
rcall lcd_enable
rcall delay50us
ret

;erzeugt den Enable-Puls

lcd_enable:

sbi PORTB, 7 ;Enable high
rcall delay50us
cbi PORTB, 7 ;Enable wieder low
ret ;wieder zurück

;Pause nach jeder Übertragung

delay50us: ;50us Pause

ldi temp2, $1E
WGLOOP0: ldi temp3, $14
WGLOOP1: dec temp3
brne WGLOOP1
dec temp2
brne WGLOOP0 ;wieder zurück

;Längere Pause für manche Befehle

delay5ms: ;5ms Pause


WGLOOP2: ldi temp2, $01
WGLOOP3: dec temp2
brne WGLOOP3
dec temp1
brne WGLOOP2

ret ;wieder zurück

;Initialisierung: muss ganz am Anfang des Programms aufgerufen werden

lcd_init:
ldi temp3,50
powerupwait:
rcall delay5ms
dec temp3
brne powerupwait
ldi temp1, 0b00000011 ;muss 3 mal hintereinander gesendet werden zur Initialisierung
out PORTB, temp1 ;1
rcall lcd_enable
rcall delay5ms
rcall lcd_enable ;2
rcall delay5ms
rcall lcd_enable ;3
rcall delay5ms
ldi temp1, 0b00000010 ;4Bit Modus einstellen
out PORTB, temp1
rcall lcd_enable
rcall delay5ms
ldi temp1, 0b00101000
rcall lcd_command
ldi temp1, 0b00001100
rcall lcd_command
ldi temp1, 0b00000100
rcall lcd_command
ret

;sendet einen Befehl zur Löschung des Displays

lcd_clear:

ldi temp1, 0b00000001 ;Display Löschen
rcall lcd_command
rcall delay5ms
ret

Lektor
30.07.2006, 19:27
Hallo Mr Bean.
Könntest du mal bitte bischen mehr zu deinen Komponenten schreiben. LCD hast du ja genannt. Mein Quellcode über deinem ist auf 4MHz eingestellt. die Warteschleifen sogar neu berechnet mit dem Programm oben.
Ich benutze ein Board Marke Eigenbau mit Steckbrettanbindung. Fotos versuche ich mal zu machen.
Habe ein LCD Display, welches auch auf einem Foto hier bei RN abgebildet ist.
Habe das Display schonmal mit einem Adapter am Parallelport getestet und es läuft.

Wenn du deinen 4MHz Quarz hast, dann kannst ja mal meinen Code reinschreiben, mußt nur auf deinen Port abändern.

LCD ist eine so wichtige Anwendung, dass ich es unbedingt hinbekommen muß. Wenn ich schon kein LCD hinbekomme, dann wird es auch nichts mit anderen sinnvollen Anwendungen.

Lektor
30.07.2006, 22:40
habe das ganze eben noch auf 8bit umgesteckt und auf PD gelegt und RS und E auf PB1-2. Ein Programm geschrieben für eine Routine, die ich mit dem Datenblatt bekommen habe. Leider hat nichts funktioniert.
Kann man die Leitungen direkt mit den Port-Pins verbinden oder müssen da noch Widerstände oder so zwischen?
Habe schon soviele Routinen ausprobiert, dass ich jetzt nur noch mit einem Schaltungsfehler rechne.



.include "m8def.inc"

.def temp1 = r16
.def temp2 = r17
.def temp3 = r18

ldi temp1, LOW(RAMEND) ; LOW-Byte der obersten RAM-Adresse
out SPL, temp1
ldi temp1, HIGH(RAMEND) ; HIGH-Byte der obersten RAM-Adresse
out SPH, temp1

ldi temp1, 0xFF ;Port D = Ausgang
out DDRD, temp1
ldi temp1, 0x02 ;Port B 1 als Ausgang und 2 als Eingang
out DDRB, temp1

rcall lcd_init ;Display initialisieren

loop:
rjmp loop

lcd_init:
rcall wait1sek ;1Sek nach Einschalten warten
ldi temp1,0x00 ;RS=0
out portb,temp1
ldi temp1,0x30 ;30h senden
out portd,temp1
rcall wait4500us ;4,5ms warten
ldi temp1,0x00 ;RS=0
out portb,temp1
ldi temp1,0x30 ;30h senden
out portd,temp1
rcall wait120us
ldi temp1,0x00 ;RS=0
out portb,temp1
ldi temp1,0x30 ;30h senden
out portd,temp1
rcall busyflagcheck ;busyflag kontrollieren E=0 PB2=0
ldi temp1,0x00 ;RS=0
out portb,temp1
ldi temp1,0x3c ;4 Displayzeilen, 8bit Ansteuerung
out portd,temp1
rcall busyflagcheck
ldi temp1,0x00 ;RS=0
out portb,temp1
ldi temp1,0x08 ;Display aus zum testen
out portd,temp1
ret


busyflagcheck:
in temp1,portb
sbrs temp1,2
rjmp busyflagcheck
ret

wait1sek:
; =============================
; delay loop generator
; 4000000 cycles:
; -----------------------------
; delaying 3999996 cycles:
ldi R17, $24
WGLOOP0: ldi R18, $BC
WGLOOP1: ldi R19, $C4
WGLOOP2: dec R19
brne WGLOOP2
dec R18
brne WGLOOP1
dec R17
brne WGLOOP0
; -----------------------------
; delaying 3 cycles:
ldi R17, $01
WGLOOP3: dec R17
brne WGLOOP3
; -----------------------------
; delaying 1 cycle:
nop
; =============================
ret

wait4500us:
; =============================
; delay loop generator
; 18000 cycles:
; -----------------------------
; delaying 17985 cycles:
ldi R17, $37
WGLOOP4: ldi R18, $6C
WGLOOP5: dec R18
brne WGLOOP1
dec R17
brne WGLOOP0
; -----------------------------
; delaying 15 cycles:
ldi R17, $05
WGLOOP6: dec R17
brne WGLOOP2
; =============================
ret

wait120us:
; =============================
; delay loop generator
; 480 cycles:
; -----------------------------
; delaying 480 cycles:
ldi R17, $A0
WGLOOP7: dec R17
brne WGLOOP0
; =============================
ret

Mehto
31.07.2006, 00:04
ganz kurz, die Taktfrequenz kann man bis 8MHZ mit den Fusebits einstellen, schau mal ins Datenblatt. Aber aufpassen, je nach Programmer ist das einstellen der Fusebits etwas verwirrend.

Bei der LCD ansteuerung halt ich mich mal lieber fein raus O:)
Hab hier nämlich auch ein LCD an dem ich bei seiner Ansteuerung verzweifelt bin (ist glaub auch nen KS0073). Am besten immer den HD4... Controller nehmen. Kann gut sein das der KS0073 anderst initialisiert werden muss.
Ich glaub ich muss doch mal ne universal LCD ansteuerroutine schreiben in der man die Portbelegung und Taktfrequenz sehr einfach ändern kann.


Viele Grüße,
Mehto