PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Interrupt + Timer



runner02
20.01.2011, 17:43
Grüß euch,


Habe wiedermal eine Frage:


Ich versuche den Timer eines Chips zu benutzen, dazu brauche ich interrupt...


Kann mir jemand helfen, wie ich zum Beispiel in folgende einfache Funktion ein Interrupt einbaue?


main ()
{
while (true)
{
waitMs(500)
}
}

Was ich hier http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Programmieren_mit_Interrupts
so mitbekommen habe,

brauche ich erstmal

#include <avr/interrupt.h>

und dann

sei;


danach nur mehr

ISR(Vectorname)? Und den Vectornamen bekomme ich aus dem Datasheet?

Der muss je nach Interrupttp gewählt werden, hab ich verstanden(?)

(Also wenn ein Eingang high wird, heißt er xyz; wenn der Timer schreit heißt er xxxy, .... ... )

Besserwessi
20.01.2011, 19:23
Je nach Version (3.xx vs. 4.xxx) von GCC unterscheidet sich die Syntax etwas. Für details siehe z.B. hier :
http://www.rn-wissen.de/index.php/Avr-gcc#Interrupts

Die Namen für die Interruptsvektoren liest man besser in den Include Files nach. Als z.B. in iom32.h oder ähnliches. Da sollte das selbe stehen wie im Datenblatt - wirklich ausschlaggebend ist aber das io....h file.

Hubert.G
20.01.2011, 20:27
Die ISR gehört nicht ins main.
Den Vectorname holst du dir am Besten aus deinem WinAVR Verzeichnis, dort sollte es ein avr-libc-user-manual geben.
Unter Library Reference und dann interrupts findest du die Vectorname.
Wenn du das AVR-Studio hast, dann unter Help.

runner02
21.01.2011, 10:29
Die ISR gehört nicht ins main.

Woher weiß sie dann, was sie unterbrechen soll?

Hubert.G
21.01.2011, 13:35
Woher weisst du wo der Program-Counter steht, wenn der Interrupt aufgerufen wird?
Die ISR ist eine Funktion die nicht in der main-Schleife aufgerufen wird, sonder durch den Interrupthandler.
Was möchtest du genau machen?

sternst
21.01.2011, 13:42
Die ISR gehört nicht ins main.

Woher weiß sie dann, was sie unterbrechen soll?Sieht so aus, als ob du das Konzept des Interrupts noch nicht so ganz verstanden hast. Ein Interrupt unterbricht nicht irgendeine spezielle Funktion, er unterbricht den Programmablauf im Allgemeinen, egal welche Funktion gerade ausgeführt wird.

runner02
21.01.2011, 16:40
Das heißt, ich rufe den Interrupt auf wie eine Funktion?

Oder definiere ich die Interruptbedingungen vorher, und dann unterbricht er einfach alles, was er macht?



Wenn sich jemand die Mühe machen könnte, und mein simples Programm in Post 1 mit einem Interrupt ausstatten könnte wäre ich sehr dankbar O:) Ich denke, am besten lernt es sich noch, wenn man einen einfachen Quellcode mit Kommentaren dabei hat :)

Hubert.G
21.01.2011, 17:35
ISR(TIMER0_OVF_vect){
Zahl++;
}

main ()
{
while (1)
{
if(Zahl>=100){
Mach was
}
}
}
Jedes mal wenn der Timer0 überläuft, wird die ISR aufgerufen, Zahl wird um eins erhöht.
In der main wird die Zahl bei jedem Durchlauf abgefragt, wenn sie >= 100 ist, dann wird das gemacht was du da hinschreibst.
Es fehlen hier natürlich alle #include, definitionen usw.

runner02
21.01.2011, 17:50
Danke, das verstehe ich schon mal. Nicht definiert ist hier aber der Timer, wenn meine Logik stimmt??

Hubert.G
21.01.2011, 18:00
Der Timer ist nicht initialisiert, die Variablen nicht definiert, das ist nur ein Ausschnitt aus einem Programm.

runner02
21.01.2011, 18:31
Und der Timer würde parallel zum Hauptprogramm, nein , im Hauptprogramm ablaufen, und die ISR unterbricht dann alles,
setzt den Timer zurück und zählt wo 1 dazu??

