Forum: Mikrocontroller und Digitale Elektronik Entprellung in der Timer-ISR


von Marcel (Gast)


Lesenswert?

Guten Morgen.

Seit gestern funktioniert die Auswertung des des Inkrementalgebers mit 
der Routine von Herrn Dannegger ganz gut und ich glaube ich habe sie 
einigermaßen verstanden.
Nun will ich zusätzlich noch den Taster des Inkrementalgebers in der ISR 
auswerten. Ich habe die Funktion für die Entprellung rufe ich in der ISR 
auf und will mir dann eine globale Variable "guc_enc_pushbutton" setzen 
welche ich dann im Hauptprogramm auswerten möchte. Leider funkrioniert 
es nicht so wie ich es mir gedacht hatte. Die Variable springt öffters 
auf 1 und wieder 0. Funktioniert die Entprellung bei mir nicht richtig? 
Auch wenn ich den Taster gedrückt halte liefert mir die Funktion 1 
zurück.
Mache ich Grundsätzlich etwas falsch?
1
//#include <avr/io.h>
2
//#include <avr/interrupt.h>
3
4
//ATmega2560
5
6
/***********************/
7
/******* Defines *******/
8
/***********************/
9
/* allgemeine Definitionen */
10
#define XTAL         16e6                   // 16MHz
11
12
/* Interruptsteuerung */
13
#define ENAB_GLOBAL_INT         asm("sei")      // Set I-Bit in SREG
14
#define DISAB_GLOBAL_INT        asm("cli")      // Reset I-Bit in SREG
15
16
/* Pin- und Portdefinitionen */
17
/********************************* Arduino-LED (Testpunkt) *********************************************************************************/
18
#define LED_ARD_DDR       DDRB |= (1<<DDB7); PORTB &= ~(1<<PORTB7) // Port B, Bit 7 => LED Arduino-Board (Atmel -> LED) -> OUTPUT, OFF   //
19
#define LED_ARD_ON        PORTB |= (1<<PORTB7)                     // LED Arduino-Board ein                                              //
20
#define LED_ARD_OFF       PORTB &= ~(1<<PORTB7)                    // LED Arduino-Arduino aus                                            //
21
#define LED_ARD_TOGGLE    PINB |= (1<<PINB7)                       // LED Arduino-Arduino toggel                                         //
22
/*******************************************************************************************************************************************/
23
24
/********************************* LEDs (Port C) ************************************************************************************************************************/
25
#define LEDS_DDR     DDRC |= (1<<DDC7) | (1<<DDC6) | (1<<DDC5) | (1<<DDC4) | (1<<DDC3) | (1<<DDC2) | (1<<DDC1) | (1<<DDC0); // Port B, LEDS (Atmel -> LEDS) -> OUTPUT  //
26
#define LEDS         PORTC              // LEDs an Vcc                                                          //
27
/********************************* LEDs (Port C) ************************************************************************************************************************/
28
29
/********************************* Drehgeber (Port K) ********************************************************************************/
30
//#define ENC_CHA_DDR       DDRK &= ~(1<<DDK2);PORTK &= ~(1<<PORTK2) // Port K, Bit 2 => CW (Atmel <- Encoder) -> INPUT, TRISTATE      //
31
//#define ENC_CHA           PINK & (1<<PINK2)                        // Drehgerber Kanal A                                             //
32
                                                                                                                                     //
33
//#define ENC_CHB_DDR       DDRK &= ~(1<<DDK1);PORTK &= ~(1<<PORTK1) // Port K, Bit 1 => CCW (Atmel <- Encoder) -> INPUT, TRISTATE     //
34
//#define ENC_CHB           PINK & (1<<PINK1)                        // Drehgerber Kanal B                                             //
35
                                                                                                                                     //
36
//#define ENC_TASTER_DDR    DDRK &= ~(1<<DDK0);PORTK &= ~(1<<PORTK0) // Port K, Bit 0 => Taster (Atmel <- Encoder) -> INPUT, TRISTATE  //
37
//#define ENC_TASTER        PINK & (1<<PINK0)                        // Drehgeber Taster                                               //
38
/*************************************************************************************************************************************/
39
40
/********************************* Drehgeber (Port B) ********************************************************************************/
41
#define ENC_CHA_DDR       DDRB &= ~(1<<DDB6);PORTB &= ~(1<<PORTK6) // Port K, Bit 2 => CW (Atmel <- Encoder) -> INPUT, TRISTATE      //
42
#define ENC_CHA           PINB & (1<<PINK6)                        // Drehgerber Kanal A                                             //
43
                                                                                                                                     //
