Forum: Mikrocontroller und Digitale Elektronik Fehler im Programm


von Christine (Gast)


Lesenswert?

LED data 090h

mov a,#010h

start:
mov dptr,#tabelle
inc a
movc a, @a+dptr
mov LED,a
call zeit

zeit:
  mov 08h,#255
loop1:  mov 01h,#255
loop2:  djnz 01h,loop2
  djnz 08h,loop1

ljmp start



tabelle:
db 3fh, 06h, 5bh, 4fh
db 66h, 6dh, 7dh, 07h
db 7fh, 6fh

END



Ich versuche das eine 7-Segment Anzeige auf 9 zählt, kann mir jemand
sagen, wo mein Fehler ist?

von Benedikt (Gast)


Lesenswert?

hier:
movc a, @a+dptr
a hat am Anfang den Wert 10h, dann erhöhst du und hast somit 11h.
Die Tabelle hat aber kein 17 Einträge !
Du musst a auf 0 setzen und vor movc a, @a+dptr sichern, denn nach movc
a, @a+dptr steht in a der Wert aus der Tabelle.

von Leopold Stockinger (Gast)


Lesenswert?

UND AUSSERDEM SOLLTEST DU DAS UNTERPROGRAMM
'zeit:' mit einem 'RET' - Befehl beenden wenn du es
mit 'call' aufrufst!

d.h.:


                 LED data 090h

                 mov a,#0FFh ; damit a beim nächsten inc 0 wird

       start:
                 mov dptr,#tabelle
                 inc a
                 push a
                 movc a, @a+dptr
                 mov LED,a
                 pop a
                 call zeit
                 ljmp start

       zeit:
                 mov 08h,#255
       loop1:    mov 01h,#255
       loop2:    djnz 01h,loop2
                 djnz 08h,loop1
                 ret

       tabelle:
                 db 3fh, 06h, 5bh, 4fh
                 db 66h, 6dh, 7dh, 07h
                 db 7fh, 6fh

        END


mfg leo

von Christine (Gast)


Lesenswert?

was sind denn diese 'push' und 'pop' Befehle, die kenne ich noch
nicht, kannst du sie mir kurz erklären,

ansonsten euch beiden: Vielen Dank !

von Christine (Gast)


Lesenswert?

mh jetzt erscheint die 0 aber ich wollte das es auf 9 hochzählt, wie
schaffe ich das ?

von pumann (Gast)


Lesenswert?

... da kann man nur das tut zur asm-Programmierung empfehlen
:http://www.avr-asm-tutorial.net/avr_de/index.html

von Sascha (Gast)


Lesenswert?

@pumann

Würde ihm auch nur helfen, wenn er einen AVR benutzen würde. So wie es
scheint, ist es ein 8051er.

Mfg Sascha

von AndreasH (Gast)


Lesenswert?

@Sascha:

bei "ihm" scheint es sich dem Namen nach um eine Sie zu handeln.

@Christine

Mit push wird ein Wert auf den Stack gelegt. Mit pop wieder
zurückgeholt. Sieh Dir dazu mal detailliert Tutorials über den Stack
des 8051 an.

push acc ; legt den Inhalt des Akkus auf den Stack

.... ; mach irgendwas anderers z.B. Akku erhöhen

pop acc ; hole den Akkuinhalt zurück

je nach Assembler kann acc auch, wie bei Dir, a heissen.

Sorry, habe im Moment keine Zeit das detailliert mit dem Stack zu
erklären.

Grüße
Andreas

von Leopold Stockinger (Gast)


Lesenswert?

ach ja, hab mich glaub ich geirrt,
es müsste korrekt
push   acc
pop    acc
heißen!
probier das mal aus!
mfg leo

von Leopold Stockinger (Gast)


Lesenswert?

funktionierts schon?
lg leo

von Christine (Gast)


Lesenswert?

also das mit dem push und pop funktioniert nicht, wenn ich das target
bilde meldet es fehler, aber ich habe am anfang auch nichts includ ...
gemacht,
es erscheint eine 0 aber sonst passiert leider nichts

von AndreasH (Gast)


Lesenswert?

Meiner Meinung nach kann das ganze nicht funktionieren.

Du erhöhst a durch inc a. Und wann soll die Schleife beendet werden.
Nach dem 10. Durchlauf wird über das Ende von "Tabelle" hinaus
zugegriffen.
irgendwo muss ein Vergleich mit a >= 10d sein und dann wieder von
Anfang an gestartet oder komplett gestoppt werden.
Sonst läuft a bis FFh und dann wieder von 0 los.

