Forum: Mikrocontroller und Digitale Elektronik ATMega16 Dot Matrix Zähler


von Tomato (Gast)


Lesenswert?

Guten Morgen alle miteinander :)

Ich habe ein kleines Projekt vor mir. Das Ziel ist es ein Mini Tetris 
Spiel über meinen ATMega16 auf zwei LED Matrizen laufen zu lassen.
Da ich noch recht neu in der uC Programmierung bin stoße ich leider auf 
ein paar Probleme (trotz Lesen des AVR Tutorials).
Zunächst probiere ich nur komplette Reihen auf einer der beiden 
Matritzen "runterfallen" zu lassen, am Besten im Sekundentakt. Jedoch 
bekomme ich nur einen binären Zähler hin, also die Reihen der Matrix 
stellen die gezählte Zahl dar. Ich habe schon überlegt mit if 
Bedingungen zu arbeiten, jedoch wird das dann nicht mit einem 
Sekundentakt funktionieren und wäre auch auf keinen Fall eine schöne 
Lösung, wie ich annehme :)

Hier also mein bisheriger Code (ohne den Versuch der if Bedingungen):
1
#define F_CPU 16000000
2
#include <avr/io.h>
3
#include <avr/interrupt.h>
4
5
//2D Array für spätere zweite Dot-Matrix
6
// uint8_t LookUpLED[5][2]={ 
7
//               {1,0}, 
8
//               {0,0}, 
9
//               {0,0}, 
10
//               {0,0}, 
11
//               {0,1}, 
12
//             };
13
            
14
uint8_t Test[5]={1,0,0,0,0};
15
16
int var;
17
int x=0;
18
19
void Init();                    
20
void InitPorts();
21
void InitTimer();
22
void LEDAusgabe();
23
24
int main(void)
25
{
26
  Init();
27
  
28
    while (1) 
29
    {   
30
  }
31
}
32
33
void Init()
34
{
35
  InitPorts();
36
  InitTimer();
37
}
38
39
void InitPorts()
40
{
41
  DDRA= 0xFF;
42
   DDRB= 0xFF;
43
  DDRC= 0xFF;
44
  DDRD= 0xFF; 
45
}
46
47
void InitTimer()
48
{
49
  //Timer 0
50
  TCCR0 |= (1<<CS00) | (1<<CS01);
51
  TIMSK |= (1<<TOIE0);
52
  
53
  //Timer1
54
  TCCR1B |= (1<<CS10) | (1<<CS11);
55
  TIMSK |= (1<<TOIE1); 
56
  
57
  sei();
58
}
59
60
void LEDAusgabe()
61
{
62
  Test[0]=x;
63
  PORTA = Test[0];  
64
}
65
66
ISR(TIMER1_OVF_vect)
67
{
68
  //Hochzählen der Reihen
69
  x++;
70
  LEDAusgabe();
71
  
72
  //Debug LED
73
  PORTA |= (1<<PA7);
74
}
75
76
ISR(TIMER0_OVF_vect)
77
{
78
  //Multiplexen der Transistoren
79
  for (int i=0; i<5; i++)
80
  {
81
    PORTB |= ~0xFF;
82
    
83
    //Debug LED
84
    PORTC |= (1<<PC7);
85
  }
86
};

Ich vermute, dass ich den Timer wahrscheinlich nicht richtig verwende, 
jedoch entzieht es sich meiner Kenntniss, wie ich mein Problem lösen 
kann.

Vielen Dank schonmal!
Tomato

von Adam P. (adamap)


Lesenswert?

Tomato schrieb:
> Jedoch
> bekomme ich nur einen binären Zähler hin

Tomato schrieb:
> void LEDAusgabe()
> {
>   Test[0]=x;
>   PORTA = Test[0];
> }

Ja weil du x erhöhst und da x eine Byte Variable ist und du diese dem 
ganzen Port zuweist, stellen deine 8 LED in Reihe diese Zahl binär dar.

Für eine Linie müsstest du den Wert 0xFF auf eine Reihe ausgeben und 
dann die Reihen (Zeilen) durchlaufen.
Natürlich die vorherige ausschalten bevor bzw. nachdem du die nächste 
Reihe angesteuert hast.

edit:
Falls ich es so verstehe das PORTA für die Spaltenansteuerung zuständig 
ist.

: Bearbeitet durch User
von Adam P. (adamap)


Lesenswert?

1. Oberste Zeile auswählen
2. PORTA den Wert 0xFF zuweisen
3. Warten...
4. PORTA den Wert 0 zuweisen
5. 2te Zeile von oben wählen
6. PORTA den Wert 0xFF zuweisen
7. ...

Falls dein Aufbau dem enstpricht.

edit:
Tomato schrieb:
> //Debug LED
>   PORTA |= (1<<PA7);

Ich glaub das sollte bei dir auch PORTC heißen und nicht A.

: Bearbeitet durch User
von Stefan F. (Gast)


Lesenswert?

Deine Timer ISR bringt alle 5 Reihen für wenige Mikrosekunden zum 
leuchten. Danach bleibt die Anzeige auf der letzten Reihe stehen, bis 
irgendwann viel später die ISR erneut aufgerufen wird.

Der Betrachter wird also immer nur die letzte Reihe sehen.

Korrektur: Die ISR soll bei jedem Aufruf nur eine Reihe darstellen.
1
ISR(TIMER0_OVF_vect)
2
{
3
  static int reihe = -1;
4
  reihe++;
5
  if (reihe>5) reihe=0;
6
7
  // Reihe zum Leuchten bringen
8
}

Das Schlüsselwort static bewirkt dass die Variable nur einmal auf -1 
initialisiert wird und dass ihr Wert zwischen den Funktionsaufrufen 
nicht verloren geht. Alternativ könntest du sie als globale Variable 
außerhalb der Funktion deklarieren.

Jetzt brauchst du noch eine Umrechnung der Zahl (Reihe) in das nötige 
Bitmuster für den Port:

0 = 00000001
1 = 00000010
2 = 00000100
3 = 00001000
4 = 00010000
5 = 00100000

Das geht ganz einfach:
1
PORTB = (1<<reihe);

Ich bin nicht sicher welchen Port du für die Ansteuerung der Reihen 
verwenden willst. Deswegen habe ich einfach mal PORTB geschrieben.

Mein Buch http://stefanfrings.de/mikrocontroller_buch/index.html könnte 
für dich interessant sein.

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.