4 Zeitlicher Arbeitsablauf

4.5 Kommunikation mit RapidForm2004

RapidForm2004 sendet Befehle die für die Drehtischsteuerung bestimmt sind an den Mikrocontroller. Diese sollen dort empfangen, ausgewertet und in verständlicher Form an die Drehtischsteuerung weiter gegeben werden. RapidForm2004 verwendet dabei verschiedene Befehlssätze für verschiedene Schrittmotorsteuerungen. Für jeden dieser Befehlssätze wird eine eigene Auswerte-Funktion geschrieben. Im folgenden Kapitel wird nun das Empfangen der Befehle beschrieben und eine erste Auswertung, die den empfangenen Befehl dem Befehlssatz einer Schrittmotorsteuerung zuordnet. Nachdem ein Befehl zugeordnet wurde und in der entsprechenden Auswerte-Funktion erkannt wurde, soll ein entsprechender Befehl an die Drehtischsteuerung gesendet und die Antwort der Drehtischsteuerung vom Mikrocontroller ausgewertet werden. Abschließend soll eine entsprechende Antwort an RapidForm2004 zurück gesendet werden. Abbildung 4.5 zeigt eine schematische Übersicht dieser Kommunikation.
Die Kommunikation mit RapidForm2004 ist ähnlich zu der mit der Schrittmotorsteuerung. Diese wurde bereits in Kapitel 4.3 ausführlich beschrieben. Daher wird die Kommunikation hier etwas oberflächlicher behandelt.

Abbildung 4.5: Schema der Kommunikation

4.5.1 Befehle empfangen

Zuerst sollen nun die Befehle von RapidForm2004 an den Mikrocontroller, gespeichert werden. Anschließend wird die automatische Auswahl des Befehlssatzes beschrieben.
Um anstehende Befehle zu empfangen wird, ähnlich wie in Kapitel 4.3.2, eine Funktion die ständig das Eingangsregister der ersten seriellen Schnittstelle abfragt verwendet (siehe Codelisting 11). Auch hier wird die Funktion uart_rx(dir) aufgerufen, jedoch mit dem Parameter D_RapidForm. Der empfangenen String wird auch hier in die Variable str_rx gespeichert. Somit können nun auch Strings von RapidForm2004 empfangen und in der Variablen str_rx gespeichert werden.

Listing 11: RS-232 Empfang - RapidForm2004
1 if ((UCSR0A & (1 << RXC0))){        // RapidForm Polling
2         LED_PORT &= ( 1 << LED2 );  // LED einschalten
3         uart_rx(D_RapidForm);             // Register auslesen
4 }

4.5.1.1 Automatische Auswahl eines Befehlssatzes

