Attiny13 Timer Overflow interrupt Problem

OP #5575264
Lesenswert?

Hallo,

folgendes Programm soll eine LED an PB4 mithilfe eines Interrupts 
regelmäßig toggeln.
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3

4
ISR(TIM0_OVF_vect)  {
5
    PORTB ^= (1 << PB4); // toggle LED pin
6
}
7

8
int main(void)  {
9
        DDRB |= (1 << DDB4); // set LED pin as OUTPUT
10
        PORTB = 0b00000000; // set all pins to LOW
11
        TCCR0B |= (1 << CS02)|(1 << CS00); // set prescaler to 1024 (CLK=1200000Hz/1024/256=4Hz, 0.25s)
12
        TIMSK0 |= (1 << TOIE0); // enable Timer Overflow interrupt
13
        sei(); // enable global interrupts
14
        while(1)    {
15
        }
16
}

Auf dem Steckbrett jedoch leuchtet die LED, welche von PB4 nach GND 
geschaltet ist, durchgehend schwach, ohne irgendwie zu blinken. Da ich 
ein Einsteiger im Thema AVR-Mikrocontroller bin, wollte ich fragen, ob 
jemand mir mit diesem Problem helfen kann.
Gast #5575305
Lesenswert?

Ich sehe keinen Fehler.

Wenn eine LED schwach glimmt hat man typischerweise vergessen, den Pin 
als Ausgang zu konfigurieren. Aber das ist hier offenbar nicht der Fall.

Sicher, dass die LED an PB4 hängt und dass dieser Pin nicht defekt ist? 
Ich hoffe, du hast der LED einen Vorwiderstand spendiert.
(Firma: Vescomp) #5575341
Lesenswert?

Armin W. schrieb:
> Ich habe nun einen 220 Ohm Vorwiderstand vor die LED geschaltet und den
> Codevorschlag
>
1
> PINB = (1 << PB4); // toggle LED pin
2
>
> übernommen, aber es tut sich nichts..

Marc V. schrieb:
> Marc V. schrieb:
>> Es läuft 10x schneller über, also alle 21,845ms.
>
>  Und mit 46Hz siehst du kein flackern, sondern nur schwaches (?)
>  leuchten.

 Es tut sich schon etwas, nur ist es zu schnell als das man es sehen
 kann.
 Probiere mal folgendes:
====================================================================
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3

4
volatile uint8_t isr_cnt = 0;
5

6
ISR(TIM0_OVF_vect)  {
7
  if(isr_cnt++ > 10) {
8
    PINB = (1 << PB4); // toggle LED pin
9
    isr_cnt = 0;
10
  }
11
}
12

13
int main(void)  {
14
        DDRB |= (1 << DDB4); // set LED pin as OUTPUT
15
        PORTB = 0b00000000; // set all pins to LOW
16
        TCCR0B |= (1 << CS02)|(1 << CS00); // set prescaler to 1024 (CLK=1200000Hz/1024/256=4Hz, 0.25s)
17
        TIMSK0 |= (1 << TOIE0); // enable Timer Overflow interrupt
18
        sei(); // enable global interrupts
19
        while(1)    {
20
        }
21
}
====================================================================
OP #5575365
Lesenswert?

Marc V. schrieb:
> Probiere mal folgendes:
> ====================================================================#inc lude
> <avr/io.h>
> #include <avr/interrupt.h>
>
> volatile uint8_t isr_cnt = 0;
>
> ISR(TIM0_OVF_vect)  {
>   if(isr_cnt++ > 10) {
>     PINB = (1 << PB4); // toggle LED pin
>     isr_cnt = 0;
>   }
> }
>
> int main(void)  {
>         DDRB |= (1 << DDB4); // set LED pin as OUTPUT
>         PORTB = 0b00000000; // set all pins to LOW
>         TCCR0B |= (1 << CS02)|(1 << CS00); // set prescaler to 1024
> (CLK=1200000Hz/1024/256=4Hz, 0.25s)
>         TIMSK0 |= (1 << TOIE0); // enable Timer Overflow interrupt
>         sei(); // enable global interrupts
>         while(1)    {
>         }
> }
> ====================================================================

