mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Problem mit Zeiger auf Array


Autor: tantal.lpt (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

ich bin grad dabei mir eine kleine uart-empfangsroutine zu schreiben und 
häng an einem Problem fest.

Also die uart läuft ohne probleme und löst auch interrupts aus.
#define rx_buffer_len 32

unsigned char rx_buffer[rx_buffer_len];
unsigned char *ptr_read = rx_buffer;
unsigned char *ptr_write = rx_buffer;


void init_uart (void){
  UBRRH = (unsigned char)(bauddivider>>8);
  UBRRL = (unsigned char)bauddivider;

  UCSRA = (1<<U2X);
  UCSRB = (1<<RXCIE)|(1<<RXEN)|(1<<TXEN);
  UCSRC = (1<<UCSZ1)|(1<<UCSZ0);

}


void uart_putchar(unsigned char c)
{
  while( !( UCSRA & (1<<UDRE)));
  UDR = c;
}



ISR(USART_RX_vect)
{
  *ptr_write= UDR;
  ptr_write++;
  if(ptr_write == rx_buffer + rx_buffer_len) ptr_write = rx_buffer;

    while ( !( UCSRA & (1<<UDRE)) );

}


int main(void){

  DDRB = 0x1F;
  PORTB = 0xFF;

  DDRD = 0x30;
  PORTD = 0x00;

  init_uart();

  sei();

  while(1){

    for(unsigned char i = 0 ; i < rx_buffer_len ; i++)
      uart_putchar(rx_buffer[i]);


    uart_putchar(*ptr_write);
    uart_putchar(*ptr_read);


    _delay_ms(5000);


  }

}

also wie schon erwähnt senden und empfangen funtioniert sehr gut.
wenn ich das programm starte bekomm ich folgendes auf dem 232-Term:

00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00

also der Buffer-inhalt + die zwei zeigerinhalte alles 00 ... soweit so 
gut
sende ich jetzt ein zeichen (z.B. 0xAA) bekomm ich so etwas:

AA 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 AA AA

das Zeichen 0xAA steht am anfang vom Buffer. Der lesezeiger (ptr_read) 
zeigt auf das erste element, was auch so sein soll ... aber wiso zeigt 
der zweite Zeiger auf das gleiche Zeichen?
wenn ich jetzt aber 0xff sende bekomm ich folgendes:

AA FF 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 AA AA

der ptr_write zeigt also immer auf das nächste element im speicher.. 
aber nur in der ISR .. sonst immer auf das erste... kamm mir da einer 
weiterhelfen? Was mache ich da falsch?

gruß Mathias

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
volatil vergessen, Variabeln die in einer ISR und in Main verwendet 
werden müssen als Volatil gekennzeichnet werden.

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
tantal.lpt schrieb:
> der ptr_write zeigt also immer auf das nächste element im speicher..
> aber nur in der ISR .. sonst immer auf das erste...
Sichwort "volatile"...

> Was mache ich da falsch?
Du hast eine unnötig komplizierte Pointerverwaltung deines Puffers...

Autor: tantal.lpt (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für die schnelle Antwort! also mit volatile hab ich schon versucht 
... da hat sich nix verbessert.

Es geht mir jetzt zwar in erster linie darum wiso das nicht funktioniert 
damit ich beim nächsten mal bescheid waiß, aber wie könnte ich denn die 
Pointerverwaltung meines Puffers verbessern?

gruß Mathias

Autor: TheMiB (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
also die ISR an sich sieht nicht sonderlich durchdacht aus.
if(ptr_write == rx_buffer + rx_buffer_len) ptr_write = rx_buffer;

hier vergleichst du die adresse des pointers ptr_write mit dem Wert von 
rx_buffer[0]+rx_buffer_len? bringt wohl nichts...also ich denke du 
willst prüfen ob du das ende erreicht hast und dann den pointer zurück 
aufs erste element setzen...also müsste es heißen:
if(ptr_write == &rx_buffer + rx_buffer_len) ptr_write = &rx_buffer;

als nächstes...die while-schleife gehört nicht in eine ISR!! Also nur 
aufs ereignis warten...pointer, etc. setzen und weiter im Text.

Bei Fehlern möge man mich bitte korrigieren...

mfg
TheMiB

Autor: tantal.lpt (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

also bei mir klappt es so mit der end of buffer erkennung ... ich mein 
auch das " *ptr = array " das gleiche ist wie " *ptr = &array[0] "

gut mit der while-schleife in der ISR is net so ganz schön .. hatte ich 
irgendwann zwischendurch eingefügt um den fehler zu finden bevor ich mir 
den ganzen puffer hab ausprinten lassen wo ich dann gesehen hab das 
soweit alles klappt mit den Puffer befüllen ...

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
TheMiB schrieb:
> also müsste es heißen:
> &rx_buffer
Wenn das nur nicht mal die Adresse des Pointers zurückgibt...
Die Adresse des ersten Elements ist  &rx_buffer[0],
und das ist das selbe wie  rx_buffer

> rx_buffer
Ist nämlich schon ein Pointer. Nämlich auf rx_buffer[0]...

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
tantal.lpt schrieb:
> also mit volatile hab ich schon versucht ... da hat sich nix verbessert.
Zeig mal, wie du das versucht hast. Hast du einen Pointer auf einen 
volatilen char gemacht oder einen volatilen Pointer auf einen char?

Autor: tantal.lpt (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
also ich habs so gemacht:
volatile unsigned char *ptr_read;
volatile unsigned char *ptr_write;

habs aber auch mal so probiert (?) :
unsigned char volatile *ptr_read;
unsigned char volatile *ptr_write;

oder macht man das bei pointern noch anders?

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
In beiden Fällen ist nicht der Pointer selber volatile, sondern das, 
worauf er zeigt (die beiden Varianten sind tatsächlich identisch).

Volatile Pointer:
typ * volatile ptr;

Autor: tantal.lpt (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
aaahhh ... ok das wusste ich nicht. Jetzt funktionierts!!

Danke euch für die schnelle hilfe!

gruß Mathias

Autor: MagIO (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du solltest nochmal über die ISR nachdenken.

Genauer: was passiert, wenn die Daten schneller ankommen, als sie 
gelesen werden? Sprich der ptr_write läuft einmal in Kreis und an 
ptr_read vorbei.

Autor: tantal.lpt (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

ja hab ich auch schon bemerkt ... besonders blöd wird es wenn genau 32 
Bytes kommen .. dann steht der Pointer genau an der selben stelle und 
man kann nicht mehr mit einem pointervergleich sehen ob was gekommen ist 
oder nich ... hab jetzt eine abbruchbedingung nach Buffer_len -1 gemacht 
... alles was dann kommt ignorier ich dann einfach ... in meinem fall 
kommen aber eh nie so viele daten auf einmal ...

trozdem danke für den Hinweis!

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
tantal.lpt schrieb:
> besonders blöd wird es wenn genau 32 Bytes kommen
Ja nun, dann ist dein Puffer zu klein. So einen Buffer-Overrun kannst du 
eigentlich niemals richtig gut abfangen...

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

Bewertung
0 lesenswert
nicht lesenswert
Und darüber
ISR(USART_RX_vect)
{
  *ptr_write= UDR;
  ptr_write++;
  if(ptr_write == rx_buffer + rx_buffer_len) ptr_write = rx_buffer;

    while ( !( UCSRA & (1<<UDRE)) );

}

solltest du auch noch einmal nachdenken. (Ich meine die letzte while 
Schleife in der ISR)

Autor: tantal.lpt (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ja wie gesagt ich bekomm eh nur max 5 Byte auf einmal und das auch nur 
max ein mal pro sec. also sollten die 32 Byte locker reichen!

die while schleife ist auch schon raus ... wie gesagt hatte sie nur bei 
der fehlersuche rein gemacht ... aber jetzt läuft alles wie es soll ..

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.