Forum: Mikrocontroller und Digitale Elektronik Variable im Interrup


von PK (Gast)


Lesenswert?

Moin,
ich habe Problem mit folgendem Programm. PB1 soll bei jedem Compare 
toggeln und PB2 quasi bei jedem 10 toggel von PB1 einmal toggeln. PB2 
hat also 1/10 der Frequenz von PB1. Leider toggelt PB1 aber nicht, nur 
PB0. Ich vermute es liegt an der Variablen a_b weiß aber nicht was ich 
falsch gemacht habe. Bin über jede Hilfe dankbar.
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
#include <stdio.h>
4
#define F_CPU 16000000UL
5
6
volatile uint8_t a_b;
7
int main()
8
{
9
DDRB =0xff;
10
ICR1=250;
11
OCR1A= 125;
12
TCCR1A = (1<<WGM11);
13
TCCR1B = (1<<WGM12)|(1<<WGM13)|(1<<CS12)|(1<<CS10);
14
TIMSK = (1<<OCIE1A)|(1<<TOIE1);
15
16
sei();
17
18
    while(1)
19
    {
20
    if (a_b>=10)
21
    {
22
      a_b = 0;
23
      PORTB^=(1<<PB1);
24
    } 
25
  }
26
}
27
ISR(TIMER1_COMPA_vect)  
28
{
29
  PORTB^=(1<<PB0);
30
  a_b++;
31
}

--
Quelltext bitte in [ c ] [ /c ] - Tags einschließen.
-rufus

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Probier doch mal, das toggeln beider Pins in die ISR zu verlegen:
1
ISR(TIMER1_COMPA_vect)
2
{
3
  PORTB^=(1<<PB0);
4
  a_b++;
5
    if (a_b>=10)
6
    {
7
      a_b = 0;
8
      PORTB^=(1<<PB1);
9
    }
10
}
Macht die Sache übersichtlicher und befreit das Hauptprogramm.

Ausserdem gibst du den Interupt für den Timeroverflow auch frei, 
behandelst ihn aber nicht (zumindest im geposteten Teil):
1
TIMSK = (1<<OCIE1A)|(1<<TOIE1);
Es kann also sein, das nach dem ersten Compare Match die Kiste resettet 
(Standardverhalten bei unbelegten ISR Vektoren) und wieder von vorne los 
geht. So kommts nie zum Toggeln von PB1.

von PK (Gast)


Lesenswert?

Ja funktioniert jetzt, danke

von OldMan (Gast)


Lesenswert?

Die Variable a_b ist nicht initialisiert.
Normaler Weise werden Variablen vom Compiler mit 0 initialisiert, darauf
sollte man sich aber nicht verlassen.
In der main würde ich a_b mit 0 initialisieren.

von Ingo (Gast)


Lesenswert?

PK schrieb:
> Ja funktioniert jetzt, danke
Woran lag es denn?

von ?!? (Gast)


Lesenswert?

OldMan schrieb:
> Die Variable a_b ist nicht initialisiert.

Doch:
PK schrieb:
> volatile uint8_t a_b;

von Falk B. (falk)


Lesenswert?

@OldMan (Gast)

>Die Variable a_b ist nicht initialisiert.

Doch. Globale Variablen sind IMMER initialisiert.

>Normaler Weise werden Variablen vom Compiler mit 0 initialisiert, darauf
>sollte man sich aber nicht verlassen.

Doch, kann man.

>In der main würde ich a_b mit 0 initialisieren.

Ist egal. selbst wenn sie nicht initialaisiert WÄRE, würde das Programm 
laufen, weil nach dem 1. if () das Ganze wieder normal ist.

Das Problem war ein freigegebener Interrupt ohne passende ISR. Dadurch 
macht der Controller immer einen Reset, wodurch aber auch die globale 
Variable immer wieder mit 0 initialisiert wird ;-)

von PK (Gast)


Lesenswert?

Ja der Fehler war der freigegebene Interrupt.
Ich habe aber schon ein neues Problem. Hoffentlich könnt ihr das auch 
lösen.
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdio.h>
#define F_CPU 3680000UL

