Schönen guten Abend, ich versuche seit 2 Stunden dieses Interrupt im ctc modus zum laufen zu bringen. Aber egal welche Zahl ich ins Register schreibe, die LED blinkt immer gleich schnell (bei dem geschriebenen Programm im Sekundentakt). Hat vielleicht jemand einen Tip für mich? Ich habe den verdacht dass mein Timer irgendwie nicht zurück gesetzt wird. Kann es sein dass der Timer nicht mit dem 20MHz quarz läuft? Vielen Dank im Vorraus Markus #include <avr/io.h> #include <asf.h> #include <math.h> #include <stdlib.h> #ifndef F_CPU #define F_CPU 20000000UL #endif #include <util/delay.h> #include <avr/interrupt.h> void servo_init(void); #define SERVOPIN 1 #define SERVOPORT PORTD #define DDRSERVO DDRD long double t=0; ISR(TIMER0_COMPA_vect) //interrupt { t++; } void servo_init(void) { TIMSK0|=(1<<OCIE0A); //interrupts TCCR0B |= (1<<CS00); //Prescale=1, TCCR0A |= (1<<WGM01); // CTC mode OCR0A = 200; //alle 10µs ein IRQ 0,00001s DDRSERVO|=(1<<SERVOPIN); //LED Pin als ausgang } int main (void) { servo_init(); sei (); //interrups an while(1) { if (t<20000)SERVOPORT|=(1<<SERVOPIN); //bis zum 20000. durchlaufen des Interrupts LED AN (200ms) else SERVOPORT &=(0<<SERVOPIN); //ab dann LED AUS if (t>40000) t=0; // bei 40000. interruptdurchlauf t zurücksetzen (insg. 400ms) } }
&=(0<<SERVOPIN) sollte natürlich &=~(1<<SERVOPIN) sein. entschuldigung
Hi
>long double t=0;
War da nicht was mit volatile?
MfG Spess
Sieht mir eigentlich alles gut aus, grad nochmal ins Datenblatt geschaut. Das mit dem Volatile kann eigentlich deshalb nicht das Problem sein, weil man sonst im Main den Counter gar nicht erhöht bekäme. Trotzdem sollte man lieber das Volatile verwenden. Aber probier mal die Register mit = statt |= zu setzen um sicherzugehen, dass sie anderen Bits auch 0 sind.
Hi >Das mit dem Volatile kann eigentlich deshalb nicht das Problem sein, >weil man sonst im Main den Counter gar nicht erhöht bekäme. Wieso Main? t wird im Interrupt erhöht. MfG Spess
Danke für die schnelle Antwort aber die Kiste blinkt immer noch im sekundentakt. Eigentlich sollten es ja 200ms sein.
Hi >Danke für die schnelle Antwort aber die Kiste blinkt immer noch im >sekundentakt. Eigentlich sollten es ja 200ms sein. CKDIV8-Fuse noch gesetzt? MfG Spess
Leider nein... delay ms zb. funktionniert. und des rechnet doch auch mit dem Takt oder?
Wenn du anstelle des long double (wozu eigentlich) ein unsigned int nimmst, dann funktioniert es.
@ Markus (Gast) >ich versuche seit 2 Stunden dieses Interrupt im ctc modus zum laufen zu >bringen. Aber egal welche Zahl ich ins Register schreibe, die LED blinkt >immer gleich schnell (bei dem geschriebenen Programm im Sekundentakt). >long double t=0; Willst du damit andeuten, den Allerlängsten zu haben? ;-) long double, die es auf dem AVR sowieso nicht gibt, sind in den seltesten Fällen sinnvoll. Ein einfacher uint16_t tut es locker. Mal ganz abgesehen davon, dass man Servos anders ansteuert. Ausserdem fehlt ein volatile, siehe Interrupt. >Danke für die schnelle Antwort aber die Kiste blinkt immer noch im >sekundentakt. Eigentlich sollten es ja 200ms sein. Möglicherweise ist die Arithmetik mit float so aufwändig und langsam, dass Interrupts verschluckt werden.
Hi >long double t=0; Brauchst du an der Stelle eine Gleitpunktzahl? >OCR0A = 200; //alle 10µs ein IRQ 0,00001s Genaue 10µs erhälst du aber mit 199. MfG Spess
spess53 schrieb: >>long double t=0; > > War da nicht was mit volatile? > > MfG Spess Hehe Spess, bist du jetzt auch zu den C-Kryptographen übergelaufen, oder leistest du bloß mal Entwicklungshilfe ;-) Bin ich dann der Letzte, der das Licht ausmacht?
Volatile steht drin. Und ich versuchs mit uint16_t. Sobald ein neues Board da is. Des jetzige is mir gerade abgeraucht. danke für die Hilfe
Hi >Hehe Spess, bist du jetzt auch zu den C-Kryptographen übergelaufen, oder >leistest du bloß mal Entwicklungshilfe ;-) Letzteres. Hilft auch um C-Programme nach Assembler umzusetzen. MfG Spess
Markus schrieb: > ich versuche seit 2 Stunden dieses Interrupt im ctc modus zum laufen zu > bringen. Aber egal welche Zahl ich ins Register schreibe, die LED blinkt > immer gleich schnell (bei dem geschriebenen Programm im Sekundentakt). Du benutzt AVR Studio 6.x? Versuch mal mit Device Programming -> Memory dein Programm auf den Atmega328 zu laden. Der Upload aus der Entwicklungsumgebung geht in AVR Studio 6.x manchmal schief, insbesonders wenn man mal den Zielprozessor geändert hat. Markus schrieb: > if (t<20000)SERVOPORT|=(1<<SERVOPIN); > else SERVOPORT &=(0<<SERVOPIN); > if (t>40000) t=0; Du darfst in main() nicht einfach so auf t zugreifen. Da t größer als ein Byte ist, besteht der Zugriff aus mehreren Assemblerbefehlen. Der TIMER0_COMPA_vect kann dann zwischen diesen Befehlen stattfinden, so dass du unter Umständen sehr seltsame Werte in t beobachten wirst. Um jeden Zugriff auf t herum muss darum der Interrupt ausgeschaltet sein. volatile allein hilft da nicht. LG, Sebastian
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.