Navigation

Mitglieder Online

· Gäste Online: 1

· Mitglieder Online: 0

· Anzahl Mitglieder: 107
· Neuestes Mitglied: Klimparfed

Neueste Artikel

Login

Benutzername

Passwort



Noch kein Mitglied?
Hier klicken um Dich zu registrieren.

Passwort vergessen?
Um ein neues Passwort anzufordern klicke hier.

Latest Downloads

Forum Themen

Neueste Themen
· Multi-Master IIC Int...
· HCS08 im DIP Gehäuse
· Rotary Encoder
· Serial Software Buffer
· Embedded World 3-5.3...
Heisseste Themen
Keine Themen erstellt

Thema ansehen

 Thema drucken
Rotary Encoder
norticum
Hallo!
Ich hab diesbezgl. scho in mikrocontroller.net einen Threat gestartet, schreibe aber hier rein weil es hier einfach besser passt. Ich arbeite gerade an der Auswertung eines mech. rastenden Rotary Encoder. Ich hab hierzu einen Sourcecode in Assembler geschrieben. Leider hänge ich in der "rotstatushandler_sub" fest und weis nicht ganz wie weiter. Ich benutze hierfür die LEDBank auf dem DEMOAW60 Board. Hier der Code:
ORG Z_RAMStart ; Insert your data definition here
RAM1: DS.B 1
RAM2: DS.B 1
left: DS.B 1
right: DS.B 1
rotstatus: DS.B 1
free DS.B 1
; code section
;
ORG ROMStart

_Startup:
LDHX #RAMEnd+1 ; initialize the stack pointer
TXS
CLI ; enable interrupts
lda #%00000000
sta SOPT
mov #%11111000,ICGC1
mov #%01110000,ICGC2 ;External 4Mhz Crystal source,~14Mhz internal Bus Clock
;mov #%11111111,ICGTRM ;~8Mhz internal Bus Clock
mov #$FF,PTFDD ;datadirection output
lda #$FF
sta PTAPE
bclr 6,PTADD ;datadirection input
bclr 2,PTADD ;datadirection input
clr RAM1
clr RAM2
clr left
clr right
clr rotstatus

mainLoop:



jsr rotencoder_sub

BRA mainLoop

rotencoder_sub:

brclr 2,PTAD,rotleft_sub
jsr delay
brclr 6,PTAD,rotright_sub
bra rotencoder_sub
rotleft_sub:
;brclr 2,PTAD,*
brset 0,rotstatus,rotleft_sub1
brset 1,rotstatus,rotleft_sub1
brset 2,rotstatus,rotleft_sub1
brset 3,rotstatus,rotleft_sub1
brset 4,rotstatus,rotleft_sub1
brset 5,rotstatus,rotleft_sub1
brset 6,rotstatus,rotleft_sub1
brset 7,rotstatus,rotleft_sub1
lda #%10000000
sta left
rotleft_sub1:
brclr 2,PTAD,*
jsr delay
brset 6,PTAD,*
jsr delay
brclr 6,PTAD,*
jsr rotstatushandler_sub
lda rotstatus
sta PTFD
rts

rotright_sub:
;brclr 6,PTAD,*
brset 0,rotstatus,rotright_sub1
brset 1,rotstatus,rotright_sub1
brset 2,rotstatus,rotright_sub1
brset 3,rotstatus,rotright_sub1
brset 4,rotstatus,rotright_sub1
brset 5,rotstatus,rotright_sub1
brset 6,rotstatus,rotright_sub1
brset 7,rotstatus,rotright_sub1
lda #%00000001
sta right

rotright_sub1:
brclr 6,PTAD,*
jsr delay
brset 2,PTAD,*
jsr delay
brclr 2,PTAD,*
jsr rotstatushandler_sub
lda rotstatus
sta PTFD
rts

rotstatushandler_sub:

lda left
cmp #%10000000
bne shiftleft_sub
lda right
cmp #%00000000
bhs shiftright_sub
bra rotstatushandler_sub


