Forum: Compiler & IDEs Fehler mit Interrupt?


von Koloblix (Gast)


Lesenswert?

Nabend Community

Hab ein kleines Problem mit einem Interrupt. Nutze den Interrupt 
zusammen mit dem 16Bit Timers des ATTiny24 als Zeitsicherung, falls der 
normalerweise auslösende Taster versagen sollte. Wenn ich den Interrupt 
global deaktiviere läuft die Steuerung normal, bzw. so wie sie sollte, 
nur halt ohne diese Sicherungsfunktion. Schalte ich den Interrupt global 
ein, dann funktioniert der erste Durchlauf normal, ab dem 2. hört man 
zwar, dass das FET an Port B2 kurz geschaltet wird, aber direkt wieder 
ausgeschaltet wird.

habe jetzt 2 Stunden mit AVR-Simulator versucht diesen Fehler zu 
reproduzieren, allerdings erfolglos.

Da ich den Fehler einfach nicht finden kann, poste ich einfach mal den 
Code, vl. sieht ja jemand den Fehler.
1
#include <avr/io.h>
2
#include <util/delay.h>
3
#include <avr/interrupt.h>
4
5
#define timer1_prescaler  (1 << CS11) | (1 << CS10)
6
#define timer1_aus      ~((1 << CS11) | (1 << CS10))
7
#define timer1_compare_value 0x61A
8
9
//******************************Variablen******************************
10
unsigned short int ammunition=1;
11
  
12
uint16_t erg;
13
14
unsigned short int fehler=0;
15
16
volatile unsigned short int error=0;
17
  
18
//**********Instellungsfariablen********************
19
  
20
//Munitionserkennung
21
unsigned short int ammo=0;
22
  
23
//Magazinerkennung
24
unsigned short int mag=0;  
25
  
26
27
void initPortA()
28
{
29
  /******************Initalisierung PortA****************************
30
  PortA wird nur für Sensoren genutzt!
31
  
32
  PINA0 = Trigger
33
  PINA1 = Cutoff
34
  PINA2 = Magazinerkennung
35
  PINA3 = Boltcatch
36
  PINA4 = Charginghandle
37
  
38
  PORTA auf Eingabe mit Pullup-Wiederständen
39
  */  
40
  
41
  DDRA = 0x00;
42
  PORTA = 0b11011111;  
43
}
44
45
void initPortB()
46
{
47
  /*****************Initalisierung PortB******************************
48
  PortB wird nur zur Motorsteuerung genutzt!
49
  
50
  PINB0 = Motorbremse  
51
  geschaltet bei PORTB &= ~(1<<PB0);
52
  
53
  PINB2 = Treibendes FET    
54
  geschaltet bei PORTB |= (1<<PB2);   !Beim alten layout ohne PWM ist es PB1!!!! 
55
  
56
  
57
  Der WErt wird erst gesetzt und dann den Pins die Ausgangsrichtung gesetzt um beim einschalten
58
  zu verhindern, dass Ausgangspins falsch stehen.
59
  */
60
61
  PORTB = 0b00000001;
62
  DDRB = (1 << DDB0) | (1 << DDB2);  
63
}
64
65
void initADC()
66
{
67
  /******************Iniialisierung ADC*******************************/
68
  if (ammo != 0)
69
  {
70
    if (!(PINA & (1<<PINA4))) //Munitionserkennung Brücke
71
    {
72
      ADCSRA = (1<<ADPS2) /*| (1<<ADPS0)*/ | (1<<ADATE); //Vorteiler = 8 ADATE = Free Running
73
      ADMUX = (1<<MUX2) | (1<<MUX0);  //Kanal 5 (PA5)  
74
      ADCSRA |= (1<<ADEN);
75
    }  
76
  }
77
}
78
79
void initTimer()
80
{
81
  /*****************Initialisierung Timer1****************************/
82
  
83
  TIMSK1 |= (1 << OCIE1A);
84
  OCR1A   = 0x1388;
85
}
86
87
void loading()
88
{
89
  while(PINA & (1<<PINA2));
90
  while(!(PINA &(1<<PINA2)))
91
  {
92
    _delay_ms(20);
93
  }
94
  ammunition=1;
95
}
96
97
void magazine()
98
{
99
  if (mag !=0)
100
  {
101
    while (!(PINA & (1<<PINA2)));
102
  }  
103
}
104
105
void WaitForTrigger()
106
{
107
  while (PINA & (1 << PINA0));
108
  if (ammunition == 0 && ammo != 0)
109
  {
110
    loading();
111
  }
112
}
113
114
void mbreak()
115
{
116
  ADCSRA |= !(1<<ADSC);
117
  PORTB &= ~(1<<PB2);
118
  _delay_ms(1);
119
  PORTB &= ~(1<<PB0);
120
  _delay_ms(100);
121
  PORTB |= (1<<PB0);  
122
  while(!(PINA & (1<<PINA0)))
123
  {
124
    _delay_ms(10);
125
  }
126
  
127
}
128
129
void shoot()
130
{
131
  ammunition = 0;
132
  ADCSRA |= (1<<ADSC);
133
  TCNT1 = 0;
134
  TIMSK1 |= (1 << OCIE1A);
135
  TCCR1B |= (1 << CS11) | (1 << CS10);
136
  PORTB |= (1<<PB2);
137
  if  (!(PINA & (1<<PINA1))) //mit Hallsensor muss die bedingung andersherum sein! ohne "!"
138
  {
139
    while (!(PINA & (1<<PINA1))); //mit Hallsensor muss die bedingung andersherum sein! ohne "!"
140
  }
141
  while ((PINA & (1<<PINA1))  && (error!=1)) //mit Hallsensor muss die bedingung andersherum sein! mit "!"
142
  {
143
    if (ammo != 0)
144
    {    
145
      erg = ADCW;
146
      if (erg < 0x0C8)
147
      {
148
      ammunition = 1;
149
      }
150
    }      
151
  }
152
  TIMSK1 &= ~(1 << OCIE1A);
153
  TCCR1B &= ~(1 << CS11) | ~(1 << CS10);
154
  error = 0;
155
  ADCSRA &= ~(1<<ADSC);
156
  mbreak();
157
}
158
159
160
int main(void)
161
{
162
  initPortA();
163
  initPortB();
164
  initADC();
165
  initTimer();
166
  
167
  //magazine();
168
  _delay_ms(100);
169
170
  //WaitForTrigger();
171
  //shoot();  
172
173
  sei();
174
  while(1)
175
  {
176
    //magazine();
177
    WaitForTrigger();
178
    shoot();
179
  }
180
}
181
182
ISR(TIM1_COMPA_vect)
183
{
184
  TIMSK1 &= ~(1 << OCIE1A);
185
  TCCR1B &= ~((1 << CS11) | (1 << CS10));
186
  error=1;
187
}

