Forum: Mikrocontroller und Digitale Elektronik Interrupt Flag in ISR zurücksetzen funktioniert nicht


von Roman D. (smarties)


Lesenswert?

Hallo!

ich habe einen Datenlogger gebaut, der alle paar Minuten für die 
Messungen von einer RTC (DS1337) geweckt wird. Datenlogger mit 
sämtlichen Schnick Schnack funktioniert, nur in der ISR nach dem 
Aufwecken läuft was schief...
Ich setz den Timer an der DS1337 und schick den ATmega324PA schlafen. 
Wenn der avr über den INT0 aufgeweckt wird, wird die ISR(INT0_vect) 
ausgeführt. Soweit OK. In der ISR steht folgendes:
1
ISR(INT0_vect){
2
  led_on();
3
  rtc_clear_alm();
4
}

Die Funktion rtc_clear_alm() soll das INT Flag in der DS1337 
zurücksetzen. Bei der Zeile i2c_start(); is aber Schluss und der avr 
steckt!
1
unsigned char rtc_clear_alm(void){
2
  
3
  unsigned char errorStatus;
4
  
5
  errorStatus = i2c_start();
6
  if(errorStatus == RTC_ERROR)
7
  {
8
    i2c_stop();
9
    return(RTC_ERROR);
10
  }
11
  
12
  errorStatus = i2c_sendAddress(DS1337_W);
13
  if(errorStatus == RTC_ERROR)
14
  {
15
    i2c_stop();
16
    return(RTC_ERROR);
17
  } 
18
19
  ...
20
21
  i2c_stop();
22
  return(!RTC_ERROR);
23
  
24
  
25
}

kann mir da jemand einen Denkanstoß geben? Bin schon leicht verzweifelt!

Vielen Dank schon mal...

Roman

von Guru (Gast)


Lesenswert?

Wahrscheinlich werden in den i2c Routinen auch Interrupts verwendet. Die 
sind natürlich solange blockiert, wie Du noch in der Interrupt-Routine 
bist.

Das eigentlich anzuwendende Schema ist sowies in Interrupts nur Flags zu 
setzen und in main, wenn dieses Flag gesetzt ist, dann die entsprechende 
Aktion auszulösen. LEDs einschalten geht ja noch, aber komplexe 
Funktionen aufrufen ist eher zu vermeiden. Du siehst ja warum.

von Helfer (Gast)


Lesenswert?

Roman Dissauer schrieb:
> Die Funktion rtc_clear_alm() soll das INT Flag in der DS1337
> zurücksetzen. Bei der Zeile i2c_start(); is aber Schluss und der avr
> steckt!

I2C ist (aus MC Sicht) grottenlangsam, sowas macht man nicht in einer 
ISR. Lagere das in die main() aus.

Der MC bleibt hängen, weil standardmässig immer nur eine ISR aktiv ist, 
und i2c eine eigene ISR mitbringt. Du kannst das zwar anders haben 
(sei), scheint mir aber keine gute Idee (tm) zu sein. :)

von Roman D. (smarties)


Lesenswert?

Guru schrieb:
> Das eigentlich anzuwendende Schema ist sowies in Interrupts nur Flags zu
> setzen und in main, wenn dieses Flag gesetzt ist, dann die entsprechende
> Aktion auszulösen. LEDs einschalten geht ja noch, aber komplexe
> Funktionen aufrufen ist eher zu vermeiden. Du siehst ja warum.

Hab ich schon probiert, nur wird die ISR(INT0_vect) immer wieder 
ausgeführt, solange INT0 auf 0V liegt! Deswegen will ich ja Das INT Flag 
der DS1337 zurücksetzen... damit ich wieder ins Main Programm komme.

Hab ich da einen Denkfehler??

von Thorsten (Gast)


Lesenswert?

Nein. Schalte einfach INT0 in der ISR aus (wieder aktivieren, bevor Du 
den uC schlafen legst).

von Roman D. (smarties)


Lesenswert?

Thorsten schrieb:
> Nein. Schalte einfach INT0 in der ISR aus (wieder aktivieren, bevor Du
> den uC schlafen legst).

Gute Idee! :-) Das hat mich den ganzen heutigen Abend gekostet...
Vielen dank für die Hilfe!

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.