Forum: Mikrocontroller und Digitale Elektronik Problem mit Funktionszeigertabelle


von Dennis (Gast)


Lesenswert?

Hallo zusammen,

ich habe ein Problem in einem C-Programm, das ich für einen Atmega32 
schreibe. Die betreffende Funktion ist Teil einer Robotersteuerung.
Im else-Zweig (ab "Bewegung nicht mehr erlaubt oder Schrittkette 
beendet") hängt sich das Programm auf. Ich kann das auf diesen Bereich 
eingrenzen, weil die übergeordnete Schrittkette weiter läuft, wenn ich 
den else-Zweig herausnehme.
Ich kann Fehler in anderen Funktionen absolut ausschließen.

Nun zum Code

Ich habe global folgendes definiert:
1
volatile unsigned char auswahl_feld;        // Anzahl der auswählbaren Bewegungen
2
3
#define MOVES 0x0b              // 11 Bewegungen möglich
4
typedef void (*VoidFct1) (void);    // Neuen Typ (Funktionszeiger) vereinb.
5
 
6
VoidFct1 array_bewegung[MOVES];      // Array von Funktionszeigern
7
            // Vom Typ VoidFct1 vereinbaren
8
            // Moves = global vereinbart mit 11


Die Funktion, die mir die Probleme bereitet, sieht so aus:
1
void us_auswahl_richtung(unsigned int mask_erl_bew, unsigned int mask_akt_bew)
2
{
3
  // Funktion macht die Auswahl der Bewegung
4
5
  // Erst wird überprüft, ob eine Bewegung läuft (mask_akt_bew) und diese
6
  // durch die Ultraschallauswertung (mask_erl_bew) noch erlaubt ist.
7
  // Dazu wird mit der Variable mask_bitpos jede Bitposition von 
8
  // mask_erl_bew und mask_akt_bew verundet. Ist das Ergebnis am Ende der For-Schleife 
9
  // größer als 1, dann hat es eine Übereinstimmung gegeben und die aktuell
10
  // laufende Bewegung ist erlaubt. In diesem Fall wird die aktuelle Bewegungsfunktion
11
  // wieder aufgerufen und die Schrittkette weiter ausgeführt.
12
13
  // Muss eine neue Bewegung ausgewählt werden (bew_fortf = 0), wird überprüft, 
14
  // welche Bewegungen erlaubt sind. Dazu wird mask_bitpos mit mask_erl_bew
15
  // verundet. Stimmt das Ergebnis mit einer Bewegung überein, wird die zur Bewegung gehörende
16
  // Funktion in das Array des Funktionszeigers geschrieben. Die Positionen der
17
  // Funktionen im Array variieren nach Erlaubnis und Reihenfolge der Auswahl.
18
  // Nach jedem Zugriff auf das Array, wird die Laufvariable auswahl_feld
19
  // inkrementiert. 
20
  // Am Ende der For-Schleife liegt eine in auswahl_feld gespeicherte Anzahl
21
  // von erlaubten Bewegungen im Array vor. 
22
23
  // auswahl_feld und MOVES sind global gültige Variablen
24
  
25
26
    unsigned char i;                        // Laufvariable For-Schleife
27
  unsigned int mask_bitpos;        // Variable zur Maskierung
28
    unsigned int auswahl;          // Ergebnis der Maskierung
29
  unsigned char bew_fortf;        // Meldevariable
30
31
  mask_bitpos = 0;
32
  bew_fortf = 0;              // Meldevariable reset
33
34
  // Überprüfen, ob Bewegung läuft und diese noch erlaubt ist
35
    for (i=0;i<MOVES;i++)          // Auswahlschleife
36
    {
37
        mask_bitpos = (1 << i);             // Bitposition auswählen
38
        auswahl = mask_erl_bew & mask_bitpos & mask_akt_bew;
39
    // |-> wird >= 1, wenn ausgewählte Bitposition in mask_erl_bew und mask_akt_bew
40
    // 1 ist
41
42
    if (auswahl > 0)          // Bewegung läuft und ist erlaubt
43
    {
44
      bew_fortf = 1;          // Meldevariable setzen
45
    }
46
  }
47
48
  if (bew_fortf == 1)            // Wenn aktuell Bewegung läuft & erlaubt
49
  {
50
    array_bewegung[auswahl_feld]();    // aktuelle Bewegungs-Schrittkette weiter ausführen
51
  }
52
  else              // Bewegung nicht mehr erlaubt oder Schrittkette beendet
53
  {
54
    auswahl_feld = 0;          // Feldposition d. Arrays auf null
55
    mask_bitpos = 0;
56
      for (i=0;i<MOVES;i++)        // Auswahlschleife
57
      {
58
          mask_bitpos = (1 << i);         // Bitposition i auswählen
59
          auswahl = mask_erl_bew & mask_bitpos;    // Bewegung erlaubt?
60
61
          switch (auswahl)        // Maskierungsergebnis auswerten
62
          {                
63
              case 1 : 
64
          array_bewegung[auswahl_feld] = move_not;
65
          auswahl_feld++;
66
              case 2 : 
67
          array_bewegung[auswahl_feld] = move_180_l;
68
          auswahl_feld++;
69
              case 4 : 
70
          array_bewegung[auswahl_feld] = move_180_r;
71
          auswahl_feld++;
72
              case 8 : 
73
          array_bewegung[auswahl_feld] = move_onspot_r;
74
          auswahl_feld++;
75
              case 16 : 
76
          array_bewegung[auswahl_feld] = move_onspot_l;
77
          auswahl_feld++;
78
              case 32 : 
79
          array_bewegung[auswahl_feld] = move_back;
80
          auswahl_feld++;
81
              case 64 : 
82
          array_bewegung[auswahl_feld] = move_90_r;
83
          auswahl_feld++;
84
              case 128 : 
85
          array_bewegung[auswahl_feld] = move_90_l;
86
          auswahl_feld++;
87
              case 256 : 
88
          array_bewegung[auswahl_feld] = move_t_r;
89
          auswahl_feld++;
90
              case 512: 
91
          array_bewegung[auswahl_feld] = move_t_l;
92
          auswahl_feld++;
93
              case 1024 : 
94
          array_bewegung[auswahl_feld] = move_forward;
95
          //auswahl_feld++;      // Nur bei weiteren Bewegungen erforderlich
96
      }                  // Ende Switch
97
    }                    // Ende For
98
  }

Ergänzende Erläuterungen:
Die Maske mask_erl_bew wird bei der Auswertung der Ultraschallmessung 
gebildet und speichert von rechts nach links die Bewegungen, die 
abhängig vom gemessenen Abstand erlaubt sind. Welchen Bitpositionen die 
Funktionen der einzelnen Bewegungen zugeordnet sind, erkennt man in der 
Switch-Case Abfrage. Die hier abgebildete Funktion soll nun in dem Array 
array_bewegung jene Funktionen ablegen, die erlaubt sind. Der Aufruf 
einer dieser Funktionen erfolgt später pseudo-zufällig.

so, ich hoffe, meine Ausführungen genügen Euch.
Die Frage: Wo ist in dieser Funktion der Fehler?

Dank Euch im Voraus für Hilfe & Tipps!

Grüße

Dennis

von holger (Gast)


Lesenswert?

Na, ich weiss nicht ob das so geht.

typedef void (*VoidFct1) (void);    // Neuen Typ (Funktionszeiger) 
vereinb.

Dein Funktionszeiger hat keine Parameter.
Diese Funktion allerdings schon.

void us_auswahl_richtung(unsigned int mask_erl_bew, unsigned int 
mask_akt_bew)

von Karl H. (kbuchegg)


Lesenswert?

1
....
2
3
         switch (auswahl)        // Maskierungsergebnis auswerten
4
          {                
5
              case 1 : 
6
          array_bewegung[auswahl_feld] = move_not;
7
          auswahl_feld++;
8
              case 2 : 
9
          array_bewegung[auswahl_feld] = move_180_l;
10
          auswahl_feld++;
11
              case 4 :

da fehlen die ganzen breaks.
Deine cases fallen alle durch und füllen dir das Array ratz fatz an. Und 
darüber hinaus.

von Dennis (Gast)


Lesenswert?

Du hast Dich verlesen, oder?
1
typedef void (*VoidFct1) (void);    // Neuen Typ (Funktionszeiger) vereinb.
2
VoidFct1 array_bewegung[MOVES];      // Array von Funktionszeigern

Die Funktion us_auswahl_richtung hat mit dem Zeiger eigentlich nichts zu 
tun.
Der Zeiger zeigt auf array_bewegung. Oder ?

von Dennis (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> da fehlen die ganzen breaks.
> Deine cases fallen alle durch und füllen dir das Array ratz fatz an. Und
> darüber hinaus.

oha .. dann habe ich switch-case wohl doch noch nicht verstanden...
Ich probiere das mal aus!

Danke

von holger (Gast)


Lesenswert?

>Du hast Dich verlesen, oder?

Jupp, sorry;)

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.