Ich brauchte mal eure Hilfe.
Folgende Hardware kommt zum Einsatz:
ATTiny44 mit 8MHz internen Takt.
Drehencoder (Drehgeber) mit Taster
4 LED's
Zur Funktion:
Mittels Drehencoder wird jeweils zwischen den LED's geschalten.
Vor, schaltet eine LED vorwärts. Zurück, jeweils 1 LED zurück. Also recht simple eigentlich.
Der Taster speichert die aktuelle Position.
Wird der Encoder nun weitergedreht, soll nach 3 Sekunden zum gespeicherten Wert zurückgesprungen werden.
Das Problem ist nun folgendes: Wenn der Encoderwert 0 beträgt funktioniert das Programm. Wird jedoch der Wert 1-3 gespeichert, passiert nicht das gewünschte.Code:#include <avr/io.h> #include <avr/interrupt.h> #include <avr/eeprom.h> #include <util/delay.h> #include <avr/sleep.h> // CPU: ATTiny44-20PU 8MHz // ======================================================================= // Ein-/Ausgänge // ----------------------------------------------------------------------- #define ENCODER_PORT PORTB #define ENCODER_DDR DDRB #define TASTER_PIN PINB #define AUSGANG_PORT PORTA #define AUSGANG_DDR DDRA #define AUSGANG_PIN PINA #define ENCODER_A (PINB & 1 << PB0) #define ENCODER_B (PINB & 1 << PB1) #define TASTER (1 << PB2) // Schalt-Muster // ----------------------------------------------------------------------- #define LOW 0x00 // 0000 0000 #define HI 0xFF // 1111 1111 #define SCHALT 0xBF // 1011 1111 #define RESET 0x40 // 0100 0000 #define KERNAL_LO 0x30 // 0011 0000 #define CBM 0x00 // 0000 0000 #define SJIFFY 0x10 // 0001 0000 #define SPEED 0x20 // 0010 0000 #define DOLPHIN 0x30 // 0011 0000 // LED-Muster // ----------------------------------------------------------------------- unsigned char led_setzen[] = {0b0001, 0b0010, 0b0100, 0b1000}; unsigned char led_loeschen[] = {0b1110, 0b1101, 0b1011, 0b0111}; // Tastendruck // ----------------------------------------------------------------------- #define REPEAT_MASK (TASTER) #define REPEAT_START 250 #define REPEAT_NEXT 100 #define DELAY_RESET 500 volatile uint8_t key_state; volatile uint8_t key_press; volatile uint8_t key_rpt; volatile int8_t enc_delta; volatile int8_t encoderwert; static int8_t last; static int16_t timeCount = 0; // Variablen/EEPROM // ----------------------------------------------------------------------- int8_t encoder = 0; uint8_t eeprom_kernalid EEMEM = 1; // 1.Byte im EEPROM für KERNAL-Wert uint8_t eeprom_encoderid EEMEM = 2; // 2.Byte im EEPROM für ENCODER-Wert uint8_t kernalid; ISR (TIM0_COMPA_vect) { int8_t new, diff; new = 0; if(ENCODER_A) new = 3; if(ENCODER_B) new ^= 1; diff = last - new; if(diff & 1) { last = new; enc_delta += (diff & 2) - 1; } static uint8_t ct0, ct1, rpt; uint8_t i; i = key_state ^ ~TASTER_PIN; ct0 = ~(ct0 & i); ct1 = ct0 ^ (ct1 & i); i &= ct0 & ct1; key_state ^= i; key_press |= key_state & i; if((key_state & REPEAT_MASK) == 0) rpt = REPEAT_START; if(--rpt == 0) { rpt = REPEAT_NEXT; key_rpt |= key_state & REPEAT_MASK; } if(timeCount > 0) { timeCount--; if(timeCount == 0) { encoder = encoderwert; } } } uint8_t get_key_press(uint8_t key_mask) { cli(); key_mask &= key_press; key_press ^= key_mask; sei(); return key_mask; } uint8_t get_key_rpt(uint8_t key_mask) { cli(); key_mask &= key_rpt; key_rpt ^= key_mask; sei(); return key_mask; } uint8_t get_key_short(uint8_t key_mask) { cli(); return get_key_press(~key_state & key_mask); } uint8_t get_key_long(uint8_t key_mask) { return get_key_press(get_key_rpt(key_mask)); } int8_t encode_read(void) { int8_t val; cli(); val = enc_delta; enc_delta = val & 1; sei(); return val >> 1; } int8_t encode_read_timeout(void) { int8_t tmp = encode_read(); if(tmp != encoderwert) timeCount = 3000; return tmp; } void kernal_id(int8_t kernalid) { AUSGANG_PORT &= ~(KERNAL_LO); // Alle Kernal-PIN auf LOW setzen AUSGANG_PORT |= (kernalid); // KERNAL-PIN setzen } void reset() { AUSGANG_DDR |= (RESET); // ResetPIN = Ausgang AUSGANG_PORT &= ~(RESET); // ResetPIN = LOW _delay_ms(DELAY_RESET); // Warten AUSGANG_DDR &= ~(RESET); // ResetPIN = Eingang AUSGANG_PORT |= (RESET); // ResetPIN = PullUp } void eeprom_var(void) { if(eeprom_read_byte(&eeprom_kernalid) != HI) { kernalid = eeprom_read_byte(&eeprom_kernalid); // KERNAL-Wert aus EEPROM auslesen encoder = eeprom_read_byte(&eeprom_encoderid); // ENCODER-Wert aus EEPROM auslesen kernal_id(kernalid); // gespeicherten KENRAL aktivieren } } void ioinit() { AUSGANG_DDR = SCHALT; // SCHALT = Ausgang/RESET = Eingang AUSGANG_PORT |= RESET; // RESET = PullUp ENCODER_DDR = LOW; // ENCODER = Eingang ENCODER_PORT = HI; // ENCODER = PullUp } void encode_init(void) { int8_t new; new = 0; if(ENCODER_A) new = 3; if(ENCODER_B) new ^= 1; last = new; enc_delta = 0; TCCR0A = (1<<WGM01); OCR0A = (uint8_t)(F_CPU / 64.0 * 1e-3 - 0.5); TCCR0B = (1<<CS01 | 1<<CS00); TIMSK0 = (1<<OCIE0A); } int main(void) { ioinit(); // PORT setzen eeprom_var(); // EEPROM-Werte auslesen reset(); // C64 Reset durchführen encode_init(); // ENCODER initialisieren sei(); // Interrupt aktivieren for(;;) { ADCSRA &= !(1<<ADEN); // ADC dekativieren encoder += encode_read_timeout(); // ENCODER-Wert auslesen if (encoder > 3) encoder = 3; // ENCODER-Wert auf 3 limitieren if (encoder < 0) encoder = 0; switch(encoder) { case 0: AUSGANG_PORT |= led_setzen[encoder]; // Aktiven LED-PIN setzen AUSGANG_PORT &= ~(led_loeschen[encoder]); // Inaktive LED-PIN löschen if (get_key_short(TASTER)) // bei kurzem Tastendruck { kernal_id(CBM); encoderwert = encoder; reset(); } if(get_key_long(TASTER)) // bei langen Tastendruck { kernal_id(CBM); eeprom_write_byte(&eeprom_kernalid, CBM); // KERNAL-Wert in EEPROM speichern eeprom_write_byte(&eeprom_encoderid, encoder); // ENCODER-Wert in EEPROM speichern reset(); } break; case 1: AUSGANG_PORT |= led_setzen[encoder]; AUSGANG_PORT &= ~(led_loeschen[encoder]); if (get_key_short(TASTER)) { kernal_id(SJIFFY); encoderwert = encoder; reset(); } if(get_key_long(TASTER)) { kernal_id(SJIFFY); eeprom_write_byte(&eeprom_kernalid, SJIFFY); eeprom_write_byte(&eeprom_encoderid, encoder); reset(); } break; case 2: AUSGANG_PORT |= led_setzen[encoder]; AUSGANG_PORT &= ~(led_loeschen[encoder]); if (get_key_short(TASTER)) { kernal_id(SPEED); encoderwert = encoder; reset(); } if(get_key_long(TASTER)) { kernal_id(SPEED); eeprom_write_byte(&eeprom_kernalid, SPEED); eeprom_write_byte(&eeprom_encoderid, encoder); reset(); } break; case 3: AUSGANG_PORT |= led_setzen[encoder]; AUSGANG_PORT &= ~(led_loeschen[encoder]); if (get_key_short(TASTER)) { kernal_id(DOLPHIN); encoderwert = encoder; reset(); } if(get_key_long(TASTER)) { kernal_id(DOLPHIN); eeprom_write_byte(&eeprom_kernalid, DOLPHIN); eeprom_write_byte(&eeprom_encoderid, encoder); reset(); } break; } } }
Ich kann mir jedoch nicht erklären woran es liegt.
Habt ihr einen Tip dazu?







Zitieren

Lesezeichen