- Akku Tests und Balkonkraftwerk Speicher         
Ergebnis 1 bis 8 von 8

Thema: UART mit ATmega128

  1. #1
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    03.07.2006
    Beiträge
    143

    UART mit ATmega128

    Anzeige

    Praxistest und DIY Projekte
    Hallo zusammen!
    Ich habe ein Modul von siphec.com mit einem Atmega 128 drauf.
    das Modul besitzt eine USB schnittstelle, die mittels einen VCP (Virtual comport Driver) direkt als RS232 angesprochen wird.
    Das system hat mir die Treiber richtig Installier, und bei mir ist ein Comport, COM5 entstanden. soweit alles i.o.

    Nun habe ich das UART Programm von AVR-gcc hier aus dem RN-WISSSEN Artikel berreich kopiert und auf den Mega128 geladen.

    https://www.roboternetz.de/wissen/in...RT_mit_avr-gcc

    Da der Atmeg128 zwei UART besitzt, habe ich mal UART0 genommen (ich habe beide Ausprobiert..)

    Vorerst hat es einen Fehler beim Compilieren gegeben in der UART.c:

    Code:
      
    UCSR0B = (1 << RXEN) | (1 << TXEN) | (1 << RXCIE);
    UCSR0C = (1 << URSEL) | (1 << UCSZ1) | (1 << UCSZ0);
    Das Flag URSEL kennt mein Atmega nicht, ist hier UMSEL0 gemeint?
    Mit Umsel komliert, und hochgeladen.

    Nun Hyperterminal gestartet, com5 und die richrige Baudrate.
    Doch es passiert leider garnix das Hyperterm verbdindet aber der Bildschirm bleibt einfach weiss...

    kann mir jemand weiterhelfen??

    viele Grüsse
    Chris

  2. #2
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    03.07.2006
    Beiträge
    143
    hmm, ich bin mittlerweile etwas schlauer geworden
    Das Board das ich habe, verwendet den UART1 des ATMega128.

    Nachdem ich alles nochmals überprüft habe, gelingt es mir jetzt über UART einen String auszugeben.
    Leider aber nicht mit der FIFO und Interrupt methode.

    Obwohl die ISR's aufgeruft werden (habe ich mit einer LED kontrolliert) sendet, und empfängt der prozessor garnichts.

    kann mir jemadn weiterhelfen???

    wen nich die funktion uart_puts2 aufrufe, bekomme ich im Hyperterminal die richtige Ausgabe...

    Doch leider kann ich keinen char einlesen

    uart.h
    Code:
    #ifndef _UART_H_
    #define _UART_H_
    
    #include <avr/io.h>
    
    extern void uart_init();
    extern int uart_putc (const uint8_t);
    extern uint8_t uart_getc_wait();
    extern int     uart_getc_nowait();
    
    static inline void uart_flush()
    {
    	while (UCSR1B & (1 << UDRIE1));
    }
    
    #endif /* _UART_H_ */
    uart.c
    Code:
    #include <avr/io.h>
    #include <avr/interrupt.h>
    #include "uart.h"
    #include "fifo.h" // erklärt im Artikel "FIFO mit avr-gcc"
    
    #define BAUDRATE 9600L
    #define BAUD 9600L          // Baudrate, das L am Ende ist wichtig, NICHT UL verwenden!
     
    #define F_CPU 16000000L    // Systemtakt in Hz, 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
    
    
    // FIFO-Objekte und Puffer für die Ein- und Ausgabe 
    #define BUFSIZE_IN  0x40
    uint8_t inbuf[BUFSIZE_IN];
    fifo_t infifo;
    
    #define BUFSIZE_OUT 0x40
    uint8_t outbuf[BUFSIZE_OUT];
    fifo_t outfifo;
    
    void uart_init()
    {
      uint8_t sreg = SREG;
    
      UBRR1H = UBRR_VAL >> 8;
      UBRR1L = UBRR_VAL & 0xFF;
    
        // Interrupts kurz deaktivieren 
        cli();
    
        // UART Receiver und Transmitter anschalten, Receive-Interrupt aktivieren 
        // Data mode 8N1, asynchron 
    	UCSR1B = (1<<RXEN1) | (1<<TXEN1) | (1 << RXCIE1);
    	UCSR1C = (1 << USBS1)|(1<<UCSZ1) | (1<<UCSZ0);
    
        // Flush Receive-Buffer (entfernen evtl. vorhandener ungültiger Werte) 
        do
        {
            // UDR auslesen (Wert wird nicht verwendet) 
            UDR1;
        }
        while (UCSR1A & (1 << RXC1));
    
        // Rücksetzen von Receive und Transmit Complete-Flags 
        UCSR1A = (1 << RXC1) | (1 << TXC1);
    
        // Global Interrupt-Flag wieder herstellen 
        SREG = sreg;
    
        // FIFOs für Ein- und Ausgabe initialisieren 
        fifo_init (&infifo,   inbuf, BUFSIZE_IN);
        fifo_init (&outfifo, outbuf, BUFSIZE_OUT);
    }
    
    // Empfangene Zeichen werden in die Eingabgs-FIFO gespeichert und warten dort 
    ISR (USART1_RX_vect)//SIG_UART1_RECV)
    {
        _inline_fifo_put (&infifo, UDR1);
    }
    
    // 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. 
    ISR (USART1_UDRE_vect)//SIG_UART1_DATA)
    {
    
        if (outfifo.count > 0)
           UDR1 = _inline_fifo_get (&outfifo);
        else
            UCSR1B &= ~(1 << UDRIE1);
    }
    
    
    
    int uart_putc2(unsigned char c)
    {
        while (!(UCSR1A & (1<<UDRE1)))  // warten bis Senden moeglich 
        {
        }
     
        UDR1 = c;                      // sende Zeichen 
        return 0;
    }
     
     
    void uart_puts2 (char *s)
    {
        while (*s)
        {   // so lange *s != '\0' also ungleich dem "String-Endezeichen" 
            uart_putc2(*s);
            s++;
        }
    }
    
    
    
    int uart_putc (const uint8_t c)
    {
        int ret = fifo_put (&outfifo, c);
    	
        UCSR1B |= (1 << UDRIE1);
    
       return ret;
    }
    
    
    
    int uart_getc_nowait ()
    {
        return fifo_get_nowait (&infifo);
    }
    
    uint8_t uart_getc_wait ()
    {
        return fifo_get_wait (&infifo);
    }

    main
    Code:
    #include <avr/interrupt.h>  // Wird nur gebraucht bei der Interrupt-Version 
    #include "uart.h"
    
    // Einen 0-terminierten String übertragen. 
    void uart_puts (const char *s)
    {
        do
        {
            uart_putc (*s);
        }
        while (*s++);
    }
    
    
    #define CR "\r\n"
    
    char text[] = "Hallo Welt2." CR;
    
    int main()
    {
        uart_init();
        sei();   // Wird nur gebraucht bei der Interrupt-Version 
    	PORTD=0x00;
    
    
     
    	int i;
    	for(i=0;i<5000;i++){
      	uart_puts (text);
    	}    
    
    
        return 0;
    }
    Fifio.c
    Code:
    #include "fifo.h"
    
    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;
    }
    
    uint8_t fifo_put (fifo_t *f, const uint8_t data)
    {
    	return _inline_fifo_put (f, data);
    }
    
    uint8_t fifo_get_wait (fifo_t *f)
    {
    	while (!f->count);
    	
    	return _inline_fifo_get (f);	
    }
    
    int fifo_get_nowait (fifo_t *f)
    {
    	if (!f->count)		return -1;
    		
    	return (int) _inline_fifo_get (f);	
    }
    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*);
    
    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;
    }
    
    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_ */

  3. #3
    Erfahrener Benutzer Robotik Einstein Avatar von SprinterSB
    Registriert seit
    09.06.2005
    Ort
    An der Saar
    Beiträge
    2.802
    So auf den ersten Blick seh ich net, daß da was offensichtlich falsch ist.

    Was ich aber mal kontrollieren würde ist:
    • Die Werte fürs Baudratenregister (im Assembler-Dump/Disassembly)
    • Schauen, ob die UCSRnx Bits nicht evtl. in einem anderen SFR stehen als beim ATmega8 (für den die Quelle ursprünglich geschrieben war)
    • Den Namen der ISRs überprüfen. Fürs Senden gibt's 2 IRQs ("data register empty" und "transmission complete" oder so.) Evtl hat sich die Bedienung etwas geändert von ATmega8 nach ATmega128. Unbedingt ins Handbuch schauen!


    Bei 16MHz sollte 9600Bd kein Problem sein; auch 38400Bd geht ohne Probleme.
    Disclaimer: none. Sue me.

  4. #4
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    03.07.2006
    Beiträge
    143
    Vielen Dank für deine Antwort!

    Ich denke die Werte für die Baudrate ist korrekt, weil die _puts2 ja funktioniert.

    die UCSR Bits mit denen bin ich etwas auf kriegsfuss, kann es sein das die im Datenblatt garnicht beschribeen sind???

    die ISR habe ich auch schon überprüft, und verschiedene Varianten ausprobiert



  5. #5
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    03.07.2006
    Beiträge
    143
    hmm, ich bin einen kleinen Schritt weiter.
    Ich habe die Flusssteuerung im Hyper term auf "keine" gestellt.
    Jetzt empfange ich teilweise dass was ich sende.
    z.b. die buchstaben "i" und "k" funktionieren perfekt, alles andere kommt irgend was komisches raus.. bei v z.b. vw...??? jemand noch eine Idee?

  6. #6
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    03.07.2006
    Beiträge
    143
    ok, ich glaube es liegt definitiv an dem USCR zeug
    wenn ich beim Hyperterm auf 7 Datenbits stelle, kommt wenn ich "b" drücke z.b.: bcdefghijklmnopqrstuvwxyz{|}~Hallo Welt77.

    der erste Buchstabe ist immer Korrekt! nur das Gemüse hinterher brauche ich nicht...
    kann mir jemand das mit den UCSR1C Register erklären?

  7. #7
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    03.07.2006
    Beiträge
    143
    Juhhu, es hat Funktioniert
    mit:
    UCSR1C = (0 << UMSEL1)|(0<<UPM11) | (0<<UPM10)| (0<<USBS1)| (0<<UCSZ02)| (1<<UCSZ11)| (1<<UCSZ10) | (0<<UCPOL1);

    für 19200 8datenbits, 1 stopbit, noparity

  8. #8
    Erfahrener Benutzer Robotik Einstein Avatar von SprinterSB
    Registriert seit
    09.06.2005
    Ort
    An der Saar
    Beiträge
    2.802
    Also 8N1 (8 Bits, No parity, 1 Stop), was die übliche Einstellung für den UART ist. Das es bei 19200 geht, aber 9600 eingestellt sind, liegt evtl an unkorrekten Fuse-Einstellungen oder einem versehentlich (nicht) gesetzten U2X-Bit, d.h. die Baudrate wird (nicht) verdoppelt.
    Disclaimer: none. Sue me.

Berechtigungen

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

MultiPlus Wechselrichter Insel und Nulleinspeisung Conrad