encoder.c


1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
#include <avr/pgmspace.h>
4
 
5
#define XTAL        4e6                 // 4MHz
6
 
7
#define PHASE_B     (PINA & 1<<PA6)     // an Pinbelegung anpassen
8
#define PHASE_A     (PINA & 1<<PA7)     // an Pinbelegung anpassen
9
 
10
#define LEDS_DDR    DDRB
11
#define LEDS        PORTB               // LEDs gegen Vcc geschaltet
12
  
13
volatile int8_t enc_delta;              // Drehgeberbewegung zwischen
14
                                        // zwei Auslesungen im Hauptprogramm
15
 
16
// Dekodertabelle für wackeligen Rastpunkt
17
// halbe Auflösung
18
int8_t table[16] PROGMEM = {0,0,-1,0,0,0,0,1,1,0,0,0,0,-1,0,0};    
19
 
20
// Dekodertabelle für normale Drehgeber
21
// volle Auflösung
22
//int8_t table[16] PROGMEM = {0,1,-1,0,-1,0,0,1,1,0,0,-1,0,-1,1,0};    
23
 
24
ISR( TIMER0_COMP_vect )             // 1ms fuer manuelle Eingabe
25
{
26
    static int8_t last=0;           // alten Wert speichern
27
 
28
    last = (last << 2)  & 0x0F;
29
    if (PHASE_A) last |=2;
30
    if (PHASE_B) last |=1;
31
    enc_delta += pgm_read_byte(&table[last]);
32
}
33
 
34
void encode_init( void )            // nur Timer 0 initialisieren
35
{
36
  TCCR0 = (1<<WGM01) | (1<<CS01) | (1<<CS00);     // CTC, XTAL / 64
37
  OCR0 = (uint8_t)(XTAL / 64.0 * 1e-3 - 0.5);       // 1ms
38
  TIMSK |= 1<<OCIE0;
39
}
40
 
41
int8_t encode_read( void )         // Encoder auslesen
42
{
43
  int8_t val;
44
 
45
  // atomarer Variablenzugriff  
46
  cli();
47
  val = enc_delta;
48
  enc_delta = 0;
49
  sei();
50
  return val;
51
}
52
 
53
int main( void )
54
{
55
  int32_t val = 0;
56
  char seg7[10] = {0b10000001,0b10110111,0b01000011,0b00010011,0b00110101,0b00011001,0b00001001,0b10110011,0b00000001,0b00010001};
57
  DDRA=0x00;
58
  PINA=0x00;
59
  LEDS_DDR = 0xFF;
60
  encode_init();
61
  sei();
62
 
63
  while(1){
64
    val += encode_read();
65
        
66
    LEDS = seg7[val % 10];
67
  }
68
}