Forum: Compiler & IDEs AVR UART Probleme


von Philipp (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,

ich habe vor einiger Zeit mit der UART beschäftigt habe aber noch sehr 
starke Defiziete an mir erkannt welche das Programmieren fast unmöglich 
macht!

Im Anhang habe ich ein Programm welches auch aus diesem Forum stand, hab 
aber Probleme es auf einem ATmega128 zum laufen zu bringen.

Wenn ich es kompiliere bekomme ich folgende Fehlermeldungen:

Compiling C: main.c
avr-gcc -c -mmcu=atmega128 -I. -gdwarf-2 -DF_CPU=8000000UL -Os 
-funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall 
-Wstrict-prototypes -Wundef -Wa,-adhlns=obj/main.lst  -std=gnu99 -Wundef 
-MD -MP -MF .dep/main.o.d main.c -o obj/main.o
main.c: In function `SendImmidate':
main.c:28: error: `UCSRA' undeclared (first use in this function)
main.c:28: error: (Each undeclared identifier is reported only once
main.c:28: error: for each function it appears in.)
main.c:31: error: `UDR' undeclared (first use in this function)
main.c: At top level:
main.c:35: warning: return type defaults to `int'
main.c:35: warning: function declaration isn't a prototype
main.c: In function `ISR':
main.c:35: warning: type of "USART_RXC_vect" defaults to "int"
main.c:36: error: `UDR' undeclared (first use in this function)
main.c: At top level:
main.c:49: warning: function declaration isn't a prototype
make.exe: *** [obj/main.o] Error 1

Es scheint als wäre meine UART Routine irgendwie nicht auf dieses 
Programm abgestimmt. Meine uart.c sieht folgendermaßen aus:
1
#include <avr/io.h>
2
#include "uart.h"
3
4
void uart_init(void){
5
  UBRR0H= 0x0;  // UART auf 9600 baud
6
  UBRR0L= 0x5F; //  UBRR= (fquarz/ (16* BAUD) ) -1
7
  
8
  UCSR0B= 0x18; // Transmitter und Receiver einschalten
9
  UCSR0C=0x86; // 8 bit 1 Stop No Parity
10
11
}
12
char uart_data_available(void){
13
  if (((UCSR0A >> RXC) & 1) ==0) return 0;
14
  else return 1;
15
}
16
17
char uart_read(void){  // Achtung ist noch blockierend!!!!
18
  
19
  while (((UCSR0A >> RXC) & 1) ==0){}  // Warten bis RXC-Bit in UCSRA gesetzt
20
  
21
  return UDR0;  // Zeichen abholen
22
}
23
24
void uart_send(char data){ // Achtung ist noch blockierend!!!!
25
26
27
  while (((UCSR0A >> UDRE) & 1) ==0){
28
    
29
  }  // warten bis UART sendebereit
30
31
32
  UDR0= data;
33
}

Wer kann mir helfen meine Probleme zu lösen und mir dabei auch noch 
einwenig zu erleutern. Bitte beachtet das ihr einen ich sag mal Anfänger 
in AVR Programmierung vor euch habt. ;-)

P.S. Um unnötige Postings zu vermeiden: Ich habe mir die Turorials auf 
dieser Seite schon angeschaut sind aber leider nicht sehr hilfreich 
gewesen.

Vielen Dank schonmal im Vorraus!

Gruß Philipp

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Die erste und zweite Fehlermeldung

main.c:28: error: `UCSRA' undeclared (first use in this function)
main.c:31: error: `UDR' undeclared (first use in this function)

sollte Dir zu Denken geben. Das bedeutet, daß die von Dir verwendeten 
symbolischen Bezeichner für die I/O-Register Deines AVR nicht bekannt 
sind.

Das kann daran liegen, daß
- Du nicht die korrekte Headerdatei einbindest
- Du zwar die korrekte Headerdatei einbindest, die interessanten Teile 
darin aber per bedingter Compilierung ausgeblendet werden, weil Du dem 
Buildsystem nicht mitgeteilt hast, daß Du einen AVR mit Hardware-UART 
verwendest


Interessanterweise aber passen die von Dir geposteten Fehlermeldungen 
nicht zum von Dir geposteten Quelltext, darin tauchen die betreffenden 
Namen nämlich gar nicht auf - was auch gar kein Wunder ist, denn Du hast 
den Quelltext der Funktion "SendImmidate" auch gar nicht gepostet, in 
dem aber die Fehler gefunden werden, wie der Compiler auch mitteilt.

Im übrigen schreibt man es korrekt "SendImmediate". Wenn schon 
englischsprachige Begriffe für Funktionsnamen verwendet werden müssen, 
dann doch bitte auch korrekt geschriebene.

