Forum: Mikrocontroller und Digitale Elektronik Programmierung des Pingpong-Spiels von Franzis in C


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Mirko H. (m1rk0)


Angehängte Dateien:

Lesenswert?

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:
1
DDRD = 0xff;

Dadurch funktioniert aber der Interrupt nicht, der bei INT0=low das 
Spiel wieder starten soll. Wenn ich dagegen die vier unteren Bits mit
1
DDRD = 0xf0;

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

von Stefan E. (sternst)


Lesenswert?

Mirko Horstmann schrieb:
> 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).

Weil zu diesem Zeitpunkt der externe Interrupt immer noch enabled ist. 
Wenn du den Pin zum Ausgang machst und eine 0 ausgegeben wird, schickt 
sich der µC quasi selber in einen Dauerinterrupt (dein Programm bleibt 
dann zwar nicht wirklich stehen, wird aber extrem langsam).

von Mirko H. (m1rk0)


Lesenswert?

Super, danke! Mit einem
1
GICR &= ~(1<<INT0);

nach dem Aufwachen funktioniert es. Jetzt frage ich mich immer noch, 
warum die Schaltung so aufgebaut wurde. Wenn das Poti einfach mit Masse 
verbunden wäre, müsste es doch auch funktionieren, oder?

Mirko

von Lutz (Gast)


Lesenswert?

Hallo Leute,

vielleicht kann mir ja jemand helfen.... Ich habe dieses tolle PingPong 
Spiel bei Conrad gekauft und versuche den Controller mit Bascom 
umzuprogrammieren. Habe mir bei amazon einen USB-Programmer (Diamex) 
gekauft und angeschlossen, Programm übertragen... aber nix passiert, 
PingPong läuft weiter auf dem Controller. Habe mir jetzt sogar den 
Minimal-Programmer, wie auf elo-web beschrieben, besorgt. Auch hiermit 
bekomme ich mein Programm nicht übertragen... pingPong läuft weiter.... 
Hat jemand einen Tipp??

Vielen Dank!

Lutz

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.