mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik UART bei Atmega88


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

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich mache gerade das GCC-Tutorial und hab da ein paar Probleme mit der
Aufgabe12 (UART2).

Versuche das Programm auf dem Atmega88 laufen zu lassen, jedoch bekomme
ich immer folgende Fehlermeldung:

avr-gcc.exe  -mmcu=atmega128 -Wall -gdwarf-2 -O0 -MD -MP -MT UART.o -MF
dep/UART.o.d  -c  ../UART.c
../UART.c: In function `main':
../UART.c:39: warning: implicit declaration of function `outp'
../UART.c:39: error: `RXCn' undeclared (first use in this function)
../UART.c:39: error: (Each undeclared identifier is reported only once
../UART.c:39: error: for each function it appears in.)
../UART.c:39: error: `UCsRnA' undeclared (first use in this function)
../UART.c:42: error: `UBRR' undeclared (first use in this function)
../UART.c:55: warning: implicit declaration of function `inp'
../UART.c:55: error: `USR' undeclared (first use in this function)
../UART.c:56: error: `UDRn' undeclared (first use in this function)
../UART.c:58: warning: implicit declaration of function `sbi'
../UART.c:61: warning: implicit declaration of function `cbi'
make: *** [UART.o] Error 1
Build failed with 7 errors and 4 warnings...


Für ein paar Tips wäre ich echt dankbar....!!!

Gruß

