Forum: Mikrocontroller und Digitale Elektronik Timer0 problem


von Daniel L. (daniel_l49)


Lesenswert?

hallo

Ich habe ein Programm geschrieben um den timer0 zu testen, aber es tut 
sich nichts
1
TCCR0  |= (1<<CS00) | (CS01);
2
TIMSK  |= (1<<TOIE0);
3
4
while(1)
5
{
6
  PORTB |= (1<<PB0);
7
  if(TCNT0 ==200)
8
     PORTB &= (1<<PB0);
9
}

von Motor (Gast)


Lesenswert?

Daniel L. schrieb:
> while(1)
> {
>   PORTB |= (1<<PB0);
>   if(TCNT0 ==200)
>      PORTB &= (1<<PB0);
> }

Auf den ersten Blick hat die letzte Zeile einen Fehler:
>      PORTB &= (1<<PB0);
soll heißen
       PORTB &= ~(1<<PB0);

von Daniel L. (daniel_l49)


Lesenswert?

ich hab das jetzt mal geändert, aber es hat nicht geholfen

von Motor (Gast)


Lesenswert?

Wie stellst du das fest?
Ich vermute mal, mit einer LED am Ausgang oder sowas in der Art.
Da wirst du aber nicht viel sehen. Mit einem Oszilloskop schon.
Der Impuls wird nur sehr kurz sein.


> while(1)
> {
>   PORTB |= (1<<PB0);
PB0 wird gesetzt
>   if(TCNT0 ==200)
wenn TCNT0 = 200 ist,
>      PORTB &= (1<<PB0);
wird PB0 rückgesetzt
> }
und im nächsten Schleifendurchlauf sofort wieder gesetzt.

von Uwe (de0508)


Lesenswert?

Hallo  Daniel,

sorry, das ist kein Programm, sondern nur ein Auszug und der lässt sich 
so nicht übersetzten !

Wo ist die Funktion main() und die prozessor spezifischen 
Include-Dateien?

von Ingo (Gast)


Lesenswert?

Daniel L. schrieb:
> if(TCNT0 ==200)
>      PORTB &= (1<<PB0);

Du müsstest schon viel Glück haben das das Programm bei genau 200 die 
Abfrage macht.
1
if (TCNT0 >= 200){
2
 PORTB &= ~(1<<PB0);
3
}else{
4
 PORTB |= (1<<PB0);
5
}
wäre besser denke ich, auch wenn es immernoch Murks ist.

von Daniel L. (daniel_l49)


Lesenswert?

Ich habe das jetzt mal außerhalb der while-Schleife versucht,aber die 
LED leuchtet durchgehend

von Karl H. (kbuchegg)


Lesenswert?

Daniel L. schrieb:
> Ich habe das jetzt mal außerhalb der while-Schleife versucht,aber die
> LED leuchtet durchgehend


Was erwartest du?

Natürlich leuchtet die durchgehend (für dich langsamen Menschen).
Aber wenn du mal eine LED daneben auf Dauer-Ein einschaltest, dann wirst 
du sehen, dass sie etwas dunkler leuchtet (wenn auch nicht viel).

Kann es sein, dass du du ganz krass die Geschwindigkeit unterschätzt? 
Rechne mal nach, wie schnell deine LED eigentlich blinkt!

: Bearbeitet durch User
von Daniel L. (daniel_l49)


Lesenswert?

Tut mir leid das habe ich jetzt nicht ganz verstanden

Wenn ein Code außerhalb der while-Schleife ist, wird dieser ja nur 
einmal durchlaufen

von Karl H. (kbuchegg)


Lesenswert?

Und bitte: kompletten Code! Inklusive der Angabe der Taktfrequenz, mit 
der der µC läuft.
Ehe du Code in Prosa beschreibst, kopiere lieber den Code hier rein. Und 
zwar alles. Das ist für dich einfacher und für uns auch. Denn dann haben 
wir ein Bild davon, wie der Code wirklich aussieht und müssen nicht 
raten.

von Daniel L. (daniel_l49)


Lesenswert?

