AVR UART Probleme

Gast #570671
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
Angehängte Dateien:
Persönliche Seite #570686
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.
Gast #570700
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.
Gast #570722
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!!!
#570746
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.
Gast #570752
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
#570754
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.
#570760
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?

Gast #570763
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"
#570831
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.
#570891
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)
Gast #571308
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?
Gast #571324
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
Gast #571357
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
#571359
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
}

  
Gast #571373
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.
Gast #571379
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

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren