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