Atmega32 Timer1 und Timer0 laufen nicht zusammen

Gast #3579278
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
}
#3579319
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.
#3579335
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().

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