Forum: Mikrocontroller und Digitale Elektronik Countdown ATMega8


von Franny (Gast)


Lesenswert?

Hallöchen alle miteinander :)

Ich habe einen ATMega8 an vier 7-Segment-Displays angeschlossen und 
möchte dort nun im Loop von 9999 auf 0000 runterzählen lassen. Ansich 
klappt das auch recht gut, nur aus irgendwelchen Gründen fängt er 
zunächst an bei 147 runter zu zählen und springt erst dann auf die 9999.
Ich denke, ich bin gerade einfach "Code-blind" nenne ich es mal, und 
finde den Fehler darin einfach nicht...
Wäre super, wenn ihr mal nen Blick rüber werfen und mir die Augen öffnen 
könntet.

Vielen Dank im Voraus!
Franny
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
#include <util/delay.h>
4
5
uint16_t damn [10] = {(0xC0), (0xF9), (0xA4), (0xB0), (0x99), (0x92), (0x82), (0xF8), (0x80), (0x90)};
6
uint8_t counts[4] = {0x90,0x90,0x90,0x90};
7
8
volatile uint16_t var = 0x90;
9
volatile uint16_t value = 0x90;
10
volatile uint16_t digit = 0x90;
11
volatile uint16_t c = 0x90;
12
volatile uint16_t btch = 0;
13
14
int main(void)
15
{
16
  uint16_t zahl = 0;
17
  
18
  DDRD |= (0x7F);
19
  DDRC |= (0x1E);
20
21
  TCCR0 |= (1<<CS00) | (1<<CS01);
22
  TIMSK |= (1<<TOIE0);
23
  
24
  TCCR1B |= (1<<CS10) | (1<<CS11);
25
  TIMSK |= (1 << TOIE1);
26
  
27
  sei();
28
  
29
  PORTD |= ~0x3F;    //Löschen der Zahl
30
  PORTC |= 0x1C;
31
  
32
  while(1)
33
  {
34
  }
35
}
36
37
ISR(TIMER1_OVF_vect)
38
{
39
  btch++;
40
  if (btch == 1)
41
  {
42
    btch = 0;
43
    c--;
44
    
45
    if (c == 0)
46
    {
47
      c = 9999;
48
    }  
49
  }
50
  else
51
  {
52
    PORTD = damn[c];
53
  }
54
  
55
  value = c;
56
  
57
  counts [3] = 0;          //Alles wieder auf 0 setzen
58
  counts [2] = 0;
59
  counts [1] = 0;
60
  counts [0] = 0;
61
  
62
  while(value >= 1000)      //Wertzerlegung
63
  {
64
    counts[0]++;
65
    value = value - 1000;
66
  }
67
  
68
  while(value >= 100)
69
  {
70
    counts[1]++;
71
    value = value - 100;
72
  }
73
  
74
  while(value >= 10)
75
  {
76
    counts[2]++;
77
    value = value - 10;
78
  }
79
  
80
  counts[3] = value;  
81
}
82
83
ISR(TIMER0_OVF_vect)        //Weitergabe über die Transistoren
84
{
85
  var++;
86
  
87
  if (var > 1)
88
  {
89
    var = 0;
90
    digit++;
91
    
92
    if (digit > 4)
93
    {
94
      digit = 1;
95
    }
96
  }
97
  
98
  PORTC |= 0x1E;
99
  PORTC &= ~(1 << digit);
100
  PORTD = damn[counts[digit - 1]];
101
}

von Stephan (Gast)


Lesenswert?

Zeile 10:
volatile uint16_t c = 0x90;

von Oliver S. (oliverso)


Lesenswert?

Auf den ersten Blick hätte ich ja erwartet, daß der bei 144 anfängt, 
daher ist 147 wirklich seltsam.

Das alles ist aber so verquer und durcheinander, da solltest du mal 
drüber shclafen, dann alles löschen, und von vorne anfangen.

Oliver

von Peter D. (peda)


Lesenswert?

Franny schrieb:
> nur aus irgendwelchen Gründen fängt er
> zunächst an bei 147 runter zu zählen

Schon merkwürdig, Du lädst ja 144 rein.

von Cyblord -. (cyblord)


Lesenswert?

Also Softwaretechnisch baut man das erst mal so auf, dass du an einer 
Stelle (von mir aus in einer Funktion, besser in einem eigenen Modul*) 
eine int16 Variable auf den 7-Segmentanzeigen ausgeben kannst.

Der Rest des Programms muss sich dann nur noch darum kümmern, diese 
simple Variable zu setzen.

Die Ausgabefunktion kann man dann auch erst mal wunderbar mit 
verschiedenen werten testen.

Das eigentliche Countdown Programm wird danach extrem einfach.


* Erstelle eine eigene .c und .h Datei für die 7 Segmentanzeige. Mit 
EINER öffentlichen Funktion (z.B. showValue(uint16_t value)) im header.
In die .c Datei machst du allen Quatsch den du für die 7Segment 
benötigst. Pins, Segment-Array usw. usw.

von Falk B. (falk)


Lesenswert?