Ausserdem verstehe ich nicht den Inhalt von "Tabelle". Wie ermittelt
sich daraus das entsprechende Zeichen für die Werte 0-9.
Im Moment sehe ich nur, daß der Wert aus Tabelle auf die Adresse 90,
also Port 1, gelegt wird. Wenn ich mich richtig an meine
7-Segment-Displays erinnere, benötigten die den Wert BCD-mäßig. Sorry
für die blöde Anmerkung. Habe schon länger nicht mehr damit
gearbeitet.

Welchen Assembler benutzt Du. Du sagst es gibt Fehlermeldungen. Aber
welche?

Grüße
Andreas

von Leopold Stockinger (Gast)


Lesenswert?

AndreasH hat Recht! Es muss ein Vergleich gemacht werden,
außerdem sieht es danach aus, als käme er vom Unterprogramm 'call'
nicht mehr zurück!
Probier mal, dass du am Anfang schreibst:

       ORG          0
       MOV          SP, #0027h

mfg leo

von Christine (Gast)


Lesenswert?

@ leo
was bewirkt das org und das mov spa,
was genau ist das ?

@ andreas
ich verwende den at89S8252
mh ich versuche jetzt mal das mit einer abfrage weil sonst geht es ja
unendlich so weiter

von buz11 (Gast)


Lesenswert?


von Josef (Gast)


Lesenswert?

Gib mal nur

LED data 090h

mov a, #3Fh
mov LED,a

Loop: ajmp Loop

ein. Jetzt muß die 0 angezeigt werden. Wenn dies funktioniert, bist
du schon recht weit.

Josef

von Josef (Gast)


Lesenswert?

Gute Links !

SG Josef

von Andi (Gast)


Lesenswert?

Bei den 8051 kann man doch mit CJNZ vergleichen (Compare) und bei
Ungleichheit wo hin springen.
Z. B. mit:
 CJNZ A,#10,START

Prüfe, ob A=10, wenn nicht, dann zu Start wenn ja, dann nächster
Befehl.

Probiere doch mal folgendes:

                 LED data 090h

                 MOV SP,#0027h

       reset:
                 mov a,#0FFh ; damit a beim nächsten inc 0 wird
       start:
                 mov dptr,#tabelle
                 inc a
                 push a
                 movc a, @a+dptr
                 mov LED,a
                 pop a
                 call zeit
                 CJNZ A,#10,START   ;Zu Start, wenn A <> 10
                 LJMP RESET         ;Ansonsten A zurücksetzen (Reset)

       zeit:
                 mov 08h,#255
       loop1:    mov 01h,#255
       loop2:    djnz 01h,loop2
                 djnz 08h,loop1
                 ret

       tabelle:
                 db 3fh, 06h, 5bh, 4fh
                 db 66h, 6dh, 7dh, 07h
                 db 7fh, 6fh

        END

Bin eigentlich ein AVR´ler aber zu den 8051 schiele ich schon ne weile
rüber.

Gruß
Andi

von Andi (Gast)


Lesenswert?

Hätt ich´s lieber gelassen!
Meinte natürlich "CJNE".
War schon spät :-)
Also, statt "CJNZ A,#10,START" "CJNE A,#10,START" schreiben.

Gruß
Andi

von Christine (Gast)


Lesenswert?

@ Andi

ich habe das jetzt mal ausprobiert aber ich kann kein target bilden
weil push a, pop a und  MOV SP,#0027h nicht erkannt werden ???

von AndreasH (Gast)


Lesenswert?

Ich meinte eigentlich mit welchen Assembler Du benutzt nicht den
Controller sondern eben welchen Assembler/Compiler.

Wenn Du sagst "Target", kann es sein dass Du den Keil meinst.

Die Idee von Josef:
mov a, #3Fh
mov LED,a

Loop: ajmp Loop

ist nicht schlecht. Das Problem ist nur, daß sie ständig die 0
angezeigt bekommt und kein Target gebildet wird. Ich vermute, da ist
was im Quellcode falsch und das assemblieren klappt nicht.

Außerdem die Frage, welche Werte braucht die BCD-Anzeige um 0/1...9
anzeigen zu können. Hier könnte auch noch ein Fehler liegen. Woher
kommen die Werte in "Tabelle".

Grüße
Andreas

von Christine (Gast)


Lesenswert?

ja ich verwende keil
die Hex-Zahlen für 1,2,3,4... haben wir in der Schule zusammen
herausgefunden die stimmen ich habe jetzt den Code und es wird nur die
0 angezeigt:

  LED data 090h
  mov r4,#0ffh


start:
  mov dptr,#tabelle
  mov a, r4
  inc a
  movc  a, @a+dptr
  mov LED,a
  call zeit
  cjne a, #09h , start

  ljmp start


