Interrupt initialisieren???

Maik15

Neues Mitglied
06. Sep. 2009
55
0
0
Sprachen
Hallo
Ich bin schon den ganzen Tag auf der Suche nach dem Interruptverständnis. :cool:

Das Grundprinzip ist schon klar aber welches Register ist für was:?:

Beispiel für einen Timer:
Soweit ich weiß ist das
TCCR1A das 1.Kontrollregister für die art der E/A Ports also in meien fall auf 00hex setzen bzw. so lassen. Weil ich ja keine Ausgabesignale haben will und auch kein Interrupt durch Externe eingaben auslösen will

TCCR1B ist das 2. Kontrollregister und für die Vorteilung verantwortlich zB. 1/1024. also 05hex

In einem Musterprogramm hab ich dann noch
TCNT1
OCR1A
TIMSK
gefunden
Aber ich weiß nicht genau wofür die sind.
Und Datenblätter mit Google zu übersetzen macht auch nur eingeschränkt sinn.

Wenn ich den Interrupt dann mal fertig hab und als Funktion (Unterprogramm) schreiben möchte muss ich ihn ja einmal in main schreiben
Das müsste dann doch mit @interrupt ..... und dann den Interrupt- Namen geschrieben werden? Oder hab ich das falsch in Erinnerung.

Gruß
Maik
 
Hallo @Maik....

herzlich willkommen im Forum.

Nun,
schau mal hier:
http://www.avr-praxis.de/forum/showthread.php?t=151

Da hatte ich am Anfang auch massive Verständnisprobleme mit.
Vielleicht hilft es Dir etwas??


Gruß von Oskar01

P.S.:
Also, Interrupts sind bei den AVR MCUs "Einsprungadressen", die hierarchisch gegliedert sind
und am Anfang des Programms definiert werden müssen.
Hinter diesen "Vektoren" steht dann meistens ein direkter Sprung in eine Interrupt-Service-Routine, die bei Interrupt-Bedingung abgearbeitet und mit RETI abgeschlossen wird mit Rücksprung auf die Stelle, wo das Hauptprogramm unterbrochen wurde .

In den einzelnen Steuerregistern ist nun noch angegeben, unter welchen Bedingungen ein
Interrupt ausgelöst werden soll, oder überhaupt nicht.

Dann die generelle Interruptfreigabe mit "sei" und Sperren mit "cli" im laufenden Programm zur Vermeidung von "kritischen" Situationen, ist noch zu nennen in diesem Zusammenhang.

TIMSK ist ein Timer-Interrupt-Maskierungs-Register, also nur für die Timer-Funktionen zuständig.

GIMSK zum Beispiel für externe "Hardware"-Interrupt-Ereignisse an bestimmten Eingängen (Flankentriggerung INT0 / INT1 etc.).

TCNT1H ist Timer-Register (high Byte) hier lädt man einen "Vorladewert" rein.
TCNT1L ist Timer-Register (low Byte)
OCR1AH ist Timer-Compare-Register (high Byte) hier wird definiert, an welchem Wert
ein "Vergleich" stattfinden soll.
OCR1AL ist Timer-Compare-Register (low Byte)

Das Erreichen eines Vergleichswertes kann dann einen entsprechenden Interrupt auslösen, oder das Überlaufen eines Timer-Zählers alleine schon löst was aus. (TOV Timer Overflow- fehlt in Deiner Auflistung....)
Da gibt es noch eine Reihe mehr von.
Darüber später mehr. Soll für den Anfang genügen.
Unten für den ATTiny2313 auszugsweise die Register Summary des Handbuches einkopiert.

Laß Dich jetzt nicht von der Fülle der Features abschrecken, vielleicht postest Du mal Deinen Code, bzw. erzählst uns etwas mehr über Dein Projekt, dann können wir Dir hier ganz gezielt Hilfestellung leisten.
 

Anhänge

  • Register.png
    Register.png
    7,8 KB · Aufrufe: 8
Danke erstmal.

Das bringt mich wieder ein kleines stück weiter.
allerdings will ich in C Programmieren.

