PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : UART bei Mega2560



Jaecko
05.12.2009, 16:53
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 M128) 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?



// 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

sternst
05.12.2009, 17:44
void USART_Init(ui8_t chan, ui32_t baud)
...
case 2:
...
UCSR0B = ...
UCSR0C = ...

Jaecko
05.12.2009, 17:50
Thx...
War mal wieder ein Klassiker.

Christian86
22.08.2012, 11:07
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?

Christian86
22.08.2012, 11:19
// 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

sternst
22.08.2012, 12:50
Wozu soll das UMSEL21 gut sein? Welchen Sinn macht es, einen Modus einzustellen, der im Datenblatt als "Reserved" gekennzeichnet ist?

Christian86
22.08.2012, 23:16
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?