www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Zwei Zahlen vergleichen und...


Autor: Maxim (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe zwei Register. In beiden befindet sich ein Wert zwischen null 
und drei. Es sollen bestimmte Kombinationen erkannt werden:

1) R1 = 0 und R2 = 2   --> Unterprogramm A
2) R1 = 0 und R2 = 1   --> Unterprogramm B
3) R1 = 2 und R2 = 3   --> Unterprogramm A
4) R1 = 2 und R2 = 0   --> Unterprogramm B
 .
 .
 .

Wie kann man das am besten Lösen? Der einfachste Weg wäre, eine Abfrage 
mit ganz vielen Sprüngen zu erstellen. Gibt es eine elegantere und vor 
allem platzsparendere Lösung?

Autor: Clemens Eisserer (linuxhippy)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
soweit ich weiß nicht, bei x86 glaub ich gibt jump-tables oder so.
So gesehen ists halb so tragisch, weil r1 ja entweder 0 oder 2 ist.

Mfg Clemens

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
So:

Funktionspointertabelle mit 16 Einträgen (denn soviele Kombinationen 
kann es ja geben), als Index in die Tabelle R2 << 2 + R1 verwenden.

Der erste Eintrag entspricht R1 = 0 und R2 = 0, der zweite entspricht R1 
= 1 und R2 = 0 etc.

Für jede Bitkombination von R1 und R2 wird in die 
Funktionspointertabelle die Adresse der aufzurufenden Funktion 
("Unterprogramm") eingetragen.

Autor: Jan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
An Adresse X kommt eine lange Liste mit Sprüngen:

rjmp ProgA    ; r1 = 0, r2= 0
rjmp ProgB    ; r1 = 0, r2= 1
...
(16 Einträge insgesamt)


Dann ein jump an die Adresse (X + r1<<2 + r2)

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wie geht die Reihe weiter?

Im Moment sieht es so aus:
Wenn Bit 1 in R2 gesetzt ist, dann kommt A zum Zug ansonsten B