Hoffe der Code ist verständlich.

Ich danke euch schon mal für eure Hilfe.

Kolo

von Peter S. (psavr)


Lesenswert?

Ein erster Tipp: statt "unsigned short int" (=16 Bit) könntest Du 
überall auch 8 Bit Variabeln verwenden, => "uint8_t"

Hilft vermutlich nicht weiter, aber macht den Code auf einer 8-Bit CPU 
deutlich effizienter...

von Stefan E. (sternst)


Lesenswert?

1
  TCCR1B &= ~(1 << CS11) | ~(1 << CS10);
Das soll wohl den Timer stoppen, aber in Wirklichkeit wird mit dieser 
Zeile kein einziges Bit in TCCR1B verändert.

von Peter S. (psavr)


Lesenswert?

>>  TCCR1B &= ~(1 << CS11) | ~(1 << CS10);
>
>Das soll wohl den Timer stoppen, aber in Wirklichkeit wird mit dieser
>Zeile kein einziges Bit in TCCR1B verändert.

Hehehe, dabei hat er's weiter oben sooooo schööööööön definiert:

#define timer1_aus      ~((1 << CS11) | (1 << CS10))

von koloblix (Gast)


Lesenswert?

Ja, daher ja die unabhängige Meinung. Hab das nicht gesehen :D Werd das 
nachher mal ändern. Aber an sich dürfte das dich nicht so viel ausmachen 
da das Compare Interrupt Flag auch auf null gesetzt wird.
1
TIMSK1 &= ~(1 << OCIE1A);

von Stefan E. (sternst)


Lesenswert?

koloblix schrieb:
> Aber an sich dürfte das dich nicht so viel ausmachen
> da das Compare Interrupt Flag auch auf null gesetzt wird.

Das ist nicht das Flag, sondern das Enable-Bit. Und das verhindert 
nicht, dass beim nächsten Erreichen des Compare-Wertes das entsprechende 
Flag gesetzt wird. Und wenn dann das Enable-Bit wieder gesetzt wird, 
kommt sofort der Interrupt, weil ja das dazugehörige Flag dann schon 
gesetzt ist.

von Koloblix (Gast)


Lesenswert?

Aha, ok das klärt einiges. THX

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.