-         

Ergebnis 1 bis 2 von 2

Thema: Variable per Timer zurücksetzen

  1. #1
    Benutzer Stammmitglied
    Registriert seit
    24.08.2009
    Beiträge
    30

    Variable per Timer zurücksetzen

    Anzeige

    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.
    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;
      }
     }
    }
    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.

    Ich kann mir jedoch nicht erklären woran es liegt.
    Habt ihr einen Tip dazu?
    Geändert von DerSchatten (15.07.2013 um 14:32 Uhr)

  2. #2
    Benutzer Stammmitglied
    Registriert seit
    24.08.2009
    Beiträge
    30
    Also in erster Linie gehts mir um diesen Teil hier:

    Code:
    int8_t encode_read_timeout(void)
    {
     int8_t tmp = encode_read();
     if(tmp != encoderwert)
     timeCount = 3000;
     return tmp;
    }
    Das funktioniert anscheinend nur wenn encoderwert = 0 zutrifft.
    Aber warum?

Ähnliche Themen

  1. Timer vor Überlauf zurücksetzen
    Von demmy im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 11
    Letzter Beitrag: 01.03.2012, 13:52
  2. P89LPC9351 - Zählerstand des Timer 2 zurücksetzen
    Von Djon im Forum Microcontroller allgemeine Fragen/Andere Microcontroller
    Antworten: 0
    Letzter Beitrag: 16.03.2010, 16:50
  3. Bootloadermega2560 - zurücksetzen?
    Von Blaner im Forum Bauanleitungen, Schaltungen & Software nach RoboterNetz-Standard
    Antworten: 3
    Letzter Beitrag: 02.03.2009, 12:04
  4. Variable von 0 auf 1 und wieder zurücksetzen
    Von mat-sche im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 5
    Letzter Beitrag: 23.02.2008, 17:32
  5. SREG Bit 7 zurücksetzen
    Von bigbehrens im Forum Assembler-Programmierung
    Antworten: 1
    Letzter Beitrag: 11.02.2007, 12:37

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •