Forum: Compiler & IDEs ATtiny861 & Drehgeber


von Holger K. (zaldo)


Lesenswert?

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

von ATtiny861 (Gast)


Angehängte Dateien:

Lesenswert?

ATtiny 861 hat zwei Control-Register für Timer0

Datenblatt studieren
********************

von Holger K. (zaldo)


Lesenswert?

Danke, das war genau das was ich mit "entscheidenden Tritt" meinte.
1
  TCCR0A = (1<<WGM10);
2
  TCCR0B = (1<<CS01) | (1<<CS00);     // CTC, XTAL / 64

und schon tuts was es soll

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.