AVR,USART,C: String Empfangen und direkt wieder versenden

OP #1567116
Hey,
kann sich bitte Jemand meinen C-Code ansehen und mir sagen warum das 
nicht funktioniert ? Ich finde den Fehler einfach nicht....Im Grunde 
will ich nur einen String über die USART in einem Array speichern und 
ihn wieder zurückschicken:

#include <avr/io.h>
#include <string.h>
#include <avr/interrupt.h>

#define USART_PRESCALE (((F_CPU / (115200 * 16UL))-1))
char Array[100];
int ToSend = 0; //ist ein kompletter String zum zurücksenden im Speicher 
?
int Counter = 0;

int main(void)  {
UCSRB |= ( 1 << TXEN ) | ( 1 << RXEN ); //Sende und Empfangsmodus 
einschalten
UCSRC |= ( 1 << URSEL ) | ( 1 << UCSZ0 ) | ( 1 << UCSZ1 ); //Modus: 
Asynchron 8N1
UBRRL = USART_PRESCALE; //Baudrate setzen
UCSRB |= ( 1 << RXCIE); //USART Interrupts aktivieren
sei(); //Interrupts einschalten

for(;;)
{
  if (ToSend != 0)
  {
    for (int i = 0;i <= strlen(Array);i++)
    {
    UDR = Array[i];
    }
  ToSend = 0;
  }
}
}

ISR(USART_RXC_vect)
{
  Array[Counter] = UDR;
  if (Array[Counter] == '\0')
  {
    ToSend = 1;
    Counter = 0;
  }
  else
  {
  Counter++;
  }
}
OP
Justus Skorps schrieb:
>  auf jeden Fall fehlen da volatiles...

Ich bin zwar neu in der C-Programmierung, aber wofür brauche ich denn 
die Volatiles?. Wenn ich es Richtig verstanden habe, dann sind die doch 
nur für einen Variablen Zugriff außerhalb des Programms, oder ?
Scholly ... schrieb:
> Justus Skorps schrieb:
>>  auf jeden Fall fehlen da volatiles...
>
> Ich bin zwar neu in der C-Programmierung, aber wofür brauche ich denn
> die Volatiles?. Wenn ich es Richtig verstanden habe, dann sind die doch
> nur für einen Variablen Zugriff außerhalb des Programms, oder ?

und was ist deine ISR?

schau dir doch mal das Assembler-Listing deines Programms an, ob da 
überhaupt was pssiert...
Gast
Also als Erstes brauchst du die volatile damit die Vars auch in der ISR 
verändert werden können.
Einfach nur Daten ins UDR zu schreiben reicht nicht um die Übertragung
anzuschubsen. Entweder auch über ISR oder manuell.
Du kannst nicht einfach nach Belieben ein Zeichen nach dem Anderen in 
UDR rein stopfen. Du musst schon warten, bis da jeweils wieder Platz 
drin ist.

Außerdem: wie wird der String zum µC gesendet? Sicher, dass da eine 
terminierende Null mitkommt?
Gast
Scholly ... schrieb:
> eu in der C-Programmierung, aber wofür brauche ich denn
> die Volatiles?. Wenn ich es Richtig verstanden habe, dann sind die doch
> nur für einen Variable

Scholly ... schrieb:
> Justus Skorps schrieb:
>>  auf jeden Fall fehlen da volatiles...
>
> Ich bin zwar neu in der C-Programmierung, aber wofür brauche ich denn
> die Volatiles?. Wenn ich es Richtig verstanden habe, dann sind die doch
> nur für einen Variablen Zugriff außerhalb des Programms, oder ?

Wenn du in einer Funktion oft auf eine Variable zugreifst, wird die oft 
irgendwo am Anfang in ein register geladen und später nur noch dort 
verändert. Ist erstmal kein Problem, denn der Compiler sieht ja an 
welchen Stellen in der Funktion auf die Variable zugegriffen und 
verändert wird. Zum Problem wird es erst, wenn die Variable von 
Ausserhalb geändert wird, zum Beispiel durch dein ISR. In dem Fall würde 
die ISR die Variable im Speicher verändern, innerhalb der Main-Funktion 
würde aber weiterhin mit dem alten Wert gearbeitet werden der im 
Register steht.
Das "volatile" gibt einfach nur an das die Variable auch von ausserhalb 
geändert werden kann (zum Beispiel in der ISR). Die Variable wird dann 
bei jedem Zugriff neu aus dem Speicher geladen und nicht im Register 
gecached.
Gast
und zerlege dein Programm erst mal in teilschritte:
also zuerst mal was definiertes senden und schauen ob es ankommt,
dann erst was empfangen und zurücksenden ...
OP
Also es funktioniert jetzt. Wenn ich einen "Test"-String reinschicke, 
wird auch genau ein "Test" + \0 zurückgesendet, das kann ich auf der 
Gegenseite (PC) sehen. Hier der Code:

#include <avr/io.h>
#include <string.h>
#include <avr/interrupt.h>

#define USART_PRESCALE (((F_CPU / (115200 * 16UL))-1))
volatile char Array[100];
volatile int ToSend = 0;
volatile int Counter = 0;

int main(void)
{
UCSRB |= ( 1 << TXEN ) | ( 1 << RXEN );
UCSRC |= ( 1 << URSEL ) | ( 1 << UCSZ0 ) | ( 1 << UCSZ1 );
UBRRL = USART_PRESCALE;
UCSRB |= ( 1 << RXCIE);
sei();

for(;;)
{
  if (ToSend != 0)
  {
    for (int i = 0;i <= strlen(Array);i++)
    {
  while (!(UCSRA & (1<<UDRE)))
    {
    }
    UDR = Array[i];
    }
  ToSend = 0;
  }
}
}

ISR(USART_RXC_vect)
{
  Array[Counter] = UDR;
  if (Array[Counter] == '\0')
  {
    ToSend = 1;
    Counter = 0;
  }
  else
  {
  Counter++;
  }
}

Ich bekomme nur Warnmeldungen vom Compiler bezgl strlen:

main.c:21: warning: passing argument 1 of 'strlen' discards qualifiers 
from pointer target type

Vielen Dank an Alle

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 16 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.