Forum: Mikrocontroller und Digitale Elektronik Diese "ollen" Pointer...


von Tobias H. (Gast)


Lesenswert?

Hi

Ich komme mit den "ollen" Pointern nicht ganz klar...

Immer wieder bekomme ich sowas, wie:

warning: assignment makes integer from pointer without a cast
oder
passing argument 2 of 'strcpy' discards qualifiers from pointer target 
type

und ähnliches. Das Kapitel Pointer ist mir denke ich zumindestens 
einigermaßen klar.

Wenn ich eine Variable (z.B.) Integer habe, dann bekomm ich da schnell 
einen Pointer draus:
char a;
char *b;
b=&a;
und schon hab ich die Variable a als Pointer b.#
Sooo, aber seit Tagen schlag ich mich mit den oben genannten 
Fehlermeldungen rum wo ich einen Pointer habe, aber eine Variable 
brauche. Ich wurtschtel mir dann meine Routinen zu Recht, dass gar keine 
Pointer entstehen, aber nun komm ich nicht mehr weiter und würds auch 
gern wissen.

Meine Pointer sind meistens Pointer auf Arrays/Strings.

Kann mir jemand helfen? Versteht man überhaupt, was ich vorhab? :-)

Ciao Tobias

von Sven DerSchreckliche (Gast)


Lesenswert?

Um ehrlich zu sein: so ganz versteh ichs nicht.
Kannst Du nicht mal die drei oder 4 Zeilen bringen, wo diese Meldung 
auftritt?

von A.K. (Gast)


Lesenswert?

"Das Kapitel Pointer ist mir denke ich zumindestens
einigermaßen klar."

Der Compiler ist da offensichtlich andere Ansicht. Und ohne Code ist das 
nicht klärbar.

von Heinz Blättner (Gast)


Lesenswert?

> Ich komme mit den "ollen" Pointern nicht ganz klar...
Kommt vor. :-)

> und ähnliches. Das Kapitel Pointer ist mir denke ich zumindestens
> einigermaßen klar.
sicher ?

> Sooo, aber seit Tagen schlag ich mich mit den oben genannten
> Fehlermeldungen rum wo ich einen Pointer habe, aber eine Variable
> brauche.
Daszu benutzt man den '*' zum dereferenzieren.

> Ich wurtschtel mir dann meine Routinen zu Recht, dass gar keine
> Pointer entstehen, aber nun komm ich nicht mehr weiter und würds auch
> gern wissen.
>
> Meine Pointer sind meistens Pointer auf Arrays/Strings.
>
> Kann mir jemand helfen?
Ich versuchs.
> Versteht man überhaupt, was ich vorhab? :-)
Im Moment noch nicht.

Um hier zu helfen braucht man mindestens das code schnipsel
dh.
- variablen declaration
- die function die der compiler nicht mag

br   heinz

von Tobias H. (Gast)


Lesenswert?

>> und ähnliches. Das Kapitel Pointer ist mir denke ich zumindestens
>> einigermaßen klar.
>sicher ?
Also ich denke, ich weiß, was Pointer sind und wie sie arbeiten. Danach 
ist allerdings schluss und deswegen lande ich hier :-)

Denn mal ein paar Codeschnipsel, wo ich unter anderem Hänge

//Beginn U(S)ART Routinen:
//Definition allgemeingültiger Variablen des U(S)ART
volatile char *puffer1;
volatile char *puffer2;
volatile unsigned char pufferauswahl;
volatile unsigned char pufferstelle;

[...]

ISR(USART_RXC_vect)
//Wenn ein Byte fertig empfangen ist, wird diese Routine ausgeführt, die 
die Daten puffern, damit sie nicht verloren gehen können
{
  if (pufferauswahl==0) pufferauswahl=1;
  if (pufferstelle==0) pufferstelle=1;
  if (pufferauswahl==1)
  {
    puffer1[pufferstelle]=uart_empfangen();
    if (puffer1[pufferstelle]==10)
    {
      pufferauswahl=2;
      pufferstelle=0;
    }
    pufferstelle++;
  }
  if (pufferauswahl==2)
  {
    puffer2[pufferstelle]=uart_empfangen();
    if (puffer2[pufferstelle]==10)
    {
      pufferauswahl=1;
      pufferstelle=0;
    }
    pufferstelle++;
  }
}

