Forum: Mikrocontroller und Digitale Elektronik Warum funzt meine Funktion nicht (Tasterentprellung)


von Rush (Gast)


Lesenswert?

Hi Leute...

Ich habe die Funktion von
http://www.mikrocontroller.net/articles/Entprellung
bereits erfolgreich auf einem ATmega8 eingesetzt.
Nun möchte ich gerne diese auf einem ATTiny2313 zum Laufen bringen. Der 
Win-AVR spuckt keinerlei Fehlermeldung oder Warnung aus, allerdings 
werden die Tastendrück nicht erkannt.

Hier der Code
1
#include <avr/io.h>
2
#include <util/delay.h>
3
#include <avr/eeprom.h>
4
#include <avr/interrupt.h>
5
#include <stdint.h>
6
7
volatile int i = 0;
8
volatile char MODE_VAL = 0;
9
#define  PWM_WS    OCR1A      //Pin Ausgang
10
#define  PWM_BL    OCR1B 
11
#define  LED_WS    PB3
12
#define  LED_BL    PB4
13
#define  DDR_IN    DDRD
14
#define  PULLUP    PORTD
15
#define  PIN_IN    PIND
16
#define  MODE    PD0
17
#define  UP      PD1
18
#define  DOWN    PD2
19
#define  PORT_IN  PORTD
20
#define  DDR_OUT  DDRB
21
#define  PORT_OUT  PORTB
22
#define  LED_CHK  PB7
23
24
#ifndef EEMEM
25
// alle Textstellen EEMEM im Quellcode durch __attribute__ ... ersetzen
26
#define EEMEM  __attribute__ ((section (".eeprom")))
27
#endif
28
29
uint16_t eeTOP_WS EEMEM;
30
uint16_t eeTOP_BL EEMEM;
31
uint16_t eePWM_WS EEMEM;
32
uint16_t eePWM_BL EEMEM;
33
uint16_t eeSPEED  EEMEM;// = 1023;  //eeTOP ist der Speicherbereich im EEPROM
34
volatile uint16_t intTOP_WS;
35
volatile uint16_t intTOP_BL;
36
volatile uint16_t intPWM_WS;
37
volatile uint16_t intPWM_BL;
38
volatile uint16_t intSPEED;
39
40
41
//------------ Taster entprellen ------------
42
#define ALL_KEYS        (1<<MODE | 1<<UP | 1<<DOWN)
43
 
44
#define REPEAT_MASK     (1<<UP | 1<<DOWN)       // repeat: key1, key2
45
#define REPEAT_START    50                        // after 500ms
46
#define REPEAT_NEXT     20                        // every 200ms
47
           // every 200ms
48
49
volatile uint8_t key_state;                                // debounced and inverted key state:
50
                                                  // bit = 1: key pressed
51
volatile uint8_t key_press;                                // key press detect
52
 
53
volatile uint8_t key_rpt;                                  // key long press and repeat
54
 
55
 
56
ISR( TIMER0_OVF_vect )                            // every 10ms
57
{
58
  static uint8_t ct0, ct1, rpt;
59
  uint8_t i;
60
 
61
  TCNT0 = (uint8_t)(int16_t)-(F_CPU / 1024 * 10e-3 + 0.5);  // preload for 10ms
62
 
63
  i = key_state ^ ~PIN_IN;                        // key changed ?
64
  ct0 = ~( ct0 & i );                             // reset or count ct0
65
  ct1 = ct0 ^ (ct1 & i);                          // reset or count ct1
66
  i &= ct0 & ct1;                                 // count until roll over ?
67
  key_state ^= i;                                 // then toggle debounced state
68
  key_press |= key_state & i;                     // 0->1: key press detect
69
 
70
  if( (key_state & REPEAT_MASK) == 0 )            // check repeat function
71
     rpt = REPEAT_START;                          // start delay
72
  if( --rpt == 0 ){
73
    rpt = REPEAT_NEXT;                            // repeat delay
74
    key_rpt |= key_state & REPEAT_MASK;
75
  }
76
}
77
 
78
///////////////////////////////////////////////////////////////////
79
//
80
// check if a key has been pressed. Each pressed key is reported
81
// only once
82
//
83
uint8_t get_key_press( uint8_t key_mask )
84
{
85
  cli();                                          // read and clear atomic !
86
  key_mask &= key_press;                          // read key(s)
87
  key_press ^= key_mask;                          // clear key(s)
88
  sei();
89
  return key_mask;
90
}
91
 
