Forum: Compiler & IDEs Programm bleibt im Interrupt hängen?


von Paul H. (powl)


Lesenswert?

Hi!

Mein Programm besteht eigentlich hauptsächlich aus einer 
Interruptroutine. Das Main-Programm besteht nur aus einer Endlosschleife 
da alles Timerbasierend im Abstand von 1ms zu erledigen ist.
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
#include <stdint.h>
4
5
6
volatile unsigned char timer_prescaler = 0;
7
8
int main(void)
9
{
10
  DDRA |= (1 << PA5);        // Ausgänge : LED
11
12
  if(timer_prescaler == 100)            // Nur so zum testen
13
  {
14
    PORTA |= (1 << PA5);
15
  }
16
17
  TCCR0 = (1 << CS00);                                // Timer0 mit Prescaler 1
18
  TIMSK = (1 << TOIE0);                                // Timer0 Overflow Interrupt enabled
19
}
20
21
ISR(TIMER0_OVF0_vect)
22
{
23
  timer_prescaler++;
24
}

Habe hier mal irrelevante codeteile rausgeschnitten. bei 
timer_prescaler++; scheint er schon beim simulieren irgendwie hängen zu 
bleiben und nichts mehr zu machen. Das Interrupt-Flag wird auch nicht 
zurrückgesetzt. Als ich noch mehr cod ein der ISR stehen hatte kam es 
mir so vor wie als wenn er den erst garnicht ausführt?

Hab ich was falsch geschrieben? Version in voller länge könnt ihr 
meinetwegen auch haben.

lg PoWl

von Karl H. (kbuchegg)


Lesenswert?

Paul Hamacher wrote:

> Hab ich was falsch geschrieben? Version in voller länge könnt ihr
> meinetwegen auch haben.

Das wird wohl auch besser sein.

> Mein Programm besteht eigentlich hauptsächlich aus einer
> Interruptroutine. Das Main-Programm besteht nur aus einer
> Endlosschleife

So?
Wo ist die?

> #include <avr/io.h>
> #include <avr/interrupt.h>
> #include <stdint.h>
>
>
> volatile unsigned char timer_prescaler = 0;
>
> int main(void)
> {
>   DDRA |= (1 << PA5);        // Ausgänge : LED
>
>   if(timer_prescaler == 100)            // Nur so zum testen
>   {
>     PORTA |= (1 << PA5);
>   }
>
>   TCCR0 = (1 << CS00);                                // Timer0 mit
> Prescaler 1
>   TIMSK = (1 << TOIE0);                                // Timer0
> Overflow Interrupt enabled

Ich seh nirgends einen sei().
Ich seh auch nirgends die angekündigte Endlosschleife.

> }
>
> ISR(TIMER0_OVF0_vect)

Wenn ich mich recht erinnere, heist der IST aber
TIMER0_OVF_vect und nicht TIMER0_OVF0_vect

> {
>   timer_prescaler++;
> }
>

