PDA

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



Crocodile
12.10.2005, 17:02
Hallo,

Kann mir jemand sagen wo der Fehler im Code liegt?Anstatt zu blinken leuchtet LED.



#include <avr/io.h>




int main() {

TCCR1B = (1<<CS11)|(1<<CS10);
TIMSK = (1<<TOIE1);


while(1)

{

if (TIFR = (1<<TOV1) )

{

DDRD |= (1<<PD6); /*Ausgang*/
PORTD |= (1<<PD6);/*Pull up an*/
PIND |= (1<<PD6); /*High*/

}
else
{
DDRD &= ~(1<<PD6); /*Ausgang*/
PORTD &= ~(1<<PD6);/*Pull up an*/
PIND &= ~(1<<PD6); /*High*/
}



}

}

Crocodile
12.10.2005, 22:05
Kann mir denn echt keiner helfen??Ich erwarte hier keinen ganzen code sondern nur das mir jemadns agen kann wo der fehler liegt!.

Dino Dieter
12.10.2005, 22:36
Hallo

Das geht so nicht

if (TIFR = (1<<TOV1) )

Sollte so aussehen

#include <avr/io.h>
...
/* Fuehre Aktion aus, wenn Bit Nr. 1 (das "zweite" Bit) in PINC gesetzt (1) ist */
if ( PINC & (1<<PINC1) ) {
/* Aktion */
}


Siehe dazu auch

http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Warten_auf_einen_bestimmten_Zustand

und

http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Warten_auf_einen_bestimmten_Zustand


MFG
Dieter

Crocodile
12.10.2005, 23:14
Vielen dank für deine antwort funktioniert zwar noch immer nicht aber wenigstens schonmal ein fehler weniger!

bluebrother
14.10.2005, 10:11
wieso schaltest du ständig zwischen Ausgang und Eingang um und machst den Pull-Up an und wieder aus? Das sollte 1x zu setzen sein und dann ist gut -- du brauchst doch nur noch den Pegel ändern durch an- und ausschalten vom PIN.
Mach mal deine Initialisierung global und schraub nicht ständig an allen Parametern gleichzeitig rum.

SprinterSB
14.10.2005, 11:14
Hallo,

Kann mir jemand sagen wo der Fehler im Code liegt?Anstatt zu blinken leuchtet LED.

Das liegt daran, daß du keine ISR (Interupt Serice Routine) für den Timer1Overflow implementiert hast. Wenn dann ein Interrupt (IRQ) auftaucht, landest du im Reset und fängt wieder alles von vorne an.

Du musst dich entscheiden, ob du mit Timer1 Overflow Interrupt arbeiten willst oder nicht.

Code mit Interrupt:

//Code mit Interrupt
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>

int main()
{
// PORTD.6 ist Ausgang
DDRD |= (1<<PD6);

// PORTD.6 ist HIGH
PORTD |= (1<<PD6);

// Timer1 zurücksetzen
TCNT1 = 0;

// TOV1-Flag löschen
TIFR = (1<<TOV1);

// Timer1 starten in Mode ???
TCCR1B = (1<<CS11)|(1<<CS10);

// Aktiviert Timer1 Overflow IRQ
TIMSK = (1<<TOIE1);

// Interrupts aktivieren
sei();

while (1)
{
// Interrupt macht den Rest
}
}

// Implementierung der ISR für Timer1 Overflow
SIGNAL(SIG_OVERFLOW1)
{
// PORTD.6 Toggeln
PORTD ^= (1<<PD6);

// TOV1-Flag wird durch die IRQ automatisch gelöscht
}


Code ohne Interrupts:

// Code ohne Interrupts
#include <avr/io.h>

