PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : RS232 Empfangen nicht möglich



beginner1101
10.07.2008, 11:06
Hallo,

nachdem ich jetzt erfolgreich Daten per RS232 vom uC zum PC schicken kann (danke an Jens =D> ) will ich nun Daten vom Pc zum uC schicken. Und zwar will ich einfach eine LED über eine Buchstabeneingabe machen. Ich hab mir schon verschiedene Threads im Forum angeschaut und auch viele verschiedene Code ausprobiert, kam aber auch kein positives Ergebnis. Kann mir jemand helfen? Ich benutze einen AT90CAN128 und das AVR-Studio.
Ich poste meinen Code.

Meine Header -datei: usart.h


#include <avr/io.h>
#include <util/delay.h>


/*### Senden per USART - RS232-Kommunikation ###*/

/*======================= Initialisierung ================================================== =========0=========*/
void USART1_Init (void)
{
uint16_t ubrr; /* Set baud rate */
ubrr = ((F_CPU/(9600*16L))-1);
UBRR1H = (unsigned char)(ubrr>>8);
UBRR1L = UBRR1L = (unsigned char) ubrr;
UCSR1C = (1<<UCSZ11) | (1<<UCSZ10) ; /* Set frame format: 8data, no parity & 1 stop bits */
UCSR1B = (1<<RXEN1) | (1<<TXEN1); /* Enable receiver and transmitter */

//Flush Receive-Buffer (entfernen evtl. vorhandener ungültiger Werte)
do

{
UDR1;
}
while (UCSR1A & (1<< RXC1));
}

/*======================= Initialisieren Senden ================================================== =============*/
void USART1_Transmit (unsigned char data)
{
while(!(UCSR1A & (1<<UDRE1)))
{
}

UDR1 = data;
}


/*======================= Befehl für Senden ================================================== =================*/
void uart_puts(char *s)
{
while(*s)
{
USART1_Transmit(*s);
s++;
}
}

/*======================= Initialisieren Empfangen ================================================== ==========*/
unsigned char USART1_Receive (void)
{
while ( ! (UCSR1A & (1<<RXC1))); /* Wait for data to be received */
return UDR1;/* Get and return received data from buffer */
}


dann noch meine Hauptroutine


#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>
#include "usart.h"


volatile char Daten;






ISR(USART1_RX_vect)
{
Daten = UDR1;
}


void main(void)
{
DDRA = 0xFF;
USART1_Init();
sei(); //Interrupts freigeben

for(;;)
{
if(Daten == 'A')
{
Daten = 0;
PORTA = (1<<PA0);
}

if(Daten == 'a')
{
PORTA = (1<<PA1);
Daten = 0;
}
else
{
PORTA = 0x00;
}


}



}


Danke schon mal für eure Hilfe.

LG Anna

sternst
10.07.2008, 16:16
So auf den ersten Blick würde ich dazu 3 Dinge sagen:

1) Man schreibt keinen Code in eine Header-Datei, außer in Ausnahmefällen, wie z.B. Inline-Funktionen.

2) Deine if-else-Struktur in main stimmt nicht. Das else bezieht sich nur auf das zweite if. Bei 'A' wird daher zwar PA0 auf Eins gesetzt, sofort danach aber wieder zurückgesetzt auf Null. Wenn du vor das zweite if noch ein else schreibst, hast du das, was du wohl eigentlich haben wolltest. Dann wird "PORTA = 0x00;" nur ausgeführt, wenn Daten weder 'A' noch 'a' ist. Ich würde das übrigens eher mit switch-case machen, insbesondere wenn noch mehr Kommando-Buchstaben dazukommen sollen.

3) Nun der eigentliche Grund, warum sich bei dir wohl gar nichts tut. Du hast den UART-Receive-Interrupt nicht enabled.
UCSR1B |= (1<<RXCIE1);

beginner1101
11.07.2008, 10:32
Hy Stefan,

danke für deine Infos.
Zu 1) es stört doch eigentlich nicht oder? Ist halt nicht sauberer Programmierstil.

Zu 2) Hab ich geändert.

Zu 3) Hab jetzt meinen Header verändert und UCSR1B |= (1<<RXCIE1); eingefügt.
Die Zeile sieht jetzt so aus: UCSR1B = (1<<RXEN1) | (1<<TXEN1) | (1<<RXCIE1);

Es hat sich leider nichts geändert......................... :-(

LG Anna

cbg
11.07.2008, 11:04
Ich weiss ja nicht, wies beim AT90CAN128 ist, aber beim ATMEGA32 lautet die RX ISR so:

SIGNAL (SIG_UART_RECV)
{
...
}

Achso, vergiss was ich gesagt hab :)
Schaut eigentlich alles richtig aus. Post mal was du jetzt hast.