Gibt es nicht irgendwo ein Programm Bibliothek in der man sich mal ein paar Programmbeispiele ansehen kann?

Gruß
Maik
 
Ja auf die Seit bin ich auch schon gestoßen.
Leider werd ich daraus nicht so reicht schlau.

Das war dann auch einer der Gründe warum ich mich hier angemeldet hab

Aber liegt vielleicht auch nur an mir.
Das ich mich so schwer damit tu.

Um zB. eine Variable k aufwärts zu zählen und es am Port B auszugeben
Müsst doch das Programm etwa so aussehen.

#include <avr/io.h>
#include <avr/interrupt.h>

int k;

@Interrupt void ISR_TIMER0 (void) //Interrupt Deklaration

TCCR1A = 0x00; //keine PWM und keine Externen Interrupts
TCCR1B = 0x05; // Vorteile von 1024
TIMSK = 0x500 //beim erreichen vom Zählerwert 500hex
//wird der Interrupt ausgelöst
...
...
//===============================================
void main(void)
{
DDRB = 0xFF;

while (1) // Endlos Schleife
{
PORTB = k; // k in das Port B schreiben
}
return 0;
}

//===============================================
@Interrupt void ISR_TIMER0 (void) // Interrupt Funktion
{
k=k+1; // k um 1 erhöhen
}

Das kann aber noch nicht alles gewesen sein weil irgendwie geht es nicht.
Kann mir vielleicht einer helfen?
Was hab ich vergessen?

Gruß
Maik
 
Hallo Maik,

willkommen in unserem Forum.

In deinem Beispiel hast du mehrere (Denk-) Fehler. Du möchtest den Overflow-Interrupt vom Timer0 nutzen, initialisierst aber Register vom Timer1. Das Register TIMSK ist 8Bit breit, du schreibst dort aber ein 16Bit-Wert rein (0x500).

Ein Tipp, wenn du Konfigurationsregsiter beschreibst, nutze immer die richtigen Bit-Namen, das macht das Programm lesbarer und wartbarer.

Schau dir auch vielleicht einmal folgenden Beitrag an: AVR-Timer-Calculator

In dem C-Beispiel wird der Timer0 und der CompareInterrupt initialisiert. Die Interruptroutine wird in dem Beispiel einmal in der Millisekunde aufgerufen. In der Interruptserviceroutine kannst du
  • entweder deine Variable direkt inkrementieren,
  • oder dort ein Flag setzen, welches du in einer Endlosschleife while(1) in main() auswertest und dort die Variable inkrementierst.
Anstelle des Compareinterrupts könntest du auch den TimerOverflowInterrupt nutzen, was allerdings nicht so elegant ist, da man in der ISR selbst den Timer wieder auf einen bestimmten Startwert setzen muss.

Die Mikrocontroller unterscheiden sich oft etwas voneinander, das heisst, nicht jeder Beispielcode ist universell für alle Mikrocontroller einsetzbar. Du wirst also nicht drumherum kommen, das Datenblatt deines Mikrocontrollers anzusehen und den Beispielcode enstsprechend anzupassen.

Schau dir einfach mal das C-Beispiel im oben angegebenen Link an und versuche zu verstehen, was ich hier mit den Timer0-Registern mache. Im Datenblatt findest du Infos im Kapitel "8Bit-Timer0/Register descriptions".

Vielleicht hilft dir das ja weiter.

Grüße,
Dirk
 
Danke für die Infos und vor allem der Link mit dem Tool ist klasse.
Werd ich sicher noch gebrauchen können.

Für diese einfach Beispiel ist sicher ein Overflow Interrupt einfacher aber da ich im Augenblick dabei bin mir Module zu Erschaffen.
Und dabei wollte ich mich wieder vertraut machen mit der Thematik.

Am ende soll dann ein gesamt Programm rauskommen.

Kurze Programmvorstellung.
Das Programm soll in einstellbaren Zeitinterwallen Analoge und Digitale Werte einlesen in einem Externem EEPROM Speichern und auf Knopfdruck die Daten an einen PC übertragen.

