PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Über RS232 etwas empfangen



MechMac
12.09.2010, 20:19
Hallo,

ich möchte gerne das mein Controller über UART etwas empfängt. Ich habe vor die interrupt gesteuerte Methode zu verwenden.

Im prinzip soll ein Steuerbefehl gesendet werden und dann eine Zahl.
Das eigentliche Problem ist, das nichts beim Controller ankommt.
Die andere Richtung, also das senden, funktioniert ohne Probleme.

Folgende Fallstricke konnte ich bereits umgehen:


sei; aktivieren
Die richtige ISR für meinen Mega644: ISR (USART0_RX_vect)


Ich habe der ISR mitgegeben, das sie eine LED einschalten soll, wenn sich etwas tut. Nun das passiert auch. Die Led leuchtet auf. Aber der Code liefert nichts.

Folgenden Code verwende ich:


#define CR "\r\n"

#define PUFFER_GROESSE 100 //Puffergröße in Byte
unsigned char puffer[PUFFER_GROESSE];
unsigned char* lesezeiger;
unsigned char* schreibzeiger;

char* tempstr;


//==============================================
//Service Routine für Empfang
//==============================================
ISR (USART0_RX_vect)
{
PORTD |= (1 << DDD5 );
//Automatisch empfangene Daten in den Puffer schreiben:
*schreibzeiger=UDR0;
schreibzeiger++;
if(schreibzeiger==puffer+PUFFER_GROESSE) schreibzeiger=puffer;
}


//==============================================
//Funktionen für den interrupt-gesteuerten Datenempfang
//==============================================
uint8_t usart_byte_avail_intr(void){
//Prüft, ob ein Datenbyte im Puffer vorhanden ist
// 1 = vorhanden, 0 = nicht vorhanden
_delay_ms(10);
if(schreibzeiger!=lesezeiger)
return 1;
else return 0;
}
//--------------------------------------------------------------
uint8_t usart_string_avail_intr(void){
//Hilfsfunktion für die Funktion usart_gets_intr
//Prüfen, ob ein kompletter String im Puffer verfügbar ist.
//Rückgabewert 1 = verfügbar, 0 = nicht verfügbar
uint8_t avail=0;
uint8_t *r=lesezeiger;
while(r!=schreibzeiger){
if(*r==0) avail=1;
r++; if(r==puffer+PUFFER_GROESSE) r=puffer;
}
return avail;
}
//--------------------------------------------------------------
uint8_t usart_getc_intr(void){
//Liest ein Byte aus dem Puffer
//Nur aufrufen, wenn usart_byte_avail_intr() vorher aufgerufen wurde und
//eine 1 lieferte.
uint8_t datenbyte=0;

if(schreibzeiger!=lesezeiger){

datenbyte=*lesezeiger;
lesezeiger++;
if(lesezeiger==puffer+PUFFER_GROESSE) lesezeiger=puffer;

}
return datenbyte;
}
//--------------------------------------------------------------
uint8_t usart_gets_intr(char *s){
//Liest eine Zeichenkette aus dem Puffer
//einschließlich Endmarke 0 in die Stringvariable s
//Wenn der Rückgabewert ok = 1 ist, war das Lesen erfolgreich,
//bei ok = 0 nicht erfolgreich.
char c;
uint8_t ok=0;
if(usart_string_avail_intr()){
ok=1;
do{
c = usart_getc_intr();
*s=c;
s++;
}while(c!=0);
}
return ok;
}



int main( void )
{

DDRD = ( 1 << PD5 );
PORTD |= (1 << DDD5 );
pause(2);
PORTD &= ~(1 << DDD5 );

lesezeiger=puffer;
schreibzeiger=puffer;

UBRR0H = (uint8_t) (UART_BAUD_CALC(UART_BAUD_RATE,16000000)>>8);
UBRR0L = (uint8_t) UART_BAUD_CALC(UART_BAUD_RATE,16000000);

UCSR0B = (1<<RXEN0) | (1<<TXEN0) | (1<<RXCIE0);
UCSR0C = (1 << UCSZ01) | (1 << UCSZ00);

tempstr ="Test";

sei();

while(1)
{
pause(4);
usart_gets_intr(tempstr);
USART_puts("->");
USART_puts(tempstr);
USART_puts(CR);
}
}



Nach diesem Code sollte er, wenn überhaupt, "->Test" senden.
Das macht er, allerdings immer. Obwohl ich mit
usart_gets_intr(tempstr);
eigentlich den Inhalt des Ringspeichers in tempstr schreibe.
In tempstr steht immer "Test".
Die Prüfung auf 1 oder 0 bei usart_gets_intr habe ich absichtlich weggelassen, da er sonst gar nix ausgibt.

Die Scripte für das empfangen sind von der Seite
http://www.tschallener.net/info/index.php/usart-mit-interrupt-atmega32-in-c.html


Weiß jemand woran das liegen könnte?

Gruß, Andreas




/////////////////EDIT//////////////////

Es liegt definitiv an den Scripten von dieser Seite.
Ich habe mal folgendes getestet:


//==============================================
//Service Routine für Empfang
//==============================================
ISR (USART0_RX_vect)
{
PORTD |= (1 << DDD5 );
//Automatisch empfangene Daten in den Puffer schreiben:
*schreibzeiger=UDR0;
schreibzeiger++;
if(schreibzeiger==puffer+PUFFER_GROESSE) schreibzeiger=puffer;
USART_putc(UDR0);
}



Augenmerk auf die letzte Zeile.
Der Controller sendet das zurück was ich im schicke. Und das klappt.
Also scheint da was mit den Scripten von tschallener.net nicht zu stimmen. Die Frage ist nur was.


/////////////////EDIT 2//////////////////
vielleicht wird der String nicht terminiert. Immerhin kommt der String, der gesendet wird von einem Pc. Der hängt bestenfalls ein #13 und #10 dran.

Ich komme da erst drauf, weil ich ja schon schrieb das usart_string_avail_intr niemals 1 zurückgibt. Also wird r wohl auch nie eine 0 finden. Also scheint der String nicht terminiert zu sein.
Er ist vielleicht da, aber halt nicht abgeschlossen.

Ich habe auch schon probiert test0 oder test\0 zu senden. Nichts.



Und ///////Edit//////// der letzte
Es ist genau so. In C werden strings nicht mit #13 und #10 terminiert. Jetzt funktioniert es.