So weit geht noch alles. Wobei mir gerade auffällt, dass ich auf die 
Pointer wie auf Arrays zugreife (Eigentlich ja flasch) - stammt 
eigentlich noch aus einer alten Routine. Komischerweise geht sie aber, 
die Routine. Hab schon Daten damit empfangen können :-)

Dann kommt:

char temp[16];
strcpy(temp,puffer1);
messwert=atol(temp);
lcd_loeschen(2);
utoa(messwert,ausgabetext,10);
lcd_ausgabe(2,ausgabetext);

Die Hin- und Herwandlung hier aus Testgründen und weil viele Leerzeichen 
im Puffer sein dürften.

An der Stelle klappt z.B. das strcpy nicht:
:434: warning: passing argument 2 of 'strcpy' discards qualifiers from 
pointer target type

mache ich daraus
strcpy(temp,*puffer1);
bekomme ich:
434: warning: passing argument 2 of 'strcpy' makes pointer from integer 
without a cast

hmm... Da liegt z.B. das Problem

Will ich puffer1 direkt ans LCD geben:
lcd_ausgabe(2,*puffer1);
bekomme ich die gleichen Meldungen. Ohne Stern die erste, mit Stern die 
zweite Meldung.
Dabei sieht die lcd-Routine so aus:
void lcd_ausgabe(unsigned char zeile,const char *text)
[...]

Jetzt eher zu verstehen, was ich meine?

Ciao Tobias

von A.K. (Gast)


Lesenswert?

  volatile char *puffer1;
  volatile char *puffer2;
macht nicht den Puffer "volatile" sondern den Zeiger darauf. Was sicher 
nicht beabsichtigt, aber Grund für die Meldungen ist.

Und
  strcpy(temp,*puffer1);
will nun einmal partout einen Zeiger als zweiten Parameter, und kein 
einzelnes Zeichen.

von A.K. (Gast)


Lesenswert?

"  volatile char *puffer1;
   volatile char *puffer2;
macht nicht den Puffer "volatile" sondern den Zeiger darauf"

Sorry, dieser Teil war Blödsinn.

Allerdings liefert der Compiler Fehler, wenn er strcpy() einen 
"volatile" Pointer als Parameter vorsetzen soll. Denn strcpy() ist ohne 
"volatile" deklariert. Und so meldet der Compiler, dass der Qualifier 
"volatile" nicht passt.

von Tobias H. (Gast)


Lesenswert?

hmm ok! Ich darf also strcpy keinen volatile Pointer vorsetzen. Nur wenn 
ich  versuche, einen nicht volatile Pointer auf ein volatile array zu 
setzen, bekomme ich das gleiche Problem:

433: warning: assignment discards qualifiers from pointer target type

Also Codemäßig sieht das so aus:

volatile char puffer1[16]; //jetzt Arrays statt Pointer
volatile char puffer2[16];
volatile unsigned char pufferauswahl;
volatile unsigned char pufferstelle;

Die ISR-Routine bleibt gleich.

Im int main(void) Teil dann:
char *puffptr1;
char *puffptr2;
puffptr1=&puffer1[0];
puffptr2=&puffer2[0];

strcpy(temp,puffptr1);

strcpy meckert nicht mehr, puffptr1=&puffer1[0]; dafür jetzt mit der 
oben genannten Fehlermeldung. Setz ich wieder
char *puffptr1;
auf volatile char *puffptr1;, meckert wieder strcpy mit der o.g. 
Fehlermeldung.

Ciao Tobias

von A.K. (Gast)


Lesenswert?

Ob
 volatile char *puffer1
oder
 volatile char puffer1[];
ist was Datentypen und Qualifiers angeht das gleiche. Lass das 
"volatile" weg (nur fast sauber, aber akzeptabel) oder caste es explizit 
weg
 strcpy (..., (char *)puffer1);

Gleiches Problem bei:
 puffptr1=&puffer1[0];
links ohne recht mit "volatile".

Merke
 volatile char *
und
 char *
sind 2 verschiedene Datentypen und nur ein eine Richtung 
zuweisungskompatibel. Nämlich andersrum.

von Tobias H. (Gast)


Lesenswert?

>Merke
> volatile char *
>und
> char *
>sind 2 verschiedene Datentypen und nur ein eine Richtung
>zuweisungskompatibel. Nämlich andersrum.

OK, was gelernt!

