Forum: Mikrocontroller und Digitale Elektronik Atmega32 Timer1 und Timer0 laufen nicht zusammen


von Jakob (Gast)


Lesenswert?

Hallo, ich hab jetzt mich damit befasst 2 Timer zu benutzen, einen rein 
für die Zeit und einen für die Taster Abfrage, damit  sich die Zeit 
nicht überschreitet wenn ein Taster gedrückt wird.

Einzeln  laufen die Timer super, aber zusammen macht es nur der Timer0.
Habe ich irgendwo ein kleinen Fehler drinnen ? Ich bin aus anderen 
Einträgen nicht schlau geworden deswegen schicke ich mal mein Code mit.
1
 
2
3
void start_timer1(uint16_t prescale)
4
{  
5
  TCCR1B = 0;
6
  //16Bit Timer Initialisierung:
7
  if (prescale == 0)
8
  {
9
    TCCR1B = (1<<CS10) | (1<<WGM12);        //Prescaler = 1, CTC    //
10
  }
11
  if (prescale == 1)
12
  {
13
    TCCR1B = (1<<CS11) | (1<<WGM12);        //Prescaler = 8, CTC
14
  }
15
  if (prescale == 2)
16
  {
17
    TCCR1B = (1<<CS11) | (1<<CS10) | (1<<WGM12);  //Prescaler = 64, CTC
18
  }
19
  if (prescale == 3)
20
  {
21
    TCCR1B = (1<<CS12) | (1<<WGM12);        //Prescaler = 256, CTC
22
  }
23
  if (prescale == 4)
24
  {
25
    TCCR1B = (1<<CS12) | (1<<CS10) | (1<<WGM12);  //Prescaler = 1024, CTC
26
  }
27
28
  TIMSK = (1<<OCIE1A);        //Timerinterrupt für Vergleich aktivieren
29
  OCR1A = 16000 - 1;          //Vergleichswert bis wohin er durchzählt  zählt!(länge des Timers abhängig vom Prescaler)
30
  sei();                //Interrupts zulassen
31
}
32
33
34
35
36
/*Timer0 prescale------------------------------------------------------------*/
37
38
39
40
void start_timer0(uint8_t prescale0){
41
  
42
  TCCR0 = 0; //8bit Timer
43
  
44
  if (prescale0 == 0)
45
  {
46
    TCCR0 = (1<<CS00) | (1<<WGM01);
47
  }
48
  
49
  if (prescale0 == 1)
50
  {
51
    TCCR0 = (1<<CS01) | (1<<WGM01);
52
  }
53
  
54
  if (prescale0 == 2)
55
  {
56
    TCCR0 = (1<<CS01) |(1<<CS00) | (1<<WGM01);
57
  }
58
  
59
  if (prescale0 == 3)
60
  {
61
    TCCR0 = (1<<CS02) | (1<<WGM01);
62
  }
63
  
64
  if (prescale0 == 4)
65
  {
66
    TCCR0 = (1<<CS02) | (1<<CS00) | (1<<WGM01);
67
  }
68
  
69
  
70
  TIMSK = (1<<OCIE0);        //Timerinterrupt für Vergleich aktivieren
71
  OCR0 = 255 - 1;
72
  sei();
73
  
74
}
75
//__________________________________________________________________________
76
77
void start_clock(void)
78
{
79
  start_timer1(0); //Prescaler 0
80
  
81
}
82
83
84
void start_clock0(void)
85
{
86
  start_timer0(0);
87
}
88
//__________________________________________________________________________
89
90
ISR(TIMER0_COMP_vect){
91
  scan_key();
92
}    
93
  