volatile uint32_t a_b;
int main()
{
DDRB =0xff;
ICR1=92;
OCR1A= 46;
TCCR1A = (1<<WGM11);
TCCR1B = (1<<WGM12)|(1<<WGM13);   //|(1<<CS12);
TIMSK = (1<<OCIE1A);

sei();

    while(1)
    {}
ISR(TIMER1_COMPA_vect)
{
  PORTB^=(1<<PB0);
  a_b++;
  if (a_b>=5714)      //a_b=22
  {
    a_b = 0;
    PORTB^=(1<<PB1);
  }
}
Ich benutze das STK500 das einen Takt von 3,68MHz hat (laut Datenblatt) 
und einen Atmega 32. Ich will PB0 mit 40kHz und PB1 mit 7Hz (duty cycle 
0,5) toggeln lassen. Deshalb ICR1=92, OCR1A=46 bzw. a_b>=5714.
Kommentiere ich CS12 ein, teile ich den Takt durch 256 und muss 
dementsprechend auch a_b durch 256 teilen also auf 22, dann kann ich die 
angeschlossenen Leds blinken sehen. So wie der Code oben ist kann ich 
PB0 natürlich nicht blinken sehen (zu schnell) aber PB1 müsste ich 
eigentlich blinken sehen. Tu ich aber nicht jmd ne Idee?

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

PK schrieb:
> TCCR1A = (1<<WGM11);
> TCCR1B = (1<<WGM12)|(1<<WGM13);   //|(1<<CS12);
> TIMSK = (1<<OCIE1A);

Nimm doch bitte Codetags. Aber da du den Timer gar nicht startest, 
kannst du auf das Blinken bis zum St. Nimmerleinstag warten. Du musst 
mindestens eines der CS1n Bits schon setzen, sonst steht der Timer.

von PK (Gast)


Lesenswert?

Vielen Dank, es geht geht jetzt. Habe cs10 gesetzt.
Ich bin ziemlich neu im Forum, was sind Codetags bzw wie benutzt man 
sie?

von npn (Gast)


Lesenswert?

PK schrieb:
> Vielen Dank, es geht geht jetzt. Habe cs10 gesetzt.
> Ich bin ziemlich neu im Forum, was sind Codetags bzw wie benutzt man
> sie?

Wenn du Code direkt einfügst, setzt du am Anfang des Codes ein "c" in 
eckige Klammer [] und am Ende ein "/c" in eckige Klammer []. Dann wird 
der Code mit Sytax-Highlighing dargestellt und ist wesentlich besser 
lesbar.

Ich nehm mal das Beispiel aus deinem vorigen Post:
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
#include <stdio.h>
4
#define F_CPU 3680000UL
5
6
volatile uint32_t a_b;
7
int main()
8
{
9
DDRB =0xff;
10
ICR1=92;
11
OCR1A= 46;
12
TCCR1A = (1<<WGM11);
13
TCCR1B = (1<<WGM12)|(1<<WGM13);   //|(1<<CS12);
14
TIMSK = (1<<OCIE1A);
15
16
sei();
17
18
    while(1)
19
    {}
20
ISR(TIMER1_COMPA_vect)
21
{
22
  PORTB^=(1<<PB0);
23
  a_b++;
24
  if (a_b>=5714)      //a_b=22
25
  {
26
    a_b = 0;
27
    PORTB^=(1<<PB1);
28
  }
29
}

von Form (Gast)


Lesenswert?

npn schrieb:
> PK schrieb:
>> Ich bin ziemlich neu im Forum, was sind Codetags bzw wie benutzt man
>> sie?
>
> Wenn du Code direkt einfügst, setzt du am Anfang des Codes ein "c" in
> eckige Klammer [] und am Ende ein "/c" in eckige Klammer []. Dann wird
> der Code mit Sytax-Highlighing dargestellt und ist wesentlich besser
> lesbar.

Und Eingeweihte können die Syntax nochmal unter Formatierung beim 
"Antwort schreiben" über dem Feld nachlesen, in dem man seinen Namen 
einträgt.

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.