volatile weglassen fällt hier doch laut Tutorial flach, da ich puffer1 
und puffer2 in einer Interrupt-Routine verwende, oder?

Und
strcpy(temp,(char *)puffer1);
messwert=atol(temp);
lcd_loeschen(2);
utoa(messwert,ausgabetext,10);
lcd_ausgabe(2,ausgabetext);

geht zwar dank des Castes ohne Compilerfehler, aber auf meinem Display 
seh ich auch nix.

Ciao Tobias

von Sven DerSchreckliche (Gast)


Lesenswert?

Volatile sind ansich nicht immer nötig. Wenn Dein Prozessor mit einem 
einzigen Assembler-Befehl die Variable holen kann, kann in den meisten 
Fällen nichts passieren.
Wenn die Variable ausserhalb der ISR verändert werden soll, kann man 
auch einfach die Interrupts vorher ausschalten, die Variable ändern und 
dann die Interrupts wieder einschalten.

von Heinz Blättner (Gast)


Lesenswert?

Hmm
die Antworten von Tobias haben Dir ja schon ein wenig geholfen.
Wenn ich Dein Problem richtig verstanden habe is es wie folgt:
- Zeichen werden über die serielle interruptgesteuert eingelesen.
- Das Hauptprogram gibt dann die Zahl auf dem Display aus.
  (die Zahl kommt in ascii und ist mit LF (0x10) terminiert.

Das ganze hast Du realisiert:
- mit 2 Wechselbuffer
- umschalten der buffer beim erkennen der EOL kennung (00x10)
##########
Kommentar:
1. Das mit den wechselbuffern is prinzip ne gute sache.
Ein paar Sachen hast Du dabei aber nicht oder nicht richtig verstanden.
Die Wechselbuffer sind dazu da das sich derjenige der den buffer gerade 
beschreibt (ISR) und derjenige der liest (main) sich nicht ins gehege 
kommen.

2. Das volatile für die buffer ist überflüssig
 (erzeugt auch nicht optimierten code weil Du den compiler damit
  dies nicht erlaubst.)
Überflüssig deshalb weil ja die ISR exclusiv NUR in den einen buffer 
schreibt
und wenn sie fertig ist dann auf den anderen buffer wechselt.

3. Das einzige was hier volatile sein muss ist die variable die den 
zugriff auf die verschiedenen buffer regelt.

4. Was sich hier noch als problematisch zeigen könnte das es hier keinen
  indikator gibt wann ein buffer voll ist bzw wann er wieder leer ist.
  z.b. die ISR schreibt buf1 voll switched auf buf2 und dann wieder auf
  buf1.
5. Was passiert wenn die Daten schneller kommen als sie aufs display
  rausgehn?
6. In welchem buffer liest main eigentlich aus?
7. Wann wechselt es den buffer?
8. Woher kennt main den zeitpunkt wann die daten gültig sind?
9. Wer verhindert den sauberen bufferüberlauf wenn mehr zeichen kommen?

######################
Vorschlag:
Das erste Zeichen im buffer wird dazu benutzt anzuzeigen das daten im 
buffer sind.
Code dann ungefährt so wie unten.

// global data
char buf0[18];
char buf1[18];
char *buffers[2] = { &buf0, &buf1 };
char *pWbuf;      // ptr zu buf den ISR gerade beschreibt
#define BUFSIZE   (sizeof(buf0) - 1)  // fuer \0 sollte platz bleiben
//---------------
ISR(USART_RXC_vect)
{
   static char wbuf = 0; // toggled 0-1-0-1 ... ACCESS only ISR
   static char *phWbuf;  // ptr in buf wo naechstes char in buf hinkommt
   char c;
   char full = 0;

   c = uart_empfangen();
   if( pWbuf != 0 ) { // buffer not yet read so far
      return;
     // d.h. es wird nix mehr eingelesen solange main nicht ausgegeben 
hat.
     // aktuelles zeichen wird verworfen
     // problem wieder richtig zu syncen nicht beruecksichtigt
   }
   if( 0x20 == c ) { // do not store SPACE in buffer
      return;
   }

   phWbuf = c;     // store char in curr buf
   phWbuf++;       // set ptr to next char
   // POST processing here
   if(0x10 == c) { // EOL
      full = 1;
   } // schutz vor buffer overflow !!!
   else if( (phWbuf - pWbuf) >= (BUFSIZE-1) ) { // platz fuer 0x10
       full = 1;    // kein ende in sicht aber buf voll also weg damit
   }

   if (full) {      // nu ist er voll wech damit
      *pWbuf = 1;   // buf status flag == FULL oder auch pWbuf[0] = 1;
      wbuf    = (wbuf + 1) & 0x01;  // toggle buffer
      pWbuf  = buffers[buf];        // grab base addr
      phWbuf = pWbuf + 1;           // set ptr to first char
      pWbuf  = 0;                   // set bug statusflag == empty
   }
}
//----------------
int main()
{
  char rbuf = 0;        // toggled 0-1-0-1 ... ACCESS only MAIN
  char *pRbuf;          // ptr wo naechster string/CMD erwartet wird.
  volatile char *pvBuf; // dito nur volatile zum pollen von buf status 
flag

   // INIT here RECEIVER must disabled
   buf0[0] = 0;  // buf status flag == empty
   buf1[0] = 0;  // dito
   buf     = 0;  // choose buf0
   phWbuf  = &buf0[1];  // ab hier werden die daten geschrieben
   pWbuf   = &buf0[0];  // ptr zeigt auf buf status flag
   pRbuf   = &buf0[0];  // dito

   // init and enable RECEIVER here
   for(;;)  // endless loop
     pvBuf    = (volatile char *)pRbuf;    // poll only buf status flag
     while(0 == *pvBuf ){ // wait for buf status flag ready
        lcd_loeschen(2);              // cast um warning los zu werden
        lcd_ausgabe(2, (const char*) (&pRbuf[1]) );
        // buffer processing now finished => set buf status flag == 
empty
        pRbuf  = 0;
     }
     // now switch to next buffer
     rbuf    = (rbuf + 1) & 0x01;  // toggle buffer
     pRbuf  = buffers[rbuf];       // grab base addr
   }
}

### wie Du siehst muss hier nur innerhalb von main ein volatile benutzt 
werden da sonst die while scheife nur einmal liest und es dann sein 
laest.
Eigentlich muesste nur das buf status flag volatile sein. :-)
Das ganze schaut nun so aus:
Die ISR beschreibt den buffer nur wenn das buf status flag ==0 ist.
main liest den buffer nur wenn buf status flag ==1 ist.
main setzt nach der ausgabe das bust status flag zurück auf 0 damit kann 
der buffer wieder von der ISR beschrieben werden.
### Aktueller sschwachpunkte:
- IST überschreibt zwar buffer nicht mahr aber es gehen zeichen 
verloren.
  es wird dann bei dieser zeichenfolge wohl das eine oder andere zeichen
  fehlen. Also kommt quatsch raus.
  mögliche lösung wäre das die ISR sich ein flag setzt und alle zeichen
  bis zum nächsten 0x10 wegwirft und damit wieder synchron ist.
  für main könnte sie eine variable incrementieren um overflow zu
  signalisieren.
ERGO:
  wenn man daten schneller bekommt als man sie verarbeiten kann muss man
  immer einen tot sterben. Die Entscheidung liegt bei dir . :-)

Ich habe das mal schnell hingetippt ein paar tipfehler werden sicher 
noch drin sein aber im prinzip wäre das eine mögliche lösung.


BR  heinz

von Heinz Blättner (Gast)


Lesenswert?

Hi an Sven den Schrecklichen.

> Volatile sind ansich nicht immer nötig.
stimmt

> Wenn Dein Prozessor mit einem einzigen Assembler-Befehl die Variable
> holen kann, kann in den meisten Fällen nichts passieren.
Du verwechstelst hier volatile mit sperren der interrupts
volatile hindert den compiler davon zugriffe auf die variablen 
wegzuoptimieren

die interrupts musst du sperren um atomic access auf die variablen zu 
bekommen vor allem wenn man mehrere ASM statments dazu braucht.

> Wenn die Variable ausserhalb der ISR verändert werden soll,
> kann man auch einfach die Interrupts vorher ausschalten,
> die Variable ändern und dann die Interrupts wieder einschalten.
siehe oben
das hilft dir aber nicht wenn der compiler deine zugriffe wegoptimiert.


BEISPIEL: das pollen auf eine status flag variable die in der ISR 
verändert wird
ohne volatile wird aus
   while(flag) {
     ; // wait for flag
   }
