Timer, Interrupt, Taster, C

Gast #4839403
Lesenswert?

Guten Abend,

ich baue momentan eine kleine Binäruhr mit einem Atmega8. Die Idee war 
eine Einfache Binäruhr (Minuten 0-59, Stunde 0-11,, 2LEDs für Sekunden) 
und diese über 2 Taster( Stunde+1, Minute+1) einzustellen. Die Binäruhr 
fängt auch schon an zu zählen das Problem liegt daran dass ich die 
Uhrzeit nicht Einstellen kann. Die Taster sind PD5 und PD2 mit dem µC 
verbunden, PullDown Wiederstände gehen von dort auf Ground.
1
#define F_CPU 8000000UL
2

3
#include <avr/io.h>
4
#include <avr/interrupt.h>
5
#include <avr/sleep.h>
6
#include <inttypes.h>
7
#include <util/delay.h>
8
#include <stdlib.h>
9

10
unsigned char sekunden = 0;
11
unsigned char minuten = 0;
12
unsigned char stunden = 0;
13

14
ISR(TIMER1_COMPA_vect){
15
  sekunden++;
16

17
  if(sekunden==60){
18
    sekunden = 0;
19
    minuten++;
20
  }
21
  if(minuten == 60){
22
    minuten = 0;
23
    stunden++;
24
  }
25
  if(stunden == 12){
26
    stunden = 0;
27
  }
28
  PORTC = minuten;
29
  PORTB = stunden;
30
  if(sekunden==0 || sekunden == 30){ PORTD ^= (1<<PD6); }
31
  PORTD ^= (1<<PD7);
32
}
33

34
int timer (void)
35
{
36
  if(sekunden == 60)
37
  {
38
    minuten++;
39
    sekunden = 0;
40
  }
41
  if(minuten == 60)
42
  {
43
    stunden++;
44
    minuten = 0;
45
  }
46
  return 0;
47
}
48

49
int main (void)
50
{
51
  DDRC = 0b00111111; // LED minute
52
  DDRB = 0b00001111; // LED stunde
53
  DDRD = 0b11000000; // LED sekunde
54
  PORTD &= ~(1<<PD2);
55
  PORTD &= ~(1<<PD5);
56

57
  
58
  //16Bit-Timer für Zeitzählung
59
  TCCR1B |= (1 << WGM12);                //CTC Modus
60
  TCCR1B |= (1 << CS12) | (0 << CS11) | (1 << CS10);   //Prescaler 1024
61
  OCR1A = 7812;                      //Compare Wert setzen
62
  TIMSK = (1<<OCIE1A);   //Interrupt bei Compare Match
63
  sei();            //Interrputs aktivieren
64
    
65
  while(1){
66

67
    if( PIND & (1<<PD2)){
68
      minuten++;  
69
    }
70
    if( PIND & (1<<PD5)){
71
      stunden++;
72
      }
73
    if(minuten>=60){
74
      stunden++;
75
    }
76
    if(stunden>=12){
77
      stunden = 0;
78
    }
79
    PORTC = minuten;
80
    PORTB = stunden;
81
    _delay_ms(100);
82
    
83
  }
84
  return 0;
85
  
86
}


Hardwaremäßig funktioniert alles (nachgemessen mit Multimeter etc.). Es 
kann gut sein dass die Uhr nicht genau Zählt, dies ist bekannt und wird 
später behoben.(Externer Quarz etc.)

Lg Sebastian
Gast #4839481
Lesenswert?

1) was macht die Routine timer() ? Ist das nicht redundant zur ISR?

2) fehlendes volatile bei stunden, minuten und sekunden wurde ja schon 
angemerkt.

3) die Taster sind nicht entprellt.

4) wenn es dann mal funktioniert (mit volatile), wird ein Tasterdruck 
die Uhr scheinbar "zufällig" verstellen, weil in jedem 
Schleifendurchlauf der Portpin gesetzt ist, und diese Schleife wird 
zigtausendmal jede Sekunde durchlaufen.
Gast #4839488
Lesenswert?

an Sebastian:
Das kann ich leider nicht beantworten, kann kein C; ich lese nur 
regelmäßig mit, und das fehlende 'volatile' im Zusammenhang mit ISRs 
scheint ein häufiger Fehler zu sein.

an Nop:
die Punkte 3 und 4 werden so halbwegs durch das
_delay_ms(100);
in der main umgangen.
Gast #4839498
Lesenswert?

S. Landolt schrieb:

> die Punkte 3 und 4 werden so halbwegs durch das
> _delay_ms(100);
> in der main umgangen.

Stimmt, zumindest das Prellen. Aber es wird schwerlich möglich sein, die 
Stunden und Minuten um genau eins vorzustellen. Das müßte man dann so 
machen, daß man den Port abfragt und nur dann eins weiterstellt, falls 
der jeweilige Portzustand im vorigen Durchlauf null war (speichert man 
in einer Statusvariable).

Der genaue Grund, wieso volatile nötig ist, ist die Optimierung des 
C-Compilers. Wenn der Kontrollfluß nicht zusammenhängend ist (wie bei 
Applikation/Interrupt), optimiert er da u.U. ungewollt Zugriffe weg.

Typisches Symptom: mit -O0 (ohne Optimierung) geht es, mit Optimierung 
(egal ob auf Zeit oder Codegröße) geht es nicht mehr.
Gast #4839503
Lesenswert?

Nop schrieb:
> 1) was macht die Routine timer() ? Ist das nicht redundant zur
> ISR?

Ja, wird noch entfernt

> 2) fehlendes volatile bei stunden, minuten und sekunden wurde ja schon
> angemerkt.
>
> 3) die Taster sind nicht entprellt.

Die Taster entprelle ich mal wenn ich zeit habe. Bis es so weit ist muss 
ich ohne klarkommen. durch das delay fällt es nicht so sehr auf.

> 4) wenn es dann mal funktioniert (mit volatile), wird ein Tasterdruck
> die Uhr scheinbar "zufällig" verstellen, weil in jedem
> Schleifendurchlauf der Portpin gesetzt ist, und diese Schleife wird
> zigtausendmal jede Sekunde durchlaufen.

Wird durch das _delay_ms(100); begrenzt. Es ist bewusst so gemacht dass 
ein schnelles verstellen möglich ist.

Mit Interrupts habe ich mich noch nicht so viel auseinandergesetzt daher 
warscheinlich das fehlende volatile.

Danke an alle. Hat mir sehr geholfen. Noch einen schönen Abend :)

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