Forum: Compiler & IDEs Global Variablen in Interrupt-Routine


von André (Gast)


Lesenswert?

Hallo miteinander,

ich bin kurz vor dem Verzweifeln:

Ich möchte in einem Projekt ganz einfach über einen Timer die globalen 
variablen sec, min, hour hochzählen. Ich habe diese Variablen jeweils 
als

volatile uint8_t deklariert.

Das irrwitzige ist, dass mein code, wenn ich in in SiSy compile und 
brenne, fehlerfrei läuft. Ich möchte aber gern in Zukunft im 
AtmelStudio6 arbeiten. Und hier läuft der code leider nicht fehlerfrei, 
da auf die globalen Vriablen nicht zugeriffen bzw. sie nicht hochgezählt 
werden. Die ISR wird zwar angesprungen und eine LED wird auch im 
Sekundentakt getoggelt, aber die Bedingung sec > 59 wird nie erreicht. 
Und beim build läuft alles ohne Warnungen und Fehlermeldung ab.

Die Interrupt-Routine ist wie folgt umgesetzt:
1
ISR(TIMER1_COMPA_vect)
2
{
3
   sec++;
4
  PORTB ^= (1<<PB0);
5
  if (sec > 59)
6
  {
7
      min++;
8
      sec = 0;
9
      PORTB ^= (1<<PB1);
10
  }
11
  if (min > 59)
12
  {    
13
    min = 0;
14
      hour++;
15
  }
16
  if (hour>23)
17
     hour = 0;  
18
}
Ich habe weitere banale Testprogramme umgesetzt, bei denen 
ausschließlich in der main-loop irgendetwas passiert, und die 
funktionieren einwandfrei. Ich meine das Problem tatsächlich auf die 
Verwendung von globalen Variablen eingrenzen zu können.

Ich bin für jeden Tipp dankbar.
André

Hier noch ein paar Eckdaten:
Ich nutze einen ATMEGA8,
AtmelStudio6 Version 6.1.2730,
gcc 4.7.2

: Bearbeitet durch User
von Michael R. (Firma: Brainit GmbH) (fisa)


Lesenswert?

Du möchtest uns sicher den ganzen Code zeigen...

von modstanden (Gast)


Lesenswert?

>aber die Bedingung sec > 59 wird nie erreicht.
Hast Du einen Debugger ? Woher weißt Du das ?
Geht es vielleicht, und nur PORTB ^= (1<<PB1); funktioniert nicht ?

von Karl H. (kbuchegg)


Lesenswert?

Dann schätze ich mal, dass ein paar vergessene 'volatile' das Problem 
sind.

FAQ: Was hat es mit volatile auf sich

: Bearbeitet durch User
von Wilhelm F. (Gast)


Lesenswert?

Karl Heinz schrieb:

> Dann schätze ich mal, dass ein paar vergessene 'volatile' das Problem
> sind.
>
> FAQ: Was hat es mit volatile auf sich

Ob da was weg optimiert wurde, das sollte sich aus den Listings aber 
heraus finden lassen. Dafür sind sie doch da.

von André (Gast)


Lesenswert?

Hallo,

ja entschuldigt bitte, dass ich nur die Hälfte des codes gepostet habe.

Nun kommt doch alles anders:
Als ich der Bitte nachkommen wollte, den ganzen code hier einzustellen, 
ist mir aufgefallen, dass der code in SiSy nicht 100% dem in AtmelStudio 
entsprach.

