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