Autor: Der inoffizielle WM-Rahul (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>RXCn, UDRn
Geil! Sowas hab ich ja noch nie gesehen.
Statt des "n" wirst du dort eine Zahl eintragen müssen.
(das n steht für eine der UARTs; scheibar hat der Mega88 bzw. der im
Tutorium verwendete Controller) mehrere davon.

"outp", "inp", "sbi", "cbi" sind obsolete (sollten nie mehr
verwendet werden) in der aktuellen gcc-Version.

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja, hast ja Recht. Musste ich selber drüber lachen....!!! Hab es jetzt
gändert.

Wie schreib ich denn outp anders....??


Gruß

Autor: Der inoffizielle WM-Rahul (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
outp: PORTx = ...
inp: var = PINx
sbi: PORTx |= (1<<bit);
cbi: PORTx &= ~(1<<bit);

wobei bit = 0..7.
x steht für den Port-Buchstaben.
var ist in der Regel eine unsigned char-Variable.

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Super, Danke...!!! Funktioniert alles!

Wie würde ich den das hier umschreiben:

if (inp (UCSR1A) & (1 << RXC1))    ?????

Autor: Uwe Nagel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
if ( UCSR1A & (1 << RXC1))  !!

Ausserdem steht in deinem Makefile wohl noch der maga128. Erste Meldung
im ersten Posting...

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke, jetzt hab ich es kapiert.

Leider zeigt er mir beim aufspielen auf den Controller die
Fehlermeldung "ISP MODE ERROR" an.

Was bedeutet das..?

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

Bewertung
0 lesenswert
nicht lesenswert
So,

hab einfach die Firmware mal neu drauf gespielt und der ISP Mode Error
ist weg.

Hab das Programm das sich im Anhang befindet nun auf den Atmega8515
umgeschrieben. Leider läuft es nicht so wie es soll. Es gehen alle
LED's an, laut Programm soll es nur eine sein. Und ein und ausschalten
lassen sie sich auch nicht.

Dann hab ich noch ne Frage, wie kannn ich dem Controller vom Rechner
aus über UART zB. eine 1 schicken. Hab gelesen mit Hyper Terminal, aber
wie?

Für ein paar Tips wäre ich super dankbar...!!!


Gruß

Autor: Thorsten Fritzke (thorsten)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
avr-gcc.exe  -mmcu=atmega128
                   ^^^^^^^^^
                   |||||||||

sicher?

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ne, sicher nicht!

Weiß nicht warum da immer der atmega128 angegeben wird. Hab eigentlich
den atmega88 gesetzt. Woran kann das liegen.....?

Gruß

Autor: Der inoffizielle WM-Rahul (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Falsches Makefile

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Gut, das mit dem Makefile hab ich auch hinbekommen.

Aber das Programm läuft immer noch nicht. Sitze schon den ganzen Tag
davor, krieg es aber einfach nicht hin. Warum leuchten bei mir denn
alle LED's? Kann sich das Programm mal bitte einer anschauen und mir
einen Tip geben. Bin schon echt verzweifelt.....

Gruß

Autor: Der inoffizielle WM-Rahul (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Benutzt du zufällig das STK500?

"Goto" ist sowieso sehr böse. Dafür benutzt man entweder eine
while(1)-Schleife oder eine for(;;)-Schleife.

switch (UDR) ist auch nicht sooo gut. Sobald einmal auf UDR zugegriffen
wurde, ist der Inhalt indifferent (oder so ähnlich).
Sicher UDR lieber in einer Variablen und setzt die in der
switch-Anweisung ein. Oder weisst du, was der Compiler aus switch(UDR)
macht?

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja, ich benutze das STK500.

Ne, keine Ahnung was der Compiler aus Switch UDR macht. Bin ziemlicher
Anfänger auf dem Gebiet.

Aber warum Leuchten denn alle LED's...??

Wie kann ich das Programm denn am besten umschreiben. Will gar kein
fertiges Programm, nur ein paar Tips in die richtige Richtung....

Autor: Der inoffizielle WM-Rahul (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das STK500 arbeitet mit inverser Logik: alles was logisch 1 sein soll
(LED ein), ist aus und anders herum (Um eine LED einzuschalten muß man
PORTx &= ~(1<<n); benutzen...

deklariere dir eine Variable z.B.

unsigned char temp;
temp = UDR;
switch(temp)...


Statt deiner Loop ... goto Loop solltest du
for(;;)
{
...
}
benutzen. Der Compiler erkennt dann, dass es sich dabei um eine
Endlosschleife handelt, und optimiert den Code entsprechend.

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ok, hab statt goto eine Schleife verwendet.

Aber mein Problem ist ja eigentlich dass die ersten 6 LED#s leuchten
und die letzten bedien nicht.  Es dürfte ja eigentlich nur eine an sein
(oder halt aus weil ich nicht PORTx &= ~(1<<n); geschrieben habe).

Ist der Code denn vom Grundprinzip falsch?

Habe vor eine LED auf dem STK500 durch senden einer 1 einzuschalten und
durch senden einer 0 auszuschalten. Das ganze soll über UART vom PC aus
erfolgen.

Autor: ecslowhand (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn die LED auf dem STK500 an seinsoll, muss der entsprechende Portpin
auf LOW liegen !!!

Autor: Der inoffizielle WM-Rahul (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Guck dir mal das Beispiel im Datenblatt (complete) auf Seite 177 zur
Initialisierung und auf den folgenden Seiten die Beispiele fürs Senden
und Empfangen an.
Prinzipiell müsste dein Programm funktionieren...

Vielleicht solltest du aber erst mal ein Lauflicht programmieren, damit
du dich mit den Portzugriffen auseinandersetzt...

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hey, Danke!

Das die Ports auf LOW liegen müssen hatte ich schon geändert.
Hab das Datenblatt hier liegen und mitlerweile das Programm schon
umgeschrieben.

Nur warum Leuchten 6 LED's obwohl ich nur Pin0 gesetzt (oder auch
nicht gesetzt habe)? Muss doch irgendeinen Grund haben, dass die
anderen auch Leuchten.

Autor: Der inoffizielle WM-Rahul (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vielleicht solltest du einfach zu beginn deines Programms mal alle LEDs
löschen (beim STK500: "PORTB = 0xFF;", sonst "PORTB = 0x00;").

Autor: Der inoffizielle WM-Rahul (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Übrigens gibt es hier auf der Seite auch ein gutes C-Tutorium.
Die Sachen von Christian Schifferle sind schon etwas "antiquiert"...

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

Bewertung
0 lesenswert
nicht lesenswert
So, hab das Programm jetzt mal für einen Atmega88 neu geschrieben.

Das empfangen von Daten klappt bestens, nur das senden vom µC zum PC
macht mir noch ein paar Probleme.

Hab es mit dem UDRE-Interrupt versucht. Wenn ich den Inreeupt direkt in
der UART-Initialisierung aktiviere, klappt es. Nur dann sendet er mir
halt dauerhaft.

Er soll mir aber nur was senden, wenn ich z.B. eine 3 eingebe. Nur das
klappt irgendwie nicht.

Wäre super wenn mir jemand einen Tip geben könnte::::!

Das Programm hab ich oben angehängt....

Autor: Jens (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Zur Veranschaulichung:

// sendet einzelnes Zeichen an PC
void USART_transmit (unsigned char c)
{
  // warte bis Senden möglich
  while (!(UCSR0A & (1<<UDRE0))) {}

  // sende übergebenes Zeichen
  UDR0 = c;
}

// sendet Zeichenkette an PC
void USART_transmit_string (unsigned char *string)
{
  // warte bis Senden möglich
  while (!(UCSR0A & (1<<UDRE0))) {}

  // sende übergebene Zeichenkette (->einzelne Zeichen mit Hilfe der
Funktion USART_transmit)
  while ( *string)
  USART_transmit (*string++);
}

Besser ist natürlich die Bibi von P. FLeury, die sich auch hier
irgendwo im Forum tummeln müsste.
Gruß

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das hab ich wohl soweit schon kapiert! Ohne Interrupt klappt es ja
auch!

Nur würd ich es halt schon gerne mit nem Interrupt machen! Sobald ein
Zeichen empfangen wird, bei einer 1 soll eine LED geschaltet
werden(klappt alles) oder bei einer 2 soll er halt in die ISR springen
und was zurückschicken....

Autor: Jens (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ahja,

am besten wird sein, du murkst nicht innerhalb einer ISR weitere IR an
(zumal zum Auslösen ja noch das UDREn Flag fehlt), sondern setzt dir
ein  Flag, und arbeitest dies denn in der main ab.

global flag;

ISR Receive
{
 if UDR=2 --> flag=true;
}


main()
 for(;;)
 {
   if(flag=true)
   {
    flag=false;
    USART_transmit_string("alles klar");
   }
 }

Autor: Karl heinz Buchegger (kbucheg)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> oder bei einer 2 soll er halt in die ISR springen
> und was zurückschicken....

Das soll er mit Sicherheit nicht.
Was er machen soll ist:
Er soll die Sende-Funktion mit einem Text als
Parameter anspringen. Direkt aus der ISR ist das aber
nicht so gut. Besser ist es, das zu Sendende erst mal
in einen Buffer zu schreiben und die Hauptschleife in main()
ruft dann die Sendefunktion auf. Die Sendefunktion
ihrerseits stellt die Zeichen in einen Ausgangspuffer,
stellt das erste Zeichen in den UART und
schaltet den Interrupt ein, der immer dann aufgerufen
wird, wenn das UART-Ausgangsregister frei zur Aufnahme
des nächsten Zeichens ist. Innerhalb der ISR wird dann
das nächste Zeichen aus dem Ausgangspuffer geholt, so
es noch eines gibt, und weggeschickt. Gibt es kein Zeichen
mehr im Ausgangspuffer, so dreht die ISR den Interrupt ab
woraufhin wieder Ruhe im µC herrscht.

Das ist dein Plan. Und wenn ich mich richtig erinnere
arbeitet die UART-Lib von Peter Fleury genau nach diesem
Plan.

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke!

Also die UART-LIB von Peter Fleury hab ich mir mir gerade mal
angeschaut. Doch das ist mir alles zu viel auf einmal, da verstehe ich
gar nix. Und nur das von ihm übernehmen und gut iss, das will ich
nicht.

Aber soweit kann ich doch mit meinem Programm auch nicht von einer
Lösung entfernt sein.

Also gehe ich nun folgendermaßen vor:

1. Ich deklariere mir einen Buffer für die zu sendenden Werte, z.B.
   unsigned char buffer;

2. Diesem wird dann bei einem bestimmten emfangenen Zeichen ein Wert
   zugewiesen.

3. Ich erstelle mir eine Sendefunktion z.B. UART_send, welche ich in
   der main() aufrufe und weise

3. In dieser Sendefunktion weise ich dem UDR0 den Wert vom Buffer
   zu, mache eine Abfrage ob das Ausgangsregister frei ist und
   schalte den Interrupt ein.

So ungefähr?

Und warum muss ich UDREn auch noch setzen? Wird das nicht automatisch
gesetzt sobald der UDRE-Interrupt gestartet wird...?

Grüße

Autor: Karl heinz Buchegger (kbucheg)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> So ungefähr?

Yep. Klingt gut.

> Und warum muss ich UDREn auch noch setzen? Wird das nicht
> automatisch gesetzt sobald der UDRE-Interrupt gestartet wird...?

Der Interrupt wird ja nicht gestartet. Der Interrupt wird nur
freigegeben. D.h. Du erlaubst nur, dass Interrupts kommen
können. Die Aussage des Interrupts ist aber: "Das zu sendende
Zeichen ist soweit abgearbeitet, dass du mir wieder ein
Zeichen geben könntest." Damit das aber zutrifft, muss irgendwann
einmal ein Zeichen in UDRn gelandet sein. Und das ist das
erste Zeichen, dass du händisch hineinschreibst. Das Zeichen
wird abgearbeitet und dann beginnt der Interrupt Mechanismus
zu laufen.

Autor: Karl heinz Buchegger (kbucheg)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Oder auf Deutsch:
Der Interrupt meldet sich bei: "Juhu, ich bin fertig. Gibts
noch was zu tun?"

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hey, hatt geklappt!

Funktionierte alles super, bis gerade! Hab nichts verändert, aber nun
muss ich das zu sendende Zeichen zweimal drücken damit es z.B. die LED
einschaltet....!

Woran kann das nun wieder liegen....

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.