shiftleft_sub:
lda left
rol left
sta rotstatus
rts

shiftright_sub:
lda right
ror right
sta rotstatus
rts


delay:
mov #$10,RAM1
del3:
mov #$10,RAM2
del4:
dec RAM2
bne del4
dec RAM1
bne del3
rts
;**************************************************************
;* spurious - Spurious Interrupt Service Routine. *
;* (unwanted interrupt) *
;**************************************************************
spurious: ; placed here so that security value
NOP ; does not change all the time.
RTI
;**************************************************************
;* Interrupt Vectors *
;**************************************************************

ORG Vrti ; Start of interrupt vectors for device

DC.W spurious ; 25 RTI
DC.W spurious ; 24 IIC1
DC.W spurious ; 23 ADC1
DC.W spurious ; 22 KEYBOARD1
DC.W spurious ; 21 SCI2TX
DC.W spurious ; 20 SCI2RX
DC.W spurious ; 19 SCI2ERR
DC.W spurious ; 18 SCI1TX
DC.W spurious ; 17 SCI1RX
DC.W spurious ; 16 SCI1ERR
DC.W spurious ; 15 SPI1
DC.W spurious ; 14 TPM2OVF
DC.W spurious ; 13 TPM2CH1
DC.W spurious ; 12 TPM2CH0
DC.W spurious ; 11 TPM1OVF
DC.W spurious ; 10 TPM1CH5
DC.W spurious ; 9 TPM1CH4
DC.W spurious ; 8 TPM1CH3
DC.W spurious ; 7 TPM1CH2
DC.W spurious ; 6 TPM1CH1
DC.W spurious ; 5 TPM1CH0
DC.W spurious ; 4 ICG
DC.W spurious ; 3 LVD
DC.W spurious ; 2 IRQ
DC.W spurious ; 1 SWI
DC.W _Startup ; 0 RESET


END
It´s not a bug!
It´s a feature!
 
ego
Hallo,

ich verstehe diese Stelle nicht ganz :

rotstatushandler_sub:

lda left
cmp #%10000000
bne shiftleft_sub
lda right
cmp #%00000000
bhs shiftright_sub
bra rotstatushandler_sub

left wird nur in shiftleft_sub geändert.
ist also immer %10000000 deshalb wird die Routine nie ausgeührt.

shiftright_sub: wird dagegen immer angesprungen. ein Branch on equal r Higer bei 0 springt immer. Was st der hintergedanke dabei ?

Eckhard
 
ego
Hallo,

ich habe den Code mal einw enig kommentiert. Ich weiß aber immer noch nicht so ganz genau was Du Dir dabei gedacht hast. Unterprogrammer werden auch nicht wirklich übersichtlicher, wenn es mehr als eine Stelle mit einem rts gibt.

hier erstmal der von mir Kommentierte Code:
Download Code  Code

ORG Z_RAMStart ; Insert your data definition here

RAM1: DS.B 1          ; Variablen für delay
RAM2: DS.B 1
left: DS.B 1
right: DS.B 1
rotstatus: DS.B 1
free DS.B 1

; code section
;

ORG ROMStart

_Startup:
LDHX #RAMEnd+1 ; initialize the stack pointer
TXS
CLI ; enable interrupts  Warum ? es werden keine Interrupts genutzt


lda #%00000000
sta SOPT                  ; COP aus, LVD aus
mov #%11111000,ICGC1
mov #%01110000,ICGC2 ;External 4Mhz Crystal source,~14Mhz internal Bus Clock
;mov #%11111111,ICGTRM ;~8Mhz internal Bus Clock

mov #$FF,PTFDD ;datadirection output
lda #$FF
sta PTAPE ; PTA interne Pullups einschalten


bclr 6,PTADD ;datadirection input
bclr 2,PTADD ;datadirection input
clr RAM1     ; Variablen auf Null setzen 
clr RAM2
clr left
clr right
clr rotstatus

mainLoop:



jsr rotencoder_sub

BRA mainLoop

rotencoder_sub:

brclr 2,PTAD,rotleft_sub      ; warten bis Pin2 an PortA auf 1 geht und dann rotleft_sub aufrufen
jsr delay            ; warten
brclr 6,PTAD,rotright_sub     ; warten bis Pin6 an PortA auf 1 geht und dann rotright_sub aufrufen

bra rotencoder_sub            ; und das gane von vorne

rotleft_sub:

;brclr 2,PTAD,*
brset 0,rotstatus,rotleft_sub1       ; wenn irgendein Bit in rotstatus gesetzt ist
brset 1,rotstatus,rotleft_sub1       ; zu rotleft_sub1 springen
brset 2,rotstatus,rotleft_sub1       ; lda rotstatus
brset 3,rotstatus,rotleft_sub1       ; bne rotleft_sub1
brset 4,rotstatus,rotleft_sub1       ; sollte auch gehen
brset 5,rotstatus,rotleft_sub1
brset 6,rotstatus,rotleft_sub1
brset 7,rotstatus,rotleft_sub1
lda #%10000000                      ; sonst %10000000 in left schreiben
sta left

rotleft_sub1:

brclr 2,PTAD,*               ; warten bis Pin2 an PTA auf 1 geht     
jsr delay                    ; warten
brset 6,PTAD,*               ; warten bis Pin6 an PTA auf 0 geht
jsr delay                    : warten
brclr 6,PTAD,*               ; warten bis Pin6 an PTA auf 1 geht
jsr rotstatushandler_sub     ; rotstatushandler aufrufen
lda rotstatus                ; rotstatus an PTF ausgeben
sta PTFD
rts                          ; und zurück ( rotencoder_sub )

rotright_sub:

;brclr 6,PTAD,*
brset 0,rotstatus,rotright_sub1   ; wenn irgenein Bit in rotstatus gesetzt ist
brset 1,rotstatus,rotright_sub1   ; rotright_sub aufrufen
brset 2,rotstatus,rotright_sub1   ; lda rotstatus
brset 3,rotstatus,rotright_sub1   ; bne rotright_sub1 sollte auch gehen
brset 4,rotstatus,rotright_sub1
brset 5,rotstatus,rotright_sub1
brset 6,rotstatus,rotright_sub1
brset 7,rotstatus,rotright_sub1
lda #%00000001                   ; sonst %00000001 in right speichern
sta right

rotright_sub1:

brclr 6,PTAD,*                   ; warten bis pin6 an PTA auf 1 geht
jsr delay                        ; warten
brset 2,PTAD,*                   ; warten bis pin2 an PTA auf 0 geht
jsr delay                        ; warten
brclr 2,PTAD,*                   ; warten bis pin2 an PTA auf 1 geht
jsr rotstatushandler_sub         ; statushandler aufrufen
lda rotstatus                    ; status an PortF ausgeben
sta PTFD
rts                              ; und zurück ( rotencoder_sub )

rotstatushandler_sub:

lda left                         ; left laden
cmp #%10000000                   ; höchstes Bit gesetzt ?
bne shiftleft_sub                ; nein dann zu shiftleft_sub springen
lda right                        ; right laden
cmp #%00000000                   ; 0 ?
bhs shiftright_sub               ; egal immer größer gleich 0 also zu  shiftright_sub springen
bra rotstatushandler_sub         ; zu statushandler_sub springen aber wie soll das Programm hier hinkommen


shiftleft_sub:                   
lda left                         ; left laden
rol left                         ; nach links rotieren
sta rotstatus                    ; und in rotstatus speichen
rts                              ; und zurück ( rotstatushandler_sub )

shiftright_sub:
lda right                        ; rechts laden
ror right                        ; nach rechts rotieren
sta rotstatus                    ; in rotstatus speichern
rts                              ; und zurück ( rotstatushandler_sub )


delay:

mov #$10,RAM1

del3:

mov #$10,RAM2

