Forum: Mikrocontroller und Digitale Elektronik Auswertung Drehgeber: GIFR INTF0 setzen funktioniert eventuell nicht?!


von Markus (Gast)


Lesenswert?

Hallo ich bin die letzen Tage dabei eine Auswertung für einen Drehgeber 
von ALPS zu programmieren.

Er soll:
- über Interrupts funktionieren (int0/int1)
- Entprellen über Timer3
- Variable "count" hochzählen/herunterzählen

Meine Hardware:
-mega162


Problem:
Er zählt an sich gut hoch und runter, allerdings fängt er oft plötzlich 
an 3-5 Schritte nacheinander in die gegenrichtung zu Zählen!!Dann wieder 
richtig! Habe mir auf einem LCD mal ein paar Hilfsvariablen darstellen 
lassen. Sie zeigen mir wenn ich Sie richtig interpretiere an, dass meine 
aufkommenden Interrupt während einer Int0/1 Routine gespeichert werden 
und trotz Gesetzen INTF0/1  nach dem Entprellvorgang durchkommen!
 und somit eine weiter Routine von int0/1 aufgerufen wird. Bin mir nicht 
sicher ob das verzählen in die andere Richtung und das deaktivieren der 
Interrupts ein und das selbe Problem sind?

Frage: Warum kommen nach dem ich INTF0 und INTF1 in  GIFR Gesetz habe 
noch Interrupts von int0 bzw. int1 durch?
1
GIFR|= _BV(INTF1) | _BV(INTF0);
 ist der Befehl vielleicht an falscher stelle?

