-         

Ergebnis 1 bis 7 von 7

Thema: UART bei Mega2560

  1. #1
    Erfahrener Benutzer Robotik Einstein Avatar von Jaecko
    Registriert seit
    16.10.2006
    Ort
    Lkr. Rottal/Inn
    Alter
    35
    Beiträge
    1.987

    UART bei Mega2560

    Anzeige

    Moin.

    Hab hier mal ein minimalistisches Stück C-Code, welches vom ATMega2560 über den UART2 was senden soll. Nur irgendwo scheint da noch ein Wurm drin zu sein. Den Ursprung hat der Code im RN-Wissen, wo er auch anfangs auf nem Mega8 lief, und das so wie gewünscht.
    Nur der Umbau auf M2560 (oder auch M12 klappt nicht so wie geplant. Wenn ich mir die Tx-Leitung mit nem Oszi anschau, rührt sich da garnix, ne schöne Null-Linie.
    Der Code ist so ausgelegt, dass in der eigentlich im Projekt verwendeten Version jeder UART (0-3) verwendet werden kann, deshalb die Angabe des Channels. Da der Code für alle 4 UARTs - bis auf die Channel-abhängigen Teile - identisch ist, hab ich die anderen, im Moment nicht nötigen Teile rausgeworfen. (UART 0, 1 und 3 gehen aber ebenfalls nicht)

    Dass die Hardware OK ist, ist sicher, da die Ausgabe mit Bascom auf allen 4 UARTs perfekt funktioniert.

    Sieht da jemand den Fehler?

    Code:
    // CPU: ATMega2560 (RN-Board) @ 16 MHz
    #include <avr/io.h>
    #include <avr/interrupt.h>
    #include <util/delay.h>
    #include "glob_type.h"
    #include "glob_errors.h"
    #include "glob_defs.h"
    
    // defines
    #define BUFSIZE2_IN   16
    #define BUFSIZE2_OUT  16
    
    
    // types
    typedef struct
    {
      ui8_t volatile count;       // # Zeichen im Puffer
      ui8_t size;                 // Puffer-Größe
      ui8_t *pread;               // Lesezeiger
      ui8_t *pwrite;              // Schreibzeiger
      ui8_t read2end, write2end;  // # Zeichen bis zum Überlauf Lese-/Schreibzeiger
    } fifo_t;
    
    
    // Function Prototypes:
    void     USART_Init(ui8_t chan, ui32_t baud);
    void     USART_PutS(ui8_t channel, const char *s);
    ui8_t    USART_PutC (ui8_t channel, const ui8_t c);
    void     FIFO_Init (fifo_t *f, ui8_t *buffer, const ui8_t size);
    e_errors FIFO_Put (fifo_t *f, const ui8_t data);
    
    
    // Global variables
    ui8_t  inbuf2[BUFSIZE2_IN];
    ui8_t  outbuf2[BUFSIZE2_OUT];
    fifo_t infifo2;
    fifo_t outfifo2;
     
    
    // Inline Functions
    static inline e_errors
    _inline_fifo_put (fifo_t *f, const ui8_t data)
    {
      if (f->count >= f->size)
      {
        return ERR_BUFFER_FULL;
      }
      
      ui8_t * pwrite = f->pwrite;
      
      *(pwrite++) = data;
      
      ui8_t write2end = f->write2end;
      
      if (--write2end == 0)
      {
        write2end = f->size;
        pwrite -= write2end;
      }
      
      f->write2end = write2end;
      f->pwrite = pwrite;
    
      ui8_t sreg = SREG;
      cli();
      f->count++;
      SREG = sreg;
     
      return ERR_OK;
    }
    
    
    static inline ui8_t 
    _inline_fifo_get (fifo_t *f)
    {
      ui8_t *pread = f->pread;
      ui8_t data = *(pread++);
      ui8_t read2end = f->read2end;
      
      if (--read2end == 0)
      {
        read2end = f->size;
        pread -= read2end;
      }
      
      f->pread = pread;
      f->read2end = read2end;
      
      ui8_t sreg = SREG;
      cli();
      f->count--;
      SREG = sreg;
      
      return data;
    }
    
    
    
    // Main
    int main (void)
    {
      USART_Init(2, 9600L);             // USART Channel 2 (Onboard/TTL)
      sei();
    
      while(1)
      {
        USART_PutS(2, "Test\r\n");
        _delay_ms(250);
      }
      return 0;
    }
    
    
    
    // Functions
    void USART_Init(ui8_t chan, ui32_t baud)
    {
      ui8_t sreg = SREG;
      ui16_t ubrr;
      switch(chan)
      {
        case 2:
          ubrr = (ui16_t) ((ui32_t) F_CPU / (16 * baud) - 1);
          UBRR2H = (ui8_t) (ubrr>>8);
          UBRR2L = (ui8_t) (ubrr);
          cli();
          UCSR0B = (1 << RXEN2) | (1 << TXEN2) | (1 << RXCIE2);
          UCSR0C = (1 << UMSEL21) | (1 << UCSZ21) | (1 << UCSZ20);
          do
          {
            UDR2;
          } while (UCSR2A & (1 << RXC2));
    
          UCSR2A = (1 << RXC2) | (1 << TXC2);
          SREG = sreg;
          FIFO_Init (&infifo2,  inbuf2,  BUFSIZE2_IN);
          FIFO_Init (&outfifo2, outbuf2, BUFSIZE2_OUT);
          break;
      } // END:switch(chan)
    }
    
    void USART_PutS(ui8_t channel, const char *s)
    {
      do
      {
        USART_PutC(channel, *s);
      } while (*s++);
    }
    
    ui8_t USART_PutC (ui8_t channel, const ui8_t c)
    {
      ui8_t ret = 0;
      switch(channel)
      {
        case 2:
          ret = FIFO_Put(&outfifo2,c);
          UCSR2B |= (1 << UDRIE2);
          break;
      }
      return ret;
    }
    
    
    void FIFO_Init (fifo_t *f, ui8_t *buffer, const ui8_t size)
    {
      f->count = 0;
      f->pread = f->pwrite = buffer;
      f->read2end = f->write2end = f->size = size;
    }
    
    
    e_errors FIFO_Put (fifo_t *f, const ui8_t data)
    {
      return _inline_fifo_put (f, data);
    }
    
    
    // Interrupts:
    SIGNAL(SIG_USART2_RECV)
    {
      _inline_fifo_put (&infifo2,UDR2);
    }
    
    SIGNAL(SIG_USART2_DATA)
    {
      if (outfifo2.count > 0)
      {
        UDR2 = _inline_fifo_get (&outfifo2);
      } else {
        UCSR2B &= ~(1 << UDRIE2);
      }
    }

    mfG
    Angehängte Dateien Angehängte Dateien
    #ifndef MfG
    #define MfG

  2. #2
    Erfahrener Benutzer Roboter Experte Avatar von sternst
    Registriert seit
    07.07.2008
    Beiträge
    672
    Code:
    void USART_Init(ui8_t chan, ui32_t baud)
    ...
        case 2:
    ...
          UCSR0B = ...
          UCSR0C = ...
    MfG
    Stefan

  3. #3
    Erfahrener Benutzer Robotik Einstein Avatar von Jaecko
    Registriert seit
    16.10.2006
    Ort
    Lkr. Rottal/Inn
    Alter
    35
    Beiträge
    1.987
    Thx...
    War mal wieder ein Klassiker.
    #ifndef MfG
    #define MfG

  4. #4
    Habe seit Tagen auch Probleme mit der USART2 Schnittstelle am RN Mega2560. Senden vom Board an den PC geht ohne Probleme. Nur leider empfängt das Board nichts!
    Die ISR wird nicht aufgerufen bzw. irgenwdwie registriert der uC die Befehle nicht.

    Code funtkioniert 100% (ist der Code von oben). Code funktioniert nämlich sowohl mit USART0 und USART1 (senden und empfangen). Hab auch alles schon 10 mal überprüft ob ich evtl ne '0' oder ne '1' anstelle ner '2' bei den Registern stehen habe... aber Fehlanzeige.
    Board kanns auch nicht sein. Hab ein zweites bereits ausprobiert.
    Hat jemand ne Ahnung was es noch sein könnte? evtl falsche Compilierung? Jaecko, hast du die USART2 Schnittstelle zum Senden UND Empfangen bekommen?
    Geändert von Christian86 (22.08.2012 um 11:17 Uhr)

  5. #5
    Code:
    // CPU: ATMega2560 (RN-Board) @ 16 MHz
    #include <avr/io.h>
    #include <avr/interrupt.h>
    #include <util/delay.h>
    #include "header/glob_type.h"
    #include "header/glob_errors.h"
    #include "header/glob_defs.h"
    
    // defines
    #define BUFSIZE2_IN   16
    #define BUFSIZE2_OUT  16
    
    
    // types
    typedef struct
    {
      ui8_t volatile count;       // # Zeichen im Puffer
      ui8_t size;                 // Puffer-Größe
      ui8_t *pread;               // Lesezeiger
      ui8_t *pwrite;              // Schreibzeiger
      ui8_t read2end, write2end;  // # Zeichen bis zum Überlauf Lese-/Schreibzeiger
    } fifo_t;
    
    
    // Function Prototypes:
    void     USART_Init(ui8_t chan, ui32_t baud);
    void     USART_PutS(ui8_t channel, const char *s);
    ui8_t    USART_PutC (ui8_t channel, const ui8_t c);
    void     FIFO_Init (fifo_t *f, ui8_t *buffer, const ui8_t size);
    e_errors FIFO_Put (fifo_t *f, const ui8_t data);
    
    
    // Global variables
    ui8_t  inbuf2[BUFSIZE2_IN];
    ui8_t  outbuf2[BUFSIZE2_OUT];
    fifo_t infifo2;
    fifo_t outfifo2;
    
    int volatile received;
    
    
    // Inline Functions
    static inline e_errors
    _inline_fifo_put (fifo_t *f, const ui8_t data)
    {
      if (f->count >= f->size)
      {
        return ERR_BUFFER_FULL;
      }
    
      ui8_t * pwrite = f->pwrite;
    
      *(pwrite++) = data;
    
      ui8_t write2end = f->write2end;
    
      if (--write2end == 0)
      {
        write2end = f->size;
        pwrite -= write2end;
      }
    
      f->write2end = write2end;
      f->pwrite = pwrite;
    
      ui8_t sreg = SREG;
      cli();
      f->count++;
      SREG = sreg;
    
      return ERR_OK;
    }
    
    
    static inline ui8_t
    _inline_fifo_get (fifo_t *f)
    {
      ui8_t *pread = f->pread;
      ui8_t data = *(pread++);
      ui8_t read2end = f->read2end;
    
      if (--read2end == 0)
      {
        read2end = f->size;
        pread -= read2end;
      }
    
      f->pread = pread;
      f->read2end = read2end;
    
      ui8_t sreg = SREG;
      cli();
      f->count--;
      SREG = sreg;
    
      return data;
    }
    
    
    
    // Main
    int main (void)
    {
      received=0;
      int i;
      char buffer [33];
          USART_Init(2, 9600L);             // USART Channel 2 (Onboard/TTL)
      sei();
    
      while(1)
      {
        i=itoa (received,buffer,10);
        USART_PutS(2, buffer);
        USART_PutS(2, "Test\r\n");
        _delay_ms(250);
      }
      return 0;
    }
    
    
    
    // Functions
    void USART_Init(ui8_t chan, ui32_t baud)
    {
      ui8_t sreg = SREG;
      ui16_t ubrr;
      switch(chan)
      {
        case 2:
          ubrr = (ui16_t) ((ui32_t) F_CPU / (16 * baud) - 1);
          UBRR2H = (ui8_t) (ubrr>>8);
          UBRR2L = (ui8_t) (ubrr);
          cli();
          UCSR2B = (1 << RXEN2) | (1 << TXEN2) | (1 << RXCIE2);
          UCSR2C = (1 << UMSEL21) | (1 << UCSZ21) | (1 << UCSZ20);
          do
          {
            UDR2;
          } while (UCSR2A & (1 << RXC2));
    
          UCSR2A = (1 << RXC2) | (1 << TXC2);
          SREG = sreg;
          FIFO_Init (&infifo2,  inbuf2,  BUFSIZE2_IN);
          FIFO_Init (&outfifo2, outbuf2, BUFSIZE2_OUT);
          break;
      } // END:switch(chan)
    }
    
    void USART_PutS(ui8_t channel, const char *s)
    {
      do
      {
        USART_PutC(channel, *s);
      } while (*s++);
    }
    
    ui8_t USART_PutC (ui8_t channel, const ui8_t c)
    {
      ui8_t ret = 0;
      switch(channel)
      {
        case 2:
          ret = FIFO_Put(&outfifo2,c);
          UCSR2B |= (1 << UDRIE2);
          break;
      }
      return ret;
    }
    
    
    void FIFO_Init (fifo_t *f, ui8_t *buffer, const ui8_t size)
    {
      f->count = 0;
      f->pread = f->pwrite = buffer;
      f->read2end = f->write2end = f->size = size;
    }
    
    
    e_errors FIFO_Put (fifo_t *f, const ui8_t data)
    {
      return _inline_fifo_put (f, data);
    }
    
    
    // Interrupts:
    ISR(USART2_RX_vect)
    {
      _inline_fifo_put (&infifo2,UDR2);
      received++;
    }
    
    SIGNAL(SIG_USART2_DATA)
    {
      if (outfifo2.count > 0)
      {
        UDR2 = _inline_fifo_get (&outfifo2);
      } else {
        UCSR2B &= ~(1 << UDRIE2);
      }
    }
    und ich verwende die header-Dateien von jaecko

  6. #6
    Erfahrener Benutzer Roboter Experte Avatar von sternst
    Registriert seit
    07.07.2008
    Beiträge
    672
    Wozu soll das UMSEL21 gut sein? Welchen Sinn macht es, einen Modus einzustellen, der im Datenblatt als "Reserved" gekennzeichnet ist?
    MfG
    Stefan

  7. #7
    stimmt, da geb ich dir Recht. Das UMSEL21 macht keinen Sinn. Es ändert aber nichts dran auch wenn ich's weglasse. Der Code funktioniert ja auch mit allen anderen USARTs. Hab auch nochmal getest ob es vielleicht an meinem MAX232 liegt. Aber Fehlanzeige.

    Ich hab was dazu gefunden. Leider weiß ich nicht wie ich das überprüfen kann (bei mir gibts keine avr-devices.c File):

    http://gcc.gnu.org/bugzilla/show_bug.cgi?id=47696

    Benutze Eclipse (Juno) mit der aktuellen AVR-Toolchain (2.4.0.201203041437). Da is glaub ich ein GCC 4.3.3. dabei. Es muss irgendwie am kompilieren liegen.

    Hat jemand ne Ahnung wie ich überprüfen kann, ob der oben genannte BUG bei mir auch auftritt?

Berechtigungen

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