Programm bleibt stehen

#4030718
Lesenswert?

Guten Abend liebe Gemeinde,

ich habe ein kleines Uhren Programm geschrieben was immer stehen bleibt 
sobald auf der Stunden und Minuten Portseite also PORTD und PORTB 
jeweils 4 PORTS gleichzeitig Low sind.

Es ist auch egal welche PORTS es sind.

Stunde       Minute

E  Z         E  Z

0  0         0  0
0  x         0  x
0  x         0  x
x  x         x  x


0  0         0  0
0  x         x  0
0  x         x  0
x  x         x  x


0  0         0  0
0  x         x  0
0  x         x  x
x  x         x  0

Könnte einer von euch bitte mal einen Blick auf mein Programm werfen 
danke schonmal.
1
/*
2
 * Wecker_01.c
3
 *
4
 * Created: 15.06.2014 15:37:42
5
 *  Author: Werkstadt
6
 */ 
7

8
#include <stdio.h>
9
#include <avr/io.h>
10
#include <avr/interrupt.h>
11
#ifndef F_CPU
12
#warning "F_CPU war noch nicht definiert, wird nun mit 1000000 definiert"
13
#define F_CPU 1000000UL
14
#endif
15
#include <util/delay.h>
16

17
#define STR 4 // Schalter RUN
18
#define STP 5 // Schalter PROG
19
#define STA 00 // Schalter ALARM
20
#define TTS 00 // Taster SNOOZE
21
#define TTMIN 0 // Taster +MIN
22
#define TTST 1 // Taster +ST
23

24
int    sek=0;
25
int    min=0;
26
int    st=0;
27
int    min_s=0;
28
int    st_s=0;
29
int    p1=0;
30
int    p2=0;
31
int    p3=0;
32
int    t01=0;
33
int    RUN=0;
34

35

36
int tast=0;
37
int min_8=0;
38
int st_8=0;
39
int foo=0;
40
int foo2=0;
41

42

43

44

45
void show (void)
46
{
47
  min_s=min;
48
  while(foo==0)
49
  {
50
    if(min_s > 9)
51
    {
52
      min_8=(min_8+0x10);
53
      min_s=(min_s-10);
54
    }
55
    else
56
    {
57
      min_8=(min_8+min_s);
58
      ++foo;
59
    }
60
  }
61
  foo=0;
62
  min_s=0;
63
  
64
  st_s=st;
65
  while(foo==0)
66
  {
67
    if(st_s > 9)
68
    {
69
      st_8=(st_8+0x10);
70
      st_s=(st_s-10);
71
    }
72
    else
73
    {
74
      st_8=(st_8+st_s);
75
      ++foo;
76
    }
77
  }
78
  foo=0;
79
  st_s=0;
80
  
81
  p1=min_8;
82
  min_8=~p1; // Wert Minuten invertieren
83
  p2=st_8; 
84
  st_8=~p2; // Wert Stunden invertieren
85
  
86
  PORTD=min_8;
87
  PORTB=st_8;
88
  
89
  min_8=0;
90
  st_8=0;
91
}
92

93
void prog (void)
94
{
95
  while(foo==0)
96
  {
97
  if(!(PINC & (1<<0))) // Abfrage Taster +Minute
98
  {
99
    ++min;
100
    if(min>59)
101
    {
102
      min=0;
103
    }
104
    _delay_ms(2);
105
    while(foo2==0)
106
    {
107
      if(PINC & (1<<0)) // Taster entprellen
108
      {
109
        ++foo2;
110
        _delay_ms(2);
111
      }
112
    }
113
    foo2=0;
114
  }
115
  
116
  if(!(PINC & (1<<1))) // Abfrage Taster +Stunde
117
  {
118
    ++st;
119
    if(st>=24)
120
    {
121
      st=0;
122
    }
123
    _delay_ms(2);
124
    while(foo2==0)
125
    {
126
      if(PINC & (1<<1)) // Taster entprellen
127
      {
128
        ++foo2;
129
        _delay_ms(2);
130
      }
131
    }
132
    foo2=0;
133
  }  
134
  show();
135
  if(PINC & (1<<5))
136
  {
137
    ++foo;
138
  }
139
  }
140
  foo=0;
141
}
142

