Forum: Compiler & IDEs Generelle fragen zum Interupt


von Gizmo (Gast)


Lesenswert?

Hallo

Ich möchte jetzt das erste mal mit einer Interupt steuerung arbeiten. 
Ich habe mir im AVR GCC Tutorial die Interupt Steuerung mal 
durchgelesen, aber es sind noch ein Paar Fragen offen.

1. Ich möchte Temperatur sensoren über I2C auslesen um ein System 
abhängig von Min. u. Max. Werten entsprechend zu kühlen oder zu heizen. 
Also sprich ich Lege 2 werte fest TempMin, TempMax, wenn TempMin 
erreicht ist wird geheizt u. wenn TempMax erreicht ist wird über Lüfter 
gekühlt.

Wie ist das jetzt zu bewerkstelligen ?

Der Temperatursensor muss ja dauernd abgefragt werden, um konstant werte 
zu liefern, die dann mit den TempMin und TempMax Variablen verglichen 
werden.
Wie löse ich nun einen Interupt aus, um aus dieser abfrage und 
vergleichs routine in die Routine reinspringe in der die Lüfter u. 
Heizungen angesteuert werden. ?

wäre nett wenn Ihr mir helfen könntet ?

Gruß Gizmo

von Karl H. (kbuchegg)


Lesenswert?

Gizmo wrote:

> 1. Ich möchte Temperatur sensoren über I2C auslesen um ein System
> abhängig von Min. u. Max. Werten entsprechend zu kühlen oder zu heizen.
> Also sprich ich Lege 2 werte fest TempMin, TempMax, wenn TempMin
> erreicht ist wird geheizt u. wenn TempMax erreicht ist wird über Lüfter
> gekühlt.

Soweit klar.

>
> Wie ist das jetzt zu bewerkstelligen ?

In einer Schleife ständig die folgenden Aktionen
wiederholen

    Sensor über I2C auslesen

    Mit Min vergleichen
    Wenn kleiner -> Heizung ein
    ansonsten -> Heizung aus

    Mit Max vergleichen
    Wenn größer -> Kühlung an
    ansonsten -> Kühlung aus

>
> Der Temperatursensor muss ja dauernd abgefragt werden, um konstant werte
> zu liefern, die dann mit den TempMin und TempMax Variablen verglichen
> werden.

Dazu packst du das ganze in eine Schleife und gut ists.

> Wie löse ich nun einen Interupt aus, um aus dieser abfrage und
> vergleichs routine in die Routine reinspringe in der die Lüfter u.
> Heizungen angesteuert werden. ?

Kein Mensch braucht dazu einen Interrupt.

Aber wenns denn unbedingt sein muss:

Du programmierst einen Timer, so dass alle paar Zig-Millisekunden
ein Interrupt ausgelöst wird. In der Interrupt Routine finden
dann die Abfrage und Auswerte Aktivitäten statt.

OK. Einen Vorteil hat diese Variante. Der Prozessor kann sich in
der Zwischenzeit schlafen legen und Strom sparen.

von Gizmo (Gast)


Lesenswert?

erst einmal Danke für Deine Hilfe.

könntest Du mir das mit dem Timer genauer erläutern ?

von Karl H. (kbuchegg)


Lesenswert?

Gizmo wrote:
> erst einmal Danke für Deine Hilfe.
>
> könntest Du mir das mit dem Timer genauer erläutern ?

Ein Timer ist erst mal einfach nur eine im µC eingebaute
'Variable'. Diese Variable wird ständig erhöht. Wie schnell
sie erhöht wird, wird mit dem Vorteiler des Timers eingestellt.
Ein Zähler ist entstanden, der ständig vor sich hinzählt.

Soweit so gut und nicht besonders aufregend.

Aber: Dieser Zähler hat wie jede andere 'Variable' einen
Datentyp. Es gibt 8-Bit Zähler und 16-Bit Zähler. Daraus
resultiert, dass es eine Obergrenze gibt, bis zu der dieser
Zähler zählen kann. Ist die Obergrenze erreicht, dann passiert
ein Overflow und der Zähler beginnt wieder bei 0.
Und genau da beginnt die Sache interesant zu werden. Denn dieser
Overflow kann einen Interrupt auslösen. Als Folge dieses Interrupts
wird ein Interrupt Handler angesprungen, der dann irgendetwas
machen kann (während der Zähler immer noch nach wie vor still
und heimlich vor sich hinzählt).

