- MultiPlus Wechselrichter Insel und Nulleinspeisung Conrad         
Seite 1 von 2 12 LetzteLetzte
Ergebnis 1 bis 10 von 15

Thema: UART sendet andauerd

  1. #1
    Neuer Benutzer Öfters hier
    Registriert seit
    10.12.2007
    Beiträge
    18

    UART sendet andauerd

    Anzeige

    LiFePo4 Akku selber bauen - Video
    Hallo zusammen,

    ich habe versucht den Beispiel über Uart/Fido aus RN-Wissen nach zu programmieren...

    Es klappt auch soweit allerdings sendet mein UART an dauernd, anstatt ein Zeichen.
    Ich verstehe dass nicht! Benütze ja keine schleifen! Bitte um Hilfe.

    Code:
    int main()
    {
        uart_init();
        sei();   // Wird nur gebraucht bei der Interrupt-Version 
    
        uart_putc ('f');
        /*uart_puts ("Hallo Welt!" CR);*/
    
        while (1)
        {
    
        }
    
        return 0;
    }

    uart:

    Code:
    /* Senden eines Chars */
    int uart_putc (const uint8_t data)
    {
    	int ret = fifo_put (&out_fifo, data);
    	UCSRB |= (1 << UDRIE);
     
      return ret;
    }
    fifo_put :
    Code:
    /* Schreibt das nächste Byte "data" in die FIFO.
     * Liefer 1 bei Erfolg und 0, falls die FIFO voll ist. */
    uint8_t fifo_put (fifo_t *f, const uint8_t data)
    {
    	return _inline_fifo_put (f, data);
    }
    und _t fifo_put:

    Code:
    /* Schreibt das nächste Byte "data" in die FIFO.
     * Liefer 1 bei Erfolg und 0, falls die FIFO voll ist. */
    static inline uint8_t _inline_fifo_put (fifo_t *f, const uint8_t data)
    {
    	if (f->count >= f->size)
    		return 0;
    		
    	uint8_t * pwrite = f->pwrite;
    	
    	*(pwrite++) = data;
    	
    	uint8_t write2end = f->write2end;
    	
    	if (--write2end == 0)
    	{
    		write2end = f->size;
    		pwrite -= write2end;
    	}
    	
    	f->write2end = write2end;
    	f->pwrite = pwrite;
    
    	uint8_t sreg = SREG;
    	cli();
    	f->count++;
    	SREG = sreg;
    	
    	return 1;
    }
    
    dank im voraus

  2. #2
    Neuer Benutzer Öfters hier
    Registriert seit
    10.12.2007
    Beiträge
    18

    Vergessen: Kontroller= ATmega32, auf RBN-FRA1.21

    Hallo nochmal,

    habe folgende wichtige Punkte vergessen:

    Kontroller= ATmega32, auf RBN-FRA1.21

    Weis aber nicht ob es diese Daten die Ursache erklären...

    Grüße
    Khan

  3. #3
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    10.08.2004
    Ort
    Großbardorf
    Alter
    37
    Beiträge
    674
    Wie sieht denn der Code zu uart_init aus? Aktivierst du da vielleicht interrupts? Wenn du dann die ISR dazu nicht schreibst, dürfte es Probleme(Reset des AVR) geben. Das würde ja genau das Verhalten deines AVRs beschreiben.

  4. #4
    Neuer Benutzer Öfters hier
    Registriert seit
    10.12.2007
    Beiträge
    18
    Danke für dein Beitrag!
    Allerdings habe ich dass was du meintest nicht ganz verstanden...

    meinst du ich tue den Kontroller irgend wo resetten?
    Dass würde natürlich alles erklären. Allerdings habe ich die Stelle nicht gefunden und arbeite mich grad in Interrupts ein...

    Wenn ein Reset stattfindet muss es nach dem ich das Zeichen gesendet habe geschehen, sonnst würde ich ja nichts bekommen wenn ich im uart_init reset machen würde....

    Wie du siehst bin ich etwas verwirrt kannst du mir bitte dies bzgl. den Ort und den Grund für mein Fehler äußern...

    Uart_init:
    Code:
    void uart_init()
    {
    	uint8_t sreg = SREG;
    	UBRRH = UBRR_VAL >> 8;
    	UBRRL = UBRR_VAL & 0xFF;
    	
    	cli();														 /* Interrupts kurz deaktivieren */
    	UCSRB |= (1<<TXCIE) | (1<<TXEN);   /* TXCompleteInterrupt u. TX einschalten */
    	UCSRC |= (1<<URSEL)| (1<<UCSZ1) | (1<<UCSZ0);    /* Asynchron 8N1 	*/
    	
    	/* Flush Receive-Buffer (entfernen evtl. vorhandener ungültiger Werte) */ 
    	do
    	{
    	 /* UDR auslesen (Wert wird nicht verwendet) */ 
    		UDR;
    	}while (UCSRA & (1 << RXC));
    	
      /* Rücksetzen von Receive und Transmit Complete-Flags */ 
      UCSRA = (1 << RXC) | (1 << TXC);
      
    	/* Global Interrupt-Flag wieder herstellen */
    	SREG = sreg;											
    	
      /* FIFOs für Ein- und Ausgabe initialisieren */ 
      fifo_init (&in_fifo,   in_buffer, BUF_SIZE_IN);
      fifo_init (&out_fifo, out_buffer, BUF_SIZE_OUT);
    }
    und
    Code:
    /*********************** INTERRUPTS ****************************************/
    // Empfangene Zeichen werden in die Eingabgs-FIFO gespeichert und warten dort 
    SIGNAL (SIG_UART_RECV)
    {
        _inline_fifo_put (&in_fifo, UDR);
    }
    
    // Ein Zeichen aus der Ausgabe-FIFO lesen und ausgeben 
    // Ist das Zeichen fertig ausgegeben, wird ein neuer SIG_UART_DATA-IRQ getriggert 
    // Ist die FIFO leer, deaktiviert die ISR ihren eigenen IRQ. 
    SIGNAL (SIG_UART_DATA)
    {
        if (out_fifo.count > 0)
           UDR = _inline_fifo_get (&out_fifo);
        else
            UCSRB &= ~(1 << UDRIE);
    }

  5. #5
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    20.05.2006
    Ort
    Lippe
    Alter
    54
    Beiträge
    524
    Hallo,

    Code:
    // Ein Zeichen aus der Ausgabe-FIFO lesen und ausgeben 
    // Ist das Zeichen fertig ausgegeben, wird ein neuer SIG_UART_DATA-IRQ getriggert 
    // Ist die FIFO leer, deaktiviert die ISR ihren eigenen IRQ. 
    SIGNAL (SIG_UART_DATA) 
    { 
        if (out_fifo.count > 0) 
           UDR = _inline_fifo_get (&out_fifo); 
        else 
            UCSRB &= ~(1 << UDRIE); 
    }
    Wahrscheinlich ist out_fifo.count immer > 0 und _inline_fifo_get (&out_fifo); ergibt immer 'f'.

    Gruß

    Jens

  6. #6
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    10.08.2004
    Ort
    Großbardorf
    Alter
    37
    Beiträge
    674
    Das ist doch wieder nicht der komplette code, oder? Wie soll man da wirklich helfen, wenn da immer irgendwo was fehlt.
    Hast du das selbst programmiert? Oder hast du das von irgendwo hergenommen? Müsste das funktionieren, falls du es übernommen hast, oder ist es eher was experimentelles?
    Was mir aufgefallen ist, ist, dass in der uart_init zwar der TXComplete-Interrupt aktiviert wird, aber da gibts keine ISR dazu und der wird ja dann ausgelöst, wenn was gesendet wurde. Und wenns dann keine ISR dazu gibt, gibts Probleme. Wahrscheinlich ist es das. Es sei denn das findet sich in einem anderen code-Teil...

  7. #7
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    20.05.2006
    Ort
    Lippe
    Alter
    54
    Beiträge
    524
    Hallo Pascal,

    Das ist doch wieder nicht der komplette code, oder?
    Das wollte ich mit meinem Posting ausdrücken.

    Gruß

    Jens

  8. #8
    Neuer Benutzer Öfters hier
    Registriert seit
    10.12.2007
    Beiträge
    18
    Ok,

    Eine ISR habe ich nicht.
    es wird aber auch nicht vom
    https://www.roboternetz.de/wissen/in...RT_mit_avr-gcc
    explizit erwähnt, oder ich habe es überlesen....

    Habe ja auch fast alles von dort kopiert...

    Hier der Gesamte Kode:

    Main.c

    Code:
    #include <avr/interrupt.h>  /* Wird nur gebraucht bei der Interrupt-Version */ 
    #include "uart.h"
    /*==================[macros]=================================================*/
    /* Ein Zeilenumbruch, abhängig davon, was die Gegenstelle haben will */ 
    /* Windows: "rn" */ 
    /* Linux  : "n"  */ 
    /* MacOS  : "r"  */ 
    #define CR "\r\n"
    /*==================[type definitions]=======================================*/
    
    /*==================[internal function declarations]=========================*/
    
    /*==================[external constants]=====================================*/
    
    /*==================[internal constants]=====================================*/
    
    /*==================[internal data]==========================================*/
    
    /*==================[external function definitions]==========================*/
    
    /*==================[internal function definitions]==========================*/
    
    
    
    
    int main()
    {
        uart_init();
        sei();   // Wird nur gebraucht bei der Interrupt-Version 
    
        uart_putc ('f');
        /*uart_puts ("Hallo Welt!" CR);*/
    
        while (1);
    
    
        return 0;
    }
    /** @} doxygen end group definition */
    /*==================[end of file]============================================*/
    uart.h:

    Code:
    #include <avr/io.h>
    
    /*==================[macros]=================================================*/
    
    /*==================[type definitions]=======================================*/
    
    /*==================[external function declarations]=========================*/
    extern void 		uart_init();
    extern int 			uart_putc(const uint8_t);
    extern uint8_t 	uart_getc_wait();
    extern int     	uart_getc_nowait();
    
    extern void uart_puts (char *string_data);
    
    /* Wartet, bis die Übertragung fertig ist. */
    static inline void uart_flush()
    {
    	while (UCSRB & (1 << UDRIE));
    }
    /*==================[external constants]=====================================*/
    
    /*==================[external data]==========================================*/
    
    
    /** @} doxygen end group definition */
    #endif /* _UART_H_ */
    /*==================[end of file]============================================*/


    uart.c:

    Code:
    #include <avr/io.h>
    #include <avr/interrupt.h>
    #include "uart.h"
    #include "fifo.h"
    /*==================[macros]=================================================*/
    #ifndef F_CPU
    /* In neueren Version der WinAVR/Mfile Makefile-Vorlage kann
       F_CPU im Makefile definiert werden, eine nochmalige Definition
       hier wuerde zu einer Compilerwarnung fuehren. Daher "Schutz" durch
       #ifndef/#endif 
     
       Dieser "Schutz" kann zu Debugsessions führen, wenn AVRStudio 
       verwendet wird und dort eine andere, nicht zur Hardware passende 
       Taktrate eingestellt ist: Dann wird die folgende Definition 
       nicht verwendet, sondern stattdessen der Defaultwert (8 MHz?) 
       von AVRStudio - daher Ausgabe einer Warnung falls F_CPU
       noch nicht definiert: */
    #warning "F_CPU war noch nicht definiert, wird nun nachgeholt mit 8000000"
    #define F_CPU 8000000L    // Systemtakt in Hz, das L am Ende ist wichtig, NICHT UL verwenden! 
    #endif
     
    #define BAUD 9600L          // Baudrate, das L am Ende ist wichtig, NICHT UL verwenden!
     
    // Berechnungen
    #define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1)   /* clever runden */
    #define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1)))     /* Reale Baudrate */
    #define BAUD_ERROR ((BAUD_REAL*1000)/BAUD-1000) /* Fehler in Promille */
    /*
    #if (((BAUD_ERROR) > (10)) || ((BAUD_ERROR) < (-10)))
      #error Systematischer Fehler der Baudrate grösser 1% und damit zu hoch! 
    #endif
    */
    #define BUF_SIZE_IN		0x40													/* FIFO-Buffergröße */
    uint8_t in_buffer[BUF_SIZE_IN];
    fifo_t in_fifo;
    
    #define BUF_SIZE_OUT		0x40													/* FIFO-Buffergröße */
    uint8_t out_buffer[BUF_SIZE_OUT];
    fifo_t out_fifo;
    
    /*********     FUNKTIONEN       ***********/
    
    void uart_init()
    {
    	uint8_t sreg = SREG;
    	UBRRH = UBRR_VAL >> 8;
    	UBRRL = UBRR_VAL & 0xFF;
    	
    	cli();														 /* Interrupts kurz deaktivieren */
    	UCSRB |= (1<<TXCIE) | (1<<TXEN);   /* TXCompleteInterrupt u. TX einschalten */
    	UCSRC |= (1<<URSEL)| (1<<UCSZ1) | (1<<UCSZ0);    /* Asynchron 8N1 	*/
    	
    	/* Flush Receive-Buffer (entfernen evtl. vorhandener ungültiger Werte) */ 
    	do
    	{
    	 /* UDR auslesen (Wert wird nicht verwendet) */ 
    		UDR;
    	}while (UCSRA & (1 << RXC));
    	
      /* Rücksetzen von Receive und Transmit Complete-Flags */ 
      UCSRA = (1 << RXC) | (1 << TXC);
      
    	/* Global Interrupt-Flag wieder herstellen */
    	SREG = sreg;											
    	
      /* FIFOs für Ein- und Ausgabe initialisieren */ 
      fifo_init (&in_fifo,   in_buffer, BUF_SIZE_IN);
      fifo_init (&out_fifo, out_buffer, BUF_SIZE_OUT);
    }
    
    /* Senden eines Chars */
    int uart_putc (const uint8_t data)
    {
    	int ret = fifo_put (&out_fifo, data);
    	UCSRB |= (1 << UDRIE);
     
      return ret;
    }
    
    /**/
    int uart_getc_nowait ()
    {
    	return fifo_get_nowait (&in_fifo);
    }
    /**/
    uint8_t uart_getc_wait ()
    {
    	return fifo_get_wait (&in_fifo);
    }
    
    /* Senden eines Strings */
    void uart_puts (char *string_data)
    {
    	while (*string_data)				/* Wiederhole bis im String '\0' erreicht wurde (*s != '\0') */
    	{
    		uart_putc (*string_data);	/* Gebe ein Zeichen aus*/
    		string_data++;						/* Erhöhe den String um ein Character */
    	}
    }
    
    /*********************** INTERRUPTS ****************************************/
    // Empfangene Zeichen werden in die Eingabgs-FIFO gespeichert und warten dort 
    SIGNAL (SIG_UART_RECV)
    {
        _inline_fifo_put (&in_fifo, UDR);
    }
    
    // Ein Zeichen aus der Ausgabe-FIFO lesen und ausgeben 
    // Ist das Zeichen fertig ausgegeben, wird ein neuer SIG_UART_DATA-IRQ getriggert 
    // Ist die FIFO leer, deaktiviert die ISR ihren eigenen IRQ. 
    SIGNAL (SIG_UART_DATA)
    {
        if (out_fifo.count > 0)
           UDR = _inline_fifo_get (&out_fifo);
        else
            UCSRB &= ~(1 << UDRIE);
    }
    /*********************** ENDE INTERRUPTS ***********************************/
    /** @} doxygen end group definition */
    /*==================[end of file]============================================*/
    fifo.h
    Code:
    #ifndef FIFO_H_
    #define FIFO_H_
    
    #include <avr/io.h>
    #include <avr/interrupt.h>
    
    typedef struct
    {
    	uint8_t volatile count;       // # Zeichen im Puffer
    	uint8_t size;                 // Puffer-Größe
    	uint8_t *pread;               // Lesezeiger
    	uint8_t *pwrite;              // Schreibzeiger
    	uint8_t read2end, write2end;  // # Zeichen bis zum Überlauf Lese-/Schreibzeiger
    } fifo_t;
    
    extern void fifo_init (fifo_t*, uint8_t* buf, const uint8_t size);
    extern uint8_t fifo_put (fifo_t*, const uint8_t data);
    extern uint8_t fifo_get_wait (fifo_t*);
    extern int fifo_get_nowait (fifo_t*);
    
    
    /* Schreibt das nächste Byte "data" in die FIFO.
     * Liefer 1 bei Erfolg und 0, falls die FIFO voll ist. */
    static inline uint8_t _inline_fifo_put (fifo_t *f, const uint8_t data)
    {
    	if (f->count >= f->size)
    		return 0;
    		
    	uint8_t * pwrite = f->pwrite;
    	
    	*(pwrite++) = data;
    	
    	uint8_t write2end = f->write2end;
    	
    	if (--write2end == 0)
    	{
    		write2end = f->size;
    		pwrite -= write2end;
    	}
    	
    	f->write2end = write2end;
    	f->pwrite = pwrite;
    
    	uint8_t sreg = SREG;
    	cli();
    	f->count++;
    	SREG = sreg;
    	
    	return 1;
    }
    
    
    /* Liefert das nächste Zeichen aus der FIFO. Ob überhaubt ein Zeichen in der FIFO
     * ist, muss vorher extra abgeprüft werden */
    static inline uint8_t _inline_fifo_get (fifo_t *f)
    {
    	uint8_t *pread = f->pread;
    	uint8_t data = *(pread++);
    	uint8_t read2end = f->read2end;
    	
    	if (--read2end == 0)
    	{
    		read2end = f->size;
    		pread -= read2end;
    	}
    	
    	f->pread = pread;
    	f->read2end = read2end;
    	
    	uint8_t sreg = SREG;
    	cli();
    	f->count--;
    	SREG = sreg;
    	
    	return data;
    }
    
    
    #endif /*FIFO_H_*/

    fifo.c:
    Code:
    #include "fifo.h"
    
    /* Initialisiert die FIFO, setzt Lese- und Schreibzeiger, etc. 
     * Die FIFO verwendet den Puffer "buffer", der "size" Bytes sein muss. */
    void fifo_init (fifo_t *f, uint8_t *buffer, const uint8_t size)
    {
    	f->count = 0;
    	f->pread = f->pwrite = buffer;
    	f->read2end = f->write2end = f->size = size;
    }
    
    /* Schreibt das nächste Byte "data" in die FIFO.
     * Liefer 1 bei Erfolg und 0, falls die FIFO voll ist. */
    uint8_t fifo_put (fifo_t *f, const uint8_t data)
    {
    	return _inline_fifo_put (f, data);
    }
    
    /* Liefert das nächste Byte aus der FIFO, bei leerer FIFO wird gewartet, 
     * bis das nächste Zeichen eintrift. */
    uint8_t fifo_get_wait (fifo_t *f)
    {
    	while (!f->count);
    	return _inline_fifo_get (f);	
    }
    
    /* Liefert das nächste Byte aus der FIFO als "int" bzw. -1, 
     * falls die FIFO leer ist. */
    int fifo_get_nowait (fifo_t *f)
    {
    	if (!f->count)		return -1;
    	return (int) _inline_fifo_get (f);	
    }

  9. #9
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    20.05.2006
    Ort
    Lippe
    Alter
    54
    Beiträge
    524
    Hallo,

    schreib mal in der main
    Code:
    while (1){
    asm("nop");
    }
    oder setz die Optimierung auf -O0

    BTW Variablen die in ISR's benutzt werden sollten imm er volatile declariert werden.
    volatile fifo_t out_fifo;

    Gruß

    Jens

  10. #10
    Erfahrener Benutzer Robotik Visionär Avatar von Hubert.G
    Registriert seit
    14.10.2006
    Ort
    Pasching OÖ
    Beiträge
    6.220
    Eine ISR habe ich nicht.
    Was ist das dann in deiner uart.c ?
    Ausserdem sicherst du in deinen Routinen das SREG, warum? In C wird das SREG, wenn notwendig, automatisch gesichert. Wenn du es sonst machen willst, solltest du genau wissen was du tust, du kannst dir da sonst einen schönen pffff... einhandeln.
    Grüsse Hubert
    ____________

    Meine Projekte findet ihr auf schorsch.at

Seite 1 von 2 12 LetzteLetzte

Berechtigungen

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

MultiPlus Wechselrichter Insel und Nulleinspeisung Conrad