Hallo zusammen! Ich habe hier eine Delay-Funktion programmiert, die auf einem ATTiny 2313 mit 8Mhz laufen soll. Leider tut diese garnichts :-( Ich würde mich sehr freuen wenn ihr mal kurz drüberschauen und vielleicht einen (dummen Anfänger-)Fehler finden würdet ;-) // Defines the different prescalers typedef enum { PRESCALE_1, PRESCALE_8, PRESCALE_64, PRESCALE_256, PRESCALE_1024 } Prescaler; // Wait micro (10^-6) seconds void Timing_wait_us( uint us ) { Timing_setupHardwareTimer( 8, PRESCALE_1, us ); Timing_startHardwareTimer(); } // Sets up the registers to simplify timer usage void Timing_setupHardwareTimer( uchar compareValue, Prescaler prescaler, uint repititions ) { // Store number of repetitions timerRepititions = repititions; // Clear counter on compare match TCCR0A = (1 << COM0A1); // Output compare register OCR0A = compareValue; // Prescaler TCCR0B = (prescaler+1); // Enable interrupts TIMSK = 2; } // Starts the hardware timer and waits for it to finish void Timing_startHardwareTimer( void ) { // Reset timer timerHasFinished = false; TCNT0 = 0; // Let's go sei(); while( !timerHasFinished ) {;} cli(); } // Timer interrupt ISR(TIMER0_OVF_vect) { if( timerRepititions > 0 ) { timerRepititions--; if( timerRepititions == 0 ) timerHasFinished = true; }//end if }
Kiaa schrieb: > // Defines the different prescalers > typedef enum > { > PRESCALE_1, > PRESCALE_8, > PRESCALE_64, > PRESCALE_256, > PRESCALE_1024 > } Prescaler; das ist gefährlich. Der Compiler beginnt mit der Zuweisung von Zahlenwerten zu den Enum Werten bei 0. Da du hier darauf angewiesen bist, dass die Konstanten mit spezifischen Zahlenwerten verknüpft werden, solltest du da für Klarheit sorgen typedef enum { PRESCALE_1 = 1 PRESCALE_8 = 2 PRESCALE_64 = 3 PRESCALE_256 = 4 PRESCALE_1024 = 5 } Prescaler; ob die Bitwerte der Zahlen jetzt zu den Konstanten laut Datenblatt passen, hab ich nicht kontrolliert. > // Sets up the registers to simplify timer usage > void Timing_setupHardwareTimer( uchar compareValue, Prescaler prescaler, > uint repititions ) > { > // Store number of repetitions > timerRepititions = repititions; timerRepititions .... Datentyp? volatile vergessen? > > // Clear counter on compare match > TCCR0A = (1 << COM0A1); > > // Output compare register > OCR0A = compareValue; > > // Prescaler > TCCR0B = (prescaler+1); > > // Enable interrupts > TIMSK = 2; Bis hierher war ich versucht zu sagen: schöner Code > // Starts the hardware timer and waits for it to finish > void Timing_startHardwareTimer( void ) > { > // Reset timer > timerHasFinished = false; timerHasFinished ... Datentyp? volatile vergessen? An dieser Stelle ist das nicht besonders gut aufgehoben. Du solltest das Flag löschen, ehe du den Timer laufen lässt. Was, wenn bei kurzen Zeiten der Timer schon abgelaufen ist, wenn das Programm hier her kommt? > TCNT0 = 0; Ditto Timereinstellungen macht man bevor der Timer sein Go bekommt. Und sein Go kriegt er mit dem Setzen des Vorteilers. Danach läuft der Timer. > > // Let's go > sei(); > while( !timerHasFinished ) {;} > cli(); > } du schaltest den Timer nicht wieder ab?
Danke für deinen qualifizierten Input. Ich habe den Code jetzt gemäß deiner Vorschläge umgestellt, und siehe da: es läuft! Allerdings ziemlich genau um den Faktor 2 zu langsam, aber das bekomme ich auch noch raus... Danke! :-)
Hm, also leider will es immer noch nicht so ganz. Es timed zwar, allerdings viel zu langsam. Die "normalen" Funktionen (_delay_ms) funktionieren wunderbar... Hier mal der überarbeitete Code: // Local flag to signalize finished timing volatile bool timerHasFinished = false; // Cou8nter used for timing volatile uint timerRepititions = 0; // Wait micro (10^-6) seconds void Timing_wait_us( uint us ) { Timing_startHardwareTimer( 8, PRESCALE_1, us ); } // Wait milli (10^-3) seconds void Timing_wait_ms( uint ms ) { Timing_startHardwareTimer( 125, PRESCALE_64, ms ); } // Wait seconds void Timing_wait_s( uint s ) { Timing_wait_ms( s*1000 ); } // Sets up the registers to simplify timer usage void Timing_startHardwareTimer( uchar compareValue, Prescaler prescaler, uint repititions ) { // Stop timer TCCR0B = 0; // Store number of repetitions timerRepititions = repititions; // Clear counter on compare match TCCR0A = (1 << COM0A1); // Output compare register OCR0A = compareValue; // Enable compare match interrupt TIMSK = 2; // Reset timer timerHasFinished = false; TCNT0 = 0; // Prescaler sei(); TCCR0B = (prescaler+1); // Let's go while( !timerHasFinished ) {;} // Stop timer TCCR0B = 0; cli(); } // Timer interrupt ISR(TIMER0_OVF_vect) { // Decrease repititions if( timerRepititions > 0 ) { timerRepititions--; if( timerRepititions == 0 ) timerHasFinished = true; } else { timerHasFinished = true; }//end if } Ich kann mir wirklich nicht erklären wo das Problem liegt :-(
> // Output compare register > OCR0A = compareValue; Bei den angegebenen Werten ist der compareValue um +1 zu hoch. => AVR-GCC-Tutorial/Die Timer und Zähler des AVR > // Enable compare match interrupt > TIMSK = 2; > ISR(TIMER0_OVF_vect) Sicher OVERFLOW, und nicht COMPARE MATCH (CTC)? Ich denke im Moment ist es um den Faktor 2 zu langsam :-) Mit welcher physikalischen Taktrate läuft dein AVR? (Hardware Taktquelle ist? AVR Fuses sind? AVR ist?) Ein komplettes kompilierbares und simulierbares Listing wäre zur Ferndiagnose hilfreich. Tipp: Längere Listings (größer ca. eine Bildschirmseite) bitte in den Anhang.
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.