dercompiler optimiert das dann so
   if(flag){
     ; // wenn schleife leer ist lässt er auch das if noch weg
   }
da hilft auch ein interrupt sperren nix mehr :-(

BR   heinz

von Tobias H. (Gast)


Lesenswert?

Hi

Danke für eure beiden Beiträge. Ich bin zur Zeit nicht zu Hause, um das 
auszuprobieren, werde das aber nachher machen und mich hier melden.

>1. Das mit den wechselbuffern is prinzip ne gute sache.
>Ein paar Sachen hast Du dabei aber nicht oder nicht richtig verstanden.
>Die Wechselbuffer sind dazu da das sich derjenige der den buffer gerade
>beschreibt (ISR) und derjenige der liest (main) sich nicht ins gehege
>kommen.

Also, der Wechselbuffer ist dafür da, dass ich immer einen vollständigen 
Wert habe und einen, wo die Übertragung läuft. So dass ich keinen Wert 
habe, an dem noch geschrieben wird.

An der Erkennung, ob ein Wert neu ist, muss ich noch arbeiten - ein Teil 
meines Projektes wird nämlich noch sein, dass man den zeitlichen Abstand 
zwischen zwei Messwerten bekommt. Dafür ist die Frage, ob ein Wert neu 
ist, natürlich Grundlage. Steht noch auf der "TODO"-Liste :-)

>Was sich hier noch als problematisch zeigen könnte das es hier keinen
>indikator gibt wann ein buffer voll ist bzw wann er wieder leer ist.
>z.b. die ISR schreibt buf1 voll switched auf buf2 und dann wieder auf
>buf1.

Die Daten, die ich empfange, kommen quasi in einer ganz bestimmten 
Abfolge. Es kommt:
-Messwert mit 2-6 Stellen
-Dezimalpunkt (eigentlich überflüssig, lässt sich aber nicht abschalten)
-CR (13)
-LF (10)
-einige Leerzeichen (Anzahl gilt es noch herauszufinden)

Insgesamt kommen Erfahrungsgemäß maximal 17 Zeichen + Stringendezeichen 
macht einen Puffer mit 18 Stellen.
Die unerwünschten Zeichen wollte ich eigentlich gleich noch rausfiltern 
- irgendwas hab ich da aber auch noch falsch, bei der Abfrage macht der 
AVR immer einen Reset... Später dazu mehr!

>Was passiert wenn die Daten schneller kommen als sie aufs display
>rausgehn?

Das Display ist langsam, das stimmt. Allerdings sind die Daten zur Zeit 
nur zu Testzwecken auf dem Display zu sehen. Später werden sie nur noch 
intern verwaltet und im Notfall einzelne Messwerte auf dem Display 
ausgegeben -> Nur noch Warnfunktion. Daher sollte der AVR dann mit der 
Berechnung eigentlich nachkommen. Ansonsten kommen die Messwerte über 
die serielle Schnittstelle laufend weiter, daher wenn ein Messwert 
verworfen wird, kommt bald der nächste und es ist nicht so schlimm.

Außerdem kann ich in meinem Sensor einen Parameter ändern, der sich auf 
die Messgeschwindigkeit auswirkt. (Der Sensor misst erst mehrfach und 
schickt den Mittelwert über die serielle Schnittstelle) Damit kann ich 
also auch die Übertragungsgeschwindigkeit regulieren. Im langsamsten 
Fall kommt ca. 1 Messwert por Sekunde, im schnellsten Fall kommen ca. 
1024 Messwerte pro Sekunde.

>In welchem buffer liest main eigentlich aus?

Immer der, auf den die Pufferauswahl gerade NICHT verweist.

>Wann wechselt es den buffer?

Der Schreiber wechselt bei einem LF (10), der Leser, wenn sich die 
Pufferauswahl geändert hat.

>Woher kennt main den zeitpunkt wann die daten gültig sind?

Der Puffer wird erst bei einem LF gewechselt. Erst nach einem Wechsel 
greift main darauf zu. Da nach einem LF die Daten komplett sind, weiß 
main bei einem Pufferwechsel, dass die Daten gültig sind.

>Wer verhindert den sauberen bufferüberlauf wenn mehr zeichen kommen?

Keiner :-) Ich vertraue auf den Sensor, der immer maximal 17 Zeichen 
sendet bis zu einem neuen LF, wo der Puffer gewechselt wird.
Kann ich überhaupt einen Puffer zum Überlaufen bekommen, wenn dieser 
keine definierte Länge hat? Ein Array kann überlaufen, aber kann ein 
Pointer überlaufen?

