www.mikrocontroller.net

Forum: Compiler & IDEs UART Datenstrom mit Array vergleichen


Autor: I. E. (anfaenger69)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich möchte den UART Datenstrom überwachen, und wenn bestimmte 7 Zeichen 
auf dem Bus vorkommen, dann soll etwas ausgelöst werden.

Ich habe es zunächst so versucht...

Ich habe einen 7 Byte großen Ringpuffer geschrieben, der jedes mal 
absucht, wenn ein neues Zeichen dazu gekommen ist, ob die 7 Zeichen 
überein stimmen:


void check_rx0_buffer(void)
{

unsigned int c;
  c = uart_getc();                      //hier kommt das nächste Byte an
  if ( c & UART_NO_DATA ){              //Peters Lib
        } else {
  rx0_buffer[6] = rx0_buffer[5];        //hier wird es in den Ringpuffer 
geschoben
  rx0_buffer[5] = rx0_buffer[4];
  rx0_buffer[4] = rx0_buffer[3];
  rx0_buffer[3] = rx0_buffer[2];
  rx0_buffer[2] = rx0_buffer[1];
  rx0_buffer[1] = rx0_buffer[0];
  rx0_buffer[0] = ((uint8_t)(c));
  mmi_rx0_string_analyze();
  }
}


void mmi_rx0_string_analyze (void)
{
  cmp_buffer[6] = 0x01;              // vergleichs-array zum test 
einfach mal fest definiert
  cmp_buffer[5] = 0x02;
  cmp_buffer[4] = 0x03;
  cmp_buffer[3] = 0x04;
  cmp_buffer[2] = 0x05;
  cmp_buffer[1] = 0x06;
  cmp_buffer[0] = 0x07;


  if(memcmp(rx0_buffer, cmp_buffer, 6))
  {
            //noch nicht die richtige Zeichenfolge erkannt
  }
  else
  {
            //die zeichen wurden erkannt
  }
}


Dieses funktioniert soweit auch, nur dauert die ganze Prozedur bei einem 
8MHz Atmega128 ganze 7ms (compiliert mit AVR-GCC). Das würde bedeuten, 
dass er nicht bei jeden ankommenden Byte eines 9600 Baud Datenstroms 
rechtzeitig fertig sein würde.

Das würde gerade noch ausreichen, weil ich habe ja noch den 
Empfangsbuffer von Peters Library, und der Datenstrom hat viele Pausen 
dazwischen, aber Euch Profis fällt bestimmt eine effektivere Methode 
ein?!? Es soll nämlich auch noch auf 10 verschiedene Zeichenketten 
überwacht werden, wo ich bestimmt auf 50-80ms kommen würde.

Nicht erschrecken, ich bin erst vor 2 Tagen von Assembler auf C 
umgestiegen, deshalb ist der Code noch sehr roh :c)