Alles was man dazu tun muss, ist:
  * Dem Timer einen Vorteiler einstellen.
    Dadurch, dass ein Vorteiler aktiviert wird, beginnt der
    Timer bereits mit seiner Zählerei.
    Der Vorteiler wird eingestellt, indem man in bestimmten,
    dem Timer zugeordneten, Steuerregistern bestimmte Bits
    setzt. Welche das sind -> Datenblatt des Prozessors

  * In weiteren Steuerregistern des Timers, gibt es Bits für
    verschiedene Eregnisse, die dem Timer zustossen können, wie
    zb. das ein Overflow passiert. Wenn man dort das richtige
    Bit setzt, dann löst der Timer einen Interrupt aus
    Welche das sind -> Datenblatt des Prozessors

  * Interrupts muessen generell freiggeben sein.
    -> sei() aufrufen

  * Dann muss man noch einen Interrupt Handler schreiben,
    damit es auch eine Aktion gibt, die bei Auftreten dieses
    speziellen Interrupts ausgeführt werden soll

Und das wars dann auch schon.

http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Die_Timer.2FCounter_des_AVR

Am Beispiel eines Mega8:
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
4
volatile uint8_t Cnt;
5
6
ISR( TIMER0_OVF_vect )      // wird aufgerufen wenn der Timer 0
7
{                           // einen Overflow Interrupt auslöst
8
  Cnt = Cnt + 1;
9
10
  if( Cnt == 5 ) {          // nach dem 5-ten Interrupt
11
    PORTB = PORTB ^ 0xFF;   // alle Pins am Port B umdrehen
12
    Cnt = 0;
13
  }
14
}
15
16
int main()
17
{
18
  DDRB = 0xFF;
19
  PORTB = 0xAA;
20
21
  TCCR0 = ( 1 << CS02 ) | ( 1 << CS01 );   // Vorteiler auf 1024
22
  TIMSK = ( 1 << TOIE0 );                  // Interrupt bei Overflow vom Timer 0
23
24
  sei();
25
26
  while( 1 )
27
    ;
28
}

Das lässt ein paar Leds am Port B blinken. Wie schnell sie blinken
hängt von der Taktfrequenz des µC ab.

Angenommen dein µC läuft mit 1Mhz.
Dann gehen diese 1Mhz auch an den Vorteiler. Der teilt durch 1024
1000000 / 1024 = 976
d.h. der Timer wird 976 mal in der Sekunde um 1 erhöht.
Da er, als 8 Bit Timer, bis 255 zählen muss ehe dann ein Overflow
passiert, bedeutet das, dass
  976 / 256 = 3.8
Overflow in einer Sekunde vorkommen. Dementsprechend wird auch
die ISR 3.8 mal in der Sekunde aufgerufen.
Da aber in der ISR bis 5 gezählt wird, ehe der Port umgeschaltet
wird, bedeutet das, dass
  3.8 / 5 = 0.76
die angenommenen Led am Port B mit einer Freuqenz von 0.76 Hz
umgeschaltet werden. Sie blinken also mit einer Frequenz von 0.38Hz
oder ( 1 / 0.38 = 2.6 ) alle 2.6 Sekunden.

von Karl H. (kbuchegg)


Lesenswert?

Vertippt.
Ich hab die falschen Vorteiler Bits genommen. Hier dir
korrekten für Mega8 - Timer0 - 1024
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
 
4
volatile uint8_t Cnt;
5
 
6
ISR( TIMER0_OVF_vect )      // wird aufgerufen wenn der Timer 0
7
{                           // einen Overflow Interrupt auslöst
8
  Cnt = Cnt + 1;
9
10
  if( Cnt == 5 ) {          // nach dem 5-ten Interrupt
11
    PORTB = PORTB ^ 0xFF;   // alle Pins am Port B umdrehen
12
    Cnt = 0;
13
  }
14
}
15
16
int main()
17
{
18
  DDRB = 0xFF;
19
  PORTB = 0xAA;
20
21
  TCCR0 = ( 1 << CS02 ) | ( 1 << CS00 );   // Vorteiler auf 1024
22
  TIMSK = ( 1 << TOIE0 );                  // Interrupt bei Overflow vom  Timer 0
23
 
24
  sei();
25
26
  while( 1 )
27
    ;
28
}

von Gizmo (Gast)


Lesenswert?

Danke erstmal

Gruß Gizmo

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.