zeit:
  mov 08h,#255
loop1:  mov 01h,#255
loop2:  djnz 01h,loop2
  djnz 08h,loop1


  ret


tabelle:
db 3fh, 06h, 5bh, 4fh
db 66h, 6dh, 7dh, 07h
db 7fh, 6fh

END

irgendwie zählt es einfach nicht hoch

von Andi (Gast)


Lesenswert?

Es geht hier doch um eine 7-Segment-Anzeige und nicht um ein LCD.
Anscheinend ist das so aufgebaut das ein High-Bit ein Segment zum
leuchten bringt.
Hier mal in Binär aufgeschlüsselt:
3fh = 00111111 = 0 , 6 Segmente leuchten
06h = 00000110 = 1 , 2 Segmente leuchten
5bh = 01011011 = 2 , 5 Segmente leuchten
4fh = 01001111 = 3 , 5 Segmente leuchten
66h = 01100110 = 4 , 4 Segmente leuchten
6dh = 01101101 = 5 , 5 Segmente leuchten
7dh = 01111101 = 6 , 6 Segmente leuchten
07h = 00000111 = 7 , 3 Segmente leuchten
7fh = 01111111 = 8 , 7 Segmente leuchten (alle)
6fh = 01101111 = 9 , 6 Segmente leuchten

Von da her stimmen die LED-Daten.

@Christine:
Wenn Du schon R4 benutzt, dann mußt Du auch dieses verarbeiten statt
den Accu.
Z. B.:

 LED data 090h

Reset:
  mov r4,#0ffh


start:
  mov dptr,#tabelle
  inc r4                  ;R4 erhöhen, nicht A
  mov a, r4
  movc  a, @a+dptr
  mov LED,a
  call zeit
  mov a,r4                ;Zum Prüfen auf 10 R4 nach A
  cjne a, #09h , start    ;Ist A(R4) = 9? Wenn nicht, dann zu Start
  ljmp Reset              ;Ansonsten zu Reset. R4 auf den Startwert

Gruß
Andi

von Dirk Broßwick (Gast)


Angehängte Dateien:

Lesenswert?

hallo,

ich habe mal ein programm geschrieben zu dein problem ...
ist in as31 unter linux entwickelt, sollte aber auch übertragbar sein.
im simulator ist es gelaufen ohne probleme.

CA

von Dirk Broßwick (Gast)


Angehängte Dateien:

Lesenswert?

und hier noch das intelhex file zum programm

CA

von Christine (Gast)


Lesenswert?

@ dirk das programm funktioniert einwandfrei
  aber ich kann mit dem loop.asm leider nicht viel anfangen

von Leopold Stockinger (Gast)


Lesenswert?

hallo christine

das mov sp, #0027h

bewirkt, dass der stackpointer (SP) auf einen gültigen wert
initialisiert wird. wenn dein compiler sp nicht erkännt, musst du aus
dem datenblatt die hexadresse von SP ermitteln und sie anstatt von SP
einsetzen!
wenn du das nicht machst kannst du ev. keine unterprogramme aufrufen,
wie z.B. 'call'!!!! das ist vielleicht der grund warum er aus dieser
routine nicht mehr zurückfindet!
außerdem musst du schreiben:
push acc
pop acc
und nicht
push a
pop a
weil: für push und pop muss 'acc' und nicht 'a' angegeben werden!
ein bisschen komisch aber es ist so!

von AndreasH (Gast)


Lesenswert?

Hast Du denn immer noch den Fehler daß Dein Target nicht gebildet wird?

Dann liegt das Problem nämlich erstmal ganz woanders. Du bekommst schon
gar kein lauffähiges Programm assembliert bzw. gelinkt.

Wenn er z.B. den SP nicht kennt, fehlt ein komplettes include-file.
Habe im Moment hier nur den Keil für den C251 und nicht für den 8051.
Daher kann ich Dir nicht sagen wie das heisst. Ich meine aber es gibt
sogar beim Keil eins für den AT89S8252.

Ich habe vor mehreren Monaten was mit dem Keil in Assembler gemacht.
Ich meine dass heisst dann push acc statt push a.

Ausserdem könnstes Du dann statt:
LED data 090h
LED data P1 oder so ähnlich schreiben. Ist kein Fehler, sieht aber
einfach schöner aus.
Erst wenn Dein Programm fehlerfrei assembliert/compiliert kannst Du
anfangen im Quellcode fehler zu suchen.
Das schöne am Keil ist, dass Du in Deiner Zielhardware debuggen kannst.
Dann siehst Du solche Fehler wie die unendliche Schleife oder dass er
über die Tabelle hinausgreift direkt. Vorausgesetzt Du hast das
Monitereprom drin.

