Forum: Compiler & IDEs Interrupt kommt zu schnell


von Icey (Gast)


Lesenswert?

Hallo,

Ich habe gerade erst angefangen mit Mikrocontroller-Programmierung. Ich 
möchte über den Timer0 eine LED zum blinken bringen, dazu habe ich 
folgendes Programm geschrieben.
1
#include <avr/io.h>
2
#include <stdint.h>
3
#include <avr/interrupt.h>
4
5
volatile char i=0;
6
7
8
ISR(TIMER0_COMP_vect)
9
{
10
  i++;
11
  PORTB ^= (1<<PB7);
12
}
13
14
int main(void)
15
{
16
  DDRB = 0xff;  //PortB als Ausgang
17
  DDRD = 0x00;  //PortD als Eingang
18
  TCCR0 = 0x0D;  //CTC-Modus Prescaler 1024
19
  OCR0 = 0x7F;  //Zählerwert eingestellt
20
  TIMSK = 0x01;  //Interrupt ermöglichen
21
  sei();
22
  
23
  
24
  PORTB = 0xff;  //LED´s aus
25
  
26
  while(1)
27
  {
28
    if(i>4)
29
    {
30
      i=0;
31
      PORTB ^= (1<<PB3);
32
    }
33
  }
34
}
Das ganze läuft mit einem ATmega8515 und einem 4MHz Quarz auf einem 
STK500. Leider läuft blinken die Lampen aber zu schnell, die 4.LED 
ungefähr 12mal in 10 Sekunden.

Irgendwie komm ich nicht so wirklich auf die Lösung warum der sowas mit 
mir macht :(

Ich benutzte WinAVR-20070525.

Ich hoffe Ihr könnt mir helfen.

Gruß,
Icey

von Andreas K. (a-k)


Lesenswert?

Mal rechnen: Alle 128*1024 Takte ein Interrupt, danach Software-Teiler 
10: 128*1024*10 = ca. 1,3Mio. Passt doch prima, wenn man mal annimmt, 
dass du vergessen hast, den Mega vom internen 1MHz Takt auf den Quarz 
umzustellen.

Bloss: Wenn er dann mal mit 4MHz läuft: Langsamer wird dadurch nicht 
blinken. Eher im Gegenteil. Wie ist denn deine Rechnung?

von Icey (Gast)


Lesenswert?

Moin,

Mist ich bin doof kopfaufdentischknall

Ich hab mich mit den Einheiten verwurstetelt, ich hab statt ns mit ms 
gerechnet, da kann ja nur das falsche rauskommen.

Danke für die schnelle Hilfe :)

Gruß,
Icey

von Simon K. (simon) Benutzerseite


Lesenswert?

Kleiner Tip: Es ist lesbarer, wenn du statt
1
TCCR0 = 0x0D;
eher sowas schreibst:
1
TCCR0 = (1<<WGM01) | (1<<CS02) | (1<<CS00);

von Bonzo (Gast)


Lesenswert?

Kleiner Tip. Es ist noch lesbarer :

TCCR0 = 0x0D;  // WGM01 CS02 CS00

von Simon K. (simon) Benutzerseite


Lesenswert?

Bonzo wrote:
> Kleiner Tip. Es ist noch lesbarer :
>
> TCCR0 = 0x0D;  // WGM01 CS02 CS00

Ja, aber man muss immer das Comment anpassen. Bei meiner Variante 
kümmert sich dann der Compiler um das Ausrechen des korrekten 
Registerwerts... Das minimiert auch Fehlerquellen.

von Rolf Magnus (Gast)


Lesenswert?

Nö. Da muß man ja doch wieder ins Datenblatt schauen und die Bits 
auseinanderklamüsern, um zu rauszubekommen, ob der Wert denn nun stimmt 
oder nicht.  Abgesehen davon ist Code, der sich selbst kommentiert, 
immer besser als unverständlicher Code, den man erst mit einem Kommentar 
erklären muß.

Am besten:

TCCR0 = _BV(WGM01) | _BV(CS02) | _BV(CS00);

von Icey (Gast)


Lesenswert?

Hallo,

Danke für die Tipps. Kommentieren kann man nie genug ;)
Werd wohl ne Mischung aus beiden Varianten machen :)

Gruß,
Icey

der sich jetzt mal am UART versucht :D

von Andreas K. (a-k)


Lesenswert?

> Werd wohl ne Mischung aus beiden Varianten machen :)

Sieht man öfter. Falscher Code und richtiger Kommentar daneben, oder 
umgekehrt. ;-)

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
Noch kein Account? Hier anmelden.