Hier der Code:
1
#include <asf.h>
2
#define F_CPU 3686400UL
3
#include <avr/io.h>
4
#include <interrupt.h>
5
#include <util/delay.h>
6
#include <stdio.h>
7
8
#define taste_gedruckt       1 
9
#define taste_nicht_gedruckt 0
10
11
volatile int k = 0;
12
13
int main (void)
14
{
15
  
16
  sei();
17
  
18
  DDRB = 0xff;
19
  DDRD = 0x00;
20
  PORTD = 0xff;
21
  
22
  int i = 0;
23
  int taste_jetzt;
24
  int taste_vorher; 
25
26
  
27
  void blink1();
28
  void blink2();
29
  
30
  TCCR0  |= (1<<CS00) | (CS01);
31
  TIMSK  |= (1<<TOIE0);
32
  
33
34
  
35
  if (!(PIND & (1<<PD2)))
36
  {
37
    taste_vorher = taste_gedruckt;
38
  } 
39
  else
40
  {
41
    taste_vorher = taste_nicht_gedruckt;
42
  }
43
  
44
  
45
  
46
    
47
  while (1)
48
  {  
49
    if(!(PIND & (1<<PD2)))
50
    {
51
      taste_jetzt  = taste_gedruckt;  
52
    }
53
    else
54
    {
55
      taste_jetzt  = taste_nicht_gedruckt; 
56
    }      
57
  
58
    if(taste_vorher != taste_jetzt)
59
    {
60
      if (taste_jetzt == taste_gedruckt)
61
      {
62
        i++;
63
        //switch(i)
64
        //{
65
          blink1(i, k);
66
        
67
        //blink2(i);
68
        //}
69
      }
70
    } taste_jetzt = taste_vorher;
71
    
72
    _delay_ms(50);
73
  }
74
}
75
76
void blink1(int i , int k )
77
{
78
  while(1)
79
  {
80
    PORTB |= (1<<PD1);
81
    if (k  >= 440)
82
    {  
83
        PORTB |= (1<<PD2);
84
        PORTB &= ~ (1<<PD1);
85
    }
86
    if (k>= 440)
87
    {  
88
      PORTB &= ~ (1<<PD2);
89
      PORTB |= (1<<PD0);
90
    }
91
    if(k>=440)
92
      PORTB &= ~ (1<<PD0);    
93
  }
94
   
95
}
96
void blink2(int i)
97
{
98
  
99
}
100
101
ISR(TIMER0_OVF_vect)
102
{
103
  k++;
104
  if (k >= 440)
105
    k=0;
106
}

Hier ist das Programm

Das Problem liegt hier in der Funktion blink1

Es sollte hier einfach die LED's umschalten

von Karl H. (kbuchegg)


Lesenswert?

Daniel L. schrieb:

> Es sollte hier einfach die LED's umschalten

Dann solltest du das auch machen.

ABer solange du den µC in der Funktion gefangen hältst
1
void blink1(int i , int k )
2
{
3
  while(1)
4
  {
5
    PORTB |= (1<<PD1);
6
    if (k  >= 440)
7
    {  
8
        PORTB |= (1<<PD2);
9
        PORTB &= ~ (1<<PD1);
10
    }
11
    if (k>= 440)
12
    {  
13
      PORTB &= ~ (1<<PD2);
14
      PORTB |= (1<<PD0);
15
    }
16
    if(k>=440)
17
      PORTB &= ~ (1<<PD0);    
18
  }
19
   
20
}

wird sich vom restlichen Programm da nichts mehr tun. Da ist eine 
Endlossschleife in der Funktion. Die Funktion wird nie mehr verlassen.
Ganz abgesehen davon, dass dein k auch mit ISR Hilfe nie größer/gleich 
440 werden kann.

Der ganze Ansatz ist Müll.
Mit der ISR hast du den perfekten Ort, um ein zeitliches Blinken zu 
realisieren.

: Bearbeitet durch User
von Daniel L. (daniel_l49)


Lesenswert?

