www.mikrocontroller.net

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


Autor: Paul H. (powl)
Datum:

Bewertung
0 lesenswert
nicht 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.
#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
}

ISR(TIMER0_OVF0_vect)
{
  timer_prescaler++;
}

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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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`"

Autor: Paul H. (powl)
Datum:

Bewertung
0 lesenswert
nicht 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
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdint.h>
#include <stdbool.h>


// Button:    PA4
// Ready-LED:  PA5
// Motor:      PA6
// Heizung:    PA7


// Laminatorsteuerung

#define motor_an()      PORTA |= (1 << PA6)
#define motor_aus()      PORTA &= ~(1 << PA6)

#define heizung_an()    PORTA |= (1 << PA7)
#define heizung_aus()    PORTA &= ~(1 << PA7)

#define Temperatur      235


volatile unsigned char timer_prescaler = 0;
volatile unsigned int isr_prescaler = 0;

volatile unsigned char button_debounce = 0;
volatile bool last_button_state = 0;

int main(void)
{
  ADMUX = (0 << REFS1) | (1 << REFS0) | (0b00010);    // Externe Referenz, ADC2
  ADCSR = (1 << ADEN) | (0b110);                      // ADC Prescaler 64

  DDRA |= (1 << PA5) | (1 << PA6) | (1 << PA7);        // Ausgänge : Ready-LED, Motor, Heizung
  PORTA |= (1 << PA4);                                // Pull-Up für Button

  motor_an();                                          // Motor zum aufheizen durchlaufen lassen
  heizung_an();

  TCCR0 = (1 << CS00);                                // Timer0 mit Prescaler 1
  TIMSK = (1 << TOIE0);                                // Timer0 Overflow Interrupt enabled
}

ISR(TIMER0_OVF0_vect)
{
  if(timer_prescaler == 31)                            // 8.000.000 / 256 = 31250 / 31 = ~1008 ISRs/Sek. bzw. 0,992ms/ISR
  {
    timer_prescaler = 0;

    // Tasterkennung + Entprellung
    if(last_button_state != bit_is_clear(PORTA, PA4) && !button_debounce)
    {
      button_debounce = 10;                            // 10ms Prellzeit
      
      if(bit_is_clear(PORTA, PA4))                    // Nur auf fallende Flanke reagieren
      {
        if(bit_is_clear(PORTA, PA6))
        {
           motor_an();
        }
        else
        {
           motor_aus();
        }
      }

      last_button_state = bit_is_clear(PORTA, PA4);
    }
    if(button_debounce)
    {
      button_debounce--;
    }

    if(isr_prescaler == 504)                          // 1008 ISRs/Sek. / 504 = 2 ISRs/Sek. bzw. 499,96ms/ISR
    {
      isr_prescaler = 0;

      // Motorsteuerung


      // Temperaturmessung + Heizungssteuerung
      if(bit_is_set(PORTA, PA7))                      // LED-Blinken zum Test
      {
        heizung_aus();
      }
      else
      {
        heizung_an();
      }
    }

    isr_prescaler++;
  }

  timer_prescaler++;
}

lg PoWl

Autor: Uwe Nagel (ulegan)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.
#include <avr/io.h>
#include <avr/interrupt.h>

ISR( TIMER0_OFV_vect )
{
  // hier die LED einschalten
}

int main()
{
  DDRxxx = ....              // Port für die Led auf Ausgang

  TCCR0 = (1 << CS00);       // Timer0 mit Prescaler 1
  TIMSK = (1 << TOIE0);      // Overflow Interrupt ein

  sei();                     // Interrupts generell ein

  while( 1 )
    ;                          
}

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.

Autor: Paul H. (powl)
Datum:

Bewertung
0 lesenswert
nicht 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

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.