www.mikrocontroller.net

Forum: Compiler & IDEs AVR UART Probleme


Autor: Philipp (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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:
#include <avr/io.h>
#include "uart.h"

void uart_init(void){
  UBRR0H= 0x0;  // UART auf 9600 baud
  UBRR0L= 0x5F; //  UBRR= (fquarz/ (16* BAUD) ) -1
  
  UCSR0B= 0x18; // Transmitter und Receiver einschalten
  UCSR0C=0x86; // 8 bit 1 Stop No Parity

}
char uart_data_available(void){
  if (((UCSR0A >> RXC) & 1) ==0) return 0;
  else return 1;
}

char uart_read(void){  // Achtung ist noch blockierend!!!!
  
  while (((UCSR0A >> RXC) & 1) ==0){}  // Warten bis RXC-Bit in UCSRA gesetzt
  
  return UDR0;  // Zeichen abholen
}

void uart_send(char data){ // Achtung ist noch blockierend!!!!


  while (((UCSR0A >> UDRE) & 1) ==0){
    
  }  // warten bis UART sendebereit


  UDR0= data;
}

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

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: A.K. (Gast)
Datum:

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

Autor: yalu (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Philipp (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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!!!

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Philipp (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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?


Autor: Philipp (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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"

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Philipp (Gast)
Datum:

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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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)

Autor: kosmonaut pirx (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Philipp (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: kosmonaut_pirx (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Philipp (Gast)
Datum:

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

Autor: kosmonaut_pirx (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du hast vergessen avr/interrupt.h zu inkludieren.
#include <avr/io.h>
#include <stdlib.h>

#include <stdio.h>
#include <stdint.h>
#include <avr/interrupt.h>    // <----------

#define XON  0x11              // steht für das ASCII Steuerzeichen DC1
#define XOFF 0x13              // steht für das ASCII Steuerzeichen DC2

#define BUFFER_LEN 20            // Buffer Größe
#define HIGH_WATER  15            // Obergrenze; XOFF wird gesendet wenn erreicht
#define LOW_WATER  5            // Untergrenze; XON wird gesendet wenn erreicht

char Buffer[BUFFER_LEN];          // Buffer Größe wird gesetzt

volatile int NextWriteBufferPos;      // Pfeil steht an einer Stelle des Buffers in dem er das nächste Zeichen schreibt wenn er empfängt
volatile int NextReadBufferPos;      // Pfeil steht an einer Stelle des Buffers und ließt diesen aus
volatile int CharsInBuffer;        // Position des Pfeils im Buffer
volatile int XoffSent;            // ???????????????????????????????????????



void SendImmediate(char c)
{
  while (!(UCSR0A & (1<<UDRE)))
  {
  }
  UDR0 = c;
}

ISR(USART0_RX_vect)              // wird aufgerufen, wenn ein Zeichen von der UART empfangen wurde
{ 
  Buffer[NextReadBufferPos] = UDR0;

  NextWriteBufferPos = (NextWriteBufferPos + 1) % BUFFER_LEN;
  CharsInBuffer++;

  if(CharsInBuffer == HIGH_WATER) 
  {
    SendImmediate(XOFF);
    XoffSent = 1;
  }
}

int main()
{
}

  

Autor: Philipp (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Philipp (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Uppps die Main vergessen! ;-)

Autor: kosmonaut_pirx (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Philipp (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke echt vielen Dank...ihr habt mir sehr geholfen!

Auf weitere gute Zusammenarbeit!

LG Philipp

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.