143
void run (void) // Ablauf Programm
144
{
145
  
146
  RUN=1;
147
  while(foo==0)
148
  {
149
    
150
    show();
151
    if(PINC & (1<<4))
152
    {
153
      ++foo;
154
      RUN=0;
155
    }
156
  }
157
  
158
  foo=0;
159
}
160

161

162
int main(void)
163
{
164
  DDRB = 0b00111111; // Ausgang LED's Stunden
165
  DDRD = 0xFF; // Ausgang LED's Minuten
166
  DDRC = 0x00; // Eingang Taster / Schalter
167
  PORTB = 0xFF; // LED's Stunden Aus
168
  PORTD = 0xFF; // LED's Minuten Aus
169
  PORTC = 0xFF; // Eingang Pullup Aktive
170
  
171
ASSR |= (1<<AS2);      //async operation
172
TCCR2 |= (1<< CS22) | (1<< CS20);  //Prescaler auf 128
173
TCNT2 = 0x00;        //Init counter
174
TIMSK |= (1<<TOIE2);      //Overflow Interrupt Enable
175
sei();
176
  
177
    while(1)
178
    {
179
  
180
  if(!(PINC & (1<<5))) // Wenn Schalter Programmierung Gesetz ist
181
  {
182
    prog();
183
  }
184
  
185
  if(!(PINC & (1<<4))) // Wenn Schalter Programm Laufen Gesetz ist
186
  {
187
    run();
188
  }
189

190
  
191
  
192
  }
193
  
194
  return 0;
195
}
196
  
197
  ISR (TIMER2_OVF_vect)
198
  {
199
    if(RUN>=1)
200
    {
201
      sek++;
202
    }
203
    
204
      if(sek>=60)
205
      {
206
        sek=0;
207
        min++;
208
      }
209
      
210
        if(min>=60)
211
        {
212
          min=0;
213
          st++;
214
        }
215
        
216
          if(st>=24)
217
          {
218
            st=0;
219
          }
220
          while(ASSR & (1<<TCN2UB | 1<<OCR2UB | 1<<TCR2UB));
221
    
222
  }
#4030748
Lesenswert?

Ich hab zwar die Hälfte deiner Programmlogik nicht auf Anhieb 
verstanden, aber ich denke mal, du hast dich mit deinen globalen 
Variablen selbst aufs Glatteis geführt.
Insbesondere foo verwendest du nach Lust und Laune und wie es dir 
beliebt.

