Hallo,
ich habe gerade angefangen, mich mit µC-Programmierung zu beschäftigen,
als Grundlage dient mir momanten das Pingpong-Spiel aus dem
Franzis-Verlag (
http://www.elo-web.de/elo/entwicklung-und-projekte/ping-pong/retro-spiel-ping-pong
), für das ich ein eigenes Spiel entwickeln möchte. Die Hardware besteht
aus einer Platine mit LED-Matrix, einem ATMega8 und zwei
Schieberegistern für das Multiplexen der LEDs, sowie zwei Potis für die
Steuerung - wie die Grafik funktioniert kann man anhand eines
C-Beispiels auf der Webseite sehr gut nachvollziehen. Andere Beispiele
dort sind leider in BASCOM geschrieben, und daher für mich nicht sehr
hilfreich. Ich verwende GCC mit dem Eclipse-AVR-Plugin unter Linux.
Hier gibt es den Schaltplan: (
http://www.elo-web.de/xattachment/0911PingPongSchaltbild.jpg ). Für
meine Frage wichtig sind vor allem die Anschlüsse K1, K2 und P1-P4. Das
Gerät besitzt einen Münzeinwurf, der einfach aus zwei Drähten an K1 und
K2 besteht - eine eingeworfene Münze stellt kurz einen Kontakt zwischen
beiden her und holt damit das Gerät aus dem Sleep-Modus, nach dem Spiel
schläft es wieder ein. Die äußeren Anschlüsse beider Potis sind an P1
und P4 angeschlossen, der Schleifer des einen an P2, der des anderen an
P3. Mein Problem ist jetzt folgendes:
K2 und P4 hängen beide an PD2/INT0. In dem erwähnten C-Beispiel (das den
Sleep-Mode nicht verwendet) wird zu Anfang PortD komplett auf Ausgang
geschaltet:
Dadurch funktioniert aber der Interrupt nicht, der bei INT0=low das
Spiel wieder starten soll. Wenn ich dagegen die vier unteren Bits mit
als Eingang konfiguriere, dann wacht der AVR zwar wieder auf, aber ich
habe dann leider ein Problem mit dem ADC: Der Wert, den ich mir ausgeben
lasse, ist offenbar immer der 10-bit-Maximalwert. Daher habe ich nun
versucht, am Anfang des Programms die Datenrichtung von PortD auf 0xff
zu lassen und erst vor dem Schlafenlegen zu ändern. Meine Funktion für
den Sleep-Modus sieht nun so aus:
1 | void sleepNow()
|
2 | {
|
3 | //Bildschirm löschen
|
4 | uint8_t i;
|
5 | for (i = 0; i<WIDTH; i++) leds[i] = 0;
|
6 |
|
7 | _delay_ms(250);
|
8 |
|
9 | //INT0 auf Eingang stellen, damit der Münzeinwurf funktioniert
|
10 | DDRD &= ~(1<<DDD2);
|
11 |
|
12 | //Sleep Enable, STAND-BY
|
13 | MCUCR |= (1<<SE) | (1<<SM2) | (1<<SM1);
|
14 | //Interrupt bei low auf INT0 erlauben
|
15 | GICR |= (1<<INT0);
|
16 |
|
17 | sleep_mode();
|
18 |
|
19 | //INT0 wieder auf Ausgang, damit das Poti funktioniert
|
20 | DDRD |= (1<<DDD2);
|
21 | }
|
Ohne die letzte Zuweisung von DDRD bekomme ich nach dem Aufwachen wieder
nur den höchsten Wert angezeigt, mit der Zuweisung reagiert das Gerät
anschließend nicht mehr (es macht den Eindruck, als ob es gar nicht
aufwacht).
Meine Frage wäre jetzt zunächst, was die Verbindung von K2, P4 und PD2
für einen Sinn hat. Es scheint ja zu funktionieren, wie man am
Originalspiel sieht, nur ist mir die Idee dahinter nicht klar. Meine
Vorstellung ist, dass die Potis als Pull-Up-Widerstände fungieren, wenn
der Pin als INT0 verwendet wird. Aber wäre es nicht sinnvoller gewesen,
P4 mit Masse zu verbinden und die Messung damit unabhängig von der
Konfiguration von PD2 zu machen?
Was muss ich unternehmen, um sowohl den Sleep-Mode als auch den ADC
verwenden zu können?
Mein momentanes Testprogramm habe ich mal angehängt (auch wenn es etwas
unordentlich aussieht). Der Wert des rechten Potentiometers wird in
Binärcode über die Breite des Bildschirms angezeigt. Wenn man es ganz
runterdreht (Wert 4, kleiner geht nicht), dann legt sich das Programm
schlafen.
Mirko