Ich habe den Code noch nicht geschrieben um die Funktion zu verlassen 
bzw.
Die schleife zu unterbrechen.

Wenn die Funktion aufgerufen wird sollten doch die LED's schon mal 
umgeschalten werden.

von Karl H. (kbuchegg)


Lesenswert?

Karl Heinz schrieb:

> Der ganze Ansatz ist Müll.
> Mit der ISR hast du den perfekten Ort, um ein zeitliches Blinken zu
> realisieren.

STeck den kompletten Blink-Code in die ISR.
1
ISR(TIMER0_OVF_vect)
2
{
3
  if( isBlinking )
4
  {
5
    k++;
6
    if (k >= 440)
7
    {
8
      k=0;
9
10
      if( k > 200 ) {
11
        PORTB |= (1<<PD2);
12
        PORTB &= ~ (1<<PD1);
13
      }
14
      else {
15
        PORTB &= ~ (1<<PD2);
16
        PORTB |= (1<<PD0);      
17
      }
18
    }
19
  }
20
}

und im Hauptprogramm schaltest du bei Tastendruck einfach nur das 
Blinken ein/aus, indem du die Variable 'isBlinking' auf 0 bzw. 1 setzt.
1
volatile uint8_t isBlinking;
2
3
....
4
5
6
    if(taste_vorher != taste_jetzt)