von A.K. (Gast)


Lesenswert?

Mega128 hat zwei UARTs, daher andere Namen für die Register und Bits.

von yalu (Gast)


Lesenswert?

Die vielen Fehlermeldung kommen daher, dass das Programm im Anhang
vermutlich für einen anderen Controllertyp geschrieben ist. Daher sind
die Namen der I/O-Register unterschiedlich.

Bsp.: Das UART-Datenregister heißt UDR bei Controllern mit nur 1 UART,
sonst UDR0, UDR1 usw.

Der Fehler in Zeile 35 (ISR ...) kommt wohl daher, dass
avr/interrupt.h nocht includiert wurde.

Was ist mit deinen eigenen Routinen, funktionieren die auch nicht? Da
scheinen zumindest die Registernamen richtig zu sein.

von Philipp (Gast)


Lesenswert?

@yalu:
Danke für den Hinweis mit dem Interrupt! Somit sind die Fehler des ISR 
weg.

Da mein ATmega also 2 UARTS hat muss ich die Bezeichnungen in meiner 
Main.c der der Uart.c anpassen, oder?

Was meinst du mit eigenen Routinen? Eigentlich hab ich euch alles 
zukommen lassen womit ich arbeitete (main.c, uart.c)


@rufus:
Die Fehlermeldungen beziehen sich auch auf meine Main.c und nicht auf 
die uart.c

Und der Rechtschreibfehler war schon da als ich mir das Prog. hier aus 
diesem Forum geholt hab. :-)

Vielen dank schonmal!!!

von Karl H. (kbuchegg)


Lesenswert?

Philipp wrote:

> Die Fehlermeldungen beziehen sich auch auf meine Main.c und nicht auf
> die uart.c

Ist natürlich auch eine Möglichkeit:
Wenn der Compiler dir sagt, dass in main.c ein paar Fehler
drinn sind, dann einfach die uart.c in den Posting-Text mit
aufzunehmen, in der keine Fehler drinn sind :-)

Die Tatsache, dass mitlerweile wahrscheinlich schon ein paar
...zig Leute deine uart.c studiert haben, während gerade
mal 3 dein main.c aus dem Anhang geholt haben sollte dir zu
denken geben.

von Philipp (Gast)


Lesenswert?

Naja ich dachte halt da es sich um Uart Fehler handelt das ich euch auch 
noch eben meine uart zeige!

Hab aber jetzt einige Problem behandeln können...finde nur nicht die 
richtige Bezeichnung für den letzten Fehler.

Meine Aktuelle Fehlermeldung:
Compiling C: main.c
avr-gcc -c -mmcu=atmega128 -I. -gdwarf-2 -DF_CPU=8000000UL -Os 
-funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall 
-Wstrict-prototypes -Wundef -Wa,-adhlns=obj/main.lst  -std=gnu99 -Wundef 
-MD -MP -MF .dep/main.o.d main.c -o obj/main.o
main.c:35: warning: `USART_RXC_vect' appears to be a misspelled signal 
handler

Linking: main.elf
avr-gcc -mmcu=atmega128 -I. -gdwarf-2 -DF_CPU=8000000UL -Os 
-funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall 
-Wstrict-prototypes -Wundef -Wa,-adhlns=obj/main.o  -std=gnu99 -Wundef 
-MD -MP -MF .dep/main.elf.d obj/main.o --output main.elf 
-Wl,-Map=main.map,--cref    -lm
C:/Programme/WinAVR/bin/../lib/gcc/avr/3.4.6/../../../../avr/lib/avr5/cr 
tm128.o:  In function `__vectors':
../../../../../avr-libc-1.4.4/crt1/gcrt1.S:51: undefined reference to 
`main'
make.exe: *** [main.elf] Error 1

von Karl H. (kbuchegg)


Lesenswert?

Philipp wrote:
> @yalu:

> Da mein ATmega also 2 UARTS hat muss ich die Bezeichnungen in meiner
> Main.c der der Uart.c anpassen, oder?

Ja.
Allerdings hast du die falsche Begründung.
Du sollst in main.c die Bezeichnungen nicht ändern, weil sie in uart.c
auch so sind. Du sollst sie ändern, weil auf deinem AVR die
Dinge nun mal so heissen.

Aber noch viel wichtiger: Eine Datei Namens uart.c impliziert
zumindest für mich, dass dort alle UART Routinen gesammelt sind.
D.h. aber auch, dass es in main.c gar keine UART Routinen geben
sollte. Insofern sollst du also in main.c gar nichts anpassen,
sondern die Routinen nach uart.c verschieben, bzw. mit den
dort vorhandenen verschmelzen.

von Karl H. (kbuchegg)


Lesenswert?

Philipp wrote:

> ../../../../../avr-libc-1.4.4/crt1/gcrt1.S:51: undefined reference to

So wie es der Compiler sagt:
Es gibt keine Funktion namens main()
Die braucht er aber, da in dieser Funktion per C-Konvention
die Programmausführung beginnt.

von Karl H. (kbuchegg)


Lesenswert?

Das hier

> main.c:35: warning: `USART_RXC_vect' appears to be a misspelled signal
> handler