>ISR überschreibt zwar buffer nicht mahr aber es gehen zeichen
>verloren.
>  es wird dann bei dieser zeichenfolge wohl das eine oder andere zeichen
>  fehlen. Also kommt quatsch raus.
>  mögliche lösung wäre das die ISR sich ein flag setzt und alle zeichen
>  bis zum nächsten 0x10 wegwirft und damit wieder synchron ist.
>  für main könnte sie eine variable incrementieren um overflow zu
>  signalisieren.
>ERGO:
>  wenn man daten schneller bekommt als man sie verarbeiten kann muss man
>  immer einen tot sterben. Die Entscheidung liegt bei dir . :-)

Entweder ein alter Messwert geht durch überschreiben des Puffers 
verloren, oder ein neuer durch Nichtauslesen der Schnittstelle.
Ich versuche, meine Programmierung am Ende so zu optimieren, dass der 
AVR mit der Verarbeitung der Sensordaten in jedem Fall hinterherkommt. 
Ansonsten kann ich hier nur sagen: Pech gehabt - was weg ist, ist weg! 
:-)

So, und jetzt noch zu dem "später mehr" von oben:
>Die unerwünschten Zeichen wollte ich eigentlich gleich noch rausfiltern - 
>irgendwas hab ich da aber auch noch falsch, bei der Abfrage macht der AVR >immer 
einen Reset
... habe ich oben geschrieben. Ich habe jetzt den Quellcode nicht zur 
Hand, aber ich denke, ich kann es einigermaßen nachprogrammieren oder 
beschreiben.

Also, die ISR-Routine steht oben.
Dort wird die Unterroutine uart_empfangen() aufgerufen.
Diese enthält praktisch nur die drei Zeilen "Warte auf Zeichen 
verfügbar", "schreibe zeichen aus UDR in Variable", "return variable;".

Sooo, in der ISR möchte ich nun gerne einige Zeichen rausfiltern. Also 
hole ich vor dem Schreiben in den Puffer das Zeichen und schreibe es in 
eine Variable.
Also:
char zeichen;
zeichen=uart_empfangen();
Dann müsste ich ja eigentlich das Zeichen überprüfen können und nur 
bedingt weiterverwenden, also:
if (zeichen!=10 && zeichen !=48 && zeichen!=32)
{
"schreibe in Puffer"
}

Ich stelle jedoch fest, dass genau diese if-Abfrage einen Reset des AVR 
auslöst - was kann das sein? Wenn ich die auskommentiere, geht alles 
bestens...

Ciao Tobias

von Simon K. (simon) Benutzerseite


Lesenswert?

>Ein Array kann überlaufen, aber kann ein Pointer überlaufen?

Au weia. Diese Frage bezieht sich wahrscheinlich auf dieses 
Codeschnipsel von dir:
1
//Beginn U(S)ART Routinen:
2
//Definition allgemeingültiger Variablen des U(S)ART
3
volatile char *puffer1;
4
volatile char *puffer2;
5
...

Bedenke!
Du hast mit
1
volatile char *puffer1;
kein Array erschaffen! Du hast dir Platz für einen Pointer geschaffen, 
aber  keinesfalls Speicherplatz für ein Array. Es wundert mich, dass 
diese Variante funktioniert.
Aber ich denke mal, da die Variablen statisch alloziiert sind, wird der 
Compiler sie mit 0 initialisieren (War doch so, oder?). Sobald du nun 
auf die Adresse schreibst, schreibst du quasi ab Speicherbereich 0. Und 
das ist NICHT reservierter Speicherplatz (und vermutlich nichtmal im RAM 
Bereich). Also gute nacht bei dieser Variante, oder ich habe jetzt einen 
Denkfehler.

PS: Der Name eines Arrays kann (teilweise) als Pointer auf das erste 
Element des Arrays behandelt werden. Deswegen sind folgende Statements 
gültig:
1
unsigned char array[20];
2
unsigned char* ptr;
3
4
ptr = array;
5
ptr = &array[0];
6
ptr[4] = 25;
7
array[2] = 44;