7
    {
8
      if (taste_jetzt == taste_gedruckt)
9
      {
10
        isBlinking = 1 - isBlinking;
11
      }
12
      ...
13
14
...

von Karl H. (kbuchegg)


Lesenswert?

PS:
Allerdings müssen dazu auch die Interrupts mitels sei() freigegeben 
worden sein. Ansonsten wird das nichts mit dem AUfruf der ISR
1
int main()
2
{
3
   ....
4
5
6
   sei();
7
   while( 1 )
8
   {
9
      ....

von Karl H. (kbuchegg)


Lesenswert?

Daniel L. schrieb:

> Wenn die Funktion aufgerufen wird sollten doch die LED's schon mal
> umgeschalten werden.


Moment.

Hast du deine Tastenauswertung für sich alleine gestestet oder hast du 
das nicht?
Funktioniert die?

von Karl H. (kbuchegg)


Lesenswert?

Karl Heinz schrieb:

> Hast du deine Tastenauswertung für sich alleine gestestet oder hast du
> das nicht?
> Funktioniert die?


Ehe da jetzt der nächste Schritt drauf gesetzt wird, sollte der Punkt 
erst mal geklärt sein. Nicht dass du/wir da jetzt einem Timer-Phantom 
nachjagen und das 'Problem' ganz woanders liegt.

1
+#include <asf.h>
2
#define F_CPU 3686400UL
3
#include <avr/io.h>
4
#include <interrupt.h>
5
#include <util/delay.h>
6
#include <stdio.h>
7
8
#define taste_gedruckt       1 
9
#define taste_nicht_gedruckt 0
10
11
volatile int k = 0;
12
13
int main (void)
14
{
15
  DDRB = 0xff;
16
  DDRD = 0x00;
17
  PORTD = 0xff;
18
  
19
  int i = 0;
20
  int taste_jetzt;
21
  int taste_vorher; 
22
23
  taste_vorher =  (PIND & (1<<PD2) ? taste_nicht_gedruckt : taste_gedruckt;
24
25
  while (1)
26
  {  
27
    taste_jetzt  = (PIND & (1<<PD2) ? taste_nicht_gedruckt : taste_gedruckt;  
28
  
29
    if(taste_vorher != taste_jetzt)
30
    {
31
      if (taste_jetzt == taste_gedruckt)
32
      {
33
        PORTB ^= ( 1 << PB2 );
34
      }
35
    } taste_jetzt = taste_vorher;
36
    
37
    _delay_ms(50);
38
  }
39
}

die LED an PB2 muss mit jedem Tastendruck umschalten.
klappt?
klappt nicht?

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

Karl Heinz schrieb:
> PS:
> Allerdings müssen dazu auch die Interrupts mitels sei() freigegeben
> worden sein.

Seh gerade, du hast das am Anfang von main() gemacht.
Keine gute Idee.

Erst mal wird alles initialisiert, die Hardware eingestellt, Variablen 
auf ihre Anfangswerte begracht.
Und erst dann, wenn alles soweit fertig und grundsätzlich lauffähig ist, 
erst dann kommt das 'Feuer frei' für die Interrupts. Als letzte Aktion 
vor der Hauptschleife.
Denn was du nicht willst: Das die Interrupts sofort zu feuern beginnen, 
wenn du in einzelnen Komponenten einen spezifischen Interrupt während 
der Konfiguration frei gibst. Du kannst nicht alles parallel und zur 
gleichen Zeit konfigurieren. Du willst aber in komplexeren Programmen 
haben, dass das Interrupt-Konzert in geordneten Bahnen läuft. Und das 
tut es im Regelfall erst dann, wenn ALLE Komponenten initialisiert sind.

: Bearbeitet durch User
von Daniel L. (daniel_l49)


Lesenswert?

1
if (!(PIND & (1<<PD2))) // wenn Taste gedrückt
2
  {
3
    taste_vorher = taste_gedruckt;
4
  } 
5
  else
6
  {
7
    taste_vorher = taste_nicht_gedruckt;
8
  }
9
  
10
  sei();  
11
  while (1)
12
  {  
13
    if(!(PIND & (1<<PD2))) // Wenn Taste gedrückt
14
    {
15
      taste_jetzt  = taste_gedruckt;  
16
    }
17
    else
18
    {
19
      taste_jetzt  = taste_nicht_gedruckt; 
20
    }      
21
  
22
    if(taste_vorher != taste_jetzt)
23
    {
24
      if (taste_jetzt == taste_gedruckt)
25
      {
26
        
27
          PORTB ^= (1<<PB0); // Wird umgeshcalten
28
        
29
        
30
      }
31
    } taste_jetzt = taste_vorher;
32
    
33
    _delay_ms(50);
34
  }
35
}

von Daniel L. (daniel_l49)


Lesenswert?

Habe gerade festgestellt, dass die LED nicht bei jedem Tastendruck 
umgeschalten wird.

von Karl H. (kbuchegg)


Lesenswert?

>     } taste_jetzt = taste_vorher;

falsch rum
1
  taste_vorher = taste_jetzt;


(und ich Depp kopier das auch noch weiter)

: Bearbeitet durch User
von Daniel L. (daniel_l49)


Lesenswert?

Ich habe das jetzt umgeändert, aber jetzt lässt sich die LED nur noch 
einschalten, aber nicht mehr ausschaltenb

von Karl H. (kbuchegg)


Lesenswert?

Daniel L. schrieb:
> Ich habe das jetzt umgeändert, aber jetzt lässt sich die LED nur noch
> einschalten, aber nicht mehr ausschaltenb


Welches Programm?
(Nach DEM Fehler trau ich dir nicht mehr)

: Bearbeitet durch User
von Daniel L. (daniel_l49)


Lesenswert?

1
#include <asf.h>
2
#define F_CPU 3686400UL
3
#include <avr/io.h>
4
#include <interrupt.h>
5
#include <util/delay.h>
6
#include <stdio.h>
7
8
#define taste_gedruckt       1 
9
#define taste_nicht_gedruckt 0
10
11
volatile int k = 0;
12
volatile bool isblinking = false;
13
14
int main (void)
15
{
16
        
17
  DDRB = 0xff;
18
  DDRD = 0x00;
19
  PORTD = 0xff;
20
  
21
  int i = 0;
22
  int taste_jetzt;
23
  int taste_vorher; 
24
25
  
26
  void blink1();
27
  void blink2();
28
  
29
  TCCR0  |= (1<<CS00) | (CS01);
30
  TIMSK  |= (1<<TOIE0);
31
  
32
33
  
34
  if (!(PIND & (1<<PD2)))
35
  {
36
    taste_vorher = taste_gedruckt;
37
  } 
38
  else
39
  {
40
    taste_vorher = taste_nicht_gedruckt;
41
  }
42
    
43
  sei();  
44
  while (1)
45
  {  
46
    if(!(PIND & (1<<PD2)))
47
    {
48
      taste_jetzt  = taste_gedruckt;  
49
    }
50
    else
51
    {
52
      taste_jetzt  = taste_nicht_gedruckt; 
53
    }      
54
  
55
    if(taste_vorher != taste_jetzt)
56
    {
57
      if (taste_jetzt == taste_gedruckt)
58
      {
59
        
60
          PORTB ^= (1<<PB0);
61
        
62
      }
63
    } taste_vorher = taste_jetzt;
64
    
65
    _delay_ms(30);
66
  }
67
}

von Karl H. (kbuchegg)


Lesenswert?

Daniel L. schrieb:

>   TIMSK  |= (1<<TOIE0);

Overflow Interrupt freigegeben


>   sei();

Interrupts generell freigegeben


> }

.... aber keine ISR.

Sowas wird mit einem µC-Reset bestraft.

Aus gutem Grund hab ich in meinem 'Testprogramm' weiter oben, den Timer 
komplett rausgelassen.

von Daniel L. (daniel_l49)


Lesenswert?

Hier noch die ISR
1
ISR(TIMER0_OVF_vect)
2
{
3
  
4
  
5
  if (isblinking == true)
6
  {
7
    k++;
8
    if (k >= 440)
9
    k=0;
10
    
11
    PORTB |= (1<<PD1);
12
    if (k == 440)
13
    {
14
      PORTB |= (1<<PD2);
15
      PORTB &= ~(1<<PD1);
16
    }
17
    if (k>= 440)
18
    {
19
      PORTB &= ~(1<<PD2);
20
      PORTB |= (1<<PD0);
21
    }
22
    if(k>=440)
23
    PORTB &= ~(1<<PD0);
24
  }
25
  
26
}

von Karl H. (kbuchegg)


Lesenswert?

Daniel L. schrieb:
> Hier noch die ISR

Schön.
Ich bin raus.

Ich sag dir einmal, du mögest den ganzen Code posten. Ich sags 
vielleicht noch ein zweitesmal ein paar Tage später. Aber nicht ein paar 
Minuten/Stunden später.
Such dir einen anderen Dummen. Ich bin das Rätselraten leid.

: Bearbeitet durch User
von Daniel L. (daniel_l49)


Lesenswert?

Oke tut mir leid hier ist der ganze Code:
1
#include <asf.h>
2
#define F_CPU 3686400UL
3
#include <avr/io.h>
4
#include <interrupt.h>
5
#include <util/delay.h>
6
#include <stdio.h>
7
8
#define taste_gedruckt       1
9
#define taste_nicht_gedruckt 0
10
11
volatile int k = 0;
12
volatile bool isblinking = false;
13
14
int main (void)
15
{
16
  
17
  DDRB = 0xff;
18
  DDRD = 0x00;
19
  PORTD = 0xff;
20
  
21
  int i = 0;
22
  int taste_jetzt;
23
  int taste_vorher;
24
25
  
26
  void blink1();
27
  void blink2();
28
  
29
  TCCR0  |= (1<<CS00) | (CS01);
30
  TIMSK  |= (1<<TOIE0);
31
  
32
33
  
34
  if (!(PIND & (1<<PD2)))
35
  {
36
    taste_vorher = taste_gedruckt;
37
  }
38
  else
39
  {
40
    taste_vorher = taste_nicht_gedruckt;
41
  }
42
  
43
  
44
  
45
  
46
  sei();
47
  while (1)
48
  {
49
    if(!(PIND & (1<<PD2)))
50
    {
51
      taste_jetzt  = taste_gedruckt;
52
    }
53
    else
54
    {
55
      taste_jetzt  = taste_nicht_gedruckt;
56
    }
57
    
58
    if(taste_vorher != taste_jetzt)
59
    {
60
      if (taste_jetzt == taste_gedruckt)
61
      {
62
      
63
             isblinking = true;
64
        
65
        
66
      }
67
    } taste_vorher = taste_jetzt;
68
    
69
    _delay_ms(30);
70
  }
71
}
72
ISR(TIMER0_OVF_vect)
73
{
74
  
75
  
76
  if (isblinking == true)
77
  {
78
    k++;
79
    if (k >= 440)
80
    k=0;
81
    
82
    PORTB |= (1<<PD1);
83
    if (k == 440)
84
    {
85
      PORTB |= (1<<PD2);
86
      PORTB &= ~(1<<PD1);
87
    }
88
    if (k>= 440)
89
    {
90
      PORTB &= ~(1<<PD2);
91
      PORTB |= (1<<PD0);
92
    }
93
    if(k>=440)
94
    PORTB &= ~(1<<PD0);
95
  }
96
  
97
}

von Michael R. (Firma: Brainit GmbH) (fisa)


Lesenswert?

ich versuch mal, dir zu helfen, dein Hirn einzuschalten:

Daniel L. schrieb:
1
   if (k >= 440)
2
       k=0;
wie groß ist k nun maximal?
1
   if (k == 440)
kann das jemals passieren?
1
   if (k>= 440)
oder kann das jemals passieren?

(dabei hatte ich erst gestern einen so vielversprechenden kandidaten für 
"useless code":
1
while (1) {
2
   break;
3
}

: Bearbeitet durch User
von LittleHelper (Gast)


Lesenswert?

Daniel L. schrieb:
> Ich habe das jetzt umgeändert, aber jetzt lässt sich die LED nur
> noch
> einschalten, aber nicht mehr ausschaltenb

Daniel L. schrieb:
> if(taste_vorher != taste_jetzt)
>     {
>       if (taste_jetzt == taste_gedruckt)
>       {
>
>              isblinking = true;
>
>
>       }
>     } taste_vorher = taste_jetzt;

else if (taste_jetzt == taste_nicht_gedruckt)
{
  isBlinking = false;
}

von Daniel L. (daniel_l49)


Lesenswert?

Oke Es kann nie passieren

von Martin (Gast)


Lesenswert?

Hallo,

Kann mir jemand sagen warum die Led bei diesem Code nicht leuchtet ?

//---------------------CODE 1-----------------------------
#include <avr/io.h>
#include <avr/interrupt.h>

long cnt;
int main(void)
{
    TCCR0 = (1<<CS01);
    TIMSK |= (1<<TOIE0);
    DDRD = 0b11110111;
    sei();
    while(1)
    {
    if(cnt > 3900)
    {
      PORTD = 0x01;
      cnt = 0;
    }

    }
}
ISR (TIMER0_OVF_vect)
{
      cnt++;
}


Bei diesem Code leuchtet die Led jedoch!!!!!!!!!!!
//---------------------CODE 2-----------------------------
#include <avr/io.h>
#include <avr/interrupt.h>

long cnt;

int main(void)
{
    TCCR0 = (1<<CS01);
    TIMSK |= (1<<TOIE0);
    DDRD = 0b11110111;
    sei();

    while(1)
    {


    }
}

ISR (TIMER0_OVF_vect)
{
      cnt++;
      if(cnt > 3900)
      {
        PORTD = 0x01;
        cnt = 0;
      }
}


Im Grunde ist es das gleiche Programm aber es funktioniert nur der Code 
2.
Wenn ich das Programm im Atmel Studio 6 Simuliere sieht es aus als würde 
nur 1 mal die while schleife augeführt werden und danach nicht mehr, was 
auch erklären würden wieso die Led nicht leuchtet. Aber Wieso? Kann mir 
jemand weiter helfen!?

von Peter II (Gast)


Lesenswert?

Martin schrieb:
> Kann mir jemand sagen warum die Led bei diesem Code nicht leuchtet ?

 cnt ist nicht volatile.

von Martin (Gast)


Lesenswert?

Super Danke. Hat funktioniert!

Bin noch Anfänger im Microcontroller programmieren bzw. ist die 
Schulzeit schon sehr sehr lange her ;)

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.