PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Einfaches Programm - Denkfehler gesucht



carrera1988
27.02.2008, 19:29
Hi,

nachdem die Beispiel-Programme ausgiebig getestet wurden fang ich grad mit meinen ersten, einfachen Programmen an, hab jedeoch ein Verständnis-Problem mit diesem Programm:

#include "RP6RobotBaseLib.h"

int main(void)
{
initRobotBase();

while(true)
{

statusLEDs.LED1=bumper_right;
statusLEDs.LED2=bumper_right;
statusLEDs.LED5=bumper_left;
statusLEDs.LED4=bumper_left;


task_Bumpers();

updateStatusLEDs();
}
return 0;
}

Ziel für mich ist es das während der Bumper Betätigt wird auf dieser Seite alle 3 Leds leuchten. Leider funktioniert das nur beim linken Bumper, nicht beim rechten, da leuchtet nur die LED die immer beim drücken leuchtet.
Bumper hab ich mit dem Selftest getestet, beide funktionieren. Irgendwie kann ich mir das verhalten nicht erklären.

Habt ihr da Tipps?

radbruch
27.02.2008, 20:59
Hallo

Über diesen "Denkfehler" bin ich auch schon gestolpert. Ursache für dieses unerwartete Verhalten ist die struct-Definition der LEDs. Mit einem Struct kann man sich eigene Datentypen erzeugen die beliebige Bitlängen haben. In "RP6RobotBaseLib.h" steht folgendes:


union {
uint8_t byte;
struct {
unsigned LEDsR:3;
unsigned LEDsL:3;
unsigned reserved:2;
};
struct {
unsigned LED1:1;
unsigned LED2:1;
unsigned LED3:1;
unsigned LED4:1;
unsigned LED5:1;
unsigned LED6:1;
unsigned reserved1:1;
unsigned reserved2:1;
};
} statusLEDs;


Unten sieht man, dass jede LED nur ein Bit belegt (LED1:1;...). Wenn man nun eine LED setzen möchte, wird vom übergebenen Wert nur ein Bit (das letzte, genannt Bit0) ausgewertet und gegebenenfalls gesetzt, z.b. statusLEDs.LED1=1 bedeutet statusLEDs.LED1=0b00000001 (dezimal 0 wäre binär 0b00000000 also LED aus.) Soweit alles klar?

Nun zu den Bumpers. Die Werte in bumper_left/bumper_right werden im Bumpers-Task durch die Funktionen getBumperLeft()/getBumperRight() eingelesen. Im Rückgabewert der Funktionen (und damit auch in den Variablen bumper_left/bumper_right) steht jeweils das Ergebniss der Portabfrage als 8-bit-Wert.

Der betreffende Eingang für den linken Bumper ist Port B0, bei gedrückten Taster wird deshalb der Wert 1 (binär 0b00000001) eingelesen und in bumper_left gespeichert. statusLEDs.LED4=bumper_left bedeutet dann statusLEDs.LED4=0b00000001 und die LED ist eingeschaltet.

Der Eingang für den rechten Bumper ist Port C6. Bei gedrücktem Bumper wird hier deshalb 2^6 oder 64 eingelesen und in bumper_right gespeichert. statusLEDs.LED1=bumper_right bedeutet dann statusLEDs.LED1=0b01000000. Bit0 ist also 0, die LED bleibt dunkel. Aha!

Lösung: Man vergleicht bumper_right mit 64 und setzt mit dem Ergebniss dieses Vergleichs die LED:

statusLEDs.LED1=bumper_right==64

Bei gedrücktem Bumper ist der Vergleich true und somit geht die LED an. (ACHTUNG! Das funktioniert nicht generell in C weil nicht definiert ist, wie der Compiler intern ein true speichert. true könnte auch z.B. 0b10000000 sein. Nur so am Rande erwähnt):


#include "RP6RobotBaseLib.h"

int main(void)
{
initRobotBase();

while(true)
{

statusLEDs.LED1=bumper_right==64;
statusLEDs.LED2=bumper_right==64;
statusLEDs.LED5=bumper_left;
statusLEDs.LED4=bumper_left;


task_Bumpers();

updateStatusLEDs();
}
return 0;
}

Der Vollständigkeit halber: Das funktioniert so nur, weil in der Rangfolge der Operatoren == vor = kommt (wie Punkt vor Strich) Im Zweifel (und zur besseren Lesbarkeit des Programms) verwendet man besser Klammern:

statusLEDs.LED1=(bumper_right==64);

Der erzeugte Code ist aber in beiden Fällen gleich.

Gruß

mic

carrera1988
29.02.2008, 08:50
Hallo,

vielen Dank für diese Super-Erklärung.
Hab das Problem verstanden und werde am WE deine Lösung testen.

Danke nochmal, echt TOP!