solltest du nicht auf die leichte Schulter nehmen.
Wenn der Compiler sagt, dass die Bezeichnung USART_RXC_vect
nicht mit den Interrupt Namen übereinstimmt, die er kennt,
dann kannst du ihm das auch glauben, dass das tatsächlich
so ist: Es gibt auf einem Mega128 keinen Interrupt, der
USART_RXC_vect heist. Teil des Problems wird wohl sein,
dass es auf einem Mega128 nicht 1 sondern 2 USART gibt.
Welche USART soll den nun den Interrupt auslösen?


von Philipp (Gast)


Lesenswert?

Also ich glaube das beide UARTS empfangen und senden können also ist es 
im Grunde genommen ja egal welchen ich nehme aber nur um die Frage zu 
beantworten natürlich den 1.

Was genau mach ich eigentlich mit diesem Befehl? "USART_RXC_vect"

von Karl H. (kbuchegg)


Lesenswert?

Philipp wrote:
> Also ich glaube das beide UARTS empfangen und senden können also ist es
> im Grunde genommen ja egal welchen ich nehme aber nur um die Frage zu
> beantworten natürlich den 1.

Und wie konfigurierst du dann, dass USART 1 bei einem Empfang
einen Interrupt auslösen soll und USART0 nicht?

>
> Was genau mach ich eigentlich mit diesem Befehl? "USART_RXC_vect"

Das ist kein Befehl.
Das ist die Bezeichnung eines Interrupts. Konkret des Interrupts
der aufgerufen werden soll, wenn das Ereeignis 'USART hat
ein Byte empfangen' eintritt. Da du aber 2 USART hast, gibt
es logischerweise auch 2 Interruptbezeichnungen. Eine für
die USART 0 und eine für die USART 1.

von Philipp (Gast)


Lesenswert?

