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

Eine eigene Frage? Dieser Thread ist über 5 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.