Hallo,
ich habe ein Problem mit meinen Lauflichtprogramm:
Aber erstmal was liegt hier vor mir:
Ich habe eine Schaltung zur Ausgabe eines Programms vom AT89c2051,
8 Transistoren und 8 LED´s.
Nun habe ich folgendes Programm in Assembler:
;Hanse Derby
INCLUDE 89c2051.mc
init:
MOV DPTR,#Tabelle ;Adresse der Tabelle angeben
MOV R0,#00h ;Schrittzähler auf 0
start:
MOV A,R0
MOVC A,@a+dptr ;Tabellenplatz berechnen
if A = #FFh THEN JMP init ;Wenn Tabelle zuende neuanfang
MOV P1,A ;Muster Ausgeben
call wait_50000 ;Pause
INC R0 ;Schrittzähler erhöhen
JMP start
Tabelle: ;Muster
DB 11111001b,
DB 11111100b,
DB 11110110b,
DB 11110011b,
DB 11111001b,
DB 11111100b,
DB 11110110b,
DB 11110011b,
DB 11111001b,
DB 11111100b,
DB 11110110b,
DB 11110011b,
DB 00001001b,
DB 00001100b,
DB 00000110b,
DB 00000011b,
DB 00001001b,
DB 00001100b,
DB 00000110b,
DB 00000011b,
DB 00001001b,
DB 00001100b,
DB 00000110b,
DB 00000011b,
DB 11111111b, ;FFh = Ende der Tabelle
INCLUDE wait.asm
END
so, folgendes Problem: es funktioniert, aber wenn das auszugebene Muster
mehr als 256 Zeilen/Schritte umfasst läuft es nicht bis zum Ende,
sondern hört bei 256 auf und fängt dann neu an. (Hier nicht der Fall
wollte nicht so ein langes Programm rein stellen.)
2.Das reguläre Ende der Tabelle ist dadurch gekennzeichnet, das alle
Kanäle leuchten (DB 11111111b,), also gemeinsames Blinken unmöglich, da
es dann neu beginnt.
3. Die pause lässt sich nur aunzureichend Abstufen, da sie nur in
50000-Schritten sich veränder lässt. Experimentell ermitellt:(call
wait_50000) oder (call wait_100000 ) usw.
Wie kann man das feiner abstufen? Wenn ich z.B. 60000 eingebe
funktioniert das Programm nicht.
4. Ich habe in der Schaltung Jumper eingebaut, die vier der Inputs von
at89c2051 nach - brücken können, nun würde ich gerne 4 Pausen vorgeben
können und je nach Jumperstellung sollte mann eine Pause wählen können.
Nun ja, fragen über Fragen.
Zur Anwendung, Hintergrund:
Das programm habe ich irgendwann irgendwo gefunden, ich habe von
Assembler keine Ahnung und will auch nur diese eine Schaltung / Programm
benutzen.
Grund: Ich baue Modelle von Fahrgeschäften und Schaustellerbuden. Um
diese nun vorbildgerecht zu beleuchten, brauch ich viel Lauflichtgeräte
mit vielen verschieden Mustern, ihr wisst ja alle wie komplex das
Lichtspiel im Orginal sein kann. Dazu ist das Obrige programm an sich
nicht schlecht, da ich das gewünschte muster direkt einsetzen kann.
Wer kann das Programm so weit umschreiben oder ein neues schreiben, das
die oben genannten Punkte berücksichtigt werden. Oder wer weis, wer es
wissen könnte wenn nicht ihr. Bei Erfolg Spende ich gerne eine
Kleinigkeit in die Kaffeekasse des erfolgreichen Entwicklers, es ist
sehr wichtig!!!
Danke im Vorraus,
Bastian Lampe
www.modellkirmes-goslar.de
den µC kenne ich jetzt nicht im Detail, aber ich vermute mal das R0 ein
8-Bit Register ist und das läuft nunmal bei 255 über auf 0. Da das
Abbruchkriterium der Schleife in den Daten liegt braucht nicht die
indirekte Adressierung mit Offset, es sollte reichen den DPTR in der
Schleife direkt zu inkrementieren.
Beim 8051 ist das DPTR-Register das einzige 16-Bit Register.
Meine 8051er-Zeit ist zwar schon etwas her, aber ich würde nach 255 DBs
einen neuen Index setzen, z.B. "Tabelle2:".
In Pseudo-Assembler (der Keil konnte sowas IMHO nicht):
> if A = #FFh THEN JMP init
also quasi:
if R0 = #FFh THEN MOV DPTR,#Tabelle2
Und dann beim Ende dieser Tabelle auf die nächste oder zurück auf den
Anfang der ersten Tabelle.
Vielleicht kommt 8051-Guru Peter ja noch...
@Turboforce
Füge als letzten Datensatz #00000000 oder zweimal oder andere nicht
vorkomende Bitkombination ein.
In der Schleife inkrementierst Du einfach den DPTR (inc DPTR)
und prüfst ab ob der letzte Datensatz, das Abbruchkreterium erfüllt und
setze deinen DPTR wieder auf den Anfang.
Turboforce wrote:
> so, folgendes Problem: es funktioniert, aber wenn das auszugebene Muster> mehr als 256 Zeilen/Schritte umfasst läuft es nicht bis zum Ende,> sondern hört bei 256 auf und fängt dann neu an. (Hier nicht der Fall> wollte nicht so ein langes Programm rein stellen.)
Nimm einfach "inc dptr" statt "inc r0"
> 3. Die pause lässt sich nur aunzureichend Abstufen, da sie nur in> 50000-Schritten sich veränder lässt. Experimentell ermitellt:(call> wait_50000) oder (call wait_100000 ) usw.> Wie kann man das feiner abstufen? Wenn ich z.B. 60000 eingebe> funktioniert das Programm nicht.
Hellsehen kann ich nicht.
Du must schon die Wait-Funktion mit posten
> 4. Ich habe in der Schaltung Jumper eingebaut, die vier der Inputs von> at89c2051 nach - brücken können, nun würde ich gerne 4 Pausen vorgeben> können und je nach Jumperstellung sollte mann eine Pause wählen können.
Mit 4 Jumpern kannst Du 16 verschiedene Pausen vorgeben, z.B.:
1
get_delay:
2
mov a, p3
3
anl a, #0Fh ;nur P3.3 - P3.0
4
add a, acc ; * 2
5
mov r7, a
6
mov dptr, #delay_tab
7
movc a, @a+dptr
8
xch a, r7 ; r7 = delay high byte
9
inc a
10
movc a, @a+dptr
11
mov r6, a ; r6 = delay low byte
12
ret
13
14
delay_tab:
15
dw 1000
16
dw 1400
17
dw 2000
18
dw 2800
19
dw 4000
20
dw 5600
21
...
> Das programm habe ich irgendwann irgendwo gefunden, ich habe von> Assembler keine Ahnung
Das ist schlecht.
Peter
Hallo,
erstmal Danke an alle, unerwartet gute Hilfe!!!!
Dank euch habe ich folgende Probleme behoben:
Programmlänge nicht meht auf 256 beschränkt, dank
""Nimm einfach "inc dptr" statt "inc r0"""
von Peter D.
Tabellenende variabel gekennzeichnet, je nach dem, welches Muster gerade
nicht vorkommt. Dank dafür an
dernixwois
Das schlimmste ist damint schon mal erledigt!!!!
DiDADankeschööön!!!
Folgende Probleme bleiben:
Das mit der Pause:
1. Die Jumper verbinden P3.2 , P3.3 , P3.4 und P3.5 je nach Auswahl mit
minus.
Die bisherige Wartesequenz wird per call wait_50000 aufgerufe, also
verweist auf INCLUDE wait.asm. Was sich dahinter verbirgt ist mir
schleierhaft.
Kann man vielleicht anders ersetzen?
Es sollte so sein, das es, wenn kein Jumper gesetzt ist es eine
Grundgeschwindigkeit gibt, und je nach dem welcher Jumper gesetzt ist,
die Geschwindigkeit steigt.
Das was Peter D. vorschlug ist bestimmt schon richtig, ich habe es
einfach an Steller von call wait_50000 eingefühgt, gab auch kein Fehler
hat aber am Ende zu keiner Ausgabe geführt, alle Kanäle durchs reset
kurz aufgeleuchtet und dan totale Finsternis. Was habe ich falsch
gemacht, wo ich doch so viel Ahnung habe, was zugegeben wirklich
schlecht ist, aber leider Realität. Wie gesagt, einmalige Angelegenheit.
Der obrige Code ist soweit komplett bis auf die beiden INCLUDEs und das
Muster ist natürlich beliebig.
Also Dank nochmal bisher all denjenigen die sich beteiligt haben, ich
freue mich auf weitere Ideen, Tipps, und Vorschläge, jeder Post ist für
mich eine neue, interessante Erkenntnis.
Bastian Lampe
Turboforce wrote:
> Die bisherige Wartesequenz wird per call wait_50000 aufgerufe, also> verweist auf INCLUDE wait.asm. Was sich dahinter verbirgt ist mir> schleierhaft.
Such einfach mal nach "wait.asm", die muß ja auf Deiner HD sein.
Include xxx heißt nur: Datei xxx einbinden.
> Das was Peter D. vorschlug ist bestimmt schon richtig, ich habe es> einfach an Steller von call wait_50000 eingefühgt, gab auch kein Fehler
Ne, die Funktion lädt nur einen 16Bit-Wert nach R7,R6.
Da sie auch DPTR verwendet, mußt Du sie am Anfang des Zyklus einbinden,
bevor Du DPTR auf die Bitmustertabelle setzt.
Die Delayfunktion muß nun den Wert aus R7,R6 laden für ihren
Delayzähler.
Peter
Hallo;
erstmal im Anhang die bisherige Warte-Sequenz, hab ich jetzt verstanden,
durch Call wait_50000 oder so wurde ein unterprogramm geöffnet, welchens
so bezeichnet wird. Hatte gedacht, das durch die Zahleneingabe ein Wert
ins Unterprogramm geschrieben wird der die Pausenlänge bestimmt und
gewundert, warum das nicht mit allen Zahlen geht.
OK, kapiert, und damit das erledigt.
Nun das Aktuelle Problem:
Ich habe den Code nun so transformiert:
INCLUDE 89c2051.mc
init:
MOV DPTR,#Tabelle ;Adresse der Tabelle angeben
MOV R0,#00h ;Schrittzähler auf 0
start:
MOV A,R0
MOVC A,@a+dptr ;Tabellenplatz berechnen
if A = #FFh THEN JMP init ;Wenn Tabelle zuende neuanfang
MOV P1,A ;Muster Ausgeben
call get_delay ;Pause
INC dptr ;Schrittzähler erhöhen
JMP start
Tabelle: ;Muster
DB 10000000b,
DB 01000000b,
DB 00100000b,
DB 00010000b,
DB 00001000b,
DB 00000100b,
DB 00000010b,
DB 00000001b,
DB 11111111b, ;FFh = Ende der Tabelle
INCLUDE wait2.asm
END
Und die Der Code von wait2.asm
get_delay:
mov a, p3
anl a, #0Fh ;nur P3.3 - P3.0
add a, acc ; * 2
mov r7, a
mov dptr, #delay_tab
movc a, @a+dptr
xch a, r7 ; r7 = delay high byte
inc a
movc a, @a+dptr
mov r6, a ; r6 = delay low byte
ret
delay_tab:
dw 1000
dw 1400
dw 2000
dw 2800
dw 4600
dw 5600
so wie ihn Peter vorschlug
Aber das klappt nicht, egal wo ich call get_delay
hinpacke, das Ergebnis ist stets ernüchternd obwohl es zuvor in der
Simulation gut aussah. Entweder es leuchtet alles, oder so wie jetzt ein
paar kanäle durchgehend.
Bitte habt gedult mit mir, ich will doch nur, das es funktioniert.
Danke
Bastian Lampe