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.