Hallo Forumnutzer,
habe versucht die Schaltung (s. Bild) zu testen. Allerdings bekomme ich
nur auf der zweiten Zeile einen gelben Strich.
Ich vermute, dass ich evtl. im Programm den Timer für die Verzögerung
wegen dem LCD falsch verwende.
Hier mal das Programm:
1
.include "tn2313def.inc"
2
3
; #Makros#
4
.equ F_CPU=1000000
5
.equ RS=PD3
6
.equ RW=PD4
7
.equ E=PD5
8
.def temp=r16
9
.def LCD_data=r17
10
.def Clock_Counter=r18
11
12
; #Code-Segment#
13
.cseg
14
; #Interrupts#
15
.org 0x00 ; RESET
16
rjmp RESET
17
; #Programm#
18
RESET:
19
; Watchdog deaktivieren
20
in temp,MCUSR
21
andi temp,(0xFF&(0<<WDRF))
22
out MCUSR,temp
23
in temp,WDTCSR
24
ori temp,(1<<WDCE)|(1<<WDE)
25
out WDTCSR,temp
26
ldi temp,(0<<WDE)
27
out WDTCSR,temp
28
; Stackpointer initialisieren
29
ldi temp,RAMEND
30
out SPL,temp
31
; Eingänge und Ausgänge definieren
32
ldi temp,0xFF ; Datenrichtungsregister B definieren
33
out DDRB,temp
34
ldi temp,(1<<RS)|(1<<RW)|(1<<E) ; Datenrichtungsregister D definieren
Tu dir selbst einen Gefallen:
von deinem Spannungsregler gehst du mit der positiven
Versorgungsspannung auf die waagrechte Pinleiste, die mit einem roten
Strich (und einem +) markiert ist. GND legst du auf die blaue Leiste.
Und dann schliesst du alle Teile so an, dass du dir die
Versorgungsspannung IMMER von dieser roten bzw. blauen Leiste holst. Man
kann auch die jeweils blauen Pinleisten bzw. roten Pinleisten
miteinander verbdinden, dann braucht man nicht immer quer übers ganze
Board mit den Kabelb, sondern holt sich zb GND für den Prozessor von der
blauen Leiste 'unter' dem µC, und Vcc von der roten Leiste 'über' dem
µC.
Im Moment kann ich in dem Kabelwirrwarr noch nicht einmal erkennen, ob
der µC überhaupt an die Stromversorgung angeschlossen ist.
Tip: sieh von der anderen Seite auf das LCD. Dann ist der Initial-Balken
nicht in der zweitern Zeile, sondern in der ersten
Hallo Karl Heinz,
>Tu dir selbst einen Gefallen:
Okay, werde morgen die Schaltung nochmal besser umverdrahten.
Ich hab mir die Schaltung im aktuellen Zustand nochmal angeschaut und
gemessen. µC bekommt Spannung sowie LCD.
Wenn ich's umverdrahtet habe, kann ich nochmal mit dem Oszi durchmessen.
>Tip: sieh von der anderen Seite auf das LCD. Dann ist der Initial-Balken>nicht in der zweitern Zeile, sondern in der ersten
Wer lesen kann, ist klar im Vortiel... (schäm)
Nur noch ne Frage zur Theorie: Stimmt der obige ASM-Code? Oder ist vllt.
ein Codefehler beim Timer des ATtinys?
Danke nochmal im Voraus!
Mit freundlichen Grüßen
PHBU
Hi
>Nur noch ne Frage zur Theorie: Stimmt der obige ASM-Code? Oder ist vllt.>ein Codefehler beim Timer des ATtinys?
Ich habe deinen Code nur überflogen: Aber mir fehlen die Wartezeiten
,lt. Datenblatt des Displaycontroller, vor der Initialisierung und nach
den einzelnen Befehlen.
MfG Spess
Wozu willst du da eigentlich einen Timer nehmen?
ob du jetzt mit dem Timer eine Anzahl an Takten abwartest, oder ob der
µC eine ausgeklügelte Anzahl an Registern in geschachtelten Schleifen
runterzählt, ist Jacke wie Hose. Ein Timer bringt dir da keinerlei
Vorteile.
(allerdings sollte man auch das TCNT Register vorher explizit auf 0
setzen. Sonst ist es ein wenig witzlos, wenn du beim Eintritt in die
delay Funktion zufällig einen Timer-Stand von 254 hast und der Timer
dann nur 1 Timertakt bis zum Überlauf braucht)
Hallo nochmal,
lag tatsächlich an der Verdrahtung: Habe PB0..7 mit PB7..0 vertauscht ->
alle Befehle und Daten wurden vom LCD-COntroller nicht verstanden.
Funktioniert jetzt alles!
Danke nochmal für eure Hilfe und sorry für die schlechte Verdrahtung.
Mit freundlichen Grüßen
PHBU
Subroutine, um Zahlen in 2 oder 3 ASCII-Zeichen umzuwandeln
1
numberLCD: ; gibt eine Zahl auf dem LCD aus
2
push LCD_data
3
push r31
4
mov r31,LCD_data
5
ldi LCD_data,'0'-1
6
numberLCD_1:
7
inc LCD_data
8
subi r31,100
9
brcc numberLCD_1
10
subi r31,-100
11
cpi LCD_data,'0' ; wenn die Hunderterstelle 0 ist, Ziffer nicht ausgeben
12
breq numberNext
13
rcall dataLCD
14
numberNext:
15
ldi LCD_data,'0'-1
16
numberLCD_2:
17
inc LCD_data
18
subi r31,10
19
brcc numberLCD_2
20
subi r31,-10
21
rcall dataLCD
22
ldi LCD_data,'0'
23
add LCD_data,r31
24
rcall dataLCD
25
pop r31
26
pop LCD_data
27
ret
Die letzte Subroutine habe ich hier vom AVR-Tutorial. Hat diese etwa
einen Fehler (was ich eigentlich nicht glaube...)?
Wenn ich das Display bzw. Programm starte, steht auf dem Display:
1
Zeit einstellen:
2
00:10
Und die 10 ist hier doch meiner Meinung nach falsch!?
Drücke ich dann den Sekunden-Taster einmal, so wird aus dem Text
folgendes:
1
00:20
Warum zählt er jetzt 10 hoch!? Bei den Minuten zählt er genauso hoch.
Ab 100 bzw. 200 zählt er die 10er-Stellen als auch die 1er-Stellen
überhaupt nicht mehr, bis er von vorne (diesmal komischerweise 00)
beginnt.
Liegts an der Subroutine oder an den Unterprogrammaufrufen?
Wäre dankbar nochmal für jede Hilfe!
Mit freundlichen Grüßen
PHBU
Hallo nochmal,
peinlich, peinlich...die Register minutes und seconds (r18 und r19)
müssen natürlich noch genullt werden, damit diese keine willkürlichen
Werte annehmen (einfach mit dem Befehl clr).
Trotzdem zählt der Zähler (hier Minuten) immer nur 10 hinzu (statt 1)
und bei 100 zählt er nur noch im Hintergrund weiter, ohne dass sich
etwas am Display ändert. Das Gleiche geschieht mit 200, bis er wieder
mit 0 anfängt.
Warum zählt er immer 10 hoch?
Danke im Voraus!
Mit freundlichen Grüßen PHBU
Hallo nochmal,
irgendwie scheint diese Routine (Dezimal->ASCII) aus dem Forum nicht zu
funktionieren...
Hier nochmal die zwei wichtigsten Routinen in meinem Programm:
dataLCD (sendet ein Zeichen, gespeichert im Register LCD_data, an das
LCD):
numberLCD (wandelt eine Zahl aus dem Register LCD_data in ASCII-Zeichen
und sendet diese per dataLCD-Routine an das LCD):
1
numberLCD: ; gibt eine Zahl auf dem LCD aus
2
push LCD_data
3
push r31
4
mov r31,LCD_data
5
ldi LCD_data,'0'-1
6
numberLCD_0:
7
inc LCD_data
8
subi r31,100
9
brcc numberLCD_0
10
subi r31,-100
11
cpi LCD_data,'0' ; wenn die Hunderterstelle 0 ist, Ziffer nicht ausgeben
12
breq numberNext
13
rcall dataLCD
14
numberNext:
15
ldi LCD_data,'0'-1
16
numberLCD_1:
17
inc LCD_data
18
subi r31,10
19
brcc numberLCD_1
20
subi r31,-10
21
rcall dataLCD
22
ldi LCD_data,'0'
23
add LCD_data,r31
24
rcall dataLCD
25
pop r31
26
pop LCD_data
27
ret
Folgendes Mini-Testprogramm
1
ldi LCD_data,147
2
rcall numberLCD
schreibt die Zahl '100' auf das LCD.
Ist die Routine etwa flasch? Ich seh da irgendwie keine Fehler...
Wäre nett, wenn sich das jemand nochmal anschauen würde.
Danke für jede Hilfe!
Mit freundlichen Grüßen
PHBU
Philipp B. schrieb:> schreibt die Zahl '100' auf das LCD.> Ist die Routine etwa flasch? Ich seh da irgendwie keine Fehler...
Sieht für mich gut aus.
Bist du schon mal im Single-Step (in der Simulation) durch die Routine
gegangen?
das ist sicherlich nicht die komplette relevante Hauptschleife. Bitte
poste die.
Es könnte auch sein, dass schon "147" auf dem LCD steht, du aber dann
den Cursor zurückpositionierst und "00" über die "47" drüber schreibst.
Kontrollieren kann das hier aber keiner, weil keiner sieht, was genau du
in deinem Mini-Testprogramm sonst noch so alles machst (woran du jetzt
gar nicht denkst, dass es damit in Zusammenhang stehen könnte)
Hallo,
danke für Eure Antworten!
Okay, nochmal zum Verständnis: aktuell soll das Display NUR die Zahl
147 anzeigen.
Hier nun die einzelnen Codeabschnitte:
Die Makros (Variablen):
ldi LCD_data,0xC ; Display ein, Cursor aus, Cursorblinken aus
13
rcall cmdLCD ; LCD-Befehl übertragen
Das primitive Hauptprogramm:
1
clr minutes
2
clr seconds
3
ldi LCD_data,147 ; die Zahl, die auf das LCD ausgegeben werden soll
4
rcall numberLCD
5
end:
6
rjmp end
Subroutine numberLCD, die eine Zahl aus dem Register LCD_data in 2 oder
3 (z.B. die Zahlen 00, 05, 12, 50, 100 oder 255) ASCII-Zeichen (bzw. in
ASCII Zahl) umwandeln soll:
1
numberLCD: ; gibt eine Zahl auf dem LCD aus
2
push LCD_data
3
push r31
4
mov r31,LCD_data
5
ldi LCD_data,'0'-1
6
numberLCD_0:
7
inc LCD_data
8
subi r31,100
9
brcc numberLCD_0
10
subi r31,-100
11
cpi LCD_data,'0' ; wenn die Hunderterstelle 0 ist, Ziffer nicht ausgeben
12
breq numberNext
13
rcall dataLCD
14
numberNext:
15
ldi LCD_data,'0'-1
16
numberLCD_1:
17
inc LCD_data
18
subi r31,10
19
brcc numberLCD_1
20
subi r31,-10
21
rcall dataLCD
22
ldi LCD_data,'0'
23
add LCD_data,r31
24
rcall dataLCD
25
pop r31
26
pop LCD_data
27
ret
Sollten Euch die anderen Subroutinen auch noch interessieren, so könnt
Ihr diese im mitgelieferten Code nachlesen/überprüfen.
Verdrahtung habe ich übrigens wie anfangs beschrieben schon geändert und
überprüft.
Danke nochmal für Eure Hilfe!
Mit freundlichen Grüßen
PHBU
Was ist auf dem LCD zu sehen, wenn Sie unmittelbar vor §end ergänzen:
[avrasm]
rcall newLine
ldi LCD_data,99
rcall numberLCD
ldi LCD_data,' '
rcall dataLCD
ldi LCD_data,100
rcall numberLCD
ldi LCD_data,' '
rcall dataLCD
ldi LCD_data,'4'
rcall dataLCD
end:
[/avrasm}
Hi
Schmeiss mal
> cpi LCD_data,'0' ; wenn die Hunderterstelle 0 ist, Ziffer nicht >ausgeben> breq numberNext
diese Zeilen raus
Damit bleibt deine Anzeige dreistellig. Wenn nämlich in deiner Anzeige
000 steht und du überschreibst das mit 01 steht dann 010 auf dem
Display.
MfG spess
S. Landolt schrieb:
>Was ist auf dem LCD zu sehen, wenn Sie unmittelbar vor §end ergänzen:>>[avrasm]> rcall newLine> ldi LCD_data,99> rcall numberLCD> ldi LCD_data,' '> rcall dataLCD> ldi LCD_data,100> rcall numberLCD> ldi LCD_data,' '> rcall dataLCD> ldi LCD_data,'4'> rcall dataLCD>end:>[/avrasm}
S. Bild.
spess53 schrieb:
>Schmeiss mal diese Zeilen raus
Moment, mach ich gleich...
Hallo,
es ist schon erstaunlich, dass die meisten Fehler so eine verdammte
Einfachheit haben. Wie bescheuert... :-O
Gut, ich kann jetzt schonmal alles einstellen, allerdings ist die
Verzögerung beim Einstellen zu kurz, d.h. die Zahlen ändern sich noch zu
schnell. Aber da bau ich einfach noch eine delay-Routine ein.
push und pop, ihr seid meine besten Freunde X-D
Danke nochmal für Eure Hilfe!
Ihn dünkt', er sähe eine Null
wo eine Neun sollt' sein.
Er guckt' noch mal und merkt', es lag
an dem Delay allein.
"Wenn das schon alles ist", sprach er,
"dann kommt push/pop hinein."