Forum: Mikrocontroller und Digitale Elektronik Peter Danneggers Entprellung und Encoder-Code - wie kombinieren


von Klaus (Gast)


Lesenswert?

Hallo zusammen,
bin noch recht unerfahren in der C-Programmierung. Ich habe sowohl Peter 
Danneggers Tasten-Entprellcode als auch seinen Drehgeber-Code auf meinem 
STK200 ausprobiert. Beides funktioniert prächtig.
Der Drehgeber und zwei Tasten sind dabei am selben Port angeschlossen.
Ich möchte nun aber beide Codes gemeinsam nutzen. Beide nutzen den 
Timer0, jedoch einmal mit einem 10ms und einmal mit einem 1ms Takt.
Kann ich nun einfach den 1ms Interrupt als Basis nehmen und bei jedem 
10. Aufruf die Entprellcode-Teile ausführen? Oder ist das Quatsch?

von Reinhard Kern (Gast)


Lesenswert?

Klaus schrieb:
> Kann ich nun einfach den 1ms Interrupt als Basis nehmen und bei jedem
> 10. Aufruf die Entprellcode-Teile ausführen? Oder ist das Quatsch?

Klar geht das, solange deine ISR im worst case nicht länger als 1 ms 
läuft. Da passt sicher noch mehr rein. Ich erledige in einer 
Basis-Timerroutine auch Display-Ausgabe und Abfrage von seriellen Ports 
(bei 9600 Baud oder weniger) und Temperaturerfassung mit Glättung usw. 
Dazu fängt bei mir die ISR mit einem Dispatcher an, der Aufgaben 
gleichmässig verteilt, die alle 1,2,4 usw. ms erledigt werden sollen, 
dann kann man ausschliessen, dass dummerweise einmal alles auf einmal 
erledigt werden muss. D.h. 2 Aufgaben, die alle 2ms anstehen, werden im 
Wechsel ausgeführt.

Gruss Reinhard

von Harald W. (wilhelms)


Lesenswert?

Klaus schrieb:

> Tasten-Entprellcode als auch seinen Drehgeber-Code

Bei richtiger Drehgeber-Dekodierung (siehe DSE-FAQ) braucht man
keine Entprellung.
Gruss
Harald

von Reinhard Kern (Gast)


Lesenswert?

Harald Wilhelms schrieb:
> Bei richtiger Drehgeber-Dekodierung (siehe DSE-FAQ) braucht man
> keine Entprellung.

Lesen können hilft: er hat einen Encoder UND 2 Tasten.

Gruss Reinhard

von Klaus (Gast)


Lesenswert?

Danke!
Funktioniert.

Könnte man das Ganze eigentlich auch eleganter lösen als ich das getan 
habe indem ich die beiden Codes zusammengewürfelt habe?

Peda verwendet in der Drehgeber-Routine den Timer0-Compare-Int und in 
der Entprellroutine den Timer0-Overflow-Int. Ist das Zufall, oder steckt 
da wieder so ein super-cleverer Gedankengang dahinter, den ich als 
Anfänger nicht sehe/verstehe?
Bietet das eventuell die Möglichkeit beide Routinen in einem Progamm zu 
nutzen? Ich denke nicht, da ja beide Routinen unabhängig am TCNT0 
manipulieren.

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Klaus schrieb:
> Bietet das eventuell die Möglichkeit beide Routinen in einem Progamm zu
> nutzen? Ich denke nicht, da ja beide Routinen unabhängig am TCNT0
> manipulieren.