Zu Code in Header Datei: Nein, es stört nicht aber das ist nicht der Sinn einer Headerdatei. Gewöhn es dir schnell ab, sonst bleibst du dran hängen.

sternst
11.07.2008, 11:24
Zu 1) es stört doch eigentlich nicht oder? Ist halt nicht sauberer Programmierstil.
Es kann aber sehr schnell störend werden. Wenn dein Projekt wächst, und du die UART-Funktionen in zwei verschiedenen C-Dateien brauchst, funktioniert dein "Header" nicht mehr.


Zu 2) Hab ich geändert.
Bitte geänderten Sourcecode mitposten. Wer weiß, ob du nicht neue Fehler eingebaut hast. ;-)


Es hat sich leider nichts geändert.
Funktioniert die serielle Kommunikation ganz generell denn überhaupt? Mach doch vor die Endlosschleife mal ein "uart_puts("Hallo\n");" und in die Schleife (am Anfang) ein Echo, also z.B.
if (Daten) {
USART1_Transmit(Daten);
Daten = 0;
}

PS: Sollte der Compiler irgendwelche Warnungen ausspucken, unbedingt mitposten.

beginner1101
11.07.2008, 13:19
Hallo ;-),


danke schon mal für die Unterstützung. =D> .


Bitte geänderten Sourcecode mitposten. Wer weiß, ob du nicht neue Fehler eingebaut hast.

Hier meine leicht veränderte Source-Datei. Immer noch ohne switch ;-) aber dass mach ich wenns überhaupt funktioniert.


]#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>
#include "usart.h"


volatile char Daten;






ISR(USART1_RX_vect)
{
Daten = UDR1;
}


void main(void)
{
DDRA = 0xFF;
USART1_Init();
sei(); //Interrupts freigeben

for(;;)
{
if(Daten == 'A')
{
Daten = 0;
PORTA = (1<<PA0);
}

else
{
PORTA = 0x00;
}


if(Daten == 'a')
{
PORTA = (1<<PA1);
Daten = 0;
}
else
{
PORTA = 0x00;
}


}



}



Funktioniert die serielle Kommunikation ganz generell denn überhaupt?

Ja, also die Schnittstelle unktioniert auf jeden Fall (Er gibt in schnellem Takt ein C aus.). Ich kann an das Hyperterminal schicken, aber halt nichts empfangen.


PS: Sollte der Compiler irgendwelche Warnungen ausspucken, unbedingt mitposten.

Komisch, aber er gibt jetzt nen Fehler auf. Aber nur wenn ich lediglich einmal auf Compilen geht. Wenn ich zweimal auf compilen drücke ist der Fehle weg. Hioer meine Warning:

warning: return type of 'main' is not `int'


Danke für die Mühen.

LG Anna

sternst
11.07.2008, 13:37
Hier meine leicht veränderte Source-Datei.
Tja, gleiches Problem, wie vorher. Wieder wird bei einem 'A' das gesetzte Bit gleich wieder gelöscht. Das "Wenn du vor das zweite if noch ein else schreibst" war wörtlich zu nehmen, also nur ein else, sonst nichts. Die if-else-Struktur muss so aussehen:
if () {
}
else if () {
}
else {
}


warning: return type of 'main' is not `int'
Ist unkritisch. Schreib einfach "int main (void)".

Ich sehe gerade, dass PortA der Analog-Port ist. Du hast doch hoffentlich AVCC angeschlossen, oder?

beginner1101
11.07.2008, 13:52
Hy Stefan,

jetzt hab ich dich verstanden :-). Ich hab die if-else-schleife verändert. Leider ohne merklichen Erfolg. AVCC hab ich angeschlossen......... Muß ich irgendwo noch ne Zeitschleife einfügen???????

LG Anna

sternst
11.07.2008, 15:23
Füge mal in main vor die Schleife "PORTA = (1<<PA2);" ein, und in die ISR "PORTA ^= (1<<PA2);". Berichte mal, was du an PA2 beobachtest. Eigentlich müsste der Port-Pin nach dem Reset auf High gehen, und dann bei jedem Zeichen, das du an den AVR sendest, den Zustand ändern.

Apropos "Zeichen senden": sendest du wirklich immer nur ein Zeichen, oder kommt nach dem Zeichen vielleicht noch ein CR oder LF? Dann wären PA0 bzw PA1 immer nur ganz kurz High.

beginner1101
14.07.2008, 10:20
Hallo Stefan,

warum auch immer jetzt funktioniert es. Ich habs heute morgen nochmal getestet. Hab deine genannten erweiterungen mit dem "PORT...." gemacht und jetzt funktioniert es. Vieln vielen Dank für die super gute Unterstützung.

LG Anna