PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Interrupt Problem mit c



avrrobot
27.09.2011, 16:14
Hallo,
Ich brauche nun für einen bestimmten Grund in relativ großen Zeitabständen (0,5-2 sekunden) einen Interrupt.
Dafür wollte ich dann den Beispielcode hier (http://www.rn-wissen.de/index.php/Timer/Counter_(Avr)) verwenden.
Ich habe ihn noch etwas verändert und nun sieht er so aus:

#ifndef F_CPU
#define F_CPU 1000000
#endif

#include <avr/io.h>
#include <util/delay.h>
#include <stdint.h>
#include <avr/interrupt.h>


volatile int stat=0;


ISR(TIMER2_OVF_vect)
{
if(stat = 0){
stat=1;
PORTB |= (1<<PB0);
}else{
stat=0;
PORTB &= ~(1<<PB0);
}
}


int main(void){
DDRB |= (1<<PB0);
sei();
TCCR2 = (1<<CS22) | (1<<CS20);
TIMSK |= (1<<TOIE2);
while(1){}
}
Ich will damit testweise eine LED an B0 zum blinken kriegen.
Es geht bloß leider nicht.
Ich verwende einen atmega32 und avr-gcc (avr studio).
Hat da irgendjemand eine Idee?

021aet04
27.09.2011, 17:25
Versuche einmal das sei direkt vor die while Schleife.

in die ISR kannst du auch "PORTB ^= (1<<PB0);" schreiben (Invertiere PB0).

Die Einstellungen habe ich mir nicht angeschaut.

MfG Hannes

avrrobot
27.09.2011, 17:47
Nee, hat immer noch nicht funktioniert.

Hubert.G
27.09.2011, 18:01
Bei dieser Zeile if(stat = 0){ sollte dir der Compiler eigentlich ein Warning ausgeben.
Richtig ist if(stat == 0){

avrrobot
27.09.2011, 18:08
Ja stimmt, hätte er gesollt.
Ich habe aber durch andre Tests herausgefunden, dass die ISR nie aufgerufen wird.
Außerdem habe ich jetzt das ganze if...else durch PORTB ^= (1<<PB0); ersetzt.

Hubert.G
27.09.2011, 18:11
In der Simulation läuft es aber. Bist du sicher das da nicht ein anderer HW-Wurm drinnen ist?

avrrobot
27.09.2011, 18:13
Wenn ich das PORTB ^= (1<<PB0); in die while(true) schreibe,
dann leuchtet die LED so mittel. Das Oszi bestätigt ein sehr schnelles PWM.
Also Hardwaremäßig läuft eigentlich alles.

021aet04
27.09.2011, 18:34
Das ist klar das dann die Led mit etwa halber Kraft leuchtet. Die Led ist so zu 50% ein und zu 50% aus => Tastgrad=50%.

Das war aber schon einmal ein guter Test, so kann man sicher sein das die Led funktioniert.

Versuche einmal ob das TOV2-Flag im Register TIFR sich ändert. Du könntest zusätzlich (damit du das siehst) eine Delay Zeit einfügen.

MfG Hannes

avrrobot
27.09.2011, 18:35
Wann soll ich das ausprobieren, zur Laufzeit?

021aet04
27.09.2011, 18:37
Du könntest es in der while Schleife das Flag prüfen. So kannst du sicher sein das der Timer läuft.

MfG Hannes

avrrobot
27.09.2011, 18:38
Ja, aber das dürfte sich ja eigentlich nicht ändern.

021aet04
27.09.2011, 18:42
Warum nicht? Wenn der Timer richtig eigestellt ist sollte sich das Flag ändern.

Könntest du den aktuellen Code posten?

MfG Hannes

avrrobot
27.09.2011, 18:44
Ach so, ja stimmt.


#ifndef F_CPU
#define F_CPU 1000000
#endif

#include <avr/io.h>
#include <util/delay.h>
#include <stdint.h>
#include <avr/interrupt.h>



ISR(TIMER2_OVF_vect)
{
PORTB ^= (1<<PB0);
}


int main(void){
DDRB |= (1<<PB0);
TCCR2 = (1<<CS22) | (1<<CS20);
TIMSK |= (1<<TOIE2);
sei();
while(1){
if((TIFR & TOV2) == 0) PORTB |= (1<<PB0);
if((TIFR & TOV2) == 1) PORTB &= ~(1<<PB0);
}
}

Die LED ist dann dauerhaft an.

021aet04
27.09.2011, 19:07
Ich habe den Code etwas geändert. Es funktioniert so. Das Flag wird gesetzt. Ich schaue noch warum der Int nicht ausgeführt wird.

Hier mein Code (den Prescaler habe ich geändert dadurch es schneller geht).


#ifndef F_CPU
#define F_CPU 1000000
#endif

#include <avr/io.h>
#include <util/delay.h>
#include <stdint.h>
#include <avr/interrupt.h>



ISR(TIMER2_OVF_vect)
{
PORTB ^= (1<<PB0);
}


int main(void){
DDRB |= (1<<PB0);
TCCR2 = (1<<CS20); //(1<<CS22) | (1<<CS20);
TIMSK |= (1<<TOIE2);
sei();
while(1)
{
while(TIFR & TOV2)
{
PORTB ^= (1<<PB0);
_delay_ms(500);
TIFR |= (1<<TOV2);
}
}
}



MfG Hannes

avrrobot
27.09.2011, 19:26
In dem Fall liegt an B0 immer 0 an.
Edit: Nur so, die LED ist aktiv, wenn 1 an B0 anliegt.

021aet04
27.09.2011, 19:27
Ich habe es mit dem Simulator getestet. Da hat es funktioniert. Leider habe ich keinen Mega32 zur Hand.

MfG Hannes

avrrobot
27.09.2011, 19:29
Ja, ich werde mal nen andren mega32 reintun.

avrrobot
27.09.2011, 19:35
Hatte doch grad nur nen mega16 da, es gibt einen astreines rechtecksignal an B0.
Edit: Hab doch noch nen mega32 gefunden, bei dem gehts auch nicht.

avrrobot
27.09.2011, 19:56
Da fragt man sich nur noch, warum das so ist?

021aet04
27.09.2011, 20:01
Habe gerade das Datenblatt angeschaut (Errata). Hier ist das Datenblatt http://www.atmel.com/dyn/resources/prod_documents/doc2503.pdf

Auf Seite 336 steht das es Probleme mit dem Timer geben kann. Es steht auch eine Lösung dort.

Füge im Code diese Zeile ein "TCNT2 = 0xff;"
Diese Zeile muss vor der Zeile mit TCCR-Register sein.

MfG Hannes

avrrobot
28.09.2011, 07:00
Also für mich sieht das eher so aus, als ob das weder 0xff noch 0x00 sein darf:
"Always check the asyncronous Timer/Counter register neither have the value 0xFF nor 0x00 before writing....

Hubert.G
28.09.2011, 10:38
Ich habe das mal auf mein Eval-Board mit einem Mega32 geladen, funktioniert einwandfrei.
Die LED auf PB0 flimmert.

avrrobot
28.09.2011, 17:59
Ok, jetzt funktioniert es auch bei mir, fragt mich nur nicht warum.