Doch, das geht natürlich. Hier ist was für den Tiny26, wo beide Routinen 
in der gemeinsamen (CTC) ISR kombiniert sind:
1
// Definitions
2
// Rotary Encoder properties
3
#define ROTARY_PORT PORTB
4
#define ROTARY_DIR DDRB
5
#define ROTARY_PIN PINB
6
#define WHEEL1 6
7
#define WHEEL2 5
8
#define BUTTON 0
9
10
#define PHASE_A  (ROTARY_PIN & 1<<WHEEL1)
11
#define PHASE_B (ROTARY_PIN & 1<<WHEEL2)
12
#define REPEAT_MASK     (1 << BUTTON)       // repeat: button
13
#define KEY_MASK REPEAT_MASK
14
#define REPEAT_START    150                        // after 1500ms
15
#define REPEAT_NEXT     100                        // every 1000ms
16
17
// for 1 ms
18
#define OCR_SET (uint8_t)(F_CPU/256*1e-3)
19
20
21
// encoder routines a la PeDa
22
void encoder_init( void )
23
{
24
  int8_t enc_new;
25
 
26
  enc_new = 0;
27
  if( PHASE_A )
28
    enc_new = 3;
29
  if( PHASE_B )
30
    enc_new ^= 1;               // convert gray to binary
31
  enc_last = enc_new;           // power on state
32
  enc_delta = 0;
33
  TCCR1A = 0;
34
  OCR1C = OCR_SET;   
35
  TCCR1B = (1<<CTC1)|(1<<CS13)|(0<<CS12)|(0<<CS11)|(1<<CS10);    // CTC, XTAL / 256
36
  TIMSK |= (1<<TOIE1);
37
}
38
ISR(TIMER1_OVF1_vect) {
39
int8_t enc_new, diff;
40
static uint8_t ct0, ct1, rpt,btimer;
41
uint8_t i;
42
43
// rotary handling
44
  enc_new = 0;
45
  if( PHASE_A )
46
    enc_new = 3;
47
  if( PHASE_B )
48
    enc_new ^= 1;                   // convert gray to binary
49
  diff = enc_last - enc_new;        // difference last - new
50
  if( diff & 1 ){                   // bit 0 = value (1)
51
    enc_last = enc_new;             // store new as next last
52
    enc_delta += ((diff & 2) - 1);  // bit 1 = direction (+/-)
53
  }
54
  btimer++;
55
  if (btimer > 9) {
56
// button handling
57
    i = key_state ^ ~ROTARY_PIN;
58
    ct0 = ~(ct0 & i);  
59
   ct1 = ct0 ^ (ct1 & i);
60
   i &= ct0 & ct1;
61
   key_state ^= i;
62
    key_press |= key_state & i;
63
    if( (key_state & REPEAT_MASK) == 0 )            // check repeat function
64
         rpt = REPEAT_START;                          // start delay
65
  if( --rpt == 0 ){
66
        rpt = REPEAT_NEXT;                            // repeat delay
67
        key_rpt |= key_state & REPEAT_MASK;
68
  }
69
    btimer = 0;  
70
  }
71
}
Wunder dich nicht, im Tiny26 bewirkt ein CTC Ereignis, das die Timer1 
Overflow ISR angesprungen wird. Port Initialisierung ist hier 
weggelassen. Abfrage von Encoder und Knöpfen wie gehabt.

: Bearbeitet durch User
von Hannes L. (hannes)


Lesenswert?

Klaus schrieb:
> Ist das Zufall, oder steckt
> da wieder so ein super-cleverer Gedankengang dahinter, den ich als
> Anfänger nicht sehe/verstehe?

Als Peter die Entprellung schrieb, verwendete er wohl einen AVR, dessen 
für die Entprellung verwendete Timer noch keine Compare-Interrupts 
hatte.

Der eigentlichen Entprellroutine ist es völlig egal, durch welchen Timer 
sie aufgerufen wird. Wichtig ist nur, dass es in (halbwegs) 
gleichmäßigen Zeitabständen passiert und zwischen den Aufrufen die 
restlichen Teile des Programms abgearbeitet werden können.

Wenn mehrere Zeittakte benötigt werden, ist es sinnvoll, die langsameren 
Takte aus dem schnellsten abzuleiten. Das verhindert gegenseitige 
Beeinflussung mehrerer Timer-Interrupts und erlaubt durch eine Art 
Taskscheibe eine schnelle Abarbeitung der ISR. Aber das wurde ja hier 
bereits erwähnt:
Beitrag "Re: Peter Danneggers Entprellung und Encoder-Code - wie kombinieren"

...

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.