Autor: Mmmh (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
http://de.wikipedia.org/wiki/Warteschlange_%28Date...

Zu dem Problem einen String in einem anderen zu finden, wobei die 
Anfangsposition sich verändern kann, gucke mal in "Algorithmen in C" von 
Sedgkwick. Gibts, denke ich, auch online.

Autor: I. E. (anfaenger69)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe gerade einen Fehler entdeckt. Die durchgeführte Messung (7ms) 
stimmt nicht. Ich habe natürlich 7 Bytes auf dem UART Bus abgewartet, 
bis ich zu ende vergleichen habe.

Richtig ist:
Die Buffer Schieberei dauert 50µs und der Zeichenkettenvergleich dauert 
auch nochmal 55µs. Ist also alles im grünen bereich. Aber Euch fällt 
bestimmt eine schönere Vergleichvariante ein, oder?

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Zusätzlich zu den 7 gespeicherten Daten könnte man noch ein Byte
spendieren, in dem der XOR-Wert aller eingetragenen Zeichen
hinterlegt ist (Parity-Byte).
Dieses Parity-Byte muß nicht bei jedem neuen Zeichen aus allen
7 neu berechnet werden, sondern es genügt mit dem alten
hinausgeworfenen Zeichen wieder einen XOR-Wert zu bilden, um
es auszutragen, ebenso mit dem neuen hinzugekommenen, um
dieses einzutragen.

Ebenfalls bildet man den XOR-Wert der Vergleichsfolge.
Wenn ich das richtig verstehe, ändert die sich ja nicht, also
muß deren Parity-Wert nur einmal bestimmt werden.

Durch diesen Mehraufwand hat man jederzeit das Parity-Byte
der Vergleichsfolge und das Parity-Byte der 7 Zeichen
aus dem Datenstrom.

Der Vorteil: es reicht als Vortest, diese beiden zu vergleichen.
Erst wenn die beiden Parity-Bytes gleich sind (was nur selten
vorkommen wird, genau genommen in 1/256 aller Fälle), könnte
ein Treffer vorliegen, und man vergleicht dann die Zeichen Byte
für Byte.

Unterm Strich (vermute ich) geht das deutlich schneller.

Autor: I. E. (anfaenger69)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die Idee ist genial, somit vergleicht man bei jedem ankommenden Byte nur 
2 Bytes... Jedoch könnte sich da wirklich ein Fehler einschleichen, 
weil:

Mein Datenstrom sieht z.B. so aus:


0x35, 0x56, 0x23, 0x67, 0x50, 0x23, 0x77  oder auch
0x35, 0x56, 0x23, 0x67, 0x23, 0x50, 0x77

Wenn ich die ersten 5 Bytes schon erfolgreich durch habe kommt beim 6ten 
Byte bei beiden Zeichenketten der gleiche XOR Wert heraus. Beim testen 
des 7ten Bytes würde ich dann gar nicht mehr wissen welche Zeichenkette 
von beiden es war.

Aber Deine Idee bleibt in meiner Sammlung als mögliche Methoden :c)

Noch eine Idee?

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bei einem solchen Dreher, bei dem zufällig der gleiche
XOR-Wert aus beiden Folgen kommt, käme dann der Notausgang
zum Zug und es müssten (wie ich bereits erwähnte) dann doch
alle 7 Bytes verglichen werden.
(Natürlich kann ich nicht in einem Byte die vollständige
Information von 7 Byte halten, das wäre eine tolle Kompression.)

Nur wird das halt nicht sehr häufig sein (bei zufälligen Daten
in weniger als 0.5% der Fälle).

Autor: I. E. (anfaenger69)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke, Mmmh

Bei Deinem Link wird der Inhalt des Ringpuffers nicht verschoben, 
sondern mit IN und Out Pointern gearbeitet. Das würde das Abspeichern 
neuer Bytes etwas verkürzen, aber nicht das vergleichen.

Noch eine Idee?

Autor: I. E. (anfaenger69)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ahhh, verstehe... Am Schluss nochmal eine komplette Prüfung...

Danke, Klaus.

Kann man das Vergleichen vom Array irgendwie einzeilig lösen? z.B. so:?

if(memcmp(rx0_buffer, (0x35, 0x56, 0x23, 0x67, 0x50, 0x23, 0x77) , 6))

oder so:?

if(memcmp(rx0_buffer, "Test12" , 6))

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Den Ringpuffer ständig zu rotieren, ist natürlich Verschwendung.
Eine Schleife von i=0...6 und Zugriff auf das Feld über
rx0_buffer(i+aktuellerOffset)%7 wäre in der Tat viel effizienter.

Außerdem legst du im Moment bei jedem Vergleich das lokale Feld
cmp_buffer neu an. Tut das Not?

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
mach das Feld mit den Vergleichswerten doch einfach static, dann
wird es nur einmal bei Programmstart angelegt.

