Lösungen in Hardware findest du oben.
Wenn es wirklich in Software sein soll, dann ist ein megaAVR schon Overkill, es sei denn, du brauchst eh einen µC.
Die Routine zur Auswertung ist super simpel und sollte so auch für BASIC-Progger verständlich sein. | ist ein oder und << sind Shifts.
Der Code ist Standard-C.
INT-Eingänge würd ich da nicht verschwenden. Es genügt, wenn du oft genug auf die Ports schaust in einer ISR, z.B. alle 1ms (hängt natürlich von der Drehgeschwindigkeit ab)
Code:
// ergibt die Drehrichtung für die beiden Quadratur-Eingänge a0 und a1
// ai = 0 --> Eingang ist nicht gesetzt
// ai != 0 --> Eingang ist gesetzt
// Return-Wert ist die Drehrichtung
// -1 Richtung x
// 1 dazu entgegengesetzt
// 0 keine Änderung
// DREH_INVALID ungültige Kombination
//
// bevor man die Rückgabewerte verwendet, sollte man die Funktion
// einmal zur Initialisierung mit gültigen Eingangswerten aufrufen,
// ohne den return-Wert zu benutzen.
//
// Die Drehrichtung ist natürlich anhängig davon,
// wie die Anschlüsse belegt sind.
#define DREH_INVALID -128
char drehgeber_step (unsigned char a0, unsigned char a1)
{
static const char drehgeber_trainsitions[] =
{
0, 1, -1, DREH_INVALID,
-1, 0, DREH_INVALID, 1,
1, DREH_INVALID, 0, -1,
DREH_INVALID, -1, 1, 0
};
static unsigned char a_alt;
unsigned char a = a_alt;
if (a0) a |= (1 << 2);
if (a1) a |= (1 << 3);
a_alt = a >> 2;
return drehgeber_trainsitions[a];
}
Und hier in Assembler:
Code:
.section .progmem.data,"a",@progbits
drehgeber_trainsitions:
.byte 0
.byte 1
.byte -1
.byte -128
.byte -1
.byte 0
.byte -128
.byte 1
.byte 1
.byte -128
.byte 0
.byte -1
.byte -128
.byte -1
.byte 1
.byte 0
.lcomm a_alt, 1
.text
; Eingabe: r24, r25
; Ausgabe: r24
; Verändert: r24, r30, r31
.global drehgeber_step
drehgeber_step:
clr r31
lds r30, a_alt
cpse r24, r31
ori r30, 4
cpse r25, r31
ori r30, 8
mov r24,r30
lsr r24
lsr r24
sts a_alt, r24
subi r30, lo8(-(drehgeber_trainsitions))
sbci r31, hi8(-(drehgeber_trainsitions))
lpm r24, Z
ret
Lesezeichen