Forum: Compiler & IDEs Programm bleibt stehen


von Pierre G. (bqube)


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
  }

von Karl H. (kbuchegg)


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.

von Marvin (Gast)


Lesenswert?

Hi,

Kannte erst mal alle Vars aus der ISR volatile deklarieren...


Gruß

von Karl H. (kbuchegg)


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
}

: Bearbeitet durch User
von Pierre G. (bqube)


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.

von Karl H. (kbuchegg)


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.

von Pierre G. (bqube)


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 ?

von Karl H. (kbuchegg)


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.

von Karl H. (kbuchegg)


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)

von Pierre G. (bqube)


Lesenswert?

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.

Mfg Bqube

von Karl H. (kbuchegg)


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)

: Bearbeitet durch User
von Karl H. (kbuchegg)


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.

: Bearbeitet durch User
von Karl H. (kbuchegg)


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.

: Bearbeitet durch User
von Pierre G. (bqube)


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
  }

von Karl H. (kbuchegg)


Lesenswert?

1
volatile uint8_t sek = 0;
2
volatile uint8_t min = 0;
3
volatile uint8_t st  = 0;

ok, sek müsste nicht volatile sein. Aber min und st.


FAQ: Was hat es mit volatile auf sich

von Karl H. (kbuchegg)


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.

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

Karl Heinz schrieb:

> das weiterzählen von min und st rausgenommen?


In diesem Sinne:
vergiss mein vorheriges Posting.
Jetzt muss sek volatile sein.


Die Variable, auf die du von der ISR und von irgendwo anders aus 
zugreifst.

von Pierre G. (bqube)


Lesenswert?

Jetzt hast du mich ein wenig verwirrt :)

von Pierre G. (bqube)


Lesenswert?

Aber ich glaube so langsam das ist ein Hardware Problem besitzte denn 
der effekt ist gleich geblieben.

von Karl H. (kbuchegg)


Lesenswert?

Abgesehen vom volatile kann ich allerdings nichts mehr entdecken.
Müsste eigentlich laufen.

von Karl H. (kbuchegg)


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!)

von Pierre G. (bqube)


Lesenswert?

Sobald ich versuche beim Zeiteinstellen auf beiden Seiten Stunden / 
Minuten 4 ausgänge gleichzeitig Low setzte steht alles.

von Karl H. (kbuchegg)


Lesenswert?

Pierre Gnauck schrieb:
> Sobald ich versuche beim Zeiteinstellen auf beiden Seiten Stunden /
> Minuten 4 ausgänge gleichzeitig Low setzte steht alles.

Lass uns systematisch vorgehen. OK?

von Pierre G. (bqube)


Lesenswert?

Ich hatte schneller geschrieben wie  gelesen

von Pierre G. (bqube)


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();

von Karl H. (kbuchegg)


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.

: Bearbeitet durch User
von Dieter F. (Gast)


Lesenswert?

Betreibst Du die LED über Vorwiderstände - wenn ja, welche Werte?

von Pierre G. (bqube)


Lesenswert?

Es sind Extra Helle LED's 20mA aber da mir das doch ein wenig zu hell 
war laufen sie pauschal über 1kohm.

von Karl H. (kbuchegg)


Lesenswert?

Ich überleg schon die ganze Zeit, aber ich werd und werd aus dem hier
1
Stunde       Minute
2
3
E  Z         E  Z
4
5
0  0         0  0
6
0  x         0  x
7
0  x         0  x
8
x  x         x  x
9
10
11
0  0         0  0
12
0  x         x  0
13
0  x         x  0
14
x  x         x  x

nicht schlau :-)

von Pierre G. (bqube)


Lesenswert?

So nun sind die Minuten an dem besagten Punkt vorbei und laufen fröhlich 
vor sich hin.

von Karl H. (kbuchegg)


Lesenswert?

Pierre Gnauck schrieb:
> So nun sind die Minuten an dem besagten Punkt vorbei und laufen fröhlich
> vor sich hin.

gut.

Hast du Sekundentakt oder Halbsekunden Takt?

von Pierre G. (bqube)


Lesenswert?

> 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


Ganz einfach die Nullen sind die LED's es sind immer 4 damit die Optik 
Symetrisch ist ^^ und die Kreuze Stellen die situation nach (LED AN)

von Karl H. (kbuchegg)


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 :-)

von Pierre G. (bqube)


Lesenswert?

Interesannt jetzt Passiert nix mehr

von Karl H. (kbuchegg)


Lesenswert?

Pierre Gnauck schrieb:
> Interesannt jetzt Passiert nix mehr

:-)

mein Fehler.
show() Aufruf vergessen.

von Pierre G. (bqube)


Lesenswert?

Läuft glücklich vor sich hin

von Karl H. (kbuchegg)


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.

von Pierre G. (bqube)


Lesenswert?

Aber es steht :)

von Karl H. (kbuchegg)


Lesenswert?

Wie sind deine Tasten angeschlossen.

Laut Programm: einfache Taster, die nach GND schalten. Nichts 
ausergewöhnliches und auch nichts zusätzliches. Nur die Taster.

von Pierre G. (bqube)


Lesenswert?

Genau Masse geht dann geschaltet auf den jeweiliegen Eingang vom PORTC

von Karl H. (kbuchegg)


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)

von Karl H. (kbuchegg)


Lesenswert?

Wie oft kannst du drücken, ehe alles steht?
Oder steht alles sofort?

von Pierre G. (bqube)


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.

von Karl H. (kbuchegg)


Lesenswert?

Das gibts doch gar nicht. Hmmmmmmm

Vielleicht doch was mit der Stomversorgung.

Bei den LED Spielchen. Hattest du da den Fall, dass wirklich alle LED 
geleuchet haben?

Wenn nicht, sollten wir das unbedingt ausprobieren und gezielt 
herbeiführen.

von Karl H. (kbuchegg)


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?

von Pierre G. (bqube)


Lesenswert?

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.

Netzteil 8V 2A --> Lm317 5V --> Schaltung mit Osci überwacht... aber nix 
zu erkennen.

von Pierre G. (bqube)


Lesenswert?

Ist doch zum Mäuse melken ja er Zählt drüber hinaus ???????

von Karl H. (kbuchegg)


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.

von Pierre G. (bqube)


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 :)

von Karl H. (kbuchegg)


Lesenswert?

Irgendwelche vertauschte LED oder Pins?

Obwohl: das wär dir beim Zählen aufgefallen

von Karl H. (kbuchegg)


Lesenswert?

Pierre Gnauck schrieb:

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

Freitag abend ist bei mir eher schlecht. Werd zusehen, dass ich online 
gehen kann.

> Ich danke dir aber schonmal für deine Mühne :)

Keine Ursache. Das interessiert mich jetzt selber was da los ist.
Sowas hab ich auch noch nie gesehen.

von Mark B. (markbrandis)


Lesenswert?

Pierre Gnauck schrieb:
> Gut mein Hund schaut mich sowieso schon an als ob ich einen an der
> Waffel hätte

Pictures please :)

von Ausgeloggt (Gast)


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
}

von Pierre G. (bqube)


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

von Pierre G. (bqube)


Angehängte Dateien:

Lesenswert?

Mark Brandis schrieb:
> Pierre Gnauck schrieb:
>> Gut mein Hund schaut mich sowieso schon an als ob ich einen an der
>> Waffel hätte
>
> Pictures please :)

Hier :-)

von Mark B. (markbrandis)


Lesenswert?

Pierre Gnauck schrieb:
>> Pictures please :)
>
> Hier :-)

Danke :-)

Oder eher so: :-----)

Bei der langen Nase die er hat ;-)

: 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.