Hallo,
ich habe ein Problem mit der seriellen Schnittstelle eines ATmega328P 
(Crumb328 mit integriertem USB-Wandler von chip45.com) und komme aktuell 
einfach nicht mehr weiter.
Anbei ein Testprogramm, welches auf dem AVR-Evalboard von Pollin mit 
einem ATmega8 (16 MHz) problemlos funktioniert. Auf dem ATmega328P (20 
MHz) werden nur Ausgaben von uart_putc korrekt ausgegeben. Versuche ich 
eine Ausgabe mit uart_puts gibt es überhaupt keine Ausgabe auf der 
seriellen Schnittstelle. Die LED blinkt in beiden Fällen.
| 1 | #include <avr/io.h>
 | 
| 2 | 
 | 
| 3 | #include <util/delay.h>
 | 
| 4 | 
 | 
| 5 | #define SLEEP(VALUE)    _delay_ms(VALUE) 
 | 
| 6 | 
 | 
| 7 | #define LED_CONFIG( DDR, LED)   DDR |= (1<<(LED))
 | 
| 8 | #define LED_ON( PORT, LED)  PORT |=  (1<<(LED))
 | 
| 9 | #define LED_OFF( PORT, LED)  PORT &= ~(1<<(LED))
 | 
| 10 | #define LED_TOGGLE( PORT, LED)  PORT ^=  (1<<(LED))
 | 
| 11 | 
 | 
| 12 | #define LED1_DDR DDRB
 | 
| 13 | #define LED1_PORT PORTB
 | 
| 14 | #define LED1 PB2
 | 
| 15 | 
 | 
| 16 | #if defined(__AVR_ATmega8__)
 | 
| 17 | 
 | 
| 18 | #define UART_MODE_8N1 (1<<URSEL) | (1<<UCSZ1) | (1<<UCSZ0)
 | 
| 19 | 
 | 
| 20 | #define UBRR0H UBRRH
 | 
| 21 | #define UBRR0L UBRRL
 | 
| 22 | #define UCSR0A UCSRA
 | 
| 23 | #define UCSR0B UCSRB
 | 
| 24 | #define UCSR0C UCSRC
 | 
| 25 | #define RXEN0 RXEN
 | 
| 26 | #define TXEN0 TXEN
 | 
| 27 | #define RXC0 RXC
 | 
| 28 | #define UDR0 UDR
 | 
| 29 | #define UDRE0 UDRE
 | 
| 30 | 
 | 
| 31 | #elif defined(__AVR_ATmega328P__)
 | 
| 32 | 
 | 
| 33 | #define UART_MODE_8N1 (1<<UCSZ01) | (1<<UCSZ00)
 | 
| 34 | 
 | 
| 35 | #endif
 | 
| 36 | 
 | 
| 37 | #define UART_BAUD_9600_16_MHZ 103
 | 
| 38 | #define UART_BAUD_9600_20_MHZ 129
 | 
| 39 | 
 | 
| 40 | 
 | 
| 41 | int uart_putc( char data)
 | 
| 42 | {
 | 
| 43 |   while( bit_is_clear( UCSR0A, UDRE0) );
 | 
| 44 | 
 | 
| 45 |   UDR0 = data;
 | 
| 46 | 
 | 
| 47 |   return 0;
 | 
| 48 | }
 | 
| 49 | 
 | 
| 50 | 
 | 
| 51 | int uart_puts( const char *data)
 | 
| 52 | {
 | 
| 53 |   uint16_t index = 0;
 | 
| 54 | 
 | 
| 55 |   while( data[index] != '\0') { 
 | 
| 56 |     uart_putc( data[index]);
 | 
| 57 |     index++;
 | 
| 58 |   }
 | 
| 59 | 
 | 
| 60 |   return index;
 | 
| 61 | }
 | 
| 62 | 
 | 
| 63 | 
 | 
| 64 | int main( void)
 | 
| 65 | {
 | 
| 66 |   LED_CONFIG( LED1_DDR, LED1);
 | 
| 67 |   
 | 
| 68 |   LED_OFF( LED1_PORT, LED1);
 | 
| 69 | 
 | 
| 70 |   uint16_t ubbr = UART_BAUD_9600_20_MHZ;
 | 
| 71 |   // uint16_t ubbr = UART_BAUD_9600_16_MHZ;
 | 
| 72 | 
 | 
| 73 |   // load uart parameter
 | 
| 74 |   UBRR0H = (uint8_t) (ubbr>>8);
 | 
| 75 |   UBRR0L = (uint8_t) ubbr;
 | 
| 76 | 
 | 
| 77 |   // enable receiver/transmitter
 | 
| 78 |   UCSR0B |= (1<<RXEN0) | (1<<TXEN0);
 | 
| 79 | 
 | 
| 80 |   // set mode (8n1)
 | 
| 81 |   UCSR0C |= UART_MODE_8N1;
 | 
| 82 | 
 | 
| 83 |   while( 1 ) { 
 | 
| 84 |     uart_putc( 't');
 | 
| 85 |     uart_putc( 'e');
 | 
| 86 |     uart_putc( 's');
 | 
| 87 |     uart_putc( 't');
 | 
| 88 |     uart_putc( '\n');
 | 
| 89 | 
 | 
| 90 |     uart_puts( "TEST\n");
 | 
| 91 | 
 | 
| 92 |     SLEEP( 500);
 | 
| 93 |     LED_TOGGLE( LED1_PORT, LED1);
 | 
| 94 |   }
 | 
| 95 | 
 | 
| 96 |   return 0;
 | 
| 97 | }
 | 
Das Testprogramm wird mit folgenden Aufrufen übersetzt und hochgeladen.
| 1 | avr-gcc -O1 -Wall -mmcu=atmega328p -DF_CPU=20000000 -c uart_test_complete.c -o uart_test_complete.o
 | 
| 2 | avr-gcc  uart_test_complete.o -o uart_test_complete.bin
 | 
| 3 | avr-objcopy -j .text -j .data -O ihex uart_test_complete.bin uart_test_complete.hex
 | 
| 4 | avrdude -P usb -c usbtiny -p m328p -U flash:w:uart_test_complete.hex
 | 
Folgende Fuses sind auf dem Crumb328 gesetzt.
| 1 | avrdude -P usb -c usbtiny -p m328p -n -v
 | 
| 2 | 
 | 
| 3 | avrdude: Device signature = 0x1e950f
 | 
| 4 | avrdude: safemode: lfuse reads as FF
 | 
| 5 | avrdude: safemode: hfuse reads as D9
 | 
| 6 | avrdude: safemode: efuse reads as 7
 | 
Ich bin dankbar für jeden Hinweis, mir sind leider die Ideen 
ausgegangen, was ich falsch gemacht habe.
Gruss
   Micha