del4:

dec RAM2
bne del4
dec RAM1
bne del3
rts
;**************************************************************
;* spurious - Spurious Interrupt Service Routine. *
;* (unwanted interrupt) *
;**************************************************************
spurious: ; placed here so that security value
NOP ; does not change all the time.
RTI
;**************************************************************
;* Interrupt Vectors *
;**************************************************************

ORG Vrti ; Start of interrupt vectors for device

DC.W spurious ; 25 RTI
DC.W spurious ; 24 IIC1
DC.W spurious ; 23 ADC1
DC.W spurious ; 22 KEYBOARD1
DC.W spurious ; 21 SCI2TX
DC.W spurious ; 20 SCI2RX
DC.W spurious ; 19 SCI2ERR
DC.W spurious ; 18 SCI1TX
DC.W spurious ; 17 SCI1RX
DC.W spurious ; 16 SCI1ERR
DC.W spurious ; 15 SPI1
DC.W spurious ; 14 TPM2OVF
DC.W spurious ; 13 TPM2CH1
DC.W spurious ; 12 TPM2CH0
DC.W spurious ; 11 TPM1OVF
DC.W spurious ; 10 TPM1CH5
DC.W spurious ; 9 TPM1CH4
DC.W spurious ; 8 TPM1CH3
DC.W spurious ; 7 TPM1CH2
DC.W spurious ; 6 TPM1CH1
DC.W spurious ; 5 TPM1CH0
DC.W spurious ; 4 ICG
DC.W spurious ; 3 LVD
DC.W spurious ; 2 IRQ
DC.W spurious ; 1 SWI
DC.W _Startup ; 0 RESET


END






Eckhard
 
norticum
Hallo!
Danke für die komments! Ich hab deshalb nichts kommentiert weil ich anfangs immer wieder an den Kommentaren was ändern müsste wenn sich der code ändert. Ich mach das eigendlich immer später wenn alles funktioniert.

rotstatushandler_sub:

lda left
cmp #%10000000
bne shiftleft_sub
lda right
cmp #%00000000 ;Da hast du recht, ich komm immer
bhs shiftright_sub ;nach shiftright_sub wenn left nicht
bra rotstatushandler_sub ;10000000 ist.

Darum bewegt sich meine Led Balkenanzeige auch immer nur in eine Richtung unabhängig von der Drehrichtung des Encoders. Im Freescaleforum hab ich einen Threat entdeckt der das Thema behandelt. Dort schreiben Sie, dass man für eine Drehrichtung immer einen KBI nehmen sollte. Nun hab ich heute morgen angefangen mich mit dem Keyboard Interrupt zu beschäftigen. Was ich derzeit in diesem Thema sehe ist, daß wenn es zu einem KBI kommt, dann immer in die selbe Routine gesprungen wird. Ich bin mir aber noch nicht sicher. Da man so etwas nützliches wie den KBI nicht unnötig "verschwenden" sollte würde ich gerne bei meinem Ansatz bleiben.

Mein Encoder hat 3 Anschlüsse. Bei rechtsdrehen bekomme ich erst zwischen links und mitte dann sofort rechts und mitte einen Kontakt gegen GND. Bei linksdrehen genau das gegenteil, rechts mitte dann links mitte. So kann die Drehrichtung bestimmt werden.

In der ersten routine warte ich einfach auf den ersten Impuls. Je nachdem wie ich drehe springt er in die richtige sub. In "rotright_sub" bzw "rotleft_sub" kontrolliere ich dann "rotstatus". Da muss ein Bit gesetzt sein bzw werden, sonst kann ich nicht shiften. Speziell nach einem Reset oder wenn die Spannung am Controller unter 5V fällt. Ausschalten z.b. Dann bremse ich die ganze Geschichte mit dem "*". Damit gehe ich nur sicher, dass meine Signalzustände nicht durchrutschen. In der "rotstatushandler_sub" würde die umverteilung der Bits passieren. Hier wollte ich left mit right vergleichen und feststellen was sich denn nun eigendlich geändert hat. Das ist etwas schwierig für mich. I müsste wohl den wert in left raufzählen und immer wieder mit right vergleichen. Wenn sich der Wert nach oben hin nicht geändert hat dann nochmal runterzählen und jedesmal vergleichen. Das ganze zweimal für left und right. Anhand dessen sollte dann der wert in rotstatus gebildet werden. Rotstatus dient später mal als merker. 8 bits, 8 Zustände bzw. 8 Verschiedene Displaytextausgaben.

