Forum: Mikrocontroller und Digitale Elektronik Timer, Interrupt, Taster, C


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Sebastian (Gast)


Bewertung
0 lesenswert
nicht 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

von Sebastian (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Die While-Schleife im main wird ausgeführt, wenn ich einen Taster drücke 
passiert jedoch nichts. An was könnte das liegen?

von S. Landolt (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Habe ich das richtig verstanden: die Taster liegen zwischen uC-Pin und 
Vcc?

von Schaltplanleser (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Sebastian schrieb:
> Die Taster sind PD5 und PD2 mit dem µC
> verbunden, PullDown Wiederstände gehen von dort auf Ground.

Das solltest du mit einem Schaltplan verdeutlichen da es
sonst keiner versteht. Oder viele missverstehen und raten.

von Sebastian (Gast)


Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
S. Landolt schrieb:
> Habe ich das richtig verstanden: die Taster liegen zwischen uC-Pin und
> Vcc?

Ja das stimmt wie man hier auf dem Bild sehen kann

von S. Landolt (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Fehlt da nicht 'volatile' für sekunden minuten stunden?

von Sebastian (Gast)


Bewertung
0 lesenswert
nicht lesenswert
S. Landolt schrieb:
> Fehlt da nicht 'volatile' für sekunden minuten stunden?

Ich hab mal volatile davor geschrieben. Scheint als wäre es hier nötig, 
doch warum eigentlich? Es sollte doch kein Problem sein auf eine Globale 
Variable zuzugreifen? Oder irre ich mich hier?

von Nop (Gast)


Bewertung
0 lesenswert
nicht 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.

von Nop (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Sebastian schrieb:
> Scheint als wäre es hier nötig, doch warum eigentlich?

Das ist immer nötig, wenn Du Variablen zwischen Applikation und 
Interrupt teilst, weil der Kontrollfluß nicht linear ist.

von S. Landolt (Gast)


Bewertung
0 lesenswert
nicht 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.

von R. F. (rfr)


Bewertung
0 lesenswert
nicht lesenswert
Triffst du denn auch mit dem Einlesevorgang den Zeitpunkt, an dem die 
Taste gedrückt ist?

Gruss

Robert

von Schaltplanleser (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Nop schrieb:
> weil in jedem
> Schleifendurchlauf der Portpin gesetzt ist, und diese Schleife wird
> zigtausendmal jede Sekunde durchlaufen.

Nö, nur ca zehnmal pro Sekunde, weil er ein _delay_ms(100)
in der Schleife hat.

von Nop (Gast)


Bewertung
0 lesenswert
nicht 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.

von Sebastian (Gast)


Bewertung
0 lesenswert
nicht 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 :)

von Rita (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Sebastian schrieb:
> 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.

Dauert doch nicht lange?

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.