Franny schrieb:
> Hallöchen alle miteinander :)

Und selbst?

> Ich habe einen ATMega8 an vier 7-Segment-Displays angeschlossen und
> möchte dort nun im Loop von 9999 auf 0000 runterzählen lassen. Ansich
> klappt das auch recht gut,

Naja, dein Programm ist etwas akademisch, scheint aber zu funktionieren.

> nur aus irgendwelchen Gründen fängt er
> zunächst an bei 147 runter zu zählen und springt erst dann auf die 9999.
> Ich denke, ich bin gerade einfach "Code-blind" nenne ich es mal, und
> finde den Fehler darin einfach nicht...

Ich hab ihn auf die Schnelle nicht gefunden, vermute aber, daß du eben 
nicht die 9999 zuerst anzeigst, sondern erstmal um eins runter zählst. 
Und das in einer ARG verkrampften Weise. Mein Gott! Übst du für den C 
obfuscation contest?

Das geht DEUTLICH einfacher und ÜBERSICHTLICHER!
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
#include <util/delay.h>
4
uint16_t damn [10] = {0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90};
5
uint8_t data[4];
6
int16_t zahl = 9999;
7
uint8_t digit;
8
9
int main(void) {
10
  
11
  DDRD |= (0x7F);
12
  DDRC |= (0x1E);
13
  TCCR0 |= (1<<CS00) | (1<<CS01);
14
  TIMSK |= (1<<TOIE0);
15
  
16
  TCCR1B |= (1<<CS10) | (1<<CS11);
17
  TIMSK |= (1 << TOIE1);
18
  
19
  sei();
20
  
21
  PORTD |= ~0x3F;    //Löschen der Anzeige
22
  PORTC |= 0x1C;
23
  
24
  while(1) {
25
  }
26
}
27
28
// Count down
29
30
ISR(TIMER1_OVF_vect) {
31
32
  zahl--;
33
  if (zahl < 0) zahl = 9999;
34
  data[3] = zahl % 10; zahl /=10;
35
  data[2] = zahl % 10; zahl /=10;
36
  data[1] = zahl % 10; zahl /=10;
37
  data[0] = zahl % 10;
38
}
39
40
// Multiplexansteuerung der Anzeige
41
42
ISR(TIMER0_OVF_vect) {
43
44
  PORTC |= 0x1E;                // alles aus
45
  digit++;
46
  if (digit > 3) digit = 0;  
47
  PORTD = damn[data[digit]];    // Muster für neues Digit
48
  PORTC &= ~(1 << (digit+1));    // Digit einschalten
49
}

Außerdem, wenn man schon alles in die ISRs packt, braucht man auch kein 
volatile, denn es gibt NUR in den ISRs den Variablenzugriff, nicht im 
normalen Programm. Ich würde das aber nicht so machen, denn man braucht 
dafür keine 2 Timer mit 2 ISRs. Eine reicht locker.

von Franny (Gast)


Lesenswert?

Stephan schrieb:
> Zeile 10:
> volatile uint16_t c = 0x90;

Super Danke! In all dem Wirrwarr hab ich das echt übersehen.

Oliver S. schrieb:
> Das alles ist aber so verquer und durcheinander, da solltest du mal
> drüber shclafen, dann alles löschen, und von vorne anfangen.

Vernünftig strukturieren steht noch auf dem Plan :)
Konnte es mir nur leider noch nicht angewöhnen von vornherein sauber zu 
arbeiten...

> Franny schrieb:
> Schon merkwürdig, Du lädst ja 144 rein.

Immer diese Tippfehler...Ich meinte 144 ^^'

Vielen Dank an euch!

von Peter D. (peda)


Lesenswert?

Franny schrieb:
> PORTD = damn[counts[digit - 1]];

Das muß man auch nicht bei jedem Multiplextakt immer wieder neu machen, 
sondern kann es einmalig bei der Zahlenumwandlung mit machen.

von Franny (Gast)


Lesenswert?

Falk B. schrieb:
> Das geht DEUTLICH einfacher und ÜBERSICHTLICHER!

Erstmal Danke für das ausführliche Drüberschauen!
Mir scheint aber beim Überfliegen, dass dein Programm nicht runter 
zählt, sondern nur zwischen 9999 und 0000 hin und her springt. Oder 
überseh ich da gerade etwas?

Peter D. schrieb:
> Das muß man auch nicht bei jedem Multiplextakt immer wieder neu machen,
> sondern kann es einmalig bei der Zahlenumwandlung mit machen.

Das wusste ich noch garnicht, danke :)

von Falk B. (falk)


Lesenswert?

Franny schrieb:
> Falk B. schrieb:
>> Das geht DEUTLICH einfacher und ÜBERSICHTLICHER!
>
> Erstmal Danke für das ausführliche Drüberschauen!
> Mir scheint aber beim Überfliegen, dass dein Programm nicht runter
> zählt, sondern nur zwischen 9999 und 0000 hin und her springt. Oder
> überseh ich da gerade etwas?

Du übersiehst was.
1
  zahl--;
2
  if (zahl < 0) zahl = 9999;

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.