zb benutzt du hier
1
void run (void) // Ablauf Programm
2
{
3
  
4
  RUN=1;
5
  while(foo==0)
6
  {
7
    
8
    show();
ein foo, (ohne es mit einem vernünftigen Wert zu versehen), dasselbe foo 
wird allerdings auch in show() benutzt.

Das ist immer ein und dieselbe Variable!

Damit einem genau so was nicht passiert, gibt es funktionslokale 
Variablen
1
void foo()
2
{
3
  int i;
4

5
  for( i = 0; i < 5; i++ )
6
    ... mach was
7
}
8

9
void bar()
10
{
11
  int i;
12

13
  for( i = 0; i < 8; i++ )
14
    foo();
15
}

das i in foo() und das i in bar() sind 2 verschiedene Variablen und 
kommen sich nicht in die Quere. Sie sind voneinander vollkommen 
unabhängig. Eine Veränderung von i in foo() verändert nicht die Logik in 
bar().

So, und jetzt muss ich mal ergründen, was du eigentlich in show() 
beabsichtigst. Das hier
1
  while(foo==0)
2
  {
3
    if(min_s > 9)
4
    {
5
      min_8=(min_8+0x10);
6
      min_s=(min_s-10);
7
    }
8
    else
9
    {
10
      min_8=(min_8+min_s);
11
      ++foo;
12
    }
13
  }
sieht alles mehr als merkwürdig aus.
#4030762
Lesenswert?

Ach. Das soll eine BCD Zerlegung sein.

Das kannst du viel einfacher schreiben.
1
//
2
// Aufteilen der Zahl in Zehner und Einer
3
// Die Zehner werden in die oberen 4 Bits des Ergebnisses geschoben
4
//
5
uint8_t toBCD( uint8_t dezimalWert )
6
{
7
  uint8_t Ergebnis;
8

9
  Ergebnis = ( dezimalWert / 10 ) << 4;
10
  Ergebnis |= ( dezimalWert % 10 );
11

12
  return Ergebnis;
13
}
14

15
void show()
16
{
17
  PORTD = toBCD( min );
18
  PORTB = toBCD( st );
19
}
#4030765
Lesenswert?

Also der teil hier
1
min_s=min;
2
  while(foo==0)
3
  {
4
    if(min_s > 9)
5
    {
6
      min_8=(min_8+0x10);
7
      min_s=(min_s-10);
8
    }
9
    else
10
    {
11
      min_8=(min_8+min_s);
12
      ++foo;
13
    }
14
  }
15
  foo=0;
16
  min_s=0;

Sorgt dafür das ich aus z.b DEZ 46(Minuten) die in der Variable "min"
steckt den BCD Code erzeuge so das ich auf einem PORT im
oberen Nibble Zehner und im unteren die Einer stehen hab.

Zum schluss geb ich das nur auf den jeweiliegen Port aus und hab meine 
Zeit.
#4030783
Lesenswert?

Marvin hat ja volatile schon angemahnt.

Wenn du den Code dann vereinfachst, dann fallen auch die meisten anderen 
Variablen auch alle weg.

Aber auf eines möchte ich noch eingehen.
Ich hab keine Ahnung, wo du die Sache mit dem foo her hast. Aber du 
schiesst dir damit ins Knie.

So etwas
1
void run (void) // Ablauf Programm
2
{
3
  
4
  RUN=1;
5
  while(foo==0)
6
  {
7
    
8
    show();
9
    if(PINC & (1<<4))
10
    {
11
      ++foo;
12
      RUN=0;
13
    }
14
  }
15
  
16
  foo=0;
17
}
ist ausser unübersichtlich nur noch unübersichtlich. Es mag Fälle geben, 
in denen man eine Schleife so abbricht und das die einfachste Lösugn 
darstellt. Aber in den meisten Fällen solltest du um solche Dinge einen 
Bogen machen.
Wann soll denn diese Schleife abbrechen? Na, wenn am PINC  das Bit 4 auf 
1 geht. D.h. die Schleife soll laufen, solange das Bit 4 am PINC auf 0 
ist. Und genau so programmierst du das auch
1
void run (void) // Ablauf Programm
2
{ 
3
  RUN = 1;
4

5
  while( !(PINC & (1<<4) )
6
  {
7
    show();
8
  }
9

10
  RUN = 0;
11
}

Viel simpler. Viel einfacher zu durchschauen. Wesentlich weniger 
Potential, sich selbst ins Knie zu schiessen. Wenn du show mindestens 1 
mal aufgerufen haben willst, dann eben so
1
void run (void) // Ablauf Programm
2
{ 
3
  RUN = 1;
4

5
  do
6
  {
7
    show();
8
  } while( !(PINC & (1<<4) );
9

10
  RUN = 0;
11
}

aber nicht mit 200 Flag-Variablen, die dann auch noch global sind. Da 
ist ein Schuss ins Knie quasi vorprogrammiert.
#4030784
Lesenswert?

Karl Heinz schrieb:
> Ach. Das soll eine BCD Zerlegung sein.
>
> Das kannst du viel einfacher schreiben.
>
>
1
> //
2
> // Aufteilen der Zahl in Zehner und Einer
3
> // Die Zehner werden in die oberen 4 Bits des Ergebnisses geschoben
4
> //
5
> uint8_t toBCD( uint8_t dezimalWert )
6
> {
7
>   uint8_t Ergebnis;
8
> 
9
>   Ergebnis = ( dezimalWert / 10 ) << 4;
10
>   Ergebnis |= ( dezimalWert % 10 );
11
> 
12
>   return Ergebnis;
13
> }
14
> 
15
> void show()
16
> {
17
>   PORTD = toBCD( min );
18
>   PORTB = toBCD( st );
19
> }
20
>

Danke schön ;) wenn ich da meinen weg vergleiche ist meiner viel zu 
umständlich.

Also kann es durch meine Globalen Variablen dazu kommen das sie sich 
überschneiden und dadurch der Programmablauf durcheinander kommt ?
#4030792
Lesenswert?

Pierre Gnauck schrieb:

> Also kann es durch meine Globalen Variablen dazu kommen das sie sich
> überschneiden und dadurch der Programmablauf durcheinander kommt ?

Ich denke mal: ja.
Auslöser dürfte sein, dass du in show das foo erhöhst, und damit dann 
aus der Schleife in run rausfällst.

Aber ich hab das nicht weiter gross analysiert. Erspars mir bitte. Du 
hast da vieles in deinem Programm wesentlich zu umständlich und 
langatmig gelöst, so dass es schwer ist, da noch den Überblick zu 
behalten.
#4030797
Lesenswert?

Karl Heinz schrieb:
> Pierre Gnauck schrieb:
>
>> Also kann es durch meine Globalen Variablen dazu kommen das sie sich
>> überschneiden und dadurch der Programmablauf durcheinander kommt ?
>
> Ich denke mal: ja.
> Auslöser dürfte sein, dass du in show das foo erhöhst, und damit dann
> aus der Schleife in run rausfällst.

Nein, ist auch nicht richtig.
Du setzt foo am Ende von show wieder auf 0.

> Erspars mir bitte.
(Gemeint ist natürlich die Analyse, was da passiert)
#4030805
Lesenswert?

In prog dasselbe wie in run()

Mach das nicht! Die ganzen Schleifen lassen sich alle viel einfacher 
formulieren, wenn du die Abbruchbedingung direkt ins while 
reinschreibst. Gleichzeitig bist du dann auch alle Kopfstände und 
Kopfzerbrechen los, wer wann welche globale Variable foo oder foo2 oder 
... verändert.

Aus dem hier
1
  if(!(PINC & (1<<1))) // Abfrage Taster +Stunde
2
  {
3
    ++st;
4
    if(st>=24)
5
    {
6
      st=0;
7
    }
8
    _delay_ms(2);
9
    while(foo2==0)
10
    {
11
      if(PINC & (1<<1)) // Taster entprellen
12
      {
13
        ++foo2;
14
        _delay_ms(2);
15
      }
16
    }
17
    foo2=0;
18
  }

wird dann das hier
1
  if(!(PINC & (1<<1))) // Abfrage Taster +Stunde
2
  {
3
    ++st;
4
    if(st>=24)
5
    {
6
      st=0;
7
    }
8

9
    _delay_ms(2);
10

11
    while( PINC & ( 1 << 1 ) )
12
      _delay_ms(2);
13
  }

einfacher, kürzer, leichter zu überschauen, keine globalen Variablen 
mehr (ausser st)
#4030819
Lesenswert?

Wenn du dir dann noch ein #define machst
1
#define STUNDEN_TASTER    1

dann verändert sich der Code weiter zu
1
  if(!(PINC & (1 << STUNDEN_TASTER)) )
2
  {
3
    ++st;
4
    if(st>=24)
5
    {
6
      st=0;
7
    }
8

9
    _delay_ms(2);
10

11
    while( PINC & ( 1 << STUNDEN_TASTER ) )
12
      _delay_ms(2);
13
  }

dann brauchst du erstens den Kommentar nicht mehr und es ist zweitens 
viel leichter zu kontrollieren, dass du beim if und beim while jeweils 
denselben Taster benutzt hast. Ausserdem steckt jetzt im Code ein 
direkter Zusammenhang drinnen, dass du in beiden Fällen wirklich mit 
voller Absicht denselben Taster gemeint hast. Diese Absicht ist auch 
dann zu sehen, wenn man nicht analysiert, was das Programm hier 
eigentlich macht.

Keine derartigen 'magischen Konstanten'! Dafür gibt es #define, damit 
man derartigen Zahlenwerten einen 'Namen' geben kann.
Das hat dann auch den netten Nebeneffekt, dass man bei einer Änderung 
des Zahlenwertes, dieses nur an einer einzigen Stelle machen muss. 
Nämlich beim #define. Der Compiler passt dann alle anderen Stellen 
anhand dieses #define an, in dem er den dort verwendeten Namen durch 
genau diese Zahl ersetzt. Im Endeffekt wird also genau der gleiche Code 
wie deiner übersetzt. Nur ist er für mich als Programmierer viel 
leichter zu lesen, zu verstehen und zu ändern.
#4030826
Lesenswert?

Pierre Gnauck schrieb:
> Gut dann werde ich mal ein wenig aufräumen, ja das mit den umständlichen
> kommt denk ich mal aus der asm Welt von der ich gerade in C einsteige.

gut.
Dann fang gleich mal damit an, zu akzeptieren, dass der Datentyp der 
Wahl für ein Byte ein uint8_t ist und nicht einfach alles als int 
gemacht wird.

generell alles als int zu nehmen ist auf Desktopsystemen in Ordnung.
Da du aus der Assemblerwelt kommst, ist dir geläufig, dass du deinem AVR 
mit 16 Bit Arithmetik nicht unwesentlich mehr Arbeit aufhalst. Wenn also 
ein Byte völlig ausreicht (weil Stunden oder Minuten nun mal locker in 1 
Byte passen), dann verpasst du deinem AVR eine Fleissaufgabe, indem du 
alles als int definierst, wo es ein uint8_t auch getan hätte.
#4030940
Lesenswert?

So ich hab das ganze ein wenig aufgeräumt nur die DEZ zu BCD geschichte 
haut mit der Funktion von dir nicht hin ?

Wenn ich es mit ihr versuche sind alle LED's an...

Hier der veränderte Teil.
1
/*
2
 * Wecker_01.c
3
 *
4
 * Created: 15.06.2014 15:37:42
5
 *  Author: Werkstadt
6
 */ 
7

8
#include <stdio.h>
9
#include <math.h>
10
#include <avr/io.h>
11
#include <avr/interrupt.h>
12
#ifndef F_CPU
13
#warning "F_CPU war noch nicht definiert, wird nun mit 1000000 definiert"
14
#define F_CPU 1000000UL
15
#endif
16
#include <util/delay.h>
17

18
#define Schalter_Run 4
19
#define Schalter_Prog 5
20
// #define Schalter_Alarm 00
21
// #define Taster_Snooze 00
22
#define Taster_Minute 0
23
#define Taster_Stunde 1
24

25
uint8_t sek = 0;
26
uint8_t min = 0;
27
uint8_t st  = 0;
28

29

30

31

32

33
void show ()
34
{
35
  uint8_t min_h = 0;
36
  uint8_t st_h  = 0;
37
  
38
  min_h  = ( min / 10 ) << 4;
39
  min_h |= ( min % 10 );
40
  
41
  st_h   = ( st / 10 ) << 4;
42
  st_h  |= ( st % 10 );
43
  
44
  PORTD = ~ min_h;
45
  PORTB = ~ st_h;
46
  
47
  
48
  
49
}
50

51
void prog (void)
52
{
53
  if(!(PINC & (1<<Taster_Minute)))
54
  {
55
    min++;
56
    
57
    if(min>59)
58
    {
59
      min=0;
60
    }
61
    
62
    _delay_ms(20);
63
    
64
    while(!(PINC & (1<<Taster_Minute)))
65
    {
66
        _delay_ms(20);
67
    }
68
  }
69
  
70
  if(!(PINC & (1<<Taster_Stunde)))
71
  {
72
    st++;
73
    if(st>=24)
74
    {
75
      st=0;
76
    }
77
    _delay_ms(20);
78
    while(!(PINC & (1<<Taster_Stunde)))
79
    {
80
        _delay_ms(20);
81
    }
82
  }
83
}
84

85

86

87

88
int main(void)
89
{
90
  DDRB = 0xFF;
91
  DDRD = 0xFF;
92
  DDRC = 0x00;
93
  PORTB = 0xFF;
94
  PORTD = 0xFF;
95
  PORTC = 0xFF;
96
  
97

98
  TIMSK &=~ ((1<<OCIE2)|(1<<TOIE2));
99
  ASSR  = (1<<AS2);
100
  TCNT2=0;
101
  OCR2=0;
102
  TCCR2 |= ((1<<CS22)|(1<<CS20));
103
  TCCR2 &=~ (1<<CS21);
104
  while(ASSR & (1<<TCN2UB | 1<<OCR2UB | 1<<TCR2UB));
105
  TIFR  = 0;
106
  TIMSK |= (1<<TOIE2);
107
  sei();
108

109
  
110
  
111
    while(1)
112
    {
113
  
114
  if(!(PINC & (1<<Schalter_Prog)))
115
  {
116
    prog();
117
    show();
118
  }
119
  
120
  if(!(PINC & (1<<Schalter_Run)))
121
  {
122
    if(sek>59)
123
    {
124
      sek=0;
125
      min++;
126
    }
127
    
128
    if(min>59)
129
    {
130
      min=0;
131
      st++;
132
    }
133
    
134
    if(st>=24)
135
    {
136
      st=0;
137
      sek=0;
138
      min=0;
139
    }
140
    show();
141
  }
142
  }
143
  return 0;
144
}
145
  
146
  ISR (TIMER2_OVF_vect)
147
  {
148
    
149
      sek++;
150
    
151
    
152
      
153
  while(ASSR & (1<<TCN2UB | 1<<OCR2UB | 1<<TCR2UB));
154
    
155
  }
#4030957
Lesenswert?

Wieso hast du denn hier
1
  ISR (TIMER2_OVF_vect)
2
  {
3
    
4
      sek++;
5
    
6
    
7
      
8
  while(ASSR & (1<<TCN2UB | 1<<OCR2UB | 1<<TCR2UB));
9
    
10
  }
das weiterzählen von min und st rausgenommen?

Das war keine gute Idee. Die würde ich da drinn lassen. Denn min und st 
müssen auch dann weiterhin hochgezählt werden, wenn dein Programm mit 
irgendwas ganz anderem stundenlang beschäftigt ist. Das Hochzählen einer 
Uhr ist als 'unteilbare EInheit' anzusehen.
#4030977
Lesenswert?

Pierre Gnauck schrieb:
> Aber ich glaube so langsam das ist ein Hardware Problem besitzte denn
> der effekt ist gleich geblieben.

NIcht so schnell.

Speck mal ordentlich ab.
1
....
2

3
int main()
4
{
5

6
  .... die ganzen Initialisierungen
7
  .... aber noch kein sei(), also keine Interrupts
8

9
  while( 1 ) {
10

11
    min++;
12
    if( min == 60 ) {
13
      st++;
14
      min = 0;
15
      if( st == 24 ) {
16
        st = 0;
17
      }
18
    }
19

20
    show();
21
    _delay_ms( 1000 );
22
  }
23
}

jetzt wollen wir mal sehen, ob deine LED funktionieren.

(Nicht alles auf einmal schreiben!)
#4030997
Lesenswert?

Wie meinst du das mit deiner Änderung sei(); ist doch bei mir vorhanden 
und zwar hier
1
TIMSK &=~ ((1<<OCIE2)|(1<<TOIE2));
2
  ASSR  = (1<<AS2);
3
  TCNT2=0;
4
  OCR2=0;
5
  TCCR2 |= ((1<<CS22)|(1<<CS20));
6
  TCCR2 &=~ (1<<CS21);
7
  while(ASSR & (1<<TCN2UB | 1<<OCR2UB | 1<<TCR2UB));
8
  TIFR  = 0;
9
  TIMSK |= (1<<TOIE2);
10
  sei();
#4031007
Lesenswert?

Pierre Gnauck schrieb:
> Wie meinst du das mit deiner Änderung sei(); ist doch bei mir vorhanden
> und zwar hier

Ja.
Aber ich möchte für den ersten Test die Interrupts mal aus dem Spiel 
nehmen.

Im Grunde braucht das Tetsprogramm nur die Ports und sonst nix. Ich will 
dir aber nicht zumuten, dass du den Timercode da rausnimmst. Ist ja doch 
etwas umfangreicher.
Daher: von mir aus soll der Timer im Hintergrund laufen. Aber er soll 
mir beim Rest nicht in die QUere kommen. Beim ersten Test brauchen wir 
ihn nicht. Jede Sekunde (realisiert durch _delay_ms) wird min um 1 
erhöht und show aufgerufen. D.h. deine LED müssen im Sekundentakt die 
Zeit hochzählen.

(1000 ist vielleicht etwas lang, 500 werdens auch tun. Wir wollen ja nur 
wissen, ob irgendetwas ungewöhnliches passiert, wenn die LEDs ihre 
Muster durchgehen. Zb Spannungseinbruch am Netzteil/Batterie)


Und damit sich der Timer aus dem Rest raushält, wird der sei() einfach 
auskommentiert.
#4031039
Lesenswert?

Vergiss die Frage, das erleben wir heut sowieso nicht mehr, wenn die 
Stunden soweit sind.

Änderung:
1
int main()
2
{
3

4
.... wie jetzt auch
5

6
  while( 1 ) {
7

8
    min++;
9
    if( min == 60 )
10
      min = 0;
11

12
    st = min % 24;
13

14
    _delay_ms( 500 );
15
  }
16
}

Das geht ein wenig schneller, so dass wir dann alle LED durch haben :-)
#4031054
Lesenswert?

Ich geh mal davon aus, dass auch das nichts ungewöhnliches mehr an den 
Tag bringen wird.

D.h. ich würde dann gerne mal die Stelltasten mit dazu nehmen. Interrupt 
bleibt nach wie vor abgeschaltet
1
.
2

3
int main()
4
{
5
  ...
6

7
  while( 1 ) {
8
    prog();
9
    show();
10
  }
11
}

Die prog Funktion hab ich durchgesehen. Aufgefallen ist mir da jetzt 
nicht wirklich was schlimmes.
#4031071
Lesenswert?

Kopfkratz

Diese Funktion
1
void prog (void)
2
{
3
  if(!(PINC & (1<<Taster_Minute)))
4
  {
5
    min++;
6
    
7
    if(min>59)
8
    {
9
      min=0;
10
    }
11
    
12
    _delay_ms(20);
13
    
14
    while(!(PINC & (1<<Taster_Minute)))
15
    {
16
        _delay_ms(20);
17
    }
18
  }
19
  
20
  if(!(PINC & (1<<Taster_Stunde)))
21
  {
22
    st++;
23
    if(st>=24)
24
    {
25
      st=0;
26
    }
27
    _delay_ms(20);
28
    while(!(PINC & (1<<Taster_Stunde)))
29
    {
30
        _delay_ms(20);
31
    }
32
  }
33
}

und du drückst auf den Taster am Portpin PORTC / 0



(Verezeih wenn ich alles 3 mal nachfrage. Aber ich muss mir hier ein 
Bild von der Situation bei dir machen. Und bei Fehlersuche stelle ich 
grundsätzlich alles in Frage)
#4031081
Lesenswert?

Ich drücke jetzt PINC.1 für Stunden so lange (Beispiel) das ich DEZ 
17:00 eingestellt hab

 Stunde       Minute
 E  Z         E  Z

 0  0         0  0
 0  x         0  0
 0  x         0  0
 x  x         0  0

Nun drücke ich auf PINC.0 für Minuten so lange das ich bis zur Zeit 
17:17 komme.

 Stunde       Minute
>
> E  Z         E  Z
>
> 0  0         0  0
> 0  x         0  x
> 0  x         0  x
> x  x         x  x

Und Jetzt passiert nix mehr.
#4031091
Lesenswert?

So zum Beispiel
(auf die Idee hätt ich auch schon vorher kommen können. Silly me)
1
...
2

3
int main()
4
{
5

6
.... wie jetzt auch
7

8
  st = 17;
9

10
  while( 1 ) {
11

12
    min++;
13
    if( min == 60 )
14
      min = 0;
15

16
    show();
17

18
    _delay_ms( 500 );
19
  }
20
}

kommt er da über die Hürde drüber?
#4031101
Lesenswert?

Pierre Gnauck schrieb:
> Wo wir hoch gezählt hatten sind wir ja bei dieser Mischung 17:17
> angekommen und weiter gekommen er bleibt echt nur beim Analogen drücken
> da stehen.

Hmm. Im Moment bin ich ratlos.
Im Code seh ich nichts, was das erklären könnte. Es ist auch die Zahl 17 
nicht irgendwie jetzt aussergewöhnlich oder würde irgendwo vorkommen 
oder hätte jetzt sonst irgendeinen Bezug.
#4031103
Lesenswert?

Gut mein Hund schaut mich sowieso schon an als ob ich einen an der 
Waffel hätte, ich würde sagen wir machen da morgen weiter.

Ich schau mir nochmal ganz genau die Schaltung an überprüfe alle und 
melde mich dann gegen abend wieder.

Ich danke dir aber schonmal für deine Mühne :)
Gast #4031341
Lesenswert?

Probier mal so
1
//add all #includes here...
2

3
#define IS_PRESSED(key)  !(PINC & (1 << key))
4
#define KEY_HOURS   1
5
#define KEY_MINUTES 2
6

7
#define WAIT_DEBOUNCE 20               //in ms
8

9
volatile uint8_t hours = 0;
10
volatile uint8_t minutes = 0;
11
volatile uint8_t seconds = 0;
12

13
static void init(void)
14
{
15
   DDRB  = 0b00111111;    // Ausgang LED's Stunden
16
   DDRD  = 0xFF;          // Ausgang LED's Minuten
17
   DDRC  = 0x00;          // Eingang Taster / Schalter
18
   PORTB = 0xFF;          // LED's Stunden Aus
19
   PORTD = 0xFF;          // LED's Minuten Aus
20
   PORTC = 0xFF;          // Eingang Pullup Aktive
21
   
22
   TIMSK &=~ ((1<<OCIE2)|(1<<TOIE2));
23
   ASSR  = (1<<AS2);
24
   TCNT2=0;
25
   OCR2=0;
26
   TCCR2 |= ((1<<CS22)|(1<<CS20));
27
   TCCR2 &=~ (1<<CS21);
28
   while(ASSR & (1<<TCN2UB | 1<<OCR2UB | 1<<TCR2UB));
29
   TIFR  = 0;
30
   TIMSK |= (1<<TOIE2);
31
   sei();
32
}
33

34
static uint8_t toBCD(uint8_t value)
35
{
36
   return ((value / 10) << 4) | (value % 10);
37
}
38

39
static void nextHour(void)
40
{
41
   hours ++;
42
   if(hours >= 24)
43
   {
44
      hours = 0;
45
   }
46
}
47

48
static void nextMinute(void)
49
{
50
   minutes ++;
51
   if(minutes >= 60)
52
   {
53
      minutes = 0;
54
   }
55
}
56

57
int main(void)
58
{
59
   init();
60
   
61
   do
62
   {
63
      // Show time
64
      PORTB = toBCD(hours);
65
      PORTD = toBCD(minutes);
66

67
      // Check key presses
68
      if(IS_PRESSED(KEY_HOURS))
69
      {
70
         nextHour();
71
         
72
         do
73
         {
74
            _delay_ms(WAIT_DEBOUNCE);
75
         } while(IS_PRESSED(KEY_HOURS));
76
      }
77
      
78
      if(IS_PRESSED(KEY_MINUTES))
79
      {
80
         nextMinute();
81
         
82
         do
83
         {
84
            _delay_ms(WAIT_DEBOUNCE);
85
         } while(IS_PRESSED(KEY_MINUTES));
86
      }
87
   } while(1);
88
   
89
   return 0;
90
}
91

92
ISR(TIMER2_OVF_vect)
93
{
94
   seconds ++;
95
   if(seconds >= 60)
96
   {
97
      seconds = 0;
98
      nextMinute();
99
      if(minutes == 0)
100
      {
101
         nextHour();
102
      }
103
   }
104
   while(ASSR & (1<<TCN2UB | 1<<OCR2UB | 1<<TCR2UB))
105
      ;
106
}
#4043742
Lesenswert?

Nabend Karl Heinz,

ich habe nun endlich mal Zeit für meinen Wecker / Uhr gefunden und siehe 
da es war kein Software sondern ein Hardware fehler, den (Schande über 
mein Haupt) ich erst nach 2 Stunden gefunden hatte.

Ich hatte alle Ausgänge und Eingänge über 1K Widerstände miteinander 
verbunden und diese sollten dann gemeinsam auf VCC gelegt werden, nur 
diese Verbindung hatte ich vergessen :-).

Mfg Bqube

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