Wäre dankbar für jede Art von Anregung oder Lösung (-:

Gruß
Markus
1
volatile uint8_t int0;
2
volatile uint8_t int1;
3
volatile uint8_t count = 0;
4
volatile uint8_t countint0 = 0;
5
volatile uint8_t countint1 = 0;
6
volatile uint8_t test;
7
volatile uint8_t test2;
8
volatile uint8_t test3;
9
10
11
void Timer3Init(void)
12
{
13
  TCCR3B = _BV(CS31);//Teiler 8 
14
  ETIMSK = _BV(OCIE3A);//overflow interrupt
15
  TCNT3 = 0;
16
  OCR3A = 60000; //ca 0.5sekunden
17
  
18
}
19
20
21
void IntInit(void)
22
{
23
  MCUCR = _BV(ISC11) | _BV(ISC01);
24
  GICR = _BV(INT1) | _BV(INT0);
25
26
}
27
28
29
ISR(INT0_vect)
30
{
31
  countint0++; //Hilfsvariable
32
  int0=1;
33
  if(int1==0 && test==0)
34
  {
35
    count++;  //wenn es der erste Interreupt ist geht er in die if schleife
36
    test=1; 
37
  }
38
  else
39
  {
40
    
41
    int1=0;
42
    int0=0;
43
    GICR &=~ (1 << INT1); //deaktvieren der Externen Interrupts
44
    GICR &=~ (1 << INT0); //deaktvieren der Externen Interrupts
45
    Timer3Init();
46
47
  }
48
49
}
50
51
52
ISR(INT1_vect)
53
{
54
  countint1++; //Hilfsvariable
55
  int1=1;
56
  if(int0==0 && test2==0)  
57
  {
58
  count--; //wenn es der erste Interreupt ist geht er in die if schleife
59
  
60
  test2=1;
61
  }
62
  else
63
  {
64
  int1=0;
65
  int0=0;
66
  GICR &=~ (1 << INT1); //deaktvieren der Externen Interrupts
67
  GICR &=~ (1 << INT0); //deaktvieren der Externen Interrupts
68
  Timer3Init();
69
  
70
  
71
  }
72
}
73
74
75
76
77
ISR(TIMER3_COMPA_vect)
78
{
79
  ETIMSK = 0x00;            //Timer3 auschalten
80
  GIFR|= _BV(INTF1) | _BV(INTF0); //****Interrupt-bit zurücksetzen (bis her aufgelaufende Int. rücksetzen)
81
  GICR = _BV(INT1) | _BV(INT0);   //Interrupt wieder anschalten
82
  
83
  test=0;    //Verriegelung
84
  test2=0;  //Verriegelung
85
  test3++;  //Hilfsvariable
86
87
}
88
89
90
91
92
int main(void)
93
{
94
    char buffer[7];
95
    
96
    
97
    DDRD &=~ (1 << PD1);   
98
    PORTD |= (1 << PD1);       
99
100
    DDRB |= (1<<PB0);
101
    PORTB |= (1<<PB0);
102
   
103
    lcd_init(LCD_DISP_ON);
104
105
    IntInit();
106
    sei();
107
 while(1)
108
                     {
109
            
110
//////////////////Nur die Anzeige der Hilfvariablen auf dem LCD////////////////////////////
111
112
                    OCR1A=count;
113
114
                       lcd_clrscr();
115
                       lcd_puts("c:");
116
                         itoa( count , buffer, 10);
117
                         lcd_gotoxy(2,0);
118
                         lcd_puts(buffer);
119
/*
120
                         lcd_gotoxy(0,1);
121
                         lcd_puts("test:");
122
                         lcd_gotoxy(5,1);
123
                         itoa( test , buffer, 10);
124
                         lcd_puts(buffer);
125
              */
126
               lcd_gotoxy(0,1);
127
                         lcd_puts("tes3:");
128
                         lcd_gotoxy(5,1);
129
                         itoa( test3 , buffer, 10);
130
                         lcd_puts(buffer);
131
/*
132
                         lcd_gotoxy(8,1);
133
                         lcd_puts("tes2:");
134
                         lcd_gotoxy(13,1);
135
                         itoa( test2 , buffer, 10);
136
                         lcd_puts(buffer);
137
*/
138
               lcd_gotoxy(8,0);
139
                         lcd_puts("i0:");
140
                         lcd_gotoxy(11,0);
141
                         itoa( countint0 , buffer, 10);
142
                         lcd_puts(buffer);
143
144
            
145
               lcd_gotoxy(8,1);
146
                         lcd_puts("i1:");
147
                         lcd_gotoxy(11,1);
148
                         itoa( countint1 , buffer, 10);
149
                         lcd_puts(buffer);
150
151
                         _delay_ms(50);
152
               
153
                     }
154
155
}

von Markus (Gast)


Lesenswert?

muss ich den beim Rücksetzen des Interruptflags irgendwas beachten außer 
das man es setzen muss?

GIFR|= _BV(INTF1) | _BV(INTF0); -> löscht doch quasi alle vorher 
anstehenden externen Interrupts das diese nicht mehr ausgeführt werden 
oder verstehe ich da was falsch?

Gruß
Markus

von spess53 (Gast)


Lesenswert?

Hi

>Er zählt an sich gut hoch und runter, allerdings fängt er oft plötzlich
>an 3-5 Schritte nacheinander in die gegenrichtung zu Zählen!!Dann wieder
>richtig!

Schon mal überlegt, das dein Drehgeber prellt?

Lass das mit den Interrupts:

http://www.mikrocontroller.net/articles/Drehgeber#Warum_Sparvarianten_nicht_gut_sind

MfG Spess

von Markus (Gast)


Lesenswert?

Hi spess,

danke für die Antwort. ja klar prellt er,das möchte ich ja mit dem 
Timer3 abfangen. Es handelt sich hierbei um eine Aufgabe von der Uni, es 
soll leider mit Interrupts gelöst werden. (-:

Gruß
Markus

von Falk B. (falk)


Lesenswert?

@  Markus (Gast)

>danke für die Antwort. ja klar prellt er,das möchte ich ja mit dem
>Timer3 abfangen.

Timer ist richtig, Interrupt auch, aber NICHT Pin Change bzw. 
Flankenwechsel an INT0/1!

MFG
Falk

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.