Ich werd mal an dem KBI arbeiten. Ist halt schade wenn ich den opfern müsste.

CLI steht danur weil es eine blöde Gewohnheitssache von mir ist wenn ich ein neues Projekt in CW Anfange steht das immer da. Sollte mir mal angewöhnen SEI rein zu schreiben wenn ich ohne Interrupts arbeite. Wie findest Du eigendlich meinen Lösungsansatz zu der Encoder Geschichte?

norticum
It´s not a bug!
It´s a feature!
 
ego
Hallo,

wenn Du den KBI nicht für was anderes nutzt ist das doch egal. Das Dumme ist dabei, daß dabei immer nur auf eine Flanke reagieren kann oder man muß in der ISR die Flanke ändern. Wenn man nur eine Flanke nutzt halbiert man ja praktisch die Auflösung.
Ich habe vor sowas demnächst auch mal zu machen, weil ich gerade mal wieder an einem Roboter am basteln bin. Im Moment kämpfe ich aber noch mit der Mechanik. Ich wollte die Encoder dann allerdings per Interrupt abfragen. Da Du ja einen Externen Takt hast könnte man hierfür den RTI verwenden. Ich weiß nicht wieviele Takte von deinen Encodern kommen. Für meine habe ich ausgerechnet das ich ca 500 Wechsel die Sekunde habe. Ich werde dann da ich keinen Externen takt verwende über einen Timer per OC ca 1500 Interrupta die Sekunde ausführen in denen ich abfrage ob sich der Encoderwert geändert habe. Ich weiß noch nicht ob ich auch die Drehrichtung auswerten werde, da ich mit dem Controller auch die Motoren steuere habe ich die Drehrichtung sowieso schon.

Eckhard
 
norticum
Hallo!

Ich bin gestern mit meinem Freund zusammen gesessen und wir haben folgendes ausgearbeitet:

mov #%00000001,rotstatus
;clr rotstatus


mainLoop:
jsr rotencoder_sub
BRA mainLoop



rotencoder_sub:
brclr 2,PTAD,rotleft_sub
brclr 6,PTAD,rotright_sub
rts
rotleft_sub:
mov rotstatus,PTFD
brclr 2,PTAD,*
brset 6,PTAD,*
jsr delay
brclr 6,PTAD,*
brset 7,rotstatus,rotleft_sub1
rol rotstatus
rts
rotleft_sub1:
sec
rol rotstatus
rts
rotright_sub:
mov rotstatus,PTFD
brclr 6,PTAD,*
brset 2,PTAD,*
jsr delay
brclr 2,PTAD,*
brset 0,rotstatus,rotright_sub1
ror rotstatus
rts
rotright_sub1:
sec
ror rotstatus
rts




delay:
mov #$10,RAM1
del3:
mov #$10,RAM2
del4:
dec RAM2
bne del4
dec RAM1
bne del3
rts

ich habe das heute morgen schnell ausgearbeitet. Es behandelt den selben Encoder. Das funktioniert schon ganz gut aber halt noch nicht ganz perfekt. Wenn ich es geschafft hab dann werd ich den code hier rein stellen. Diese Routine arbeitet ohne grosses "tamtam" und die KBI spar ich auch. Also mit Sicherheit besser als das was ich vorher hatte.
It´s not a bug!
It´s a feature!
 
Springe ins Forum:
Seitenaufbau: 0.05 Sekunden
714,214 eindeutige Besuche