Autor: Mmmh (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Danke, Mmmh

>Bei Deinem Link wird der Inhalt des Ringpuffers nicht verschoben,
Genau so macht man das. NIEMAND verschiebt Bytes in einem Puffer.

>sondern mit IN und Out Pointern gearbeitet. Das würde das Abspeichern
>neuer Bytes etwas verkürzen, aber nicht das vergleichen.

>Noch eine Idee?

Nun, das abspeichern zu verkürzen wäre aus meiner Sicht schon ein 
Gewinn.

Und der andere Hinweis? Schon gelesen? Noch ein Stichwort dazu: 
Knuth-Morris-Pratt-Algorithmus

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mmmh schrieb:
> Knuth-Morris-Pratt-Algorithmus

Hm, das ist ziemlich viel Code und lohnt sich vielleicht eher
bei längeren Texten?

Autor: I. E. (anfaenger69)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Außerdem legst du im Moment bei jedem Vergleich das lokale Feld
>cmp_buffer neu an. Tut das Not?


Ich werde ja 10 verschiedene Zeichenketten vergleichen. Im Moment weiss 
ich mir nicht anders zu helfen, als die erste Zeichekette in den 
cmp_buffer zu legen, vergleichen, dann die zweite Zeichenkette in den 
cmp_buffer zu legen und wieder vergleichen usw.

Das ist hier bei dem Beispielcode noch nicht sichtbar. Deshalb aber auch 
meine Frage, ob man den Vergleich von 10 verschiedenen Zeichenketten 
einzeilig lösen kann.

z.B.

if(memcmp(rx0_buffer, (0x35, 0x56, 0x23, 0x67, 0x50, 0x23, 0x77) , 
6))...
if(memcmp(rx0_buffer, (0x35, 0x78, 0x23, 0x67, 0x23, 0x50, 0x77) , 
6))...
if(memcmp(rx0_buffer, (0x66, 0x56, 0x23, 0x55, 0x50, 0x23, 0x87) , 
6))...
if(memcmp(rx0_buffer, (0x65, 0x56, 0x33, 0x67, 0x50, 0x10, 0x05) , 
6))...
.
.
.

Autor: I. E. (anfaenger69)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>mach das Feld mit den Vergleichswerten doch einfach static, dann
>wird es nur einmal bei Programmstart angelegt.


Ja, ich habe die Puffer am Anfang deklariert:

unsigned char rx0_buffer[7];
unsigned char cmp_buffer[7];

Sie werden also nicht immer neu angelegt, sondern bei jedem Vergleich 
neu beschrieben.

>Knuth-Morris-Pratt-Algorithmus

Ja, in 6 Zeilen nur 6 Bytes zu verschieben ist schneller, als mit In und 
Out Pointern zu rechnen, das lohnt sich eher beim 128 Byte Puffer, wie 
in Peters Lib, aus der ich die Zeichen ja auch heraus hole.

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Erstens: das mit memcmp macht eh keinen Sinn, weil du dafür
deinen Ringpuffer ingesamt rotieren müsstest, und das
ist wie mehrfach gesagt Unfug.
Sinnvoller wäre es, den Vergleich selbst zu schreiben; dann
kann man mit %7 in den Puffer fassen.

Zweitens: mach doch einmal ein Feld mit allen deinen
Vergleichsmustern, und vergleiche mal mit dem einen und mal
mit dem anderen Feldelement (was dann jeweils ein Zeiger auf
die 7 Zeichen ist).

Autor: Mmmh (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Klaus Wachtler schrieb:
>> Knuth-Morris-Pratt-Algorithmus
>
> Hm, das ist ziemlich viel Code und lohnt sich vielleicht eher
> bei längeren Texten?

Möglicherweise passt der Algorithmus hier nicht so gut. Das ist mir halt 
bei der Problembeschreibung eingefallen. Danach ist die Position des 
Schlüsselwortes im Zeichenstrom nicht festgelegt und es gibt keine 
Synchronzeichen (irgendeine Art von Protokoll).
Die anderen Ideen hier gehen auch in die Richtung, das Ergebnis schon 
durchgeführter aber letztlich fehlgeschlagener (Teil-)Vergleiche zu 
speichern. Sowas in der Richtung habe ich intuitiv mit Knuth-Pratt 
verbunden.

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Es geht hier übrigens nicht um eine Warteschlange mit
variabler Länge, sondern immer um 7 Byte.

Deshalb brauchst du nicht getrennt In- und Out-Pointer,
es reicht ein Index.
Je nach Laune kann der das letzte eingetragene Zeichen
indizieren oder das nächste.

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
BTW: wieso werden bei deinem memcmp nur 6 Byte verglichen?

Autor: I. E. (anfaenger69)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke Klaus,

>dann kann man mit %7 in den Puffer fassen.
das mit %7 kenne ich noch nicht. Kannst Du mal ein paar Einzelheiten 
geben?


>mach doch einmal ein Feld mit allen deinen Vergleichsmustern
leuchtet ein, gute Idee. Das wird aber auch ein ganz schöner Code, nur 
für die 10*7 Bytes? Bei 100*7 Bytes wäre das bisher die effektivste 
Idee.

Autor: I. E. (anfaenger69)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>BTW: wieso werden bei deinem memcmp nur 6 Byte verglichen?

Weil ich nicht wusste, ob er von 0-6 oder von 1-7 zählt :c)  Array geht 
nur von 0-6, deklariert ist es mit rx0_buffer[7]. Beim benutzen des 
rx_buffer[7] hat mit der GCC jedoch einen Fehler ausgespukt, dass der 
Wert höher ist, als das definierte Array. Beim memcmp wollte ich erst 
einmal kein Risiko eingehen und hätte es später durch testen erkannt, ob 
er die 6 oder 7 braucht :c)
Nach Deinem Kommentar gehe ich mal von der 7 aus :c)

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
es gibt auch Doku zu memcmp().
Probieren ist natürlich auch ein Weg.