44
#define ENC_CHB_DDR       DDRB &= ~(1<<DDB5);PORTB &= ~(1<<PORTK5) // Port K, Bit 1 => CCW (Atmel <- Encoder) -> INPUT, TRISTATE     //
45
#define ENC_CHB           PINB & (1<<PINK5)                        // Drehgerber Kanal B                                             //
46
                                                                                                                                     //
47
#define ENC_TASTER_DDR    DDRB &= ~(1<<DDB4);PORTB &= ~(1<<PORTK4) // Port K, Bit 0 => Taster (Atmel <- Encoder) -> INPUT, TRISTATE  //
48
#define ENC_TASTER        PINB & (1<<PINK4)                        // Drehgeber Taster                                               //
49
/*************************************************************************************************************************************/
50
51
/*************************/
52
/******* Variables *******/
53
/*************************/
54
volatile int8_t gsc_enc_delta;               // -128 ... 127
55
static int8_t gsc_enc_code_old;
56
57
volatile int32_t gsl_enc_count;
58
volatile uint8_t guc_enc_pushbutton;
59
60
61
/*************************/
62
/******* Functions *******/
63
/*************************/
64
void v_test_init (void);
65
void v_encode_init (void);
66
int8_t sc_encode_read1 (void);
67
int8_t sc_encode_read2 (void);
68
int8_t sc_encode_read4 (void);
69
int8_t sc_encode_pushbutton (void);
70
71
/******************************************************************************/
72
/*****| Name:          test_init                                         |*****/
73
/*****| Funktion:      Definiert den Controllerpin, an den die Arduino-  |*****/
74
/*****|                LED angeschlossen ist als Ausgang und schaltet    |*****/
75
/*****|                diese aus. LED_ARD wird als Testpin zum Debugging |*****/
76
/*****|                benutzt.                                          |*****/
77
/*****| Übergabewerte: keiner                                            |*****/
78
/*****| Rückgabewert:  keiner                                            |*****/
79
/******************************************************************************/
80
void v_test_init (void)
81
{
82
  LED_ARD_DDR;    
83
}
84
85
void v_encode_init (void)
86
{
87
  int8_t sc_enc_code;                // Variable fuer den Code den der Drehgeber liefert
88
  
89
  ENC_TASTER_DDR;                  // Konfiguration Portpins...  
90
  ENC_CHA_DDR;
91
  ENC_CHB_DDR;
92
93
  sc_enc_code = 0;                // Variable fuer den Code mit 0 initialisieren
94
    
95
  if (ENC_CHA)                  // High an Channel A?
96
    sc_enc_code = 3;              //    
97
98
  if (ENC_CHB)                  // High an Channel B?
99
    sc_enc_code ^= 1;              // 
100
101
  gsc_enc_code_old = sc_enc_code;          // Neuen Code merken
102
  
103
  gsc_enc_delta = 0;
104
  
105
  TCCR0A = (1<<WGM01);                   // CTC
106
  TCCR0B = (1<<CS01) | (1<<CS00);            // CTC, prescaler 64
107
  
108
  OCR0A = (uint8_t)(XTAL / 64.0 * 1e-3 - 0.5);    // 1ms
109
  TIMSK0 |= 1<<OCIE0A;
110
}
111
112
int8_t sc_encode_read1 (void)                    // read single step encoders
113
{
114
  int8_t val;
115
116
  cli();
117
  val = gsc_enc_delta;
118
  gsc_enc_delta = 0;
119
  sei();
120
  return val;                              // counts since last call
121
}
122
123
int8_t sc_encode_read2 (void)                     // read two step encoders
124
{
125
  int8_t val;
126
127
  cli();
128
  val = gsc_enc_delta;
129
  gsc_enc_delta = val & 1;
130
  sei();
131
  return val >> 1;
132
}
133
134
int8_t sc_encode_read4 (void)                      // read four step encoders
135
{
136
  int8_t val;
137
138
  cli();
139
  val = gsc_enc_delta;
140
  gsc_enc_delta = val & 3;
141
  sei();
142
  return val >> 2;
143
}
144
145
int8_t sc_encode_pushbutton (void)                    // read four step encoders pushbutton
146
{
147
  static uint8_t uc_state;
148
    int8_t  sc_return_val = 0;
149
  
150
    if (uc_state == 0 && !(ENC_TASTER))        //Taster wird gedrueckt (steigende Flanke)
151
    {
152
        uc_state = 1;
153
        sc_return_val = 1;
154
    Serial.println (sc_return_val, DEC);
155
    }
156
    else if (uc_state == 1 && !(ENC_TASTER))  //Taster wird gehalten
157
    {
158
        uc_state = 2;
159
        sc_return_val = 0;
160
    }
161
    else if (uc_state == 2 && !(ENC_TASTER))  //Taster wird losgelassen (fallende Flanke)
162
    {
163
        uc_state = 3;
164
        sc_return_val = 0;
165
    }
166
    else if (uc_state == 3 && !(ENC_TASTER))  //Taster losgelassen
167
    {
168
        uc_state = 0;
169
        sc_return_val = 0;
170
    }
171
  
172
    return sc_return_val;
173
}
174
175
/*********************************/
176
/******* Main ********************/
177
/*********************************/
178
int main (void)
179
{
180
  int32_t sl_val = 0;
181
  int8_t i;
182
  
183
  LEDS_DDR;
184
  
185
  //Serial.begin (9600);
186
  v_test_init ();
187
  v_encode_init ();
188
  
189
  gsl_enc_count = 0;
190
  guc_enc_pushbutton = 0;
191
  
192
  //LED_ARD_TOGGLE;
193
  //_delay_ms (1000);
194
  //LED_ARD_TOGGLE;
195
  //_delay_ms (1000);
196
  //LED_ARD_TOGGLE;
197
  //_delay_ms (1000);
198
  //LED_ARD_TOGGLE;
199
  //_delay_ms (1000);
200
  
201
  sei ();
202
  
203
  while (1)
204
  {  
205
    sl_val += sc_encode_read4 ();              // read four step encoders
206
    LEDS = sl_val;
207
    //gsl_enc_count += sc_encode_read4 ();            // read four step encoders
208
 
209
    
210
    if (guc_enc_pushbutton)
211
    {
212
      LED_ARD_TOGGLE;
213
      //Serial.println (guc_enc_pushbutton, DEC);
214
    }
215
  }
216
}
217
218
/**********************************/
219
/******* Interrupt routines *******/
220
/**********************************/
221
ISR (TIMER0_COMPA_vect)                     // 1ms fuer manuelle Betätigung des Drehgebers
222
{
223
  int8_t sc_enc_code;
224
  int8_t sc_diff;
225
  
226
  sc_enc_code = 0;              // Variable fuer den Code mit 0 initialisieren
227
  
228
  if (ENC_CHA)                // High an Channel A?
229
    sc_enc_code = 3;            //    
230
231
  if (ENC_CHB)                // High an Channel B?
232
    sc_enc_code ^= 1;            // 
233
    
234
  sc_diff = gsc_enc_code_old - sc_enc_code;  // Differenz zwischen zwei Schritten ermitteln  
235
  
236
  if (sc_diff & 1)               // Bit 0 hat nur den Wert 1 wenn die Differenz 1 ist
237
  {                           
238
    gsc_enc_code_old = sc_enc_code;      // Neuen Code merken
239
    gsc_enc_delta += (sc_diff & 2) - 1;     // Bit 1 ist die Richtung (+/-)
240
  }
241
  
242
  guc_enc_pushbutton = sc_encode_pushbutton ();
243
}

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


Lesenswert?

Marcel schrieb:
> Mache ich Grundsätzlich etwas falsch?

Du hast ja wieder alles umgeschrieben, so das man den ursprünglichen 
Code mühsam vergleichen muss.
Ich habe das so gemacht - die Drehgeber ISR wird alle 1ms aufgerufen. 
Nach der Behandlung des Drehgebers wird eine static Variable hoch 
gezählt und wenn diese die 10 erreicht hat (alle 10ms) wird die Button 
Routine durchgespielt, die Variable wird dann wieder auf null gesetzt.
Die Abfrage geschieht dann durch die üblichen 'enc_read4' aus dem 
Drehgeber- und 'get_key_press' Routinen aus dem Entprellungsartikel.

von Marcel (Gast)


Lesenswert?

Okay, danke für die schnelle Antwort. Ich werde es ausprobieren.

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.