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.

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.
| 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.
| 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 | } |
| 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 | } |