Warte mal. ich mache ein Beispiel...

Autor: I. E. (anfaenger69)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe gerade festgestellt, dass memcmp nicht alles vergleicht, 
sondern abbricht, wenn das erste Byte schon nicht stimmt. Somit 
vergleicht er eigentlich genau so schnell/effektiv, als das vergleichen 
des Arrays mit einem Pointer. Nur das herumschieben beim Emfang ist 
nicht schön. Aber mit 50µs kann ich voll leben.

Ich würde nur gerne den cmp_array schöner befüllen. Im Assember konnte 
ich die Zeichenketten einfach in eine db schreiben:

Zeichenkette 1:
.db 0x35, 0x56, 0x23, 0x67, 0x50, 0x23, 0x77)
Zeichenkette 2:
.db 0x35, 0x78, 0x23, 0x67, 0x23, 0x50, 0x77)
.
.


Um in C das memcmp damit zu füttern wäre ein zweidimensionales Array 
sinnvoll. Wie befülle ich das Array am schönsten mit diesen Werten?

Mir fällt nur das ein:
cmp_array[0][0] = 0x35;
cmp_array[0][1] = 0x56;
.
.
.

Da gibts doch bestimmt was schöneres oder?

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
So würde es ohne die XOR-Geschichte aussehen (inkl. kleinem
Testprogramm, 10 verschiedenen Tests und Ringpuffer ohne
verschieben):
#include <stdlib.h>
#include <stddef.h>
#include <stdio.h>
#include <string.h>


// nur zum Test: simuliert die Bytes von der UART:
static int     i = 0;
static char    simulationsdaten[] =
  {
    "hallo ich bin doof, aber gottseidank weiss ich es nicht, "
    "bin aber nicht der einzige."
    "Jedenfalls noch helle genug, um mein Geld ehrlich zu verdienen."
    "Noch muss ich nicht bei der FDP anheuern..."
  };
const int nSimulationsdaten = sizeof(simulationsdaten);

unsigned int uart_getc()
{

  return simulationsdaten[i++%nSimulationsdaten];
}
const int UART_NO_DATA = 0xff00;  // nie ein gültiges Zeichen, nur zum Testen



// Demo, wie ich mir das vorstelle:



// Der Index, wo im Ringpuffer das NÄCHSTE Zeichen abzulegen ist:
static int     ndx_RingpufferNext = 0;
static char    rx0_buffer[7] = { 0 };

// Die Vergleichsfolgen:
char          *cmp_buffer_arr[10] =
  {
    "\x35\x56\x23\x67\x50\x23\x77", // zum Testen 0 angehängt...
    "\x35\x78\x23\x67\x23\x50\x77", // zum Testen 0 angehängt...
    "\x66\x56\x23\x55\x50\x23\x87", // zum Testen 0 angehängt...
    "\x65\x56\x33\x67\x50\x10\x05", // zum Testen 0 angehängt...
    "Jedenfa",
    "nheuern",
    "einzige",
    "ich bin",
    "es nich",
    "Noch mu",
  };



