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