Forum: Mikrocontroller und Digitale Elektronik AVR ISR bekommt geänderte Variablen nicht mit


von Michael N. (garril)


Lesenswert?

Hallo,

ich setze in der main-Funktion immer wieder andere Werte in Variablen.
Diese Werte werden dann beim Overflow des Timers gebraucht.

(Timer baue ich noch um, damit der nicht bis 255 sondern wie benötigt 
bis 50 zählt. So wusste ich halt, dass es geht und habs deshalb 
gelassen)

Hier mein Code:
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
4
#define F_CPU 16000000L                  // Systemtakt in Hz
5
#define an(port,b) (port) |= (1<<(b))
6
#define aus(port,b) (port) &= ~(1<<(b))
7
8
  // aktueller Counterstand
9
  int pwm_counter=0;
10
  int poti_counter=0;
11
12
  // Helligkeit von 1 bis 50
13
  int pb1_soll = 1; //zw. 1 und 50: BLAU
14
  int pb2_soll = 1; //zw. 1 und 50: GRÜN
15
  int pb3_soll = 1; //zw. 1 und 50: ROT
16
17
int main(void) {
18
19
  // Für ADC Werter
20
  uint16_t result;
21
22
  // Ausgänge setzen
23
  DDRB|=(1<<PB1);
24
  DDRB|=(1<<PB2);
25
  DDRB|=(1<<PB3);
26
27
  //ADC zum Poti auslesen
28
  ADMUX = (0<<REFS1) | (1<<REFS0);  // ADC Ref auf Avcc, PC0 gewählt, normale Formatierung
29
  ADCSRA= (1<<ADEN) | (1<<ADSC) | (0<<ADFR) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0);
30
  while (ADCSRA & (1<<ADSC) ) {}  // auf Abschluss der Konvertierung warten
31
  result = ADCW; //Dummy auslesen
32
  ADCSRA|= (1<<ADSC); //Aktuellen tatsächlichen Wert holen, wird später für erstes Poti verwendet
33
34
  // Timer 0 konfigurieren
35
  TCCR0 = (1<<CS00); // Prescaler 0!!!
36
37
  // Overflow Interrupt erlauben
38
  TIMSK |= (1<<TOIE0);
39
 
40
  // Global Interrupts aktivieren
41
  sei();
42
43
  while (1) {
44
    //folgende Zeilen sind nur zum Debuggen. LED wird nicht heller!
45
    int pb1_soll=pb1_soll+1;
46
    int pb2_soll=pb2_soll+1;
47
    int pb3_soll=pb3_soll+1;
48
49
    //Poti an PC0 ->steuert-> PB1
50
    if (poti_counter==0) {
51
      while (ADCSRA & (1<<ADSC) ) {}  // auf Abschluss der Konvertierung warten
52
      result = ADCW; //PC0 auslesen
53
      pb1_soll=result/20;
54
      ADMUX = (0<<REFS1) | (1<<REFS0) | (0<<MUX2) | (0<<MUX1) | (1<<MUX0);  // ADC Ref auf Avcc, PC1 gewählt, normale Formatierung
55
      ADCSRA|= (1<<ADSC); //Aktuellen tatsächlichen Wert holen
56
      poti_counter++;
57
    }
58
    if (poti_counter==1) {
59
      while (ADCSRA & (1<<ADSC) ) {}  // auf Abschluss der Konvertierung warten
60
      result = ADCW; //PC1 auslesen
61
      pb2_soll=result/20;
62
      ADMUX = (0<<REFS1) | (1<<REFS0) | (0<<MUX2) | (1<<MUX1) | (0<<MUX0);  // ADC Ref auf Avcc, PC1 gewählt, normale Formatierung
63
      ADCSRA|= (1<<ADSC); //Aktuellen tatsächlichen Wert holen
64
      poti_counter++;
65
    }
66
    if (poti_counter==2) {
67
      while (ADCSRA & (1<<ADSC) ) {}  // auf Abschluss der Konvertierung warten
68
      result = ADCW; //PC2 auslesen
69
      pb3_soll=result/20;
70
      ADMUX = (0<<REFS1) | (1<<REFS0) | (0<<MUX2) | (0<<MUX1) | (0<<MUX0);  // ADC Ref auf Avcc, PC1 gewählt, normale Formatierung
71
      ADCSRA|= (1<<ADSC); //Aktuellen tatsächlichen Wert holen
72
      poti_counter=0;
73
    }
74
  }
75
}
76
77
#ifndef TIMER0_OVF_vect
78
// Für ältere WinAVR Versionen z.B. WinAVR-20071221 
79
#define TIMER0_OVF_vect TIMER0_OVF0_vect
80
#endif
81
// Interrupt
82
ISR (TIMER0_OVF_vect) {
83
  if (pb1_soll==pwm_counter) {
84
    aus(PORTB,PB1);
85
  }
86
  if (pb2_soll==pwm_counter) {
87
    aus(PORTB,PB2);
88
  }
89
  if (pb3_soll==pwm_counter) {
90
    aus(PORTB,PB3);
91
  }
92
  if (pwm_counter>=50) {
93
    pwm_counter=0;
94
    if (pb1_soll>0) {
95
      an(PORTB,PB1);
96
    }
97
    if (pb2_soll>0) {
98
      an(PORTB,PB2);
99
    }
100
    if (pb3_soll>0) {
101
      an(PORTB,PB3);
102
    }
103
  }
104
  else {
105
    pwm_counter++;
106
  }
107
108
}

Die Farben der LEDs (bzw. ist es eine RGB-LED) ändert sich nicht.
Die Werte bleiben immer wie ich sie am Anfang der Variablendeklaration 
von pb1_soll, pb2_soll und pb3_soll eingestellt habe.

Schonmal Danke für eure Hilfe.

von moep (Gast)


Lesenswert?

Variablen, die du sowohl in deiner main als auch in ISRs benutzt müssen 
als "volatile" deklariert werden.

von moep (Gast)


Lesenswert?

Und:

> int pb1_soll=pb1_soll+1;
> int pb2_soll=pb2_soll+1;
> int pb3_soll=pb3_soll+1;

Die "int"s müssen hier weg

von Glaskugel (Gast)


Lesenswert?

volatile
volatile wirkt zusammen mit Typdeklarationen als Modifizierer.

  volatile typ name;

Das Schlüsselwort volatile teilt dem Compiler mit, daß die mit name 
bezeichnete Variable mit dem Datentyp typ durch Ereignisse außerhalb der 
Kontrolle des (normalen) Programmflusses verändert werden kann.
Der Wert der Variablen muß deshalb vor jedem Zugriff neu aus dem 
Hauptspeicher eingelesen werden, d.h. er darf nicht in einem Register 
des Prozessors zwischengespeichert werden.

[leicht geändertes Zitat von 
http://www.imb-jena.de/~gmueller/kurse/c_c++/c_volat.html]

von Michael N. (garril)


Lesenswert?

Danke ihr seid meine Helden :)

Es funktioniert.

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.