92
///////////////////////////////////////////////////////////////////
93
//
94
// check if a key has been pressed long enough such that the
95
// key repeat functionality kicks in. After a small setup delay
96
// the key is reported beeing pressed in subsequent calls
97
// to this function. This simulates the user repeatedly
98
// pressing and releasing the key.
99
//
100
uint8_t get_key_rpt( uint8_t key_mask )
101
{
102
  cli();                                          // read and clear atomic !
103
  key_mask &= key_rpt;                            // read key(s)
104
  key_rpt ^= key_mask;                            // clear key(s)
105
  sei();
106
  return key_mask;
107
}
108
 
109
///////////////////////////////////////////////////////////////////
110
//
111
uint8_t get_key_short( uint8_t key_mask )
112
{
113
  cli();                                          // read key state and key press atomic !
114
  return get_key_press( ~key_state & key_mask );
115
}
116
 
117
///////////////////////////////////////////////////////////////////
118
//
119
uint8_t get_key_long( uint8_t key_mask )
120
{
121
  return get_key_press( get_key_rpt( key_mask ));
122
}
123
124
125
126
void pwm_init(void)
127
{
128
  //http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#PWM_.28Pulsweitenmodulation.29
129
  //fast-pwm; clear on compare match, set at top
130
  TCCR1A |= (1<<WGM10) | (1<<WGM11) | (1<<WGM12) | (1<<COM1A1) | (1<<COM1A0) | (1<<COM1B1) | (1<<COM1B0);
131
  TCCR1B |= (1<<CS10);
132
  //OCR1A = pwm;    //compare match
133
}
134
135
void debounce_init(void)
136
{
137
  TCCR0A = (1<<CS02)|(1<<CS00);      // divide by 1024; timer for decouncing
138
  TIMSK = 1<<TOIE0;
139
}
140
141
void init_io(void)
142
{
143
  DDR_OUT |= (1<<LED_WS) | (1<<LED_BL) | (1<<LED_CHK);
144
  PORT_OUT |= (1<<LED_WS) | (1<<LED_BL) | (1<<LED_CHK);
145
  DDR_IN &=~ (1<<MODE) | (1<<UP) | (1<<DOWN);
146
  PULLUP |= (1<<MODE) | (1<<UP) | (1<<DOWN); 
147
  
148
149
150
}
151
void flush(void)
152
{
153
  for (i = 0; i < intTOP_WS; i++)
154
  { 
155
    PWM_WS++; 
156
    PWM_BL--;
157
  _delay_ms(6);
158
159
  }
160
161
  for (i = 0; i < intTOP_BL; i++)
162
  { 
163
    PWM_WS--; 
164
    PWM_BL++;
165
  _delay_ms(6);
166
167
  }
168
169
}
170
171
void main(void)
172
 {
173
   init_io();
174
   debounce_init();
175
   pwm_init();
176
   intTOP_WS = eeprom_read_word(&eeTOP_WS);
177
   intTOP_BL = eeprom_read_word(&eeTOP_BL);
178
   PWM_BL = intTOP_BL;
179
   sei();
180
   while(1)
181
   {
182
   if( get_key_press( 1<<MODE ) || get_key_rpt( 1<<MODE ))
183
      
184
   {
185
    PORT_OUT &=~ (1<<LED_CHK);
186
    intTOP_WS = 250;
187
      eeprom_write_word(&eeTOP_WS, intTOP_WS); // schreiben
188
    intTOP_WS = eeprom_read_word(&eeTOP_WS);
189
190
191
    intTOP_BL = 250;
192
      eeprom_write_word(&eeTOP_BL, intTOP_BL); // schreiben
193
    intTOP_BL = eeprom_read_word(&eeTOP_BL);
194
    PWM_BL = intTOP_BL;
195
   }
196
197
  // - Pwm in eprom ablegen und auf ocxn schalten
198
  /*if ( !(PIN_IN & (1<<MODE)) )
199
  {
200
    PORT_OUT &=~ (1<<LED_CHK);
201
    intTOP_WS = 250;
202
      eeprom_write_word(&eeTOP_WS, intTOP_WS); // schreiben
203
    intTOP_WS = eeprom_read_word(&eeTOP_WS);
204
205
206
    intTOP_BL = 250;
207
      eeprom_write_word(&eeTOP_BL, intTOP_BL); // schreiben
208
    intTOP_BL = eeprom_read_word(&eeTOP_BL);
209
    PWM_BL = intTOP_BL;
210
    }*/
211
212
   
213
    
214
215
     flush();
216
217
 
218
     }
219
220
221
    
222
    
223
   
224
  }
Das selbe Programm mit der IF-Abfrage in der main funktioniert wie 
erwartet, lediglich mit der get_key_press-Funktion nicht.
Die Register des mega8 und des Tiny2313 habe ich bereits verglichen. 
Stimmt alles!