int main()
{
// PORTD.6 ist Ausgang
DDRD |= (1<<PD6);

// PORTD.6 ist HIGH
PORTD |= (1<<PD6);

// Timer1 zurücksetzen
TCNT1 = 0;

// Timer1 starten in Mode ???
TCCR1B = (1<<CS11)|(1<<CS10);

while (1)
{
// TOV1-Flag löschen
TIFR = (1<<TOV1);

// Warten bis Flag auf 1
while (!(TIFR & (1<<TOV1))
{
}

// PORTD.6 Toggeln
PORTD ^= (1<<PD6);
}
}

Andun
14.10.2005, 11:59
Ich hab deinen Code grad ausprobiert und Fehler oder so, bekomm ich auch nciht, aber kann es sein, dass das blinken einfach immer noch viel zu schnell ist und auf uns wie ein durchgehenes an-sein wirkt? Weil meine 8Mhz durch 1024 sind doch so ungefähr 8khz und diese dann durch 256 sind auf jeden fall immer noch mehr als die fürs menschliche Auge sichtbaren 26 Herz.

Also falls ich jetzt Mist erzählt habe, sagts mir, aber so verstehe ich das.

SprinterSB
14.10.2005, 12:22
Das mit der Frequenz stimmt natürlich.

CS1:2-0 = 011 gibt einen prescale von 64, bei 8MHz macht das eone Overflow1-Frequenz von knapp 2Hz, also müsste die LED mit 1Hz blinken.

Der Code, wie er oben steht, funktioniert definitv nicht, alleine schon

if (TIFR = (1<<TOV1))
Ist ein semantisches Leckerli, wo man ins schwitzen kommt (TIFR ist volatile!).
Diese Bedingung ist immer erfüllt, denn (1<<TOV1) ist ungleich 0, abwohl man etwas anderes erwarten würde.
Also passiert in der Schleife nicht wirklich was spannendes. Selbst wenn das Konstrukt funzen würde, lefert es nicht das angedachte.

Andun
14.10.2005, 12:30
[quote="SprinterSB"]
CS1:2-0 = 011 gibt einen prescale von 64, bei 8MHz macht das eone Overflow1-Frequenz von knapp 2Hz, also müsste die LED mit 1Hz blinken.
[quote]

Hä??? Sorry, aber könntest du das nochmal etwas genauer erklären? Weil ich les hier auch grad das AVR-GCC Tutorial und versuche nebenbei im Datenblatt vom meinem mega16 was zu verstehen.

Also es blinkt bei mir schon, mit der von dir angegeben Frequenz aber ich versteh noch nciht ganz warum.

Wenn ich 8Mhz hab und jetzt als Vorteiler 64. Dann komm ich doch auf *rechne* 125Khz. (oder hab cih da schon einen Fehler?). Und wenn da jetzt nur jedes 256. mal getoggelt wird, so ergibt dass nach meiner rechnung immer noch ne Frequenz von 488Hz.

Sorry, aber das versteh ich ncoh nciht.

Nachtrag:

Achsoo . .. . es ist doch ein 16Bit Timer, ne? Also mit ~65000 Zähler . .. Dann passts ja .... :D

Crocodile
14.10.2005, 18:34
Ich danke euch allen für euer bemühen hab es gelöst bekommen.Ich sollte mir mal angewöhnen tutorialsbis zum ende zu lesen.Hier der Code.


/* Timer0 8-Bit Vorteil = 1024 mit 1Mhz */


#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>
#include <avr/iom32.h>
#include <avr/delay.h>

volatile int counter;

int main() {

DDRD |= (1<<PD6); /*Ausgang*/
TCCR0 = (1<<CS00)|(1<<CS02);/*CPU-Takt / 1024*/
TIMSK = (1<<TOIE0); /* Timer0 Overflow Interrupt enable*/
TCNT0 = 0; /*Timer auf o setzen*/
sei(); /* Global Enable Interrupt Flag setzen */


while(1)
{
if (counter == 1) {

PORTD |= (1<<PD6);/*Pull up an*/
PIND |= (1<<PD6); /*High*/
_delay_ms(100);
counter = 0;
}
if (counter == 0)
{

PORTD &= ~(1<<PD6);/*Pull up an*/
PIND &= ~(1<<PD6); /*High*/

}
}


}


SIGNAL (SIG_OVERFLOW0) /*Interrupt-Routine*/
{

counter++; /*um eins inkrementieren*/



}

Andun
14.10.2005, 20:34
Ja, zu Ende lesen . . . . hehe .. .

Aber was mich jetzt immer ncoh wundert:

Du definierst oben PD6 als Ausgang. Und unten machst du es dann völlig richtig, dass du PORTD |= (1<<PD6); benutz um die LED anzumachen, allerdings ist deine Kommentierung stuss. Dadurch geht die LED an und der Ausgang wird "high". Die Zeile mit PIND kannst du dir komplett sparen.

Da solltest du vielelicht noch mal lesen. :D Bei Ausgängen sind Pullups 1. nicht möglich und werden 2. auch nciht gebraucht und acuh gar nciht machbar.

Andun

Crocodile
14.10.2005, 21:11
Hi,

komisch im Microcontroler.net tutorial steht das PORTtx Register Für pull up ist und PINx für High oder low, klär mich bitte auf.

Andun
14.10.2005, 21:18
Ja, stimmt :D Steht da.

Aber das was du grade zitierst gilt nur wenn du die Ports als Eingang nutzt. Du benutzt sie ja als Ausgang. Schau mal nach, da gibts irgendwo so ne Tabelle, in der das gut erklärt ist.

Crocodile
14.10.2005, 21:31
ok, alles klar vielen dank nochmal für deine hilfe.