7 Segment Multiplexing Zähler

Gast #6807974
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 :)
Gast #6807983
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.
#6808010
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
}

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