avrrobot
21.01.2011, 19:21
zu der variable zahl, die du noch definieren musst

runner02
23.01.2011, 19:49
Ich habe es nun erstmals geschafft, den Timer zu verwenden...

Aber ein Problem blieb:


//----------------------------------------------------------------------
// Titel : Töne
//----------------------------------------------------------------------
// Funktion : ...
// Schaltung : ...
//----------------------------------------------------------------------
// Prozessor : ...
// Takt : 1 MHz
// Sprache : C
// Datum : ...
// Version : ...
// Autor : ...
//----------------------------------------------------------------------
#define F_CPU 1000000 // Taktfrequenz des myAVR-Boards
#include <avr\io.h> // AVR Register und Konstantendefinitionen
//----------------------------------------------------------------------
main () // Hauptprogramm, startet bei Power ON und Reset
{

int i,j = 0;
DDRB=0b00001111;
TCCR0B=TCCR0B|(1<<CS00); //Timer0 einstellen + starten: prescaler=1 -> 1Mhz
// Timer läuft synchron zu allem ab!

while (true)
{
for(i=0;i<10000;i++) // ungefähr 1 sek Ton halten
{

if (j>=10)
{ PORTB^=(1<<PB2);
}

if (TCNT0 >= 113) // TCNT0 = Speichervariable für Timer0, geht nur bis 255 weil 8bit
{
TCNT0=0; // Reset Timer -> fängt wieder bei 0 an
j++;

}

}

waitMs(500);
j,i=0;
TCNT0=0;


for(i=0;i<10000;i++) // ungefähr 1 sek Ton halten
{

if (j>=10)
{ PORTB^=(1<<PB2);
}

if (TCNT0 >= 85) // TCNT0 = Speichervariable für Timer0, geht nur bis 255 weil 8bit
{
TCNT0=0; // Reset Timer -> fängt wieder bei 0 an
j++;

}

}

waitMs(500);

j,i=0;
TCNT0=0;


for(i=0;i<10000;i++) // ungefähr 1 sek Ton halten
{

if (j>=10)
{ PORTB^=(1<<PB2);
}

if (TCNT0 >= 64) // TCNT0 = Speichervariable für Timer0, geht nur bis 255 weil 8bit
{
TCNT0=0; // Reset Timer -> fängt wieder bei 0 an
j++;

}

}

waitMs(500);


j,i=0;
TCNT0=0;


for(i=0;i<10000;i++) // ungefähr 1 sek Ton halten
{

if (j>=10)
{ PORTB^=(1<<PB2);
}

if (TCNT0 >= 95) // TCNT0 = Speichervariable für Timer0, geht nur bis 255 weil 8bit
{
TCNT0=0; // Reset Timer -> fängt wieder bei 0 an
j++;

}

}

waitMs(500);

}
}
//----------------------------------------------------------------------




Die Töne, die gespielt werden sollen, sind A (440 Hz), D (170 Hz), G (128 Hz) und C (191 Hz)


Der erste Ton kling tief, der zweite höher.
Das passt also noch.

Aber der dritte und vierte sind genau gleich wie der zweite!!!

selbst mit erneutem setzen der Zählvariablen i und j....

:-s

runner02
06.03.2011, 12:17
Hallo Leute, mein Beitrag hier ist wohl während dem Umbau der Site ins Nirvana verloren gegangen...

Hier nochmal:
Ich will einen möglichst einfachen (und daher leicht zu verstehenden) Interrupt programmieren können.

Mein Ansatz war der:




ISR (INT0_vect)

{

i++;

}



main ()
{

int i=0; // Zählervariable
sei(); // Interrupts global einschalten
GIMSK=(1<<6) // bzw. (1<<INT0) ?? Enable INT0
MCUCR=MCUCR|(1<<ISC01)|(1<<ISC001) // rising edge -> wenn
//PORTBx 5v wird

while(true)
{
if (i==100)
{
LED EIN, WARTREN UND LED AUS
i=0;
}
}
}
Dann kam die Antwort




Du kannst im Interrupt nicht die lokale Variable einer Funktion verändern. i muss global sein (und das "volatile" nicht vergessen).
Worauf meine Vermutung war, dass ich also unter # define F_CPU und #include<...>
noch int voltaile i=0 hinzufügen muss. Soweit korrekt??


Mfg