Seht ihr noch etwas was ich falsch gemacht habe ?

Danke schonmal im Voraus...

von g-ast (Gast)


Lesenswert?

Wo und wie sind denn die Tasten angeschlossen?

von Rush (Gast)


Lesenswert?

Ich benutzte momentan noch das STK500.
Tasten schalten gegen Masse.
Und wo die Tasten angeschlossen sind siehst du in den Defines.
1
#define  MODE    PD0
2
#define  UP      PD1
3
#define  DOWN    PD2

von Peter D. (peda)


Lesenswert?

Rush wrote:

>
1
> #define REPEAT_MASK     (1<<UP | 1<<DOWN)       // repeat: key1, key2
2
...
3
>    if( get_key_press( 1<<MODE ) || get_key_rpt( 1<<MODE ))
4
>

get_key_rpt( 1<<MODE ) liefert immer 0, da MODE nicht als Repeat-Taste 
definiert ist.


Peter

von Rush (Gast)


Lesenswert?

Ich habe mich noch nie so richtig mit diesen Entprellfunktionen 
beschäftigt, bin nur froh dass sie funktionieren ;-)
Aber sind die Tasten die als REPEAT_MASK definiert sind nicht nur die 
Tasten die auf längere Tastendrücke reagieren sollen und nicht nur auf 
kurzzeitige?

Durch Hinzufügen der Taste MODE zu REPEAT_MASK reagiert das Programm 
ebenfals nicht auf den Tastendruck.

von Peter D. (peda)


Lesenswert?

Teile Deine Problem auf und prüfe nacheinander, was funktioniert.

Und beschreibe mal, was das Programm überhaupt machen soll und wie es 
davon abweicht.

Wenn ich das richtig verstehe, wird beim 1. Tastendruck 2-mal 250 in den 
EEPROM geschrieben.
Danach passiert scheinbar nichts mehr, da ja die 250 gespeichert 
bleiben.


Peter

von Rush (Gast)


Lesenswert?

Ja fast richtig
1
if( get_key_press( 1<<MODE ) || get_key_rpt( 1<<MODE ))
2
      
3
   {
4
    PORT_OUT &=~ (1<<LED_CHK);
5
    intTOP_WS = 250;
6
      eeprom_write_word(&eeTOP_WS, intTOP_WS); // schreiben
7
    intTOP_WS = eeprom_read_word(&eeTOP_WS);
8
9
10
    intTOP_BL = 250;
11
      eeprom_write_word(&eeTOP_BL, intTOP_BL); // schreiben
12
    intTOP_BL = eeprom_read_word(&eeTOP_BL);
13
    PWM_BL = intTOP_BL;
14
   }

Wenn das Programm hier angekommen ist läuft bereits TIMER1 im PWM-Mode. 
Er soll mir zwei an OC1A und OC1B angeschlossene LEDs dimmen. Wenn der 
Taster nicht gedrück ist, werden die LEDs nicht gedimmt da intTOP_WS und 
intTOP_BL noch NULL sind.
1
void flush(void)
2
{
3
  for (i = 0; i < intTOP_WS; i++)
4
  { 
5
    PWM_WS++; 
6
    PWM_BL--;
7
  _delay_ms(6);
8
9
  }
10
11
  for (i = 0; i < intTOP_BL; i++)
12
  { 
13
    PWM_WS--; 
14
    PWM_BL++;
15
  _delay_ms(6);
16
17
  }
18
19
}

Nachdem ich den Taster gedrückt habe, wird der Wert 250 in intTOP_WS und 
intTOP_BL geschrieben. Dann dimmen die LEDs. Die Variablen PWM_WS und 
PWM_BL sind OCR1A und OCR1B, also die Vergleichsregister.

Also wie gesagt, die Entprellfunktionen auf einem mega8 laufen ohne 
Probleme, nur auf dem Tiny2313 eben nicht.
Wenn ich die Abfrage über die klassische IF-Funktion mache, funktioniert 
das Programm ja ohne Probleme. Also muss das Problem irgendwo in den 
Entprellfunktionen oder in deren Aufruf liegen.
Die Register für die Funktionen sind die selben wie beim mega8. Das habe 
ich wie gesagt schon überprüft.

von Rush (Gast)


Lesenswert?

Entwarnung.... habs jetzt hinbekommen.

Es lag an dem TCCR0A Register. Es muss das TCCR0B sein und nicht das A.

Aber trotzdem vielen Dank für die Bemühungen.

Gruß, Konrad

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.