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
"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.
> 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
>> 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
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.
" 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.
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
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.
>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
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.
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
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
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
>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
volatilechar*puffer1;
4
volatilechar*puffer2;
5
...
Bedenke!
Du hast mit
1
volatilechar*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
unsignedchararray[20];
2
unsignedchar*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
unsignedcharbuf[64];
2
unsignedcharbufhead=0;
3
unsignedcharbuftail=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.
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.
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
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
>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...
Jap, die genannten Verbesserungen sind empfehlenswert. Beachte aber,
dass Rahuls Methode nur funktioniert, wenn die Puffergröße ein
Vielfaches von 2 ist.
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