// vergleicht 7 Zeichen aus rx0_buffer (ab Position
// (ndx_RingpufferNext+1) modulo 7) mit den 7 Zeichen ab cmp_buffer
// und liefert 0, wenn nicht gleich bzw. 1, wenn gleich:
int mmi_rx0_string_analyze ( const char *cmp_buffer )
{
  int iZeichen;
  for( iZeichen=0; iZeichen<7; ++iZeichen )
  {
    if( rx0_buffer[(ndx_RingpufferNext+iZeichen)%7]!=cmp_buffer[iZeichen] )
    {
      return 0;
    }
  }
  return 1;
}



void check_rx0_buffer()
{
  unsigned int c;
  c = uart_getc();                      //hier kommt das nächste Byte an
  if ( c & UART_NO_DATA )
  {                                     //Peters Lib
  }
  else
  {
    int iVergleich;
    rx0_buffer[ndx_RingpufferNext++] = c; // c eintragen,
                                          // ndx_RingpufferNext weiter setzen
    ndx_RingpufferNext %= 7;              // ndx_RingpufferNext auf
                                          // 0...6 begrenzen

    for( iVergleich=0; iVergleich<10; ++iVergleich )
    {
      if( mmi_rx0_string_analyze( cmp_buffer_arr[iVergleich] ) )
      {
        printf( "Text %s gefunden\n", cmp_buffer_arr[iVergleich] );
      }
    }
  }
}



int main( int nargs, char **args )
{
  int iGelesen;
  for( iGelesen=0; iGelesen<nSimulationsdaten; ++iGelesen )
  {
    check_rx0_buffer();
  }
  return 0;
}

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das %7 berechnet aus einem Wert dessen Divisionsrest beim Teilen
durch 7. D.h. der Wert in den Bereich 0 bis 6 verschoben und
der Index bleibt dadurch immer im Feld; anstatt hinten
rauszulaufen fängt man wieder vorne an.

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der Vollständigkeit halber hier noch die Variante mit XOR
(läuft auf meinem PC unter Linux mit gcc ohne Optimierung
um Faktor 3 schneller):
#include <stdlib.h>
#include <stddef.h>
#include <stdio.h>
#include <string.h>

#define   PARITY_BESCHLEUNIGUNG


// nur zum Test: simuliert die Bytes von der UART:
static int     i = 0;
static char    simulationsdaten[] =
  {
    "hallo ich bin doof, aber gottseidank weiss ich es nicht, "
    "bin aber nicht der einzige."
    "Jedenfalls noch helle genug, um mein Geld ehrlich zu verdienen."
    "Noch muss ich nicht bei der FDP anheuern..."
  };
const int nSimulationsdaten = sizeof(simulationsdaten);

unsigned int uart_getc()
{

  return simulationsdaten[i++%nSimulationsdaten];
}
const int UART_NO_DATA = 0xff00;  // nie ein gültiges Zeichen, nur zum Testen



// Demo, wie ich mir das vorstelle:



// Der Index, wo im Ringpuffer das NÄCHSTE Zeichen abzulegen ist:
static int     ndx_RingpufferNext = 0;
static char    rx0_buffer[7] = { 0 };

#ifdef  PARITY_BESCHLEUNIGUNG
// Parity-Byte des Ringpuffers:
static char    parity_rx0_buffer = 0;
#endif


// Die Vergleichsfolgen:
char          *cmp_buffer_arr[10] =
  {
    "\x35\x56\x23\x67\x50\x23\x77", // zum Testen 0 angehängt...
    "\x35\x78\x23\x67\x23\x50\x77", // zum Testen 0 angehängt...
    "\x66\x56\x23\x55\x50\x23\x87", // zum Testen 0 angehängt...
    "\x65\x56\x33\x67\x50\x10\x05", // zum Testen 0 angehängt...
    "Jedenfa",
    "nheuern",
    "einzige",
    "ich bin",
    "es nich",
    "Noch mu",
  };

