Hallo, ich bin ein blutiger Anfänger (habe gerade mal das Anfängertutorial auf der Seite durchgemacht) auf diesem Gebiet und bin gerade dabei eine Atxmega64a3u so zu programmieren dass eine kommunikation über einen seriellen Port am PC stattfinden kann. Ich habe um auf die <util/setbaud.h> die BAUD definiert, allerdings gibt er mir bei der Zeile #define BAUD 9600 immer den Fehler "expected identifier or '(' before numeric constant" aus. Ich habe das define vor dem include gemacht weil er sonst sagt dass die BAUD definiert werden muss. Ich verwende AtmelStudio 6.2. Ich wäre über jede Hilfe sehr dankbar.
:
Verschoben durch User
Ji Luo schrieb: > Ich wäre über jede Hilfe sehr dankbar. dann zeige bitte dein Quellcode. Das define selber kann so einen Fehler nicht erzeugen.
Zeig mal deinen Code ......
sry bisschen peinlich der code weil ich so ein Anfänger bin...
1 | #ifndef F_CPU
|
2 | #define F_CPU 64000000UL
|
3 | #endif
|
4 | |
5 | #ifndef BAUD
|
6 | #define BAUD 9600
|
7 | #endif
|
8 | |
9 | |
10 | #include <avr/io.h> |
11 | #include <avr/interrupt.h> |
12 | #include <util/delay.h> |
13 | #include <util/setbaud.h> |
14 | #include <stdio.h> |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | void io_init(void){ |
21 | PORTC_DIR |= (1<<4); |
22 | }
|
23 | |
24 | void setUPSerial() |
25 | {
|
26 | PORTC_REMAP |= 0x16; |
27 | |
28 | PORTC_OUTSET = PIN3_bm; |
29 | PORTC_DIRSET = PIN3_bm; |
30 | |
31 | PORTC_OUTCLR = PIN2_bm; |
32 | PORTC_DIRCLR = PIN2_bm; |
33 | |
34 | |
35 | USARTC0_BAUDCTRLB = 0; |
36 | USARTC0_BAUDCTRLA = 0x22; |
37 | USARTC0_CTRLA =0; |
38 | USARTC0_CTRLC = USART_CHSIZE_8BIT_gc; |
39 | USARTC0_CTRLB = USART_TXEN_bm | USART_RXEN_bm; |
40 | }
|
41 | int main(void) |
42 | {
|
43 | io_init(); |
44 | setUPSerial(); |
45 | while(1) |
46 | {
|
47 | _delay_ms(10000); |
48 | PORTC_OUT &= ~(1<<4); |
49 | _delay_ms(100); |
50 | PORTC_OUT |= (1<<4); |
51 | |
52 | }
|
53 | return 0; |
54 | }
|
Das setbaud.h wird anscheinend ganz komisch eingebaut. Es soll so aussehen:
1 | static void |
2 | uart_38400(void) |
3 | {
|
4 | #undef BAUD // avoid compiler warning
|
5 | #define BAUD 38400
|
6 | #include <util/setbaud.h> |
7 | UBRRH = UBRRH_VALUE; |
8 | UBRRL = UBRRL_VALUE; |
9 | #if USE_2X
|
10 | UCSRA |= (1 << U2X); |
11 | #else
|
12 | UCSRA &= ~(1 << U2X); |
13 | #endif
|
14 | }
|
Hier liegt das Problem iox64a3.h
1 | typedef struct TWI_MASTER_struct |
2 | {
|
3 | register8_t CTRLA; /* Control Register A */ |
4 | register8_t CTRLB; /* Control Register B */ |
5 | register8_t CTRLC; /* Control Register C */ |
6 | register8_t STATUS; /* Status Register */ |
7 | register8_t BAUD; /* Baurd Rate Control Register */ |
8 | // ****
|
9 | register8_t ADDR; /* Address Register */ |
10 | register8_t DATA; /* Data Register */ |
11 | } TWI_MASTER_t; |
es gibt einen anderen Namen 'BAUD'. Dann ist natürlich alles klar. Da kommt jetzt alles durcheinander. Du musst das #define für BAUD unmittelbar vor den #include für setbaud.h ziehen.
:
Bearbeitet durch User
Karl Heinz schrieb: > Du musst das #define für BAUD unmittelbar vor den #include für setbaud.h > ziehen. Also so
1 | #define F_CPU 64000000UL
|
2 | |
3 | |
4 | #include <stdio.h> |
5 | #include <avr/io.h> |
6 | #include <avr/interrupt.h> |
7 | #include <util/delay.h> |
8 | |
9 | #define BAUD 9600
|
10 | #include <util/setbaud.h> |
11 | |
12 | void io_init(void){ |
13 | PORTC_DIR |= (1<<4); |
14 | }
|
15 | ....
|
und die #ifndef lässt du besser weg. Das hat sich als keine gute Idee herausgestellt.
Ji Luo schrieb: > Atxmega64a3u > #define F_CPU 64000000UL Laut Datenblatt kann der nur 32 Mhz. Karl Heinz schrieb: > es gibt einen anderen Namen 'BAUD'. Dann ist natürlich alles klar. Da > kommt jetzt alles durcheinander. Da sieht man übrigens auch prima, warum es eine gute Idee ist, komplett großgeschriebene Namen ausschließlich für Makros zu reservieren.
Karl Heinz schrieb: > Also so Nein, das ist auch keine gute Idee. Das zerstört in der Umkehrung wieder die TWI_MASTER_t. Da haben die Jungs bei Atmel aber ordentlich geschlafen!
Fritz Ganter schrieb: > Das setbaud.h wird anscheinend ganz komisch eingebaut. Es soll so > aussehen: Und selbst das ist nur die halbe Miete. Nach der Verwendung muss das Makro wieder entfernt werden
1 | static void |
2 | uart_38400(void) |
3 | {
|
4 | #undef BAUD // avoid compiler warning
|
5 | |
6 | #define BAUD 38400
|
7 | #include <util/setbaud.h> |
8 | UBRRH = UBRRH_VALUE; |
9 | UBRRL = UBRRL_VALUE; |
10 | #undef BAUD // und: tschuess <----------
|
11 | |
12 | #if USE_2X
|
13 | UCSRA |= (1 << U2X); |
14 | #else
|
15 | UCSRA &= ~(1 << U2X); |
16 | #endif
|
17 | }
|
:
Bearbeitet durch User
Karl Heinz schrieb: > Fritz Ganter schrieb: >> Das setbaud.h wird anscheinend ganz komisch eingebaut. Es soll so >> aussehen: > > Und selbst das ist nur die halbe Miete. > Nach der Verwendung muss das Makro wieder entfernt werden Eh. Klingt nach Gemurkse. Das muss besser gehen ;-)
Mark Brandis schrieb: > Karl Heinz schrieb: >> Fritz Ganter schrieb: >>> Das setbaud.h wird anscheinend ganz komisch eingebaut. Es soll so >>> aussehen: >> >> Und selbst das ist nur die halbe Miete. >> Nach der Verwendung muss das Makro wieder entfernt werden > > Eh. Klingt nach Gemurkse. Das muss besser gehen ;-) Würde es. Wenn entweder * Atmel besser aufgepasst hätte und nicht 2 mal denselben Identifier benutzt hätte oder * In diesen Strukturen nicht einfach alles gross schreiben würde. Hab nachgesehen: ein register8_t ist nichts anderes als ein
1 | typedef volatile uint8_t register8_t; |
es gibt daher überhaupt keinen Grund, hier
1 | typedef struct TWI_MASTER_struct |
2 | {
|
3 | register8_t CTRLA; /* Control Register A */ |
4 | register8_t CTRLB; /* Control Register B */ |
5 | register8_t CTRLC; /* Control Register C */ |
6 | register8_t STATUS; /* Status Register */ |
7 | register8_t BAUD; /* Baurd Rate Control Register */ |
8 | register8_t ADDR; /* Address Register */ |
9 | register8_t DATA; /* Data Register */ |
10 | } TWI_MASTER_t; |
alle 'Register'-Namen in Grossbuchstaben zu schreiben. Ist ja nicht so, dass diese Grossschreibungskonvention eine der wenigen Konventionen wäre, auf die man sich weltweit verlassen könnte. Atmel muss da wieder sein eigenes Süppchen kochen und alles ignorieren, was sich seit 50 Jahren bewährt hat. (Wird Zeit dass der Komet kommt)
Mein Tip für Anfänger: Ganz auf Defines und Macros verzichten und sich auf die Sprache konzentrieren. So kann man ein Konstante deklarieren mit static const int Baudrate=9600; die dann ganz normal verwendet werden kann ohne irgendwelche Seiteneffekte durch Textersetzungen. Das macht das Leben einfacher.
PittyJ schrieb: > Mein Tip für Anfänger: Ganz auf Defines und Macros verzichten und sich > auf die Sprache konzentrieren. > > So kann man ein Konstante deklarieren mit > static const int Baudrate=9600; > die dann ganz normal verwendet werden kann ohne irgendwelche > Seiteneffekte durch Textersetzungen. Das macht das Leben einfacher. Das ist aber nur in C++ eine echte Konstante. In C sind die einzigen Konstanten die Zahlenwerte, die man direkt hinschreibt. Deshalb werden dafür ja immer Makros verwendet. Außerdem braucht deine Variable zusätzliches RAM. Makros sind auch kein Voodoo. Wenn man sich an ein paar einfache Regeln hält, funktionieren sie sehr gut. Ärgerlich ist es natürlich, wenn der Lieferant einer Bibliothek sich nicht an diese Regeln gehalten hat.
Rolf Magnus schrieb: > Außerdem braucht deine Variable zusätzliches RAM. Nur auf Harvard-Systemen. Außerhalb des AVR-Tellers liegt so etwas nur da, wo es hingehört: Im ROM.
Ich glaube nicht, dass der To Interesse an theoretischen Grundsatzdiskussionen hat. Ihm gehts wohl eher darum, sein konkretes Problem zu lösen. Da er konkret auf nem AVR unterwegs ist ist die Aussage > Außerdem braucht deine Variable zusätzliches RAM. zu 100% (in diesem Kontext) richtig.
Karl Heinz schrieb: > Und selbst das ist nur die halbe Miete. > Nach der Verwendung muss das Makro wieder entfernt werden > > [c] > static void > uart_38400(void) > { > #undef BAUD // avoid compiler warning wobei dieses erste #undef wiederrum keine gute Idee ist Wenn ausserhalb, zb auf der Command Line zum Aufruf des Compilers eine Baudrate vorgegeben wird (jetzt mal von dem Problem mit der struct abgesehen), dann will man die auch übernommen wissen. Wenn es eine Warnung gibt, dass durch einen weiteren #define diese Vorgabe nichts gilt, dann ist das ok und es soll auch so sein, dass ich als Programmierer darauf hingewiesen werde, dass sich da was beisst. Was aber auf keinen Fall sein darf, dass ist, dass der Compiler angewiesen wird, eine derartige Vorgabe einfach sang und klanglos zu ignorieren, in dem man sie ganz einfach löscht. Das ist ganz grosser Murks. Ich weiss nicht, was sich die Atmel Leute dabei gedacht haben. Das Beste wär wirklich, wenn sie in den sauren Apfel beissen, und die Identifier in der Struktur umbenennen. Das gibt jetzt ein Jahr lang Gemaule, aber dann wird wohl ein Grossteil des bereits existierenden Codes entsprechend geändert sein und dann ist wieder Ruhe. 'Augen zu und durch'. Je früher sie das wieder bereinigen, desto besser. 'Abwarten und Tee trinken' ist die falsche Strategie; das Problem regelt sich nicht von selbst. > > #define BAUD 38400 > #include <util/setbaud.h> > UBRRH = UBRRH_VALUE; > UBRRL = UBRRL_VALUE; > #undef BAUD // und: tschuess <----------
:
Bearbeitet durch User
Karl Heinz schrieb: > Das Beste wär wirklich, wenn sie in den sauren Apfel beissen, und die > Identifier in der Struktur umbenennen. Alternative: Den Namen "BAUD" für die Baudrate in "BAUDRATE" umbenennen ...
Vielen Dank euch allem, das hat mir sehr viel weitergebracht!! Allerdings hab ich ein weiteres Problem im Moment, und zwar ist der nächste Schritt für mich eine Kommunikation mit dem Serialport aufzubauen. Durch ein Paar Versuche hab ich nun die In und Outputs gesetzt. Allerdings liefert das printf keinerlei Ergebnisse, könnt ihr mir vielleicht nochmal helfen?
1 | #define F_CPU 32000000UL
|
2 | |
3 | #include <avr/io.h> |
4 | #include <avr/interrupt.h> |
5 | #include <util/delay.h> |
6 | #define BAUD 9600
|
7 | #include <util/setbaud.h> |
8 | #undef BAUD
|
9 | #include <stdio.h> |
10 | |
11 | |
12 | static int uart_putchar(char c, FILE *stream); |
13 | |
14 | FILE * uart_str; |
15 | |
16 | void io_init(void){ |
17 | PORTC_DIR |= (1<<4); |
18 | }
|
19 | void clock_init(void){ |
20 | OSC.CTRL |= OSC_RC32MEN_bm; |
21 | while(!(OSC.STATUS & OSC_RC32MRDY_bm)); |
22 | CCP = CCP_IOREG_gc; |
23 | CLK.CTRL = (CLK.CTRL & ~CLK_SCLKSEL_gm) | CLK_SCLKSEL_RC32M_gc; |
24 | }
|
25 | void setUPSerial() |
26 | {
|
27 | PORTC_REMAP |= 0x16; |
28 | PORTC_OUTSET = PIN3_bm; |
29 | PORTC_DIRSET = PIN3_bm; |
30 | |
31 | PORTC_OUTCLR = PIN2_bm; |
32 | PORTC_DIRCLR = PIN2_bm; |
33 | |
34 | |
35 | USARTC0_BAUDCTRLB = 0; |
36 | USARTC0_BAUDCTRLA = 0x22; |
37 | USARTC0_CTRLA =0; |
38 | USARTC0_CTRLC = USART_CHSIZE_8BIT_gc; |
39 | USARTC0_CTRLB = USART_TXEN_bm | USART_RXEN_bm; |
40 | }
|
41 | printf("Ready!\n"); |
42 | |
43 | void sendChar(char c) |
44 | {
|
45 | |
46 | while( !(USARTC0_STATUS & USART_DREIF_bm) ); |
47 | |
48 | USARTC0_DATA = c; |
49 | |
50 | }
|
51 | void sendString(char *text) |
52 | {
|
53 | while(*text) |
54 | |
55 | {
|
56 | sendChar(*text++); |
57 | }
|
58 | }
|
59 | |
60 | static int uart_putchar (char c, FILE *stream) |
61 | {
|
62 | if (c == '\n') |
63 | uart_putchar('\r', stream); |
64 | |
65 | while ( !(USARTC0_STATUS & USART_DREIF_bm) ); |
66 | |
67 | USARTC0_DATA = c; |
68 | |
69 | return 0; |
70 | }
|
71 | |
72 | char usart_receiveByte() |
73 | {
|
74 | while( !(USARTC0_STATUS & USART_RXCIF_bm) ); |
75 | return USARTC0_DATA; |
76 | }
|
77 | |
78 | int uart_getchar(FILE *stream) |
79 | {
|
80 | while( !(USARTC0_STATUS & USART_RXCIF_bm) ); |
81 | char data = USARTC0_DATA; |
82 | if(data == '\r') |
83 | data = '\n'; |
84 | uart_putchar(data, stream); |
85 | return data; |
86 | }
|
87 | |
88 | int main() |
89 | {
|
90 | io_init(); |
91 | clock_init(); |
92 | setUPSerial(); |
93 | printf("Ready!\n"); |
94 | uart_str = fdevopen(uart_putchar, uart_getchar); |
95 | stdout = stdin = uart_str; |
96 | printf("Hello World!\n\r"); |
97 | while(1) |
98 | {
|
99 | _delay_ms(100); |
100 | PORTC_OUT &= ~(1<<4); |
101 | _delay_ms(100); |
102 | PORTC_OUT |= (1<<4); |
103 | }
|
104 | return 0; |
105 | }
|
:
Bearbeitet durch User
Ich sehe da ein printf() zwischen den Funktionen setUPSerial() und sendChar(), wo es bestimmt nicht hingehört. Kompiliert das denn überhaupt?
achso das war nur zum Testen, vergessen auszukommentieren, ja der Code compiliert.
Karl Heinz schrieb: > * Atmel besser aufgepasst hätte und nicht 2 mal denselben Identifier > benutzt hätte Naja, der aus <util/setbaud.h> stammt nicht von Atmel, sondern von der avr-libc. Der ist dort seit Oktober 2007 vorhanden. Die erste Version der Datenblätter vom ATxmegaA / ATxmegaA1 (der ATxmega128A1 war der erste Xmega) datiert auf 02/2008. Das ist die erste öffentliche Version, zuvor wurde innerhalb von Atmel da schon eine ganze Weile an den Xmegas gearbeitet. Insofern ist es sehr wahrscheinlich, dass sich die beiden Implementierungen des Makros BAUD „überkreuzt“ haben.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.