Forum: Mikrocontroller und Digitale Elektronik Fragen zur Komfortroutine zum Entprellen


von dex (Gast)


Lesenswert?

Hallo, bin seit einigen tagen fleißig am avr lernen und bin jetzt an 
dabei mich beim Taster Entrprellen einzuarbeiten. Für ein kleines 
Beispielprogramm habe ich die Komfortroutine aus dem Tut genommen und 
sie an mein Code angepasst. im prinzip funktioniert es, aber leider 
nicht so wie ich es haben will und mir fehlt da ein wenig das 
Verständnis für diese Routine.

Ich hab hier schon gelesen, dass der Algorithmus tricky und nur sehr 
schwer zu verstehen ist, aber wenn man diesen Code an seinen eigenen 
anpassen will, muss man schon etwas genauer wissen wie etwas 
funktioniert.

Meine schaltung ist wie folgt aufgebaut:

Verwendet wird ein Atmega8 mit einer LED an PB0 und PB1. Zusätzlich habe 
ich einen Taster an PD0 mit einem externen Pullup widerstand

Mein Code sind so aus

1
/*
2
 * TASTER_LED.c
3
 *
4
 * 
5
 * 
6
 */ 
7
#ifndef F_CPU
8
#define F_CPU           1000000                   // processor clock frequency
9
#warning kein F_CPU definiert
10
#endif
11
#define REPEAT_MASK     (1<<PD0 )                  // repeat: key1, key2
12
#define REPEAT_START    50                    // after 500ms
13
#define REPEAT_NEXT     20                   // every 200ms
14
#include <avr/io.h>
15
#include <avr/interrupt.h>
16
17
18
volatile uint8_t key_state;                                // debounced and inverted key state:
19
                               // bit = 1: key pressed
20
volatile uint8_t key_press;                   // key press detect
21
 
22
volatile uint8_t key_rpt;                                  // key long press and repeat
23
 
24
 
25
ISR( TIMER0_OVF_vect )                            // every 10ms
26
{
27
  static uint8_t ct0, ct1, rpt;
28
  uint8_t i;
29
 
30
  TCNT0 = (uint8_t)(int16_t)-(F_CPU / 1024 * 10e-3 + 0.5);  // preload for 10ms
31
 
32
  i = key_state ^ ~PIND;                       // key changed ?
33
  ct0 = ~( ct0 & i );                             // reset or count ct0
34
  ct1 = ct0 ^ (ct1 & i);                          // reset or count ct1
35
  i &= ct0 & ct1;                                 // count until roll over ?
36
  key_state ^= i;                                 // then toggle debounced state
37
  key_press |= key_state & i;                     // 0->1: key press detect
38
 
39
  if( (key_state & REPEAT_MASK) == 0 )            // check repeat function
40
     rpt = REPEAT_START;                          // start delay
41
  if( --rpt == 0 ){
42
    rpt = REPEAT_NEXT;                            // repeat delay
43
    key_rpt |= key_state & REPEAT_MASK;
44
  }
45
}
46
 
47
///////////////////////////////////////////////////////////////////
48
//
49
// check if a key has been pressed. Each pressed key is reported
50
// only once
51
//
52
uint8_t get_key_press( uint8_t key_mask )
53
{
54
  cli();                                          // read and clear atomic !
55
  key_mask &= key_press;                          // read key(s)
56
  key_press ^= key_mask;                          // clear key(s)
57
  sei();
58
  return key_mask;
59
}
60
 
61
///////////////////////////////////////////////////////////////////
62
//
63
// check if a key has been pressed long enough such that the
64
// key repeat functionality kicks in. After a small setup delay
65
// the key is reported being pressed in subsequent calls
66
// to this function. This simulates the user repeatedly
67
// pressing and releasing the key.
68
//
69
uint8_t get_key_rpt( uint8_t key_mask )
70
{
71
  cli();                                          // read and clear atomic !
72
  key_mask &= key_rpt;                            // read key(s)
73
  key_rpt ^= key_mask;                            // clear key(s)
74
  sei();
75
  return key_mask;
76
}
77
 
78
///////////////////////////////////////////////////////////////////
79
//
80
// check if a key is pressed right now
81
//
82
uint8_t get_key_state( uint8_t key_mask )
83
 
84
{
85
  key_mask &= key_state;
86
  return key_mask;
87
}
88
 
89
///////////////////////////////////////////////////////////////////
90
//
91
uint8_t get_key_short( uint8_t key_mask )
92
{
93
  cli();                                          // read key state and key press atomic !
94
  return get_key_press( ~key_state & key_mask );
95
}
96
 
97
///////////////////////////////////////////////////////////////////
98
//
99
uint8_t get_key_long( uint8_t key_mask )
100
{
101
  return get_key_press( get_key_rpt( key_mask ));
102
}
103
 
104
int main( void )
105
{
106
  PORTB = 0xFF;
107
  DDRB = 0xFF;                     
108
 
109
  DDRD  =0x00;                // configure key port for input
110
  PORTD =0x00;                // and turn on pull up resistors
111
 
112
  TCCR0 = (1<<CS02)|(1<<CS00);         // divide by 1024
113
  TCNT0 = (uint8_t)(int16_t)-(F_CPU / 1024 * 10e-3 + 0.5);  // preload for 10ms
114
  TIMSK |= 1<<TOIE0;                   // enable timer interrupt
115
 
116
  sei();
117
 
118
  while(1){
119
    if( get_key_short( 1<<PD0 ))
120
    PORTB ^= 1<<PB0;
121
 
122
 
123
   //  if( get_key_long( 1<<PD0 ))
124
  //  PORTB ^= 1<<PB1;
125
 
126
  
127
     
128
 
129
    
130
 
131
     //if( get_key_press( 1<<KEY2  get_key_rpt( 1<<KEY2 )){
132
       //uint8_t i = LED_PORT;
133
 
134
      //i = (i & 0x07) | ((i << 1) & 0xF0);
135
      //if( i < 0xF0 )
136
      //  i |= 0x08;
137
      //LED_PORT = i;      
138
    //}
139
  }
140
}



Jetzt zum Problem:

PORTB wird ja auf 0xFF gesetzt, das bedeutet, dass beide LEDs zu Beginn 
leuchten. Drücke ich den Taster, dann wird PORTB xor verknüpft und geht 
somit aus.
Jetzt möchte ich aber, dass die LED nicht ausgeht wenn ich den Taster 
drücke sondern dass sie angehen. Ich setze also PORTB=0x00 aber so 
funktioniert das nicht.

KAnn mir dann noch jemand erklären wofür der genau die key_repeat ist 
und wofür die dritte if abfrage in der while ist?

von Hilo (Gast)


Lesenswert?

dex schrieb:
> Jetzt möchte ich aber, dass die LED nicht ausgeht wenn ich den Taster
> drücke sondern dass sie angehen.

Stichwort active-low und active-high

von dex (Gast)


Lesenswert?

Danke für deine antwort,
aber beide Varianten haben keine Veränderung bewirkt

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.