PS: Achja, wenn ich auch noch meinen Senf dazugeben darf:
Ich würde das ganze ein wenig anders machen. Benutze doch einen 
Ringbuffer mit der Größe von 2*17 (oder mehr) Zeichen.

Ungefähr so:
1
unsigned char buf[64];
2
unsigned char bufhead = 0;
3
unsigned char buftail = 0;
4
5
main()
6
{
7
  while(1)
8
  {
9
    if (bufhead != buftail)
10
    {
11
      //lese und analysiere zeichenweise den string an buf[bufhead],
12
      //bis bufhead == buftail. verhindere dabei überlauf. checke dabei
13
      //jedes zeichen auf LF
14
    }
15
  }
16
}
17
      
18
ISR(...)
19
{
20
  buf[buftail++] = UDR;
21
  if (buftail > 63) buftail = 0;
22
}
Ich hoffe ich hab jetzt hier kein Denkfehler drin. Ist nur so ganz 
schnell hingeschrieben.

von Werner B. (Gast)


Lesenswert?

Er mein natürlich
1
buf[buftail++] = UDR;
2
  if (buftail > 63) buftail = 0;

von Simon K. (simon) Benutzerseite


Lesenswert?

Ups, ja meint er. Moment ich editiers grad. Danke für diesen Hinweis.

PS: Man könnte die ISR sogar noch beschleunigen indem man das 
Dereferenzieren per [] weglässt und stattdessen statische globale 
unsigned char pointer benutzt.

von Werner B. (Gast)


Lesenswert?

Vorrausetztung ist hier ein
1
volatile unsigned char buftail = 0;
denn buftail wird in der ISR verändert und in der Hauptschleife 
abgefragt. Einer beispielhafter Fall für die Notwendigkeit eines 
"volatile".

Und in der while(1) steht dann
1
if (bufhead != buftail)
2
    {
3
      //lese und analysiere zeichenweise den string an buf[bufhead],
4
      //bis bufhead == buftail. verhindere dabei überlauf. checke dabei
5
      //jedes zeichen auf LF
6
      unsigned char asychar = buf[bufhead++];
7
      if(bufhead > (sizeof(buf)/sizeof(unsigned char)) bufhead = 0;
8
9
     /* Und jetzt machwas mit asychar */
10
    }

von Michael Wilhelm (Gast)


Lesenswert?

if (buftail > 63) buftail = 0;
buf[buftail++] = UDR;
Ich würde das so rum machen, da im anderen Fall buftail den Wert 64 
annehmen kann und somit das Array überläuft, bzw. undefiniert ins RAM 
geschrieben wird.

MW

von fieser Rahul (auch Oskar genannt) (Gast)


Lesenswert?

>if(bufhead > (sizeof(buf)/sizeof(unsigned char)) bufhead = 0;

Kann man auch so machen:
bufhead &= (sizeof(buf)/sizeof(unsigned char)-1);

Aus dem rechten Teil sollte der Compiler einen konstanten Ausdruck 
machen...

von Simon K. (simon) Benutzerseite


Lesenswert?

Jap, die genannten Verbesserungen sind empfehlenswert. Beachte aber, 
dass Rahuls Methode nur funktioniert, wenn die Puffergröße ein 
Vielfaches von 2 ist.

von Werner B. (Gast)


Lesenswert?

1
bufhead &= (sizeof(buf)/sizeof(unsigned char)-1);
funktioniert nur wenn (sizeof(buf)/sizeof(unsigned char) eine 
Zweierpotenz ist (2^1=2,2^2=4,2^3=8,2^4=16,2^5=32,2^6=64,...).

von fieser Rahul (auch Oskar genannt) (Gast)


Lesenswert?

>funktioniert nur wenn (sizeof(buf)/sizeof(unsigned char) eine
>Zweierpotenz ist (2^1=2,2^2=4,2^3=8,2^4=16,2^5=32,2^6=64,...).

Ja...

von fieser Rahul (auch Oskar genannt) (Gast)


Lesenswert?

Ist aber auch die schnellste Variante...

von Heinz B. (heinz)


Lesenswert?

Hi Michael,

Überlege bitte nochmal was passiert wenn
buftail = 63 ist und dein vorgeschlagener code durchlaufen wird !!!

Michael Wilhelm wrote:
>
> if (buftail > 63) buftail = 0;
> buf[buftail++] = UDR;

!!! buftail ist nun 64 bis zur nächsten abfrage. !!!!

br heinz

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.