94
ISR(TIMER1_COMPA_vect){
95
  
96
  
97
  
98
  MilSek++;
99
  if (MilSek==1000)
100
  {
101
    Sek++;
102
    MilSek=0;
103
    //PORTB = 0xFF;
104
  }
105
  
106
  if (Sek==59)
107
  {
108
    //PORTB = 0x00;
109
    Sek = 0;
110
  }
111
112
//__________________________________________________________________________
113
114
void scan_key() {
115
  
116
  
117
  unsigned  char key1,key2;
118
  key1 = PIND;
119
  key1 ^= 0x00;
120
  key1 &= 0xFF;
121
  if (key1 != 0){
122
    _delay_ms(4);
123
    key2 = PIND;
124
    key2 ^=0x00;
125
    key2 &=0xFF;
126
    if ((key1 == key2) & (key1 != lastkey)) {
127
      lastkey = key1;
128
      if (keybuf == 0){
129
        keybuf = key1;
130
      }
131
    }
132
  }
133
  else lastkey = 0;
134
}

von Wolfgang S. (wsm)


Lesenswert?

Wenn ein TimerIRQ aktiv ist, wird der andere IRQ ausgeschaltet.

Dann muss man in der ISR die anderen IRQs wieder aktivieren.

W.

von Thomas E. (thomase)


Lesenswert?

Jakob schrieb:
>   TIMSK = (1<<OCIE1A);        //Timerinterrupt für Vergleich aktivieren

>   TIMSK = (1<<OCIE0);        //Timerinterrupt für Vergleich aktivieren

Je nach Reihenfolge der Aufrufe wird damit der vorige Interrupt wieder 
abgeschaltet.
TIMSK |= .....!!!

mfg.

von Jakob (Gast)


Lesenswert?

Ahhhh , vielen Dank jetzt ist es klar

von Karl H. (kbuchegg)


Lesenswert?

Jakob schrieb:
> Hallo, ich hab jetzt mich damit befasst 2 Timer zu benutzen, einen rein
> für die Zeit und einen für die Taster Abfrage, damit  sich die Zeit
> nicht überschreitet wenn ein Taster gedrückt wird.

Nimm eine ordentliche Entprellung, dann hast du dieses Problem nicht.
Ein _delay_ms(4) in einer ISR ist nicht akzeptabel.
Wo auch immer du diese Entprellung her hast, sie ist nicht gut.

Entprellung
Die sog. PeDa Entprellung spielt alle Stücke, die du je brauchen wirst. 
Das Nachladen des Timers in der ISR kannst du dort rausnehmen, das ist 
alles nicht zeitkritisch. Wenn die ISR eine Aufrufhäufigkeit im kleinen 
Millisekundenbereich hat, dann reicht das. Das muss nicht allzu genau 
sein. Und genau den Fall hast du mit deiner Zeit-ISR. Die wird jede 
Millisekunde aufgerufen. Passt perfekt.

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

Tu dir weiterhin selbst einen Gefallen und sieh den sei() nicht als Teil 
der Timer Initialisierung an.


Das sei() kommt am besten hier hin ....
1
int main()
2
{
3
4
  alle Initialisierungen
5
6
7
  sei();              // <-----------------
8
9
  while( 1 )
10
  {
11
12
     Programmlogik
13
14
  }
15
}

... ist also die letzte Anweisung vor der Hauptschleife in main.

Dort ist er gut aufgehoben. Steckst du ihn aber in die diversen 
Initialisierungsfunktionen und hast du mehrere solche 
Initialisierungsfuntkionen, wirst du schnell den Überblick verlieren, 
welche Initialisierungen eigentlich noch mit abgeschalteten Interrupts 
laufen und bei welchen Initialisierungen die Interrupts schon global 
eingeschaltet sind. Je nachdem in welcher Reihenfolge du diese 
Initialisierfunktionen aus dem ersten Abschnitt in main() aufrufst ist 
das jedesmal anders.
Das sei() hat in diesen Funktionen nichts verloren. Er ist die globale 
Interruptfreigabe und die wird erst getätigt, nachdem das Setup ALLER 
Komponenten vollständig komplett ist.
'globale Freigabe', sozusagen der Hauptschalter -> daher in main().

: Bearbeitet durch User
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.