Find ich nicht so dolle. Vor allem, wenn es Dir auf Geschwindigkeit ankommt.
Jeder Drehgeberausgang bekommt einen IRQ. Dann fragst Du ab, in welche Richtung sich dieser Porteingang geändert hat. Diesen Gesamtzustand (aus allen 4 Ports) speicherst Du anschließend ab und hast dann den Ausgangszustrand für den nächsten IRQ.
Jetzt kannst Du die Drehrichtung auswerten und die aktuelle Position absspeichern.
Alles andere außerhalb des IRQ.
Guckst Du hier (für Atmega in C). So habe ich es mal gemacht:
Code:
#define TURN_ENC_1 PD7
#define TURN_ENC_2 PD6
volatile uint8_t iTurnOldEncPort;
volatile uint8_t iTurnNewEncPort;
volatile int16_t lTurnActPosition;
volatile int16_t lTurnTargetPosition;
ISR(INT0_vect) { VerticalEncoderRead(); }
void TurnEncoderRead(void) {
iTurnNewEncPort = PIND;
if ( iTurnOldEncPort & (1<<TURN_ENC_1) ) {
if ( iTurnNewEncPort & (1<<TURN_ENC_1) ) {
if ( iTurnOldEncPort & (1<<TURN_ENC_2) ) {
if (!( iTurnNewEncPort & (1<<TURN_ENC_2) )) lTurnActPosition++;
}
else {
if ( iTurnNewEncPort & (1<<TURN_ENC_2) ) lTurnActPosition--;
}
}
else {
if ( iTurnOldEncPort & (1<<TURN_ENC_2) ) {
if ( iTurnNewEncPort & (1<<TURN_ENC_2) ) lTurnActPosition--;
else lErrorFlags |= ERR_TURN_ENC;
}
else {
if ( iTurnNewEncPort & (1<<TURN_ENC_2) ) lErrorFlags |= ERR_TURN_ENC;
else lTurnActPosition++;
}
}
}
else {
if ( iTurnNewEncPort & (1<<TURN_ENC_1) ) {
if ( iTurnOldEncPort & (1<<TURN_ENC_2) ) {
if ( iTurnNewEncPort & (1<<TURN_ENC_2) ) lTurnActPosition++;
else lErrorFlags |= ERR_TURN_ENC;
}
else {
if ( iTurnNewEncPort & (1<<TURN_ENC_2) ) lErrorFlags |= ERR_TURN_ENC;
else lTurnActPosition--;
}
}
else {
if ( iTurnOldEncPort & (1<<TURN_ENC_2) ) {
if (!( iTurnNewEncPort & (1<<TURN_ENC_2) )) lTurnActPosition--;
}
else {
if ( iTurnNewEncPort & (1<<TURN_ENC_2) ) lTurnActPosition++;
}
}
}
iTurnOldEncPort = iTurnNewEncPort;
}
Das "TURN" kannst Du weglassen. Das ist für eine Mehrachsensteuerung.)
Gruß
pctoaster
Lesezeichen