Wenn du ein Programm kürzt, was ja grundsätzlich löblich ist,
dann solltest du vor dem Posten noch mal abklären, ob das
Programm auch den Fehler zeigt, den du zeigen möchtest.
Das heist: compilieren, auf den µC brennen und noch mal
testen.
Niemand hier nimmt gerne ein Programm auseinander und listet
20 Fehler auf, nur um dann zu hören: "Im richtigen Code habe ich
die alle nicht gemacht. Andere Vorschläge`"

von Paul H. (powl)


Lesenswert?

Hi, danke erstmal.

Ich wusste nicht, ob er das I-Bit automatisch setzt ;-) Mit 
endlosschleife mein ich nur dass in der main-function am ende einfach 
schluss ist. Gewöhnlicherweise macht der compiler ja da eine kleine 
endlosschleife rein dass der adresszeiger im flash nicht sonst irgendwo 
hinläuft.

Die genannten Probleme treten auch im gekürzten Code auf, hier in voller 
Länge:

Das ganze soll eine Laminatorsteuerung werden. Die Timer-ISR wird durch 
zwei software-teiler "verzögert". Einer Stoppt ungefär 1ms ab, und ein 
innerer etwa 500ms. Das ganze dient dazu einen Taster zu bedienen und zu 
entprellen, den Motor zu steuern und die Heizung nach Temperatur mit dem 
ADC. Der Code ist noch nicht fertig.

TIMER0_OVF0_vect stimmt, da ich einen ATtiny26 benutze. Laut avr-lib 
Manual heißt das bei dem so ;-) Wenn ich was anderes reinschreib krig 
ich auch ne Warnung vom Compiler
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
#include <stdint.h>
4
#include <stdbool.h>
5
6
7
// Button:    PA4
8
// Ready-LED:  PA5
9
// Motor:      PA6
10
// Heizung:    PA7
11
12
13
// Laminatorsteuerung
14
15
#define motor_an()      PORTA |= (1 << PA6)
16
#define motor_aus()      PORTA &= ~(1 << PA6)
17
18
#define heizung_an()    PORTA |= (1 << PA7)
19
#define heizung_aus()    PORTA &= ~(1 << PA7)
20
21
#define Temperatur      235
22
23
24
volatile unsigned char timer_prescaler = 0;
25
volatile unsigned int isr_prescaler = 0;
26
27
volatile unsigned char button_debounce = 0;
28
volatile bool last_button_state = 0;
29
30
int main(void)
31
{
32
  ADMUX = (0 << REFS1) | (1 << REFS0) | (0b00010);    // Externe Referenz, ADC2
33
  ADCSR = (1 << ADEN) | (0b110);                      // ADC Prescaler 64
34
35
  DDRA |= (1 << PA5) | (1 << PA6) | (1 << PA7);        // Ausgänge : Ready-LED, Motor, Heizung
36
  PORTA |= (1 << PA4);                                // Pull-Up für Button
37
38
  motor_an();                                          // Motor zum aufheizen durchlaufen lassen
39
  heizung_an();
40
41
  TCCR0 = (1 << CS00);                                // Timer0 mit Prescaler 1
42
  TIMSK = (1 << TOIE0);                                // Timer0 Overflow Interrupt enabled
43
}
44
45
ISR(TIMER0_OVF0_vect)
46
{
47
  if(timer_prescaler == 31)                            // 8.000.000 / 256 = 31250 / 31 = ~1008 ISRs/Sek. bzw. 0,992ms/ISR
48
  {
49
    timer_prescaler = 0;
50
51
    // Tasterkennung + Entprellung
52
    if(last_button_state != bit_is_clear(PORTA, PA4) && !button_debounce)
53
    {
54
      button_debounce = 10;                            // 10ms Prellzeit
55
      
56
      if(bit_is_clear(PORTA, PA4))                    // Nur auf fallende Flanke reagieren
57
      {
58
        if(bit_is_clear(PORTA, PA6))
59
        {
60
           motor_an();
61
        }
62
        else
63
        {
64
           motor_aus();
65
        }
66
      }
67
68
      last_button_state = bit_is_clear(PORTA, PA4);
69
    }
70
    if(button_debounce)
71
    {
72
      button_debounce--;
73
    }
74
75
    if(isr_prescaler == 504)                          // 1008 ISRs/Sek. / 504 = 2 ISRs/Sek. bzw. 499,96ms/ISR
76
    {
77
      isr_prescaler = 0;
78
79
      // Motorsteuerung
80
81
82
      // Temperaturmessung + Heizungssteuerung
83
      if(bit_is_set(PORTA, PA7))                      // LED-Blinken zum Test
84
      {
85
        heizung_aus();
86
      }
87
      else
88
      {
89
        heizung_an();
90
      }
91
    }
92
93
    isr_prescaler++;
94
  }
95
96
  timer_prescaler++;
97
}

lg PoWl

von Uwe N. (ulegan)


Lesenswert?

1. Auf die Endlosschleife am Ende von main() würde ich mich nicht 
verlassen. Der Compiler 'erfindet' eigentlich keinen Code dazu.
Schau dir mal den erzeugten Assemblercode an.
Oder hänge einfach ein while(1); hintendran.
2. Den Interrupt solltest du auch einschalten. Das *Global Interrupt 
Flag* wird mit der sei(); Funktion gesetzt. Sonst kannst du lange auf 
einen Interrupt warten.

Gruß Uwe

von Karl H. (kbuchegg)


Lesenswert?

Und schreib nicht zuviel Code auf einmal.
Es hat keinen Sinn mit Unmengen Code dazustehen und dann
nciht zu wissen, wo man mit der Suche anfangen soll.
Dankbar ist es immer, zu Testzwecken eine LED einzuschalten.
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
4
ISR( TIMER0_OFV_vect )
5
{
6
  // hier die LED einschalten
7
}
8
9
int main()
10
{
11
  DDRxxx = ....              // Port für die Led auf Ausgang
12
13
  TCCR0 = (1 << CS00);       // Timer0 mit Prescaler 1
14
  TIMSK = (1 << TOIE0);      // Overflow Interrupt ein
15
16
  sei();                     // Interrupts generell ein
17
18
  while( 1 )
19
    ;                          
20
}

und damit spielst du jetzt erst mal rum und siehst nach
ob der Interrupt ausgelöst wird und die LED leuchtet.
Ruhig auch mal den Gegentest machen und die LED im
Interrupt ausschalten.

von Paul H. (powl)


Lesenswert?

danke, mit sei() und der while(1); schleife geht es!

Bisher hat er immer eine Endlosschleife reingemacht wenn ich nix mehr 
dazugeschrieben hätte. Hab mich darauf verlassen dass er das nun auch so 
macht aber dem war nicht so.

Nun funktioniert alles :-)

lg PoWl

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.