Forum: Compiler & IDEs Definition der baudrate: Fehler- "expected identifier or '(' before numeric constant"


von Ji L. (g44)


Lesenswert?

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
von Peter II (Gast)


Lesenswert?

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.

von NurEinGast (Gast)


Lesenswert?

Zeig mal deinen Code ......

von Ji L. (g44)


Lesenswert?

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
}

von Fritz G. (fritzg)


Lesenswert?

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
   }

von Karl H. (kbuchegg)


Lesenswert?

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
von Karl H. (kbuchegg)


Lesenswert?

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.

von Rolf M. (rmagnus)


Lesenswert?

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.

von Karl H. (kbuchegg)


Lesenswert?

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!

von Karl H. (kbuchegg)


Lesenswert?

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
von Mark B. (markbrandis)


Lesenswert?

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

von Karl H. (kbuchegg)


Lesenswert?

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)

von PittyJ (Gast)


Lesenswert?

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.

von Rolf M. (rmagnus)


Lesenswert?

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.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

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.

von Haro (Gast)


Lesenswert?

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.

von Karl H. (kbuchegg)


Lesenswert?

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
von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

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

von Ji L. (g44)


Lesenswert?

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
von Mark B. (markbrandis)


Lesenswert?

Ich sehe da ein printf() zwischen den Funktionen setUPSerial() und 
sendChar(), wo es bestimmt nicht hingehört. Kompiliert das denn 
überhaupt?

von Ji L. (g44)


Lesenswert?

achso das war nur zum Testen, vergessen auszukommentieren, ja der Code 
compiliert.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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
Noch kein Account? Hier anmelden.