Hallo zusammen,
ich stolpere mich gerade in die AVR-GCC Prigrammierung und versuche auf
einem tiny861 den Code zum einlesen eines Encoders hier von der Seite
https://www.mikrocontroller.net/articles/Drehgeber zum laufen zu
bringen.
Nun geht da nicht draus hervor für welchen µC der irgendwann mal
geschrieben wurde, jedenfalls heißen die Timer-Register beim 861 anders.
Ich habe mich nach besten Möglichkeiten bemüht, Die Timer Register
angepasst aber das Dingens tut nichts. Vermutlich liegt der Fehler in
der Zeile
1 | TCCR0A = (1<<WGM01) | (1<<CS01) | (1<<CS00); // CTC, XTAL / 64
|
denn im Control Register A gibts keine Bits mit den Namen WGM01, CS01
und CS00. Nun bin ich im Umgang mit Timern zu schlecht, in C generell
noch nicht gut und der Code nicht ausreichend dokumentiert um zu
erahnen, was diesem Register mitgeteilt werden will, bzw. welche Bits
hier gesetzt werden sollen.
Könnt Ihr mir den entscheidenden Tritt in die richtige Richtung geben?
Hier nochmal der Code mit den geänderten Registern. Im wesentlichen habe
ich die Verweise auf TIMER0 nach TIMER0A geändert:
1 | #include <avr/io.h>
|
2 | #include <avr/interrupt.h>
|
3 | #include <avr/pgmspace.h>
|
4 |
|
5 | #define XTAL 8e6 // 8MHz
|
6 |
|
7 | #define PHASE_A (PINA & 1<<PA6) // an Pinbelegung anpassen
|
8 | #define PHASE_B (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 | const 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 | //const 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_COMPA_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 | TCCR0A = (1<<WGM01) | (1<<CS01) | (1<<CS00); // CTC, XTAL / 64
|
37 | OCR0A = (uint8_t)(XTAL / 64.0 * 1e-3 - 0.5); // 1ms
|
38 | TIMSK |= 1<<OCIE0A;
|
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 | PORTA |= 0b11000000;
|
56 | int32_t val = 0;
|
57 |
|
58 | LEDS_DDR = 0xFF;
|
59 | encode_init();
|
60 | sei();
|
61 |
|
62 | while(1){
|
63 | val += encode_read();
|
64 | LEDS = val;
|
65 | }
|
66 | }
|
Gruß
Holger