- 3D-Druck Einstieg und Tipps         
Ergebnis 1 bis 10 von 10

Thema: RS232 Empfangen nicht möglich

  1. #1

    RS232 Empfangen nicht möglich

    Anzeige

    Powerstation Test
    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
    Code:
    #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

    Code:
    #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

  2. #2
    Erfahrener Benutzer Roboter Experte Avatar von sternst
    Registriert seit
    07.07.2008
    Beiträge
    672
    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);
    MfG
    Stefan

  3. #3
    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

  4. #4
    Benutzer Stammmitglied
    Registriert seit
    13.09.2007
    Beiträge
    39
    Ich weiss ja nicht, wies beim AT90CAN128 ist, aber beim ATMEGA32 lautet die RX ISR so:
    Code:
    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.

  5. #5
    Erfahrener Benutzer Roboter Experte Avatar von sternst
    Registriert seit
    07.07.2008
    Beiträge
    672
    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.
    MfG
    Stefan

  6. #6
    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.

    Code:
    ]#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

  7. #7
    Erfahrener Benutzer Roboter Experte Avatar von sternst
    Registriert seit
    07.07.2008
    Beiträge
    672
    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?
    MfG
    Stefan

  8. #8
    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

  9. #9
    Erfahrener Benutzer Roboter Experte Avatar von sternst
    Registriert seit
    07.07.2008
    Beiträge
    672
    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.
    MfG
    Stefan

  10. #10
    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

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

MultiPlus Wechselrichter Insel und Nulleinspeisung Conrad