Weißt du wo ich die korrekten Bezeichnungen für mein ATmega128 
herbekomme? Googlen hilft nicht wirklich :-(

von Karl H. (kbuchegg)


Lesenswert?

Ich rate jetzt einfach mal

USART0_RXC_vect

Das war nicht wirklich schwer zu raten, oder?
Das Konfigurationsregister heist nicht UCSRA sondern USCR0A.
Das Datenregister des UART heist nicht UDR sonern UDR0.
Wie also wird der Receiver Interrupt der UART 0 heissen?

Ansonsten machst du in deinem AVR Studio einfach mal die
Datei iom128.h auf (die ist im Projekt dabei) und scrollst durch
bis du auf den richtigen Abschnitt stösst. (Oder aber du
benutzt die Suche und lässt nach USART suchen)

von kosmonaut pirx (Gast)


Lesenswert?

hallo,
du benutzt die avr-libc. dann hier rtfm:

http://www.nongnu.org/avr-libc/user-manual/

das ist der anlaufpunkt für informationen.
bye kosmo

von Philipp (Gast)


Lesenswert?

Vielen Dank! Hab mir die Lib angeschaut und auch die richtigen 
Bezeichnungen gefunden. Aber wenn ich jetzt versuche zu kompilieren 
meckert er wegen dem Vektor?

Compiling C: main.c
avr-gcc -c -mmcu=atmega128 -I. -gdwarf-2 -DF_CPU=8000000UL -Os 
-funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall 
-Wstrict-prototypes -Wundef -Wa,-adhlns=obj/main.lst  -std=gnu99 -Wundef 
-MD -MP -MF .dep/main.o.d main.c -o obj/main.o
main.c:38: warning: return type of 'main' is not `int'
main.c: In function `main':
main.c:40: warning: static declaration of '__vector_18' follows 
non-static declaration
main.c:39: warning: previous declaration of '__vector_18' was here

Was ist das Überhaupt?

von kosmonaut_pirx (Gast)


Lesenswert?

hallo,
der Compiler gibt dir die entsprechenden hinweise schon:

in zeile 39 deklarierst du etwas, was du eine zeile später noch einmal 
deklarierst, aber leicht abgewandelt.

dekalrieren kannst du natürlich, wie du lustig bist, nur sollten die 
qualifier auch übereinstimmen. ist letztendlich nur eine warnung, aber 
ist ein hinweis darauf, dass da was nicht ganz iO ist.

bye kosmo

von Philipp (Gast)


Lesenswert?

Da hast du recht aber die Zeilen 39 und 40 sehen so aus:
1
ISR(USART0_RX_vect)  // Zeile 39     
2
   {                       // Zeile 40
Und mit der geschweiften Klammer deklariere ich den Interrupt ja nicht 
nochmal.

von kosmonaut_pirx (Gast)


Lesenswert?

hallo,
ist alles bischen seltsam. vermutlich hast du wieder im code 
rumgefrickelt, der hinweis vom compiler auf das main in zeile 38 deutet 
darauf hin. entsprechend passt das von dir gepostete main.c nicht mehr, 
und so kann nur geraten werden.
musst nochmal posten zur not,
bye kosmo

von Karl H. (kbuchegg)


Lesenswert?

Du hast vergessen avr/interrupt.h zu inkludieren.
1
#include <avr/io.h>
2
#include <stdlib.h>
3
4
#include <stdio.h>
5
#include <stdint.h>
6
#include <avr/interrupt.h>    // <----------
7
8
#define XON  0x11              // steht für das ASCII Steuerzeichen DC1
9
#define XOFF 0x13              // steht für das ASCII Steuerzeichen DC2
10
11
#define BUFFER_LEN 20            // Buffer Größe
12
#define HIGH_WATER  15            // Obergrenze; XOFF wird gesendet wenn erreicht
13
#define LOW_WATER  5            // Untergrenze; XON wird gesendet wenn erreicht
14
15
char Buffer[BUFFER_LEN];          // Buffer Größe wird gesetzt
16
17
volatile int NextWriteBufferPos;      // Pfeil steht an einer Stelle des Buffers in dem er das nächste Zeichen schreibt wenn er empfängt
18
volatile int NextReadBufferPos;      // Pfeil steht an einer Stelle des Buffers und ließt diesen aus
19
volatile int CharsInBuffer;        // Position des Pfeils im Buffer
20
volatile int XoffSent;            // ???????????????????????????????????????
21
22
23
24
void SendImmediate(char c)
25
{
26
  while (!(UCSR0A & (1<<UDRE)))
27
  {
28
  }
29
  UDR0 = c;
30
}
31
32
ISR(USART0_RX_vect)              // wird aufgerufen, wenn ein Zeichen von der UART empfangen wurde
33
{ 
34
  Buffer[NextReadBufferPos] = UDR0;
35
36
  NextWriteBufferPos = (NextWriteBufferPos + 1) % BUFFER_LEN;
37
  CharsInBuffer++;
38
39
  if(CharsInBuffer == HIGH_WATER) 
40
  {
41
    SendImmediate(XOFF);
42
    XoffSent = 1;
43
  }
44
}
45
46
int main()
47
{
48
}

  

von Philipp (Gast)


Lesenswert?

So jetzt läufts...hatte den Interrupt in die Main geschrieben.

Jetzt hät ich da noch ne Frage und zwar wie wird der Interrupt 
ausgelößt? In der Beschreibung des Interrupts steht das er ihn auslößt 
sobald er ein Zeichen empfängt. Muss ich diesen Interrupt jetzt in 
meiner Main irgendwie aktivieren oder macht er das Automatisch wenn er 
ein Zeichen empfängt?

Hab mein Programm mal im Anhang gepackt! Um kurz zu erleutern was ich 
mit meinem Programm eigentlich machen will. Ich möchte im Hyperterminal 
meines PC ein Zeichen an mein ATmega128 schicken bis er mir sagt "Voll" 
(Möchte ich auch im Hyperterminal angezeigt bekommen) und sobald er dann 
wieder "Leer" ist kann das Datenschicken weitergehen. u.s.w

Die Daten die ich an mein Modul schicke müssen "vorerst" nicht 
gespeichert werden und dürfen so verfallen.

von Philipp (Gast)


Angehängte Dateien:

Lesenswert?

Uppps die Main vergessen! ;-)

von kosmonaut_pirx (Gast)


Lesenswert?

hallo,
du musst den mikrocontroller selbestverständlich dazu bringen, 
interrupts zuzulassen.
steht alles in der doku.

ein kurzes "sei()" in der main wird's tun, schätze ich.
bye kosmo

von Philipp (Gast)


Lesenswert?

Danke echt vielen Dank...ihr habt mir sehr geholfen!

Auf weitere gute Zusammenarbeit!

LG Philipp

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.