Forum: Mikrocontroller und Digitale Elektronik 7 Segment Multiplexing Zähler


von Tomato (Gast)


Lesenswert?

Hallo an alle!

Ich möchte mit meinem ATMega8 vier 7 Segment Displays hochzählen lassen. 
Also von 0-9999.
Leider bin ich bisher darin echt nicht bewandert und möchte, bevor ich 
selber meinen Code schreibe, zunächst einmal an einem Beispielcode 
nachvollziehen können wie das Ganze abläuft.
Folgendes habe ich dabei gefunden:
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
#include <util/delay.h>
4
5
#define F_CPU 8000000
6
7
int damn [10] = {~(0x3F), ~(0x06), ~(0x5B), ~(0x4F), ~(0x66), ~(0x6D), ~(0x7D), ~(0x07), ~(0x7F), ~(0x6F)};
8
  
9
volatile uint16_t x = 0;
10
volatile uint16_t y = 0;
11
12
void seven_write(uint16_t i_digit)
13
{
14
  PORTD = damn[i_digit];
15
}
16
17
int main(void)
18
{
19
  DDRB |= (1 << PB0);
20
  DDRC |= 0x1E;
21
  DDRD |= 0x7F;
22
  
23
  PORTD = 0x7F;  //alle PORT Pins als output
24
  PORTC = 0x7F;
25
  
26
  TIMSK |= (1 << TOIE0);  
27
  TCCR0 |= (1 << CS01) | (1 << CS00);
28
  
29
  TCCR1B |= (1 << WGM12) | (1 << CS10) | (1 << CS11);  //für multiplexing
30
  OCR1A = 15625;
31
  TIMSK |= (1 << OCIE1A);
32
  
33
  sei();  
34
35
    while (1) 
36
    {
37
    }
38
}
39
40
ISR (TIMER0_OVF_vect)
41
{
42
  PORTC &= ~(1 << (y+4));
43
  y ^= 1;
44
  
45
  if (y == 0)
46
  {
47
    seven_write(x%10);
48
  }
49
  else
50
  {
51
    seven_write(x/10%10);
52
  }
53
  
54
  PORTC |= (1 << (y+4));
55
}
56
57
ISR (TIMER1_COMPA_vect)
58
{
59
  x++;  
60
}

Wenn ich mir das so anschaue, dann vermute ich, dass hier nur eine 
Segmentanzeige angesteuert wird. Aber mir erschließt sich noch nicht 
ganz, wie ich das zu vier Segmentanzeigen erweitern kann.

Bitte seid etwas gnädig. Ich habe mir auch schon diverse Tutorials dazu 
durchgelesen, jedoch erschließt sich mir das Thema so noch nicht zu 
100%.

LG :)

von MaWin (Gast)


Lesenswert?

Tomato schrieb:
> Wenn ich mir das so anschaue, dann vermute ich, dass hier nur eine
> Segmentanzeige angesteuert wird

Nein, 2, an PC4 und PC5.

Tomato schrieb:
> wie ich das zu vier Segmentanzeigen erweitern kann.

y von 0 bis 3 zählen lassen, dann PC6 und PC7 mit nutzen. Leider wird 
PC7 als Input definiert.

Aber auch seven_write muss dann für jede der 4 Stellen aufgerufen 
werden.

von Falk B. (falk)


Lesenswert?

Tomato schrieb:
> Ich möchte mit meinem ATMega8 vier 7 Segment Displays hochzählen lassen.
> Also von 0-9999.

Siehe LED-Matrix.

> Leider bin ich bisher darin echt nicht bewandert und möchte, bevor ich
> selber meinen Code schreibe, zunächst einmal an einem Beispielcode
> nachvollziehen können wie das Ganze abläuft.
> Folgendes habe ich dabei gefunden:

Naja, ganz schön akademischer Ansatz. Es reicht eine ISR, da kann man 
alles Nötige machen. man muss auch keine Portzuweisung als FUnktion 
ausführen, da ist übertrieben. Eher so.
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
#include <util/delay.h>
4
#define F_CPU 8000000
5
6
// Kodierung der 7 Segment Anzeige
7
8
uint8_t bcd2seg [10] = {0x3F, 0x06, 0x5B, 0x4F, 0x66,  // 0-4
9
                        0x6D, 0x7D, 0x07, 0x7F, 0x6F}; // 5-9
10
  
11
volatile uint8_t data[4] = 0;  // data für Anzeige
12
volatile uint8_t flag100ms;
13
14
// Zahl in Daten für Anzeige umwandeln
15
16
void convert(uint16_t zahl) {
17
  data[3] = ~bcd2seg[zahl % 10]; zahl /= 10;
18
  data[2] = ~bcd2seg[zahl % 10]; zahl /= 10;
19
  data[1] = ~bcd2seg[zahl % 10]; zahl /= 10;
20
  data[0] = ~bcd2seg[zahl % 10];
21
}
22
23
int main(void) {
24
  uint16_t zahl=0;
25
26
  DDRB |= (1 << PB0);
27
  DDRC |= 0x1E;
28
  DDRD |= 0x7F;
29
  
30
  PORTD = 0x7F;  //alle PORT Pins als output
31
  PORTC = 0x7F;
32
33
  // timer 0, prescaler 64
34
  TIMSK |= (1 << TOIE0);  
35
  TCCR0 |= (1 << CS01) | (1 << CS00);
36
  
37
  sei();  
38
    while (1) {
39
       if (flag100ms) {
40
         flag100ms=0;
41
         zahl++; 
42
         convert(zahl);
43
       }
44
    }
45
}
46
47
// Timer 0 ISR, 488 Hz
48
ISR (TIMER0_OVF_vect) {
49
  static uint8_t digit, cnt;
50
  
51
  PORTC = 0;         // Stelle aus
52
  digit++;
53
  if (digit > 3) digit = 0;
54
  PORTD = data[digit];
55
  PORTC = 1<<digit;   // neue Stelle ein
56
57
  // 100ms Flag
58
  cnt++;
59
  if (cnt==49) {
60
    cnt = 0;
61
    flag100ms=1;
62
  }
63
}

von Tomato (Gast)


Lesenswert?

Hey ihr beiden, danke für eure schnelle Antwort :)
@falk! Das ist grandios :) ich arbeite das mal durch, und wenn ich 
Fragen habe, melde ich mich nochmal

LG

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.