Autor: Maxim (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Theoretisch gibt es nur 8 mögliche Kombinationen. Bezieht man alle 
möglichen Störfälle ein, gibt es 16 mögliche.

Kann man bei dem 8051 wirklich so eine Tabelle anlegen? Das heißt doch 
look up table oder?

Autor: Hannes Lux (hannes)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich denke, Du suchst eine Sprungtabelle.

Falls es sich um einen (nicht zu kleinen und zu alten) AVR handelt, dann 
bietet sich der indirekte Sprung mittels 'ijmp' an.

Dazu wird der Z-Pointer auf die Adresse mit der Sprungtabelle 
positioniert, dann der Index draufaddiert, dann mit ijmp die Adresse 
angesprungen, auf die der Z-Pointer zeigt. Dort steht dann die oben 
bereits erwähnte Liste mit rjmp xyz - Einträgen.

Geht gut und recht schnell, nutze ich gerne bei größeren Menüdialogen.

...

Autor: Maxim (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ist ein AT89S8252, so weit ich weiß, kennt er kein IJMP. Aber indirekte 
Sprünge sollen mit z.B. JMP @A+DATAPOINTER
Ich bin leider noch nicht so weit, um das alles 100% zu verstehen.

Also ich stelle mir das so vor:
Man hat im Speicher z.B. 5 Adressen mit bestimmten Werten, welche man 
zuvor auf den uC geladen hat. Das Programm spricht nacheinander diese 
Adresse an und vergleicht sie mit einem Wert (z.B. im ACCU), wenn der 
Wert übereinstimmt, wird eben ein Unterprogramm aufgerufen.
Man kann das entweder nacheinander für jeden Wert in der Tabelle machen 
oder eine Art Schleife durch indirekte Sprünge Programmieren. Stimmt das 
so?

Könnte mir bitte jemand ein kleines Beispiel mit einer Tabelle im 
Flash-Speicher zeigen?

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
mov a, r1
add a, acc
add a, acc      ; * 4
orl a, r2
anl a, #0Fh     ; table = 16 entries
rl a            ; * 2 (AJMP = 2 byte)
mov dptr, #tabelle
jmp @a+dptr
tabelle:
ajmp ...
ajmp ...
...


Peter

Autor: Joe (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Peters Beispiel ist ok allerdings mußt du bei ajmp berücksichtigen das 
dass Sprungziel innerhalb eines 2k Segmentes liegt.

Autor: Maxim (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke euch soweit!

Das Programm verstehe ich noch nicht ganz.

mov a, r1
add a, acc
add a, acc      ; * 4
orl a, r2
anl a, #0Fh     ; table = 16 entries

Hier werden Werte aus R1 und R2 in ein register kopiert und 
nebeneinander platziert: 0 | 0 | 0 | 0 | R1 | R1 | R2 | R2

------------------------------------------------------------------------ 
--

rl a            ; * 2 (AJMP = 2 byte)

Hier werden die Bits gedreht: R2 | R2 | R1 | R1 | 0 | 0 | 0 | 0

------------------------------------------------------------------------ 
--

mov dptr, #tabelle

Die Adresse der Tabelle wird in den Datapointer geladen. Irgendwie 
erkennt mein Assembler dptr nicht, ist wohl nicht in der Bibliothek 
vorhanden. Welche Adresse hat der Datapointer?

------------------------------------------------------------------------ 
--

jmp @a+dptr

Relativsprung an die Adresse:
R2 | R2 | R1 | R1 | 0 | 0 | 0 | 0 | T | T | T | T | T | T | T | T
Oder sind die zwei Bytes vertauscht?

------------------------------------------------------------------------ 
--

tabelle:
ajmp ...
ajmp ...

Das ist ein Label im Speicher, wo die 16 Kombinationen in 16 Adressen 
gespeichert sind. Warum kommt drunter ajmp?

------------------------------------------------------------------------ 
--

Klärt mich bitte auf.

Autor: Maxim (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hey, last mich auf halber Strecke nicht hängen.

Autor: Dirk Hofmann (arm-dran)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Peter Dannegger wrote:

Ganz Einfach


>
> mov a, r1

R1 in den Akku

> add a, acc

Mit sich selbst addieren heiß also x 2

> add a, acc      ; * 4

Ergebnis noch mal mit sich addieren also nochmal x 2
Beiden Add Befehle ersetzen ein Multiplikation mit 4

> orl a, r2

den Wert aus R2 dazu ODERN (wie "addieren")
Vorraussetzung hier ist, daß der Wert aus R1 nie größer als 3
ist sonst gehts nicht

> anl a, #0Fh     ; table = 16 entries

die unteren 4 Bit ausfiltern, sodaß 16 Kombinationen übrig blieben

> rl a            ; * 2 (AJMP = 2 byte)

einmal nach links um auf eine 32Byte Tabelle zu erweitern
Wie oben geschrieben sind AJMp Befehle im auf eine 2KB Page beschränkt
Wenn Du Programmerweiterungen machst und den Sourcecode verschiebst
kann es Probleme geben
Um mit LJMP statt AJMP Befehlen zu arbeiten schreibst du statt RL A golgendes

mov  B,A
rl   A
add  A,B

dann hast du eine 3x16 Byte Tabelle

> mov dptr, #tabelle

Datenpointer an Tabellenanfang

> jmp @a+dptr

Zur Funktion springen

> tabelle:
> ajmp ...
> ajmp ...
> ...
> 
>
>
> Peter

Gruß

Dirk

Autor: Maxim (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ach so, ich habe gedacht, der Befehl RL dreht das Register um die eigene 
Achse. In Wirklichkeit wird es ja nur um eine Stelle verschoben.

Jetzt sollte es klappen, danke noch Mal.

Autor: Dirk Hofmann (arm-dran)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja so ein Befehl wäre auch schön,

sowas hätte ein paar Leute hier im Forum echt glücklich gemacht

Autor: Maxim (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hm, ich sitze hier jetzt seit einer Stunde und kann den Fehler nicht 
finden. Wahrscheinlich läuft irgendwo ein Register über, der uC hängt 
sich auf, wenn SIG_A = 0 und SIG_B = 1 ist.
;Zweiter Versuch mit dem Drehimpulsencoder

include REG8252.INC

;Zuweisungen
SIG_A       EQU P3.3  
SIG_B       EQU P3.2  
LAST_STATE  EQU R6

;Resets
MOV  P2, #0
MOV  LAST_STATE, #0

;***************************************************************************************************

;Die Hauptschleife
LOOP:   ACALL CHECK_DIG_STATE
        SJMP  LOOP

;***************************************************************************************************

CHECK_DIG_STATE:  ACALL   READOUT_DIG      
      MOV  A, LAST_STATE
      MOV  B, #04h        
      MUL  AB

      ACALL   READOUT_DIG
      ORL  A, LAST_STATE
      ANL  A, #0Fh      
                    
      MOV  DPTR,  #TABLE
      JMP  @A+DPTR

;***************************************************************************************************

;Liest den Drehimpulsgeber aus und speichert den Zustand im Register LAST_STATE

READOUT_DIG: JB   SIG_A, A_TRUE
       SJMP A_FALSE
        
A_TRUE:      JB   SIG_B, STATE_2
       SJMP STATE_1
        
A_FALSE:     JB   SIG_B, STATE_3
       SJMP STATE_0

STATE_0: MOV  LAST_STATE, #0  ;SIG_A=0 and SIG_B=0
   RET
      
STATE_1: MOV  LAST_STATE, #1  ;SIG_A=1 and SIG_B=0
   RET

STATE_2: MOV  LAST_STATE, #2  ;SIG_A=1 and SIG_B=1
   RET

STATE_3: MOV  LAST_STATE, #3  ;SIG_A=0 and SIG_B=1
   RET

;***************************************************************************************************

TABLE:  SJMP  NOA
  SJMP  CW
  SJMP  ERR
  SJMP  CCW
  SJMP  CCW
  SJMP  NOA
  SJMP  CW
  SJMP  ERR
  SJMP  ERR
  SJMP  CCW
  SJMP  NOA
  SJMP  CW
  SJMP  CW
  SJMP  ERR
  SJMP  CCW
  SJMP  NOA

;***************************************************************************************************

NOA:    NOP
        RET

ERR:    NOP
  RET

CW:     SETB P2.7
  RET
    
CCW:    CLR  P2.7
  RET

END

Autor: Dirk Hofmann (arm-dran)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Maxim,

hänge den Sourcecode mal als Textdatei an,

ich korrigiere Ihn Dir.

Dirk

Autor: Maxim (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Vor Freude wuße ich erstmal gar nicht, wo ich die Datei suchen soll ...

Autor: Dirk Hofmann (arm-dran)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Maxim wrote:
> Vor Freude wuße ich erstmal gar nicht, wo ich die Datei suchen soll ...

Hallo Maxim,

habs mir durchgesehen, tut mir leid aber das wird und kann nie 
funktionieren.
Wenn Du möchtest, poste ich hier ne Routine um nen Encoder auszulesen.
Die funktioniert schon in viele Geräten!

?????

Autor: Dirk Hofmann (arm-dran)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
So, ich hab mal in den Anhang gelegt.

Viel Spaß damit.

Wenn es Fragen gibt, dann melde Dich.

Gruß

Dirk

Autor: Maxim (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Schade, dass mein Programm nicht funktioniert. Aber da habe ich mir wohl 
zu viel für einen Einstieg vorgenommen.

Ich habe dein Programm durchgelesen und einen PAP erstellt. Mit der 
Logik habe ich mich aber noch nicht beschäftigt, jedoch erahne ich, wie 
es funktioniert. Bin heute zu müde, um da noch etwas zu machen.

Der PAP ist angehängt.

Danke für deine Hilfe.

Autor: Peter Dannegger (peda)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hier mal die Assemblerversion meines Encoderprogramms.

Ich taste ihn im Timerinterrupt ab.


Peter

Autor: Dirk Hofmann (arm-dran)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Peter,

das funktioniert schon.
Aus leidlicher Erfahrung weiß ich aber, das wenn sich zwischen den 
Auswertungen der beiden Signale der Phasenzustand ändert, eine 
Fehlauswertung stattfindet. Dies kann auch passieren wenn ein höher 
priorisierter Ínterrupt zwischen der Auswertung der beiden Signale 
ausgeführt wird und die Distanz der Phasenauswertung verschiebt.

Deswegen sollte man, beide Signal zeitsynchron latchen.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dirk Hofmann wrote:
> Aus leidlicher Erfahrung weiß ich aber, das wenn sich zwischen den
> Auswertungen der beiden Signale der Phasenzustand ändert, eine
> Fehlauswertung stattfindet. Dies kann auch passieren wenn ein höher
> priorisierter Ínterrupt zwischen der Auswertung der beiden Signale
> ausgeführt wird und die Distanz der Phasenauswertung verschiebt.

Ein nicht korrigierbarer Fehler kann erst dann auftreten, wenn 
dazwischen 2 Phasenübergänge liegen, d.h. Du hast nen exorbitant langen 
Interrupt dazwischen oder das Intervall des Timerinterrupts ist zu groß.

Man sollte also immer dem Encoder-Interrupt die höchste Priorität geben 
und das Timerintervall kurz genug wählen.

Idealer Weise sollte die Timerinterruptfrequenz mindestens doppelt so 
hoch wie die maximale Schrittfrequenz des Encoders sein, damit man auch 
noch Zeit hat, Preller zu korrigieren.


Peter

P.S.:
Du hast das warscheinlich damit verwechselt, den gleichen Pin mehrmals 
in der Routine abzufragen. Dann kann in der Tat sonstwas passieren, wenn 
er sich genau zwischen 2 Abfragen ändert.
Man muß immer darauf achten, innerhalb eines Auswertezyklus asynchrone 
Eingänge nur einmalig einzulesen und dann zwischenzuspeichern, wenn 
deren Zustand nochmal benötigt wird.

Autor: Maxim (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Habe mich gerade hingesetzt und den PAP (da hat sich ein kleiner Fehler 
eingeschliechen auf dem Bild ...) manuell abgelaufen. Habe den 
Algorithmus weitgehend verstanden. Ich muss sagen, der ist ziemlich 
raffiniert, im vergleich zum meinem ... ;-) Wie kommt man nur auf solche 
"einfachen" Lösungen?

Autor: Dirk Hofmann (arm-dran)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Peter,

mir ist das schon klar, mit Interruptpriorisierung.
Da Maxim gerade einsteigt, wollte ich auf diese Problematik hinweisen,
das daß nicht zur Frustration führt und zur Veranschaulichung.

Hab mal ne Frage an Dich. Hattest Du schon mal was mit Software JPEG 
decodierung zu tun? Hab noch keine gute Beschreibung gefunden, hab zwar 
das Buch von John Miano, aber der File Aufbau geht nicht direkt klar.


Maxim, wenn man ne Weile programmiert, erarbeitet man sich Viele 
Problemlösungsstrategien systematisch, also immer weiter machen und dran 
bleiben. Learning by doing sozusagen

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.