Forum: Compiler & IDEs Atmega32 + ISR funktioniert nicht


von Storm (Gast)


Lesenswert?

Hallo,

ich bin noch ziemlicher anfänger in der c- und mikrocontroller 
-programmierung und versuche zur Zeit, eine Servosteuerung mittels 
pwm-signal zu realisieren. Dabei soll Timer2 die pwm-signale erzeugen, 
was auch gut funktioniert. Allerdings möchte ich dem Servo mittels 
timer1 (16-bit-timer) ein gewisses "zeitgefühl" geben, also die 
verschiedenen Servopositionen sollen verschieden lange (zw. 3 und 8 
sek.) angesteuert werden.

Hier Ausschnitte vom Code:
1
#include <avr/io.h>
2
#include <stdint.h> //was ist das??
3
#include <avr/interrupt.h>
4
5
struct {
6
  unsigned Interrupt_BIT_1:1;
7
} volatile x; 
8
9
// Initialisierung für Timer1 
10
void timer_warte_initial (void) {
11
  
12
  TCNT1 = 0x0000;                     //Startwert 0 setzen
13
  TIMSK = (1<<OCIE1A);            //Output Compare Interrupt enable
14
  sei();                             //Enable Global Interrupt 
15
  TCCR1A = 0x00;       
16
  TCCR1B = ((1<<WGM12) | (1<<CS12));   //CTC-Mode, Prescaler 256
17
}
18
19
//Interrupt-service- Routine
20
ISR(TIMER1_COMPA_vect) {      //Compare Match A - Vector 
21
  x.Interrupt_BIT_1 = 1;   
22
  reti();                    // beendet die ISR
23
}
24
25
int main(void) {
26
sei();
27
     
28
  timer2_initial();
29
  OCR2 = 0x3A;
30
31
  while(1) {
32
  
33
 if (ADWert > 624) {
34
    OCR2 = 0x99; 
35
    OCR1A = 0x5b8d; // 23437,5 (3 Sek.) Output-compare-register, soll     Interrupt auslösen
36
    timer_warte_initial();            // startet timer1
37
 }
38
39
  if (x.Interrupt_BIT_1 ==1) {
40
    OCR2 = 0x19;  
41
  } 
42
 }
43
}

Dazu muss ich noch erwähnen, dass an den AD_wandler ein Abstandssensor 
angeschlossen ist, welcher Werte in ADWert schreibt. Der AD-wandler und 
die gelieferten Werte stimmen aber alle.

also was das Programm manchen soll, ist Folgendes: Wenn der AD-Wandler 
einen Wert >624 liefert, soll die Servoposition 0x99 angefahren werden, 
Timer1 soll gestartet werden, welcher nach 3 Sekunden (OCR1A = 0x5b8d, 
CTC-Mode, Prescaler 256, CPU-Takt 2 MHz) einen Interrupt auslöst.
In der Interrupt-Routine wird die Variable x.Interrupt_BIT_1 auf 1 
gesetzt und die Routine wird verlassen. Im Hauptprogramm wird der Wert 
dieser Varablen abgefragt und wenn der Wert = 1 ist, soll die 
Servoposition
OCR2 = 0x19 angefahren werden.
Das funktioniert aber nicht, irgendwie wird scheinbar die Variable 
x.Interrupt_BIT_1 nie auf 1 gesetzt, denn die position OCR2 = 0x19 wird 
nie angefahren, sondern immer nur die position OCR2 = 0x3A, das 
allerdings nach den gewünschten 3 sek.(s.3.Zeile der main-funktion, wenn 
ich diese Zeile weg lasse, bleibt der Servo allerdings immer in der 
Position OCR2 = 0x99).
Jetzt ist meine Frage warum das nicht funktioniert.
ich hoffe mein Problem ist deutlich geworden und bin für alle Hinweise 
dankbar,
Grüße,
Storm

von Stefan E. (sternst)


Lesenswert?

Das reti() hat in der ISR nichts verloren. Das zerstört dir den Stack.

von gerro (Gast)


Lesenswert?

Du mußt das Interrupt_BIT_1 wieder auf 0 setzen.

 if (x.Interrupt_BIT_1 ==1) {
    OCR2 = 0x19;
    x.Interrupt_BIT_1 = 0;
  }


Gerro

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.