PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Interrupt von PWM-Signal



kautz
01.01.2008, 16:36
Hallo,
ich möchte einen 40kHz Burst erzeugen. Dazu stelle ich den Oszillator auf ca. 40 kHz und erzeuge einen Interrupt, der dann bis ca. 16 (Perioden) zählt und dann den Oszillator stoppt. Aber irgendwie funzt wieder mal gar nichts.
Hier ist mein Code:


void _40khz_init (void) {
DDRB = 0xFF;
OCR1A = 12; // PWM einstellen, bevor der Timer startet
OCR1B = 800;
ICR1 = 25; // TOP-wert

TCCR1A = (1<<COM1A1) | (1<<COM1B1) | (1<<WGM11);
TCCR1B = (1<<WGM13)|(1<<WGM12) | (1<<CS10);
}
SIGNAL (TIM1_OVF) {
send ("0");
}

SIGNAL (TIM1_COMPA) {
send ("1");
}
SIGNAL (TIM0_OVF) {
send ("2");
}
SIGNAL (TIM1_COMPB) {
send ("3");
}

int main(){

_40khz_init();
uart_init();

/*Timer-Interrupt*/
TIMSK |= (1 << TOIE0) ;

sei();//enable Interrupts

for(;;);

}

wkrug
01.01.2008, 20:14
Welcher Controller? Wo ist die Interrupt Routine die den 40kHz Generator stoppt ? Schon über AVR Studio simuliert und debuggt ?

kautz
01.01.2008, 20:47
Also mein Controller ist ein Atmega8.
Ich habe jetzt versucht innerhalb des Interrupts den Counter auszuschalten und den Interrupt zu löschen:


TIMSK &= ~(1 << TOIE0);
TIMSK &= ~(1 << OCIE1A);
TIMSK &= ~(1 << TOIE1);
TCCR1A &= ~(1<<COM1A1);
TCCR1A &= ~(1<<COM1B1);

Aber leider funktioniert es nicht.

wkrug
02.01.2008, 16:27
@kautz
Wenn Du den Interrupt nicht löscht, werden dann die 40 kHz dauernd erzeugt ?
Wird die Interruptroutine tatsächlich angesprungen ?

Probier das doch mal im AVR Studio 4 aus, dafür ist der Debugger da.

kautz
02.01.2008, 19:07
Ja, danke. Ich habe jetzt AVRStudio installiert und debuggt.
Er springt nicht in den Handler. Der Compiler zeigt mir auch an, dass das Signal "misspelled" ist.
Aber ich finde keine Konstanten im Interrupt.h. Und wenn ich dort 0x08 reinschreibe, kompiliert er es nicht. Irgendwie schein ich da was nicht zu verstehen.



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

#define F_CPU 1000000

int schalter=0;

void _40khz_init (void) {

DDRB = 0xFF;

OCR1A = 12; // PWM einstellen, bevor der Timer startet
OCR1B = 800;
ICR1 = 25; // TOP-wert
// 2-Kanal "non-inverting"
// 10-Bit = 2^10 = 1024
TCCR1A = (1<<COM1A1) | (1<<COM1B1) | (1<<WGM11); // 2-Kanal "non-inverting"
TCCR1B = (1<<WGM13)|(1<<WGM12) | (1<<CS10); //Fastpwm, mit ICR1 als TOP
}

SIGNAL (TIMER0_COMPB_vect){

TIMSK &= ~(1 << TOIE0);
TIMSK &= ~(1 << OCIE1A);
TIMSK &= ~(1 << TOIE1);
TCCR1A &= ~(1<<COM1A1);
TCCR1A &= ~(1<<COM1B1);
schalter = 1;

}

SIGNAL (TIMER0_COMPA_vect){
TIMSK &= ~(1 << TOIE0);
TIMSK &= ~(1 << OCIE1A);
TIMSK &= ~(1 << TOIE1);
TCCR1A &= ~(1<<COM1A1);
TCCR1A &= ~(1<<COM1B1);
schalter = 1;
}

int main(void)
{
_40khz_init();
TIMSK |= (1 << OCIE1B); //|(1<<OCIE1A)|(1<<TOIE1);
sei();//enable Interrupts
while(1){};


}

wkrug
02.01.2008, 23:05
Das Problem ist also, das die Interruptroutine nicht angesprungen wird.
Ich vermute mal, das Du AVR GCC benutzt.

Ich hab leider Codevision und da geht die Interruptabarbeitung ein wenig anders.

Schau mal in die Hilfe deines Compilers unter der Rubrik Interrupts.
Bei den Meisten Compilern mus eine Interruptroutine mit bestimmten Schlüsselwörtern z.B. "Interrupt Service Routine" oder "_isr..." belegt werden, damit Sie der Compiler auch als Interruptroutinen erkennt und einrichtet.

Am Schluß muss im Assemblercode, in den entsprechenden Adressen deines Controllers der Einsprungpunkt zum Interrupthandler hinterlegt sein.

Dann sollte das auch funzen.

Schau mal diesen Threat https://www.roboternetz.de/phpBB2/viewtopic.php?t=33571
( Beispielcode ) Eventuell hilft Dir das dein Problem zu finden.