Grüße
Andreas

von AndreasH (Gast)


Lesenswert?

Sorry,

Leopold und mein Beitrag haben sich überschnitten.
Klar geht das mit der hex-Adresse. ISt aber unsauberer Programmierstil
und zum anderen kennt der Keil die Bezeichnungen für den Stack.
Der muß auf jeden Fall initialisiert sein, sonst gehen die Calls
daneben.

von Leopold Stockinger (Gast)


Lesenswert?

ok christine,
hab kurz ins datenblatt gesehen... schreib mal:

                 SP  equ  081h
                 ACC equ  0E0h

                 LED data 090h

                 mov SP,#0027h

       reset:
                 mov a,#0FFh ; damit a beim nächsten inc 0 wird
       start:
                 mov dptr,#tabelle
                 inc a
                 push ACC
                 movc a, @a+dptr
                 mov LED,a
                 pop ACC
                 call zeit
                 cjnz a,#10,start   ;Zu Start, wenn A <> 10
                 ljmp reset


       zeit:
                 push 08h
                 push 01h
                 mov 08h,#255
       loop1:    mov 01h,#255
       loop2:    djnz 01h,loop2
                 djnz 08h,loop1
                 pop 01h
                 pop 08h
                 ret

       tabelle:
                 db 3fh, 06h, 5bh, 4fh
                 db 66h, 6dh, 7dh, 07h
                 db 7fh, 6fh

       END


sag bescheid wies läuft!

mfg leo

von Dirk Broßwick (Gast)


Lesenswert?

hallo christine,

wenn du mit den asm-file nix anfangen kannst recht es einfach mal die
komentare zu lesen mit einen text-editor, ich denke mal dann kommt ein
bischen licht ins dunkle. Es sollte dann auch kein problem sein das auf
dein programm deiner wahl zu übertragen.

CA

von Christine (Gast)


Lesenswert?

@ all

vielen dank ihr habt mir sehr geholfen !

@leo danke das programm funktioniert wirklich :-)

ich versuche jetzt alles nachzuvollziehen und dann eventuell bis 99
zählen zu können

von Leopold Stockinger (Gast)


Lesenswert?

na toll, falls etwas unklar ist, melde dich!
kannst auch mailen!
lg & gute nacht, leo

von Christine (Gast)


Lesenswert?

Ich versuche jetzt mein Programm weiter zu entwickeln,
sodass mein Zähler auf 99 Zählen kann, aber ich habe Probleme
mit der Ansteuerung der anderen 7Segment Anzeigen.
Also auf der Platine sind 4 7Segmentanzeigen und zwei
Ports. Das eine Port wählt automatisch die erste
Anzeige aus und das andere Port da muss man irgendwas
setzten um die anderen Anzeigen anwählen zu können, es
ist sozusagen das Steuerport,
hast du vielkleicht eine Ahnung?

von Andi (Gast)


Lesenswert?

Über das "Steuerport" muß das ganze nun gemultiplext werden.
Da wird das "Zählen" total zur Nebensache und Du mußt Dich nun auf
die Darstellung einer 16Bit-Zahl per Timer-Multiplexer und
Binär-BCD-Wandlung konzentrieren.

Gruß
Andi

von Christine (Gast)


Lesenswert?

kannst du mir das nochmal erklären ich verstehe es leider nicht ganz

von Andi (Gast)


Lesenswert?

Im groben kann man das so machen:
 1. Main-Programm: Wert hochzählen oder aktuallisieren so ungefähr
    wie gehabt.
 2. Aktuallisierten (hochgezählten) Wert zu einem Unterprogramm
    schicken (Binär zu BCD) und dem die einzelnen 4 Ziffern ermitteln
    lassen.
    Diese einzelnen Ziffern sollten in 4 einzelne RAM-Bytes
    gespeichert werden.
    Also 1 Byte für die 1000´er-Stelle, 1 für die 100´er-Stelle,
    10´er Stelle und 1´er Stelle.
 3. Du mußt ein Interrupt-Programm (Timer-Interrupt) mit ca. 200Hz
    erstellen welches die einzelnen 7-Segment-Dinger am Steuerport der
    Reihe nach aktiviert (multiplext), sich die zugehörige
    Ziffer für die 1000´er- 100´er-Stelle etc. im RAM abholt und dann
    per gehabter Tabelle ausgibt.

Das ganze ist nicht so einfach und ich kann Dir leider kein fertiges
Programm dafür geben (AVR-User).
Aber so in der Art funktioniert das.
Google einfach ein bißchen nach "8051 7-Segment multiplexen" etc.
Wirst schon noch drauf kommen.

Gruß
Andi

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.