PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : [ERLEDIGT] Variable per Timer zurücksetzen



DerSchatten
15.07.2013, 14:24
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.


#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?

DerSchatten
15.07.2013, 20:45
Also in erster Linie gehts mir um diesen Teil hier:



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?