
Zitat von
markusj
... verschiedene Möglichkeiten ... abhängen, wie komplex das Protokoll ...
Schöne Erklärung Markus, danke. Irgendwann muss ich mich wohl wirklich mit Sinn, Zweck, Anwendungs- und (allgemein) Möglichkeiten der struct´s und union´s beschäftigen. Ich finde, dass die einfache Reihenfolge mehrerer Bytes aber eine Stolperstelle sein könnte. Ich habe mein Protokoll dran aufgehängt, dass ich eine führende Kennung bei mehreren Bytes verwende, wobei für sehr wichtige Aktionen die Kennung als Information alleine (also NUR EIN Byte senden!) ausreicht.
Beispiele:
Code:
// ============================================================================== =
// == Lies den Puffer rx_buff[RX0_SIZE]
// ============================================================================== =
void u0st1 (void) // Schreib+Les RX-Tx-UART0(PD) z Einstellen + FUnktionswahl
{ //
#define KOMMANDO_APPS 'A' // Anwendungsprogramme fahren, diverse
#define KOMMANDO_APPS_LEN 7 // Annkkkk
// nn =: 01..99 - Programmnummer
// kkkk Parameter für Prog
//...
#define KOMMANDO_NORM 'N' // Normposition der Servos anfahren
#define KOMMANDO_NORM_LEN 1 // Kommandolänge´
//...
#define KOMMANDO_POSER 'P' // Positionierbefehl Servo
#define KOMMANDO_POSER_LEN 6 // Pn3600 {1-9, j, z} 10 Servo
// n =: 1..9, j=10, z=alle
//...
// Muss nur das laengste Kommando aufnehmen koennen.
#define KOMMANDO_BUFFER_LAENGE 14
//...
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Diese for-Schleife ist das eigentliche UART0-Stellprogramm.
for (;;)
{
// ...
/* Auch wir nutzen diese GoTo-Variante um auf Inhalt im FIFO zu warten. */
if ( ! ukbhit0 () )
continue;
/* EIN EINZIGES Zeichen aus FIFO lesen. */
zeichen_aus_fifo = ugetchar0();
// ==================================================
/* Wenn noch kein Kommando bekannt ist, muessen wir erst einen
Kommando-Buchstaben erkennen.
Randbemerkung
Hier ist auch ein switch/case-Dingsda erlaubt, da zeichen_aus_fifo und
auch der Define genau ein char-Zeichen bzw. ein numerisch auswertbarer
einfacher Datentyp sind. */
if (zeiger == 0)
{ //
if (zeichen_aus_fifo == KOMMANDO_APPS) // Fahre Anwendungsprogramme
telegrammlaenge = KOMMANDO_APPS_LEN; // mit und ohne Parameter
//...
if (zeichen_aus_fifo == KOMMANDO_NORM) // Servo Normposition
telegrammlaenge = KOMMANDO_NORM_LEN; // anfahren
//...
// Beispiel für korrekten Befehl
if (zeichen_aus_fifo == KOMMANDO_POSER) // Pn3250: n{1-9, j, z} Servo,
telegrammlaenge = KOMMANDO_POSER_LEN; // j=10, z alle Servos
//...
}
/* Und jetzt das geniale Ergebnis:
Wenn nun "zeiger" und "telegrammlaenge" gleich sind,
dann haben wir ein fertig empfangenes Kommando mit
seiner erwarteten Laenge. */
if (zeiger == telegrammlaenge)
{
//...
/* Die Funktionen koennen nun gemuetlich das
Telegramm auswerten. */
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Fahre verschiedene Anwendungsprogramme, je nach Nummer
if (mein_rx_buff [0] == KOMMANDO_APPS) // Tastatur-Eingabe "Annkkkk"
{ // Annkkkk
// nn =: 01..99 - Programm-Casenummer
// kkkk Parameter für Prog
// Dekodiere Programmkennziffer im Byte mein_rx_buff 1 und 2
for ( u8 i=0; i<=1; i++) { s[i] = mein_rx_buff [i + 1]; }
s[2] = 0; // Markiere Stringende "0"
nmbr = atoi ( s ); //
// - - - - - - - - - - - - - - -
// case
// 10 Augen rollen k mal (erstes "k")
// 11 Alle Lider auf, full speed
// 13 Alle Lider auf, SlowMo 50
//...
switch (nmbr) // Fahre gewählte Aktionen
{ //
case 10: // Augen rollen k-mal
s[0] = mein_rx_buff [3]; s[1] = 0; // Dekodiere 1stes k
npar1 = atoi ( s ); //
AuRoll ( npar1 , 100 ); // Augen rollen mit Standard-slow
for ( u8 i=1; i<=6; i++) {mein_rx_buff [i] = '9'; }
mein_rx_buff [7] = 0; // Hilft das bei unvollständiger Eingabe ?
break;
//...
default:
break;
} // Ende switch (nmbr)
} // Ende if (mein_rx_buff [0] == KOMMANDO_APPS)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Wurde "KOMMANDO_NORM" = "N" erkannt ? Normposition der Servos anfahren
if (mein_rx_buff [0] == KOMMANDO_NORM) // Tastatur-Eingabe "N"
{ //
uputs0 ("\r\tServonormposition,"); //
kal_0(); // Initialiswerte einstellen kal
uputs0 ("\tneue Servodaten :"); //
dat_aus (); // Servodaten ausgeben
} // Ende if (mein_rx_buff [0] == KOMMANDO_NORM)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//...
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Wurde "KOMMANDO_POSER" erkannt ? (PO sition SER vo stellen)
if (mein_rx_buff [0] == KOMMANDO_POSER) // Pa3250 ... a-j=ServoNr, z=alle
{ //
// Mal sehen, ob ALLE zehn Servos gemeint sind:
if ( (mein_rx_buff[1] == GRZ) || (mein_rx_buff[1] == klz) )
// Alle zehn Servos ??
{ // ja, alle zehn Servos auf Wert ansteuern
for ( u8 all = 1; all <= 10; all++ )
{ //
mein_rx_buff[1] = all; // Servonummer ist 1 .. 10
do_poser (mein_rx_buff); // Alle zehn Servos ansteuern
} // Ende von for ( u8 all = 1; all..
} // weiter mit else
else // NUR ein einziger Servo ist dran
{ // Dekodiere Servonummer
nsrv = mein_rx_buff[1] - '0';
if ( mein_rx_buff[1] == 'j' ) nsrv = 10;
if ( mein_rx_buff[1] == '0' ) nsrv = 10;
mein_rx_buff[1] = nsrv; //
do_poser (mein_rx_buff); // z.B.: 3250 : neuen Position rUn
} // ENDE if ( (mein_rx_buff[1] == GRZ) ||..
} // Ende if (mein_rx_buff [0] == KOMMANDO_POSER)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//...
// - - - - - - - - - - - - - - -
} // Ende if (zeiger == telegrammlaenge)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
} // Ende for (;;) ...
// - - - - - - - - - - - - - - -
return; // Ende von void u0st1 (void)
} //
// ============================================================================== =
(Hoffentlich sind diese Auszüge meines funktionierenden PC-Controller-Schriftwechsels nicht zuuu stark gekürzt und unverständlich . . . .)
So ist das gesendete Byte "D" eine Aufforderung, den aktuellen Zustand bestimmter Variablen über UART zu senden (DISPLAY), ein "N" stellt den NORMAL-Zustand (sozusagen Default- bzw. Startwerte) her. Um den Servo 10 (oder drei) auf die Position 3247 zu stellen funke ich eben:
für Servo 10: P03247
für Servo 03: P33247
für alle ......: Pz3247
Lesezeichen