Die Aufnahmeinterwalle sollen zwischen 100ms und 10min liegen.
Ich denke mal das geht mit Compareinterrupts leichter zu machen.
Auch wen das einrichten bedeutend schwerer ist.
Je nach dem welche Abtastzeit eingestellt wird, wird der Comparwert oder der Vorteiler geändert. Das müsste doch funktionieren.

Gruß
Maik
 
So ich glaub jetzt hab ich es hinbekommen.

Zumindest in der Simulation klappt alles.
Aber wenn ich das Programm auf das Bord lade leichte nur das Ganze PortB.


Sind meine Augen zu langsam?
Oder hab ich doch noch einen Fehler in dem Programm?
So weit ich es berechnet hab müsste dort bei 4MHz ein 32sek Blinken bei raus kommen.

Code:
#include <avr/io.h>		        //Datei für Ein und Ausgänge
#include <avr/interrupt.h>		//Datei für Interrupt

//===============================================================

int k;

//===============================================================

	ISR (TIMER1_COMPA_vect)			// Interrupt Vektorvariable vom Timer1 Compare
		{
		k=k+1; 					// k um 1 erhöhen
		}
	
//===============================================================

int main(void)
	{

	cli ();				//alle Interrupts sperren um 16Bit Register zu beschreiben
	
	TCCR1A = 0x40; 		//keine PWM und OC1 wird beim Interrupt invertiert
	TCCR1B = 0x0D; 		//Compare Modus (vergleich mit Sollwert) & Vorteile 1024

	OCR1AH = 0xFF;		//16 Bit Compare Register A die 8 Hohen Bits (Vergleichswerte Register)
	OCR1AL = 0x0F;		//16 Bit Compare Register A die 8 Niedrige Bits (Vergleichswerte Register)
	
	sei ();				        //alle Interrups wieder freigeben 

	TIMSK |= (1<< OCIE1A); 		//Compare Interrupt aktivieren

//===============================================================

	DDRB = 0xFF;					// PortB als Ausgabeport
	PORTB = 0x00;
		
	while (1) 						// Endlos Schleife
		{
		if (k>= 0x02)
			{
			PORTB++;
			k = 0x00;
			}
		}
	return 0;
	}
Wäre echt nett wenn mir jemand weiter helfen kann.

Gruß
Maik
 
Hallo Maik,

welchen Mikrocontroller verwendest du? Es kann sein, dass du es schon mal erwähnt hast und ich es einfach nur übersehen habe.

Was ich jetzt schon mal sagen kann, du wählst die alternative Portfunktion OC1A (?), also den OutputComparePin, benötigst du den eigentlich?

Dirk
 
Hi Dirk

Ich benutze einen Mega32.
Ich bin davon ausgegangen das der OP1 gesetzt sein muss damit der Compare Interrupt funktioniert.


Gruß
Maik
 
Hi Maik,
Ich bin davon ausgegangen das der OP1 gesetzt sein muss damit der Compare Interrupt funktioniert

nein, das ist ein zusätzliches Feature. Ich sehe mir das nachher mal an, habe gerade keine Zeit :)

Dirk
 
Ich habe mir dein Programm mal angesehen.

Den OutputCompare-Pin benötigst du nicht (Bit OC1A=0). Du musst den Timer Mode 4 einstellen (Compare Event mit OCR1A Register), das ist auch soweit richtig.



CodeBox C

//** Timer initialisieren **
TCCR1A = 0x00; // nach Reset nicht notwendig
TCCR1C = 0x00; // nach Reset nicht notwendig
TCNT1 = 0x0000; // Startwert Counter
OCR1A = 62499; // 16s Comparezeit bei fosc=4MHz und Timerprescaler=1024. Du verdoppelst die zeit durch k ja nochmal, erreichst also 32s
TIFR |= (1<<OCF1A); // Interruptanforderungsflag sicherheitshalber löschen
TIMSK |= (1<<OCIE1A); // OutputCompareInterrupt freigeben
TCCR1B = (1<<WGM12) | (1<<CS12) | (1<<CS0); // CTC Mode 4, Prescaler 1024, OCR1A Compare Event, Timer Start