Nun geht es darum, dass der Mikrocontroller anhand eines ersten Befehls der empfangen wird, festlegt, mit welchem Befehlssatz fortan kommuniziert werden soll. Die Kennung für den Befehlssatz wird in einer globalen Variable gespeichert und alle weiteren Befehle werden an die entsprechende Auswerte-Funktion für diesen Befehlssatz übergeben.
In der Funktion uart_rx(dir)(Codelisting 12) wird nun in der ersten if-Abfrage entschieden, von welcher Schnittstelle der empfangene Befehl kam. Diese verzweigt nun, da D_RapidForm übergeben wurde, in den else-Teil. In diesem wird mit mehreren if-Abfragen überprüft, ob bereits der Befehlssatz für einen bestimmten Motor ausgewählt wurde. Ist dies nicht der Fall, wird der empfangende String an die Funktion switch_Motor(str_rx)(Codelisting 13) übergeben. Diese prüfte mit der aus Kapitel 4.3.3 bekannten Funktion FindStringInArray(str_rx, pOptions, 3), den angekommenen String gegen die Initialisierungsbefehle der einzelnen Befehlssätze. Die Initialisierungsbefehle sind die ersten Befehle die RapidForm2004 an eine Schrittmotorsteuerung sendet um zu prüfen ob diese vorhanden ist. In diesem ersten Schritt wird der String nur zur Identifizierung des von RapidForm2004 verwendeten Befehlssatzes verwendet. Das Antworten auf einen String wird erst in den nachfolgenden Kapiteln beschrieben. Die Funktion switch_Motor(str_rx) gibt einen numerischen Wert zurück. Jede Zahl entspricht dabei dem Befehlssatz für eine Schrittmotorsteuerung. Die Zahlenwerte werden dabei mittels Makro-Definitionen (Codelisting 13 Zeile 1-6) durch lesbare Text-Variablen ersetzt. Dies erhöhte die Lesbarkeit und das Verständnis. War dieser Schritt erfolgreich, wird in den folgenden if-Abfragen die richtige Auswerte-Funktion aufgerufen. Konnte die Funktion switch_Motor(str_rx) den empfangen Befehl nicht zuordnen, gibt sie M_UNK zurück und es wird auf dem Display Unbekannter Motor! ausgegeben.
Somit ist es möglich Befehle von RapidForm2004 zu empfangen und an die richtige Auswerte-Funktionen zu übergeben. Zusätzlich wird die Programmierung dadurch wesentlich robuster, da unbekannte Befehle ignoriert werden.
Der Nachteil dieses Vorgehens besteht darin, dass für ein wechseln des Befehlssatzes der Mikrocontroller neu gestartet werden muss. Ein Beheben dieses Nachteils wäre nicht ohne weiteres möglich gewesen.

Listing 12: Funktion: uart rx()
1 // UART Empfangsregister auslesen
2 void        uart_rx                                (int dir) {
3         uart_get_string(str_rx, dir);   // String aus Empfangsregister auslesen
4         if (dir == D_Stepper)         // Empfangsregister Stepper
5                 switch_Stepper(str_rx);             // Uebersung Stepper
6         else{                               // Empfangsregsiter RapidForm
7                 // Uebersetzungsfunktion auswaehlen
8                 if(Initialized == M_UNK){ // Unbekannter Initialisierungsbefehl
9                         lcd_puts("Unbekannter Motor!\n");
10                         Initialized = M_NOTI;    // Variable Initialized zuruecksetzen
11                 }
12                 if(Initialized == M_NOTI){ // Befehlssatz bestimmen
13                         Initialized = switch_Motor(str_rx); //Automatische Befehlssatzwahl
14                 }
15                 if(Initialized == M_ISEL)  // Uebersetzung ISEL
16                         switch_Isel(str_rx);
17                 if(Initialized == M_CSG)  // Uebersetzung CSG
18                         switch_csg(str_rx);
19                 if(Initialized == M_ZETA)  // Uebersetzung Zeta
20                         switch_Zeta(str_rx);
21                 if(Initialized == M_TERMINAL)  // Uebersetzung Terminal
22                         switch_Terminal(str_rx);
23         }
24 }
Listing 13: Funktion: switch Motor()
1 define M_UNK              -2
2 define M_NOTI              -1
3 define M_ISEL               0
4 define M_CSG               1
5 define M_ZETA               2
6 define M_TERMINAL       3
7 int        Initialized = M_NOTI;
8 // Automatische Befehlssatzwahl
9 int        switch_Motor                (char * str_rx) {
10         const char* pOptions[] = {       // Array mit Initialisierungsbefehlen
11                         "@01",          // 0 - Isel
12                         "Q:",           // 1 - CSG
13                         "ECHO0",        // 2 - Zeta
14                         "!Terminal",    // 3 - Terminal ansteuerung!
15                         0 };
16         // Ankommenden String gegen Array pruefen
17         switch (FindStringInArray(str_rx, pOptions, 3)) {
18         case 0:             // 0 - ISEL
19                 return M_ISEL;
20                 break;
21         case 1:             // 1 - CSG
22                 return M_CSG;
23                 break;
24         case 2:                     // 2 - Zeta
25                 return M_ZETA;
26                 break;
27         case 3:                     // 3 - Terminal ansteuerung
28                 return M_TERMINAL;
29                 break;
30         default:
31                 return M_UNK;
32         }
33 }