#ifdef  PARITY_BESCHLEUNIGUNG
// Parity-Bytes der Vergleichsfolgen:
static char    parity_cmp_buffer_arr[10];
#endif


// vergleicht 7 Zeichen aus rx0_buffer (ab Position
// (ndx_RingpufferNext+1) modulo 7) mit den 7 Zeichen ab cmp_buffer
// und liefert 0, wenn nicht gleich bzw. 1, wenn gleich:
int mmi_rx0_string_analyze ( const char *cmp_buffer )
{
  int iZeichen;
  for( iZeichen=0; iZeichen<7; ++iZeichen )
  {
    if( rx0_buffer[(ndx_RingpufferNext+iZeichen)%7]!=cmp_buffer[iZeichen] )
    {
      return 0;
    }
  }
  return 1;
}



void check_rx0_buffer()
{
  unsigned int c;
  c = uart_getc();                      //hier kommt das nächste Byte an
  if ( c & UART_NO_DATA )
  {                                     //Peters Lib
  }
  else
  {
    int iVergleich;
#ifdef  PARITY_BESCHLEUNIGUNG
    // alten Wert austragen:
    parity_rx0_buffer ^= rx0_buffer[ndx_RingpufferNext];
#endif
    rx0_buffer[ndx_RingpufferNext++] = c; // c eintragen,
                                          // ndx_RingpufferNext weiter
                                          // setzen
    ndx_RingpufferNext %= 7;              // ndx_RingpufferNext auf
                                          // 0...6 begrenzen
#ifdef  PARITY_BESCHLEUNIGUNG
    // neuen Wert eintragen:
    parity_rx0_buffer ^= c;
#endif

    for( iVergleich=0; iVergleich<10; ++iVergleich )
    {
      if(
#ifdef  PARITY_BESCHLEUNIGUNG
          parity_rx0_buffer==parity_cmp_buffer_arr[iVergleich]
          &&
#endif
          mmi_rx0_string_analyze( cmp_buffer_arr[iVergleich] )
          )
      {
        //printf( "Text %s gefunden\n", cmp_buffer_arr[iVergleich] );
      }
    }
  }
}



int main( int nargs, char **args )
{
  int iGelesen;

#ifdef  PARITY_BESCHLEUNIGUNG
  // einmalig die Parity-Bytes der Vergleichsstrings intialisieren:
  int iVergleich;
  for( iVergleich=0; iVergleich<10; ++iVergleich )
  {
    int iByte;
    for( iByte=0; iByte<7; ++iByte )
    {
      parity_cmp_buffer_arr[iVergleich] ^= cmp_buffer_arr[iVergleich][iByte];
    }
  }
#endif

  size_t  i;
  for( i=0; i<500000; ++i )
  {
    for( iGelesen=0; iGelesen<nSimulationsdaten; ++iGelesen )
    {
      check_rx0_buffer();
    }
  }
  return 0;
}

Autor: I. E. (anfaenger69)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wow, danke, Klaus.

Das mit %7 ist eine geniale Funktion. Ich bereue es jetzt schon auf 
keinen Fall von Assembler auf C umgestiegen zu sein. Mit jeder Funktion, 
die man dazu lernt, eröffnen sich neue Welten :c)



>char          *cmp_buffer_arr[10] =
>  {
>    "\x35\x56\x23\x67\x50\x23\x77", // zum Testen 0 angehängt...
>    "\x35\x78\x23\x67\x23\x50\x77", // zum Testen 0 angehängt...
>    "\x66\x56\x23\x55\x50\x23\x87", // zum Testen 0 angehängt...
>    "\x65\x56\x33\x67\x50\x10\x05", // zum Testen 0 angehängt...
>    "Jedenfa",
>    "nheuern",
>    "einzige",
>    "ich bin",
>    "es nich",
>    "Noch mu",
>  };
>

Genau das brauche ich. Danke dafür. Was bedeutet eigentlich dieser Stern 
(*) vor dem cmp_buffer_arr[10] ?