Soweit müsste eigentlich alles stimmen, ich habe einen etwas anderen Wert für OCR1A, aber der ist nur minimal unterschiedlich zu deinem Wert.

Definiere deine globale Variable k mal als 8bit, 16bit brauchst du nicht und als volatile. Ausserdem solltest du k initialisieren.


CodeBox C

volatile uint8_t k;


Bist du sicher, dass der Mikrocontroller wirklich mit 4MHz läuft. Eventuell einfach mal in einer while(1) Schleife Pause und Pin-Toggeln.

Hmmm, ansonsten fällt mir im Moment auch nichts mehr ein. :hmmmm:

Grüße,
Dirk
 
Danke für die Mühe

Ich hab gerade Abendbrot gegessen und hab dabei Das Bord nicht ausgeschaltet.
Also ich wieder am Schreibtisch war waren einige LED's aus.
Hab das jetzt mal im länger beobachtet.
Die Interruptzeit scheint auf 4min und 30sek zu stehen.

Da muss ich nich ja tierisch verrechnet haben.
Und zu allem überfluss sind die LED's anscheint Low Aktiv.
Deshalb haben alle geleuchtet.

Ich bin immer davon ausgegangen das die High Aktiv sind.
Na je so lernt man langsam das Bord auch kennen.

Tut mir leid das Du soviel arbeit mit mir hattest.
Aber Danke noch mal echt super das Forum

gruß
Maik
 
Ach ja eine Frage hab ich noch.

Gibt es eigentlich ein Tool womit man in Echtzeit in den Controller kucken kann.
Um die Register und Speicher ansehen zu können?
So wie man es ja Simulieren kann.
Aber das ist ja nun mal nicht Echt.

Das hätte mir heut echt geholfen.:pcguru:

gruß
Maik
 
Hi Maik,
Ach ja eine Frage hab ich noch.

Gibt es eigentlich ein Tool womit man in Echtzeit in den Controller kucken kann.
Um die Register und Speicher ansehen zu können?
So wie man es ja Simulieren kann.
Aber das ist ja nun mal nicht Echt.

Das hätte mir heut echt geholfen.:pcguru:

sowas nennt sich Emulator. Direkt von Atmel gibts den JTAGICEmkII und den AVR One, ich setze beide selber ein. Wir haben beide in unserem Onlineshop.

Nochmal wegen deinem Programm, dort stimmt trotzdem noch irgendwas nicht so richtig, da die Zeit zu groß ist. Welches Developmentboard setzt du denn eigentlich ein, STK500?

Noch einen schönen Abend,
Dirk
 
Na gut für bei dem Preis werd ich wohl darauf verzichten.

Das Bord ist übrigens ein STK 500.
Der Chip ist noch in der Herstellereinstellung (zumindest was die Fuse Bit angeht)

gruß
Maik
 
Ja, die Programmer/Emulatoren sind nich billig :(

Das Bord ist übrigens ein STK 500.
Der Chip ist noch in der Herstellereinstellung (zumindest was die Fuse Bit angeht)

... dann läuft der Mikrocontroller mit internem RC-Oszillator 1MHz.

Fusebits CKSEK3..0 = 0001

Gruß,
Dirk
 

Über uns

  • Makerconnect ist ein Forum, welches wir ausschließlich für einen Gedankenaustausch und als Diskussionsplattform für Interessierte bereitstellen, welche sich privat, durch das Studium oder beruflich mit Mikrocontroller- und Kleinstrechnersystemen beschäftigen wollen oder müssen ;-)
  • Dirk
  • Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  •  Registriere dich

User Menu

 Kaffeezeit

  • Wir arbeiten hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und der Server regelmäßig gewartet wird. Auch die Themen Datensicherheit und Datenschutz sind uns wichtig und hier sind wir auch ständig aktiv. Alles in allem, sorgen wir uns darum, dass alles Drumherum stimmt :-)

    Dir gefällt das Forum und unsere Arbeit und du möchtest uns unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft!
    Wir freuen uns auch über eine Spende für unsere Kaffeekasse :-)
    Vielen Dank! :ciao:


     Spende uns! (Paypal)