Forum: Mikrocontroller und Digitale Elektronik Komplexes Lauflicht/ Hilfe zur Verbesserung.


von Turboforce (Gast)


Lesenswert?

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

von JojoS (Gast)


Lesenswert?

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.

von Thomas (Gast)


Lesenswert?

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...





von dernixwois (Gast)


Lesenswert?

@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.


von Peter D. (peda)


Lesenswert?

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

von dernixwois (Gast)


Lesenswert?

@Turboforce

Poste doch den ganzen Code!

An welchem Port sind die Dipschalter oder was auch immer für die 
Pauseeinstellung?

von Turboforce (Gast)


Lesenswert?

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

von Peter D. (peda)


Lesenswert?

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

von Turboforce (Gast)


Angehängte Dateien:

Lesenswert?

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

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.