Forum: Mikrocontroller und Digitale Elektronik Interruptauslöser im Code ändern


von P. F. (pfuhsy)


Lesenswert?

Hallo,

in meinen Code versuche ich zwischen 2 Interruptauslösern hin- und 
herzuschalten. Geht das überhaupt so einfach ?
Vor der Hauptschleife hab ich ein Interrupt initialisiert, damit er mir 
den µC (Atmega88) aus dem Sleepmodus weckt. In der Hauptschleife muss 
ich ihn vorübergehend ausschalten, weil bei den Funktionsaufruf 
"Status_senden" der INT0, wegen der Elektronik die am Controller hängt, 
immer auf low liegt. Somit würde die ISR immer ausgeführt werden. Das 
funktioniert zwar, gefällt mir aber nicht so gut. Da gibt es sicherlich 
elegantere Lösungen. Bin für Tipps offen. Im weiteren Programmablauf 
wird eine andere Funktion aufgerufen die einen flankengesteuerten 
Interrupt benötigt und eine andere Interruptinitialisierung abarbeitet. 
Diese sieht fast identisch zur ersten aus. Und zu guter letzt soll der 
"alte" Interrupt wieder hergestellt werden und den Controller in Sleep 
versetzten.
1
void initInterrupt() //Port Interrupt initialisieren
2
{
3
//  EICRA |= (1<<ISC01) | (0<<ISC00);   //fallende Flanke am INT0 zum Datenempfang  
4
  EICRA |= (0<<ISC01) | (0<<ISC00);   //Low Level zum WakeUp (notwentig bei Power down)
5
  EIMSK |= (1<<INT0);          //externen Interrupt 0 einschalten
6
  PCICR |= (1<<PCIE2);        //PCIE2 auf pcint 23 bis 16 aktiviert 
7
  PCMSK2 |= (1<<PCINT19);        //Pin Change Interrupt 19 einschalten  
8
}
9
void initInterrupt_2() //Port Interrupt initialisieren
10
{
11
  EICRA |= (1<<ISC01) | (0<<ISC00);   //fallende Flanke am INT0 zum Datenempfang
12
  //EICRA |= (0<<ISC01) | (0<<ISC00);   //Low Level zum WakeUp (notwentig bei Power down)
13
  EIMSK |= (1<<INT0);          //externen Interrupt 0 einschalten
14
  PCICR |= (1<<PCIE2);        //PCIE2 auf pcint 23 bis 16 aktiviert
15
  PCMSK2 |= (1<<PCINT19);        //Pin Change Interrupt 19 einschalten
16
}
17
18
int main(void)      /***Hauptprogramm***/
19
{
20
  initInterrupt();  //Interrups initialisieren
21
  sei();
22
23
  while(true) //Hauptschleife
24
  {
25
   cli();          //Interrupts ausschalten
26
   Status_Senden();    //Status der Anlage zusammenfassen und senden    
27
   initInterrupt();    //Interrups initialisieren
28
   sei();          //Interrupts einschalten
29
     
30
    //Interrupt umstellen
31
    cli();
32
    initInterrupt_2();
33
    sei();
34
    Daten_auswerten();
35
    
36
    //alten Interrupt wieder herstellen
37
    cli();
38
    initInterrupt();
39
    sei();
40
41
    Sleep();        //Controller schlafen legen    
42
  }
43
}

Problem dabei ist ganz einfach, der erste Teil für sich alleine geht, 
die kombi nicht. Der Controller führt einmal die Funktion 
"Status_senden" aus, geht in sleep und wacht nicht mehr auf.
1
cli();          //Interrupts ausschalten
2
Status_Senden();    //Status der Anlage zusammenfassen und senden    
3
initInterrupt();    //Interrups initialisieren
4
sei();          //Interrupts einschalten

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Peter F. schrieb:
> Somit würde die ISR immer ausgeführt werden.

Das gilt allerdings nicht für Pinchange Interrupts. Wenn du statt INT0 
einen solchen auf den Pin PD2 legst, wird nur eine Flanke (allerdings 
jede Flanke) den IRQ auslösen.

von P. F. (pfuhsy)


Lesenswert?

Ich kann kein Pinchange auf INT0 legen, weil ich zum wecken des 
Controller ein low level brauche.

Wie kann ich die Auslöser den hin und her schalten ?

von Peter D. (peda)


Lesenswert?

Peter F. schrieb:
> Wie kann ich die Auslöser den hin und her schalten ?

Erstmal den ganzen redundanten Code rausziehen und einmal im Init vor 
der Mainloop machen. Redundanter Code verwirrt nur.

|= kann keine Bits löschen.

von P. F. (pfuhsy)


Lesenswert?

Peter D. schrieb:
> |= kann keine Bits löschen.

Ach Mensch, das ist es gewesen. Manchmal sinds doch die einfachsten 
Dinge. Danke, Peter.

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.