ich werde mir jetzt mal die Arbeit machen und schauen welche 
Vergleichsmethode schneller ist :c)

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Igor Ebner schrieb:
> Genau das brauche ich. Danke dafür. Was bedeutet eigentlich dieser Stern
> (*) vor dem cmp_buffer_arr[10] ?

weil cmp_buffer_arr ein Feld von 10 Zeigern auf char ist.
Jeder dieser Zeiger zeigt dann auf den Anfang eines der Teilfelder.

>
>
> ich werde mir jetzt mal die Arbeit machen und schauen welche
> Vergleichsmethode schneller ist :c)


Meine natürlich, weiß ich vorher :-)

Autor: I. E. (anfaenger69)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
So, als erstes mal Dein Messergebnis vom ersten code ohne XOR:

Das schieben in den Ringpuffer per %7 dauerte bei jedem ankomenden Byte 
100µs.
Das Auswerten dauerte dann 400µs.

Wenn ich meine Methode verwende und die Bytes im ir_buffer herum 
schiebe, dauert die Herumschieberei inkl laden des 7.ten Bytes 40µs. Und 
das Auswerten per memcmp nochmal 100µs.

Ich denke bei so wenig Zeichen macht die dumme Methode weniger 
Rechenaufwand. Deine Methode würde sich - rein theoretisch und 
rechnerisch, ab ca 20 Zeichen lohnen. Die XOR Methode habe ich nicht 
mehr ausprobiert, aber die wird vermutlich an 40/100µs nicht ran kommen 
:c)


Trotzdem vielen Dank an Dich, dass Du dir so viel Mühe gemacht hast. Du 
hast mir mehrere tolle Sachen beigebracht...

%7
XOR compression und
*cmp_buffer_arr

...und ich werde Dich heute in mein Nachtgebet mit Aufnehmen :c)

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
oh Gott, ich bin streng gläubiger Atheist!

Autor: I. E. (anfaenger69)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich auch,

da bekommt die Aussage Dich ins Gebet mit aufzunehmen eine ganz neue 
Bedeutung :c)

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
In der Tat.

Um nicht zu sagen, das mit dem Gebet war doch irgendwie gelogen :-)

Autor: Thomas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Eine Alternative bei einer/wenigen festen Vergleichszeichenkette(n) 
wäre, den Zeichenstrom in einen Zustandsautomaten zu leiten, in diesem 
Fall ist das  wegen des enormen Schreibaufwandes natürlich fehl am Platz 
und ca. halb so schnell. (allerdings auf meinem PC mit -O3 um ca. 1% 
schneller ;) )
void CheckForHELLO(uint8_t ch)
{
    static uint8_t CharactersOK = 0;
    switch (CharactersOK)
    {
    case 0:
        if (ch == 'H')
            CharactersOK = 1;
        else
            CharactersOK = 0;
        break;
    case 1:
        if (ch == 'E')
            CharactersOK = 2;
        else
            CharactersOK = 0;
        break;
    case 2:
        if (ch == 'L')
            CharactersOK = 3;
        else
            CharactersOK = 0;
        break;
    case 3:
        if (ch == 'L')
            CharactersOK = 4;
        else
            CharactersOK = 0;
        break;
    case 4:
        if (ch == 'O')
            DoSomething();
        CharactersOK = 0;
        break;
    }
}

Autor: I. E. (anfaenger69)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hört er dann nicht auf, wenn der erste Buchstabe getestet wurde? Wie 
kommt er zu den weiteren cases?

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die Idee dieses Konstrukts ist es, dass nicht erst gewartet wird, bis 
der String komplett empfangen wurde, sondern jedes Zeichen, sobald es 
empfangen wurde, in dieses Konstrukt eingeleitet wird. Und so handelt 
sich dieses Konstrukt von einem case zum nächsten (bei jeweils dem 
nächsten Funktionsaufruf mit dem jeweils gültigen Zeichen).

Autor: I. E. (anfaenger69)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ahhhh, verstehe... :c)
Wenn man jedoch 10 verschiedene Zeichenketten zum überwachen hat, dann 
ist der Aufwand aber nicht mehr geringer, als mit einem Rollpuffer...

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.