Hab ich versucht, ohne Wirkung.
Auch das einsetzen eines anderen Vorwiderstandes (10K) und einer anderen 
LED änderten nichts.
Könnte es daran liegen, das ich die gesamte Schaltung an den VCC/GND 
Pins eines Arduino Unos betreibe?
Beitrag #5575391 wurde von einem Moderator gelöscht.
Beitrag #5575395 wurde von einem Moderator gelöscht.
(Firma: Vescomp) #5575402
Lesenswert?

Stefanus F. schrieb:
> Marc V. schrieb:
>>  Es läuft 10x schneller über, also alle 21,845ms.
>
> Wie kommst du darauf?

 Heute ist nicht mein Tag.
 Ich habe glatt mit 12MHz gerechnet.

 See ya, gehe schlafen, genug Unfug für heute angerichtet.

 P.S.

Armin W. schrieb:
> Könnte es daran liegen, das ich die gesamte Schaltung an den VCC/GND
> Pins eines Arduino Unos betreibe?

 Nein.
 Aber es könnte sehr wohl daran liegen, dass sich der Tiny dauernd
 resetet.
OP #5575724
Lesenswert?

Ich habe mal zum Test ein Blink-Programm ohne Timmer-Interrupt mit der 
delay-Funktion geschrieben, was anstandslos funktioniert.
1
#include <avr/io.h>
2
#define F_CPU    10000000UL
3
#include <util/delay.h>
4

5

6

7
int main (void) {
8
    DDRB |= (1 << DDB4); //DDRB |= (1 << PB4); funktioniert auch
9
    while(1)    {
10
        //PORTB = 0b00010000;
11
        PORTB |= (1 << PB4);
12
        _delay_ms(100);
13
        //PORTB = 0b00000000;
14
        PORTB &= ~(1 << PB4);
15
        _delay_ms(100);
16
    }
17
    return 0;                 
18
}
(Firma: Vescomp) #5575730
Lesenswert?

Armin W. schrieb:
> Ich habe mal zum Test ein Blink-Programm ohne Timmer-Interrupt mit der
> delay-Funktion geschrieben, was anstandslos funktioniert.

 Na und, ich habe das alte Programm (von mir) ausprobiert, es läuft
 ohne Probleme, nur eben in 2,5s Takt.

 Interrupt kann bestimmt nicht daran Schuld sein, aber das dein Tiny
 dauernd in den Reset gesprungen ist, das kann sehr wohl sein.
(Firma: matzetronics) #5575819
Lesenswert?

Armin W. schrieb:
> #define F_CPU    10000000UL

Da ist doch was faul. Entweder läuft dein Tiny13 im Auslieferzustand, 
dann sind es 9,6 MHz geteilt durch 8, also 1,2 MHz. Oder du hast an den 
Fuses schon rumgefummelt, dann sind es entweder 9,6 MHz ohne die CKDIV8 
Fuse, oder 4,8 Mhz mit oder ohne CKDIV8 Fuse, das wären 4,8 Mhz resp. 
500 kHz.

10 Mhz hingegen erreichst du nur mit einem externen Oszillator.
OP #5576057
Lesenswert?

Bei meinem Attiny13 habe ich noch nie was an den Fuses verändert (wie 
kann man die über avrdude auslesen?).
Aber auch bei einem anderen Programm, welches einen externen Interrupt 
nutzt, leuchtet die LED die ganze Zeit schwach.
Könnte es sein, das ich die ganze Zeit ungewollt ein Interrrupt auslöse, 
welcher keine ISR besitzt und deshalb den Attiny13 wie "neustartet"?
OP #5576092
Lesenswert?

1
#include <avr/io.h>
2
#define F_CPU    10000000UL
3
#include <avr/interrupt.h>
4

5
volatile uint8_t isr_cnt = 0;**
6

