Dieser Code soll genau wait_ms(10) soll den IC genau 1ms warten lassen, leider ist das nicht der Fall, kann mir einer sagen wodran es liegt, IC löuft mit 20mhz, es ist ein atmega 644. #define F_CPU 20000000 #define IRQS_PER_SECOND 10000 /* 500 µs */ //jede microsekunde einen auslöser #define IRQS_PER_10MS (IRQS_PER_SECOND / 1000) #include <avr/io.h> #include <util/delay.h> #include <stdint.h> #include <avr/interrupt.h> #if (F_CPU/IRQS_PER_SECOND > 65536) || (IRQS_PER_10MS < 1) || (IRQS_PER_10MS > 255) # error Diese Werte fuer F_CPU und IRQS_PER_SECOND # error sind ausserhalb des gueltigen Bereichs! #endif //Prototypen void sleep_ms(uint16_t ms); // Zähler-Variable. Wird in der ISR erniedrigt und in wait_10ms benutzt. static volatile uint8_t timer_10ms; //LED Defines //Hier müssen die richtigen Angaben hin #define LED_DDR DDRB //DDRA, DDRB... #define LED_PORT PORTB //PORTA, PORTB... #define LED_PORTPIN PB3 //PA0, PA1..., PB0, PB1..., ... // ////////////////////////////////////////////////////////////////////// // Die Interrupt Service Routine (ISR). // In interrupt_num_10ms werden die IRQs gezählt. // Sind IRQS_PER_10MS Interrups geschehen, // dann sind 10 ms vergangen. // timer_10ms wird alle 10 ms um 1 vermindert und bleibt bei 0 stehen. SIGNAL (SIG_OUTPUT_COMPARE1A) { static uint8_t interrupt_num_10ms; // interrupt_num_10ms erhöhen und mit Maximalwert vergleichen if (++interrupt_num_10ms == IRQS_PER_10MS) { // 10 Millisekunden sind vorbei // interrupt_num_10ms zurücksetzen interrupt_num_10ms = 0; // Alle 10ms wird timer_10ms erniedrigt, falls es nicht schon 0 ist. // Wird verwendet in wait_10ms if (timer_10ms != 0) timer_10ms--; } } void timer1_init() { // Timer1: keine PWM TCCR1A = 0; // Timer1 ist Zähler: Clear Timer on Compare Match (CTC, Mode #4) // Timer1 läuft mit vollem MCU-Takt: Prescale = 1 #if defined (CTC1) && !defined (WGM12) TCCR1B = (1 << CTC1) | (1 << CS10); #elif !defined (CTC1) && defined (WGM12) TCCR1B = (1 << WGM12) | (1 << CS10); #else #error Keine Ahnung, wie Timer1 fuer diesen AVR zu initialisieren ist! #endif // OutputCompare für gewünschte Timer1 Frequenz // TCNT1 zählt immer 0...OCR1A, 0...OCR1A, ... // Beim überlauf OCR1A -> OCR1A+1 wird TCNT1=0 gesetzt und im nächsten // MCU-Takt eine IRQ erzeugt. OCR1A = 200; // OutputCompareA-Interrupt für Timer1 aktivieren #if defined (TIMSK1) TIMSK1 |= (1 << OCIE1A); #elif defined (TIMSK) TIMSK |= (1 << OCIE1A); #else #error Keine Ahnung, wie IRQs fuer diesen AVR zu initialisieren sind! #endif } // ////////////////////////////////////////////////////////////////////// // Wartet etwa t*10 ms. // timer_10ms wird alle 10ms in der Timer1-ISR erniedrigt. // Weil es bis zum nächsten IRQ nicht länger als 10ms dauert, // wartet diese Funktion zwischen (t-1)*10 ms und t*10 ms. void wait_ms (long int t)//wait_10ms (const uint8_t t) { timer_10ms = t; while (timer_10ms); } int main(void){ /*Den Pin wo die LED angeschlossen ist als Ausgang setzen */ // LED_DDR |= (1<<LED_PORTPIN); DDRD |= (1<<PD6); PORTD |= (1<<PD6); // Timer1 initialisieren timer1_init(); // Interrupts aktivieren sei(); DDRB |= (1<<PB0); //PORTB |= (1<<PB0); //wait_ms (50000); PORTB |= (1<<PB0); wait_ms (10000); PORTB &= ~(1<<PB0); int a = 0; while(a != 1500){ PORTB |= (1<<PB3); // LED_PORT |= (1<<LED_PORTPIN); //Den Portpin auf high setzen sleep_ms(1); PORTB &= ~(1<<PB3); // LED_PORT &= ~(1<<LED_PORTPIN); //Den Portpin auf low setzen sleep_ms(19); a++; } PORTD &= ~(1<<PD6); //DDRD &= (1<<PD6); int c = 0; int d= 200 ; //Die LED die ganze Zeit an und aus schalten while(1){ LED_PORT |= (1<<LED_PORTPIN); //Den Portpin auf high setzen wait_ms(c); LED_PORT &= ~(1<<LED_PORTPIN); //Den Portpin auf low setzen wait_ms(d); c++; d--; if(c==20){c=0;d=200;} } } /* Diese Funktion lässt den Controller "ms" Millisekunden warten. Die while-Schleife wird so oft durchlaufen, wie der Funktion übergeben wurde. Bei jedem Duchlauf wir noch 1ms gewartet. */ void sleep_ms(uint16_t ms){ while(ms){ ms--; _delay_ms(1); } }
Seba wrote: > Dieser Code soll genau wait_ms(10) soll den IC genau 1ms warten lassen, ^^ ^^^ > leider ist das nicht der Fall, kann mir einer sagen wodran es liegt, IC > löuft mit 20mhz, es ist ein atmega 644. > > #define F_CPU 20000000 > #define IRQS_PER_SECOND 10000 /* 500 µs */ //jede microsekunde einen ^^^^^ > auslöser > #define IRQS_PER_10MS (IRQS_PER_SECOND / 1000) ^^^^^^^^^^^^^^^^^^^^^^ 1/ Passt irgendwie alles nicht. // 1s sind 1000ms // 1ms sind 1000s // => 1s sind 1000x1000 µs also #define IRQS_PER_SECOND 1000000L // 1ms hat IRQS_PER_SECOND / 1000 IRQs // 10ms haben 10x soviel #define IRQS_PER_10MS ((IRQS_PER_SECOND / 1000) * 10) 2/ Für einen 10ms Timer einen 20 MHz µC bei Prescaler 1 laufen zu lassen... ist wie mit einem Ferrari nur im ersten Gang nach Maranello zu fahren.
ADD:
Betreff ("1/10ms Timer") und Code ("Wartet etwa t*10 ms") widersprechen
sich etwas.
> OCR1A = 200;
Den Wert für den 1/10ms Timer1 halte ich um den Faktor 10 für zu klein.
Bei 20 MHz Takt und Prescaler 1 hast du 20.000.000 Takte pro Sekunde am
Timer. Das sind 20.000 Takte pro Millisekunde. Das sind 2.000 Takte pro
1/10 ms (= pro 100us).
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.