Hier der code, wie ich ihn in SiSy nutze:
1
#define   F_CPU   3686400
2
#include <avr\io.h>
3
#include <avr\interrupt.h>
4
5
volatile uint8_t sec, min, hour;
6
7
ISR(TIMER1_COMPA_vect)
8
{
9
  sec++;
10
  PORTB ^= (1<<PB0);
11
  if (sec > 5)
12
  {
13
    min++;
14
    sec = 0;
15
    PORTB ^= (1<<PB1);
16
  }
17
  if (min > 59)
18
  {
19
    min = 0;
20
    hour++;
21
  }
22
  if (hour>23)
23
  hour = 0;
24
  
25
}
26
27
28
ISR(ADC_vect)
29
{
30
  // Beginn der Ereignisbehandlung
31
  uint16_t wert=ADC;   // Einlesen des Analogwertes Low+High-Teil
32
}
33
34
35
void init()
36
{
37
38
  DDRB=0b00000011; // Ports initialisieren
39
  TCCR1B=0x03;   // Teiler 1/64
40
  TCCR1B|=0x08;   // Zählen bis Vergleichswert
41
  OCR1A=57600;   // Vergleichswert speichern
42
  TIMSK|=0x10;   // Interrupt bei Vergleichswert
43
  ADMUX=0x40;   // Port, Referenzspannung und Auflösung
44
  ADCSRA=0xED;   // Modus, Interrupt und Start
45
  
46
  sei();
47
}
48
49
50
int main()
51
{
52
  
53
  init();
54
  while (1)
55
  {
56
    
57
  }
58
}

Hier ist noch eine zusätliche, eigentlich unnütze ISR(ADC_vect), da ich 
keinen ADC initialisert habe. Um hier ein Minimalbesipiel zu posten, 
habe ich also diese ISR im Code gelöscht. Das Resultat war, dass nun 
auch das Programm in SiSy nicht mehr läuft. (???)

Wenn ich die Zeilen
1
ISR(ADC_vect)
2
{
3
  // Beginn der Ereignisbehandlung
4
  uint16_t wert=ADC;   // Einlesen des Analogwertes Low+High-Teil
5
}
auch in den code im AtmelStudio einfüge, funktioniert das Hochzählen der 
globalen Variablen auch.

Das ist einerseits erfreulich, dass ein und derselbe code in 
unterschiedlichen Entwicklungsumgebungen zum selben Ergebnis führt, ABER 
was hat der funktionierende Programablauf mit der überflüssigen Routine
1
ISR(ADC_vect)
2
{
3
  // Beginn der Ereignisbehandlung
4
  uint16_t wert=ADC;   // Einlesen des Analogwertes Low+High-Teil
5
}
zu tun?

Mache ich bei der Interruptbehandlung grundlegend etwas falsch?

Vielen dank für Eure Hilfe und ich entschuldige mich für die gestifftete 
Verwirrung
André

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

Gibts du einen Interrupt frei, für den du keinen Handler hast, wird das 
mit einem Programm-Reset bestraft.

Ich  hab keine Ahnung, was da hier
1
  ADCSRA=0xED;   // Modus, Interrupt und Start

tatsächlich alles freigegeben wird.
Mich interessiert es nämlich nicht mehr, mir die Bitbelegung aus dem 
Datenblatt rauszusuchen. Wenn du nicht in der Lage bist, das so zu 
schreiben, dass man das leicht sehen kann, dann such dir selber raus, ob 
hier ein Interrupt freigegeben wird oder nicht.

: Bearbeitet durch User
von Basti (Gast)


Lesenswert?

Da wird also in eine  Interrupt gesprungen dens nicht gibt und du 
fragst, was falsch sein könnte? Lies doch erstmal deine eigenen 
Codekommentare ;)

von Karl H. (kbuchegg)


Lesenswert?

Selbiges hier
>  TIMSK|=0x10;   // Interrupt bei Vergleichswert

Wie gesagt:
gibst du einen Interrupt frei, brauchst du einen Handler dafür.
Zuwiderhandlungen werden mit einem Reset bestraft.

von André (Gast)


Lesenswert?

Hallo miteinander,

ich war wohl schon betriebsblind und habe bei copy/paste die 
Initialisierung des ADC mitgeschleppt und garnicht mehr auf dem Schirm 
gehabt, Sorry.

Das kommt davon, wenn man versucht seinem Hobby zwischen Tür und Angel 
nachzugehen und eigentlich doch nicht die nötige Ruhe dafür hat.

Aber eins ist sicher: Hier im Forum bekommt man immer die Lösung für 
sein (hausgemachtes) Problem geliefert. Vielen Dank dafür.

Und nochmals Entschuldigung für die Verwirrung.

Gruß
André

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.