7
ISR(TIM0_OVF_vect)  {
8
  if(isr_cnt++ > 10) {
9
    PINB = (1 << PB4); // toggle LED pin
10
    isr_cnt = 0;
11
  }
12
}
13

14
int main(void)  {
15
        DDRB |= (1 << DDB4); // set LED pin as OUTPUT
16
        PORTB = 0b00000000; // set all pins to LOW
17
        TCCR0B |= (1 << CS02)|(1 << CS00); // set prescaler to 1024 (CLK=1200000Hz/1024/256=4Hz, 0.25s)
18
        TIMSK0 |= (1 << TOIE0); // enable Timer Overflow interrupt
19
        sei(); // enable global interrupts
20
        while(1)    {
21
        }
22
}

Nein

Könnte ein fehlerhaftes Fuse-Bit solche Probleme verursachen?
Denn bei Marc V. funktioniert das Programm ja...
Beitrag #5576141 wurde von einem Moderator gelöscht.
Beitrag #5576191 wurde von einem Moderator gelöscht.
#5576676
Lesenswert?

Nee, das Konzept ist falsch.

  PORTB ^= (1 << PB4); // toggle LED pin

bedeutet PORTB lesen, aendern, schreiben.

nun sollte man erstens PINB lesen, nicht PORTB, und dann stimmen die 
Spannungen nicht. Denn nur weil man eine Null schreibt, ist beim 
Ruecklesen nicht unbedingt eine Null dort. Wir haben ja eine Diode.

Also ueber eine globat statische Zwischenvariable gehen.
also

 volatile  int ledstate=0;

 interrupt() {
  ledstate != ledstate;
  portb = ledstate;
  ..
  }

 Den interrupt ueberpruft man am Besten mit einem Oszilloskop.
(Firma: matzetronics) #5576705
Lesenswert?

Beim Tiny13 reicht es, eine 1 ins PINB Register an die gewünschte Stelle 
zu schreiben, dann toggelt der Pin.
1
PINB = (1 << PB4);
Das ist in Armins letztem Programm schon richtig gemacht.
'isr_cnt' kann auch eine static Variable in der ISR sein, wenn man ihren 
Wert nur innerhalb der ISR benötigt.

Allerdings steht da immer noch
Armin W. schrieb:
> #define F_CPU    10000000UL
was nicht stimmt.
#5576900
Lesenswert?

Jetzt ist G. schrieb:
> nun sollte man erstens PINB lesen, nicht PORTB, und dann stimmen die
> Spannungen nicht. Denn nur weil man eine Null schreibt, ist beim
> Ruecklesen nicht unbedingt eine Null dort. Wir haben ja eine Diode.

Das ist ja nun völliger Unsinn.

Matthias S. schrieb:
> Allerdings steht da immer noch
> Armin W. schrieb:
>> #define F_CPU    10000000UL
> was nicht stimmt.

Spielt erst eine Rolle, wenn der Compiler Berechnungen damit durchführt. 
tut er in diesem Fall aber nicht. Nichtsdestotrotz gehört da natürlich 
1,2MHz hingeschrieben. Denn die Fuses hat er ja nach eigener Aussage 
nicht angefasst.

Andererseits ist die Sache doch schon längst geklärt:

Armin W. schrieb:
> Es könnte am Breadboard liegen, denn auf einem anderen funktioniert die
> Schaltung, wenn auch unzuverlässig (geht nur ab und zu).

Das Breadboard ist Scheiße. Und das zweite auch nicht besonders.

Wurde aber auch schon frühzeitig drauf hingewiesen:

Georg M. schrieb:
> Armin W. schrieb:
>> Auf dem Steckbrett …
>
> Da muss man aufpassen: schlechte Kontakte, fehlende Abblockkondensatoren
> usw.
Gast #5599663
Lesenswert?

Es gibt da einige Abkürzungen, die ich auch schon öfter gelesen habe. 
Man muss sie nicht benutzen.

Ich benutze immer einfach den richtigen Namen des Mikrocontrollers (so 
wie attiny13a) und genau den selben String benutze ich auch für avrdude.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren