www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik uart probleme oder?


Autor: overseer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hi, ich bin es mal wieder :>

ich versuche gerade eine uart verbindung zu übungszwecken in gang 
zubekommen

dazu sendet ein atmega8 6zeichen zu einem anderen

das ganze funktioniert auch....
und zwar exakt einmal :P

vorweg ich benutze den internen quarz bei 4800baud
ich weiß zwar das der recht ungenau sein soll. aber einmal funktioniert 
die übertragung ja vondaher glaube ich eher an einen fehler meinerseits 
:/
außerdem kommen die zeichen sauber an nur in falscher reihenfolge.

F_cpu ist daher 1mhz
und baudrate 4600

[code]

UCSRC = (1<<URSEL) | (1<<UCSZ1) |(1<<UCSZ0); //8bit character size
UCSRB |= (1<<RXEN); //receiver mode

for(;;)
{
while(j<6)
{
while((UCSRA & 0b10000000)-128) {} //wartet bis udr voll
Out[j]=UDR;
j++;
}

if(j==6)
{
j=0;
lcd_sendstring(Out);     //schickt den string zum lcd >funktioniert
lcd_choporder(0x02);     //setzt den coursor auf position 0
_delay_ms(500);
_delay_ms(500);
_delay_ms(500);
_delay_ms(500);
_delay_ms(500);
_delay_ms(500);
Out[j]=UDR;
//kam mir so in den sinn da udr wenn es nicht ausgelesen wird nicht 
aktualisiert wird...funkt aber (so) scheinbar nicht
}
}
[code]
ich habe mich dabei am wiki beispiel orientiert


ich bin mir sicher das der fehler durch die dauer der ausgabe zustande 
kommt...

beim erstenmal gibt er den richtigen string aus
anschließend kommen zwar die zeichen die auch in dem string vorkommen 
aber in kauderwelsch reihenfolge :/
also nicth nur um x stellen versetzt :/

ich hatte mir gedacht das das evtl. dadurch kommt das ja UDR noch einen 
byte enthält und sich nicht weiter aktualisiert und somit dann dieser 
byte irgendwo in der kette auftauchen könnte beim nächsten 
auslesen...aber dem ist nicht so (oder mein schutz mechanismus 
funktioniert so nicht)


gruß

Autor: overseer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
sorry für den code :/ hab einen slash vergessen :(

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
und sorry dafür, daß er beswcheiden formatiert ist.

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
es gibt keinen internen Quarz.
Siehe Tutorial.

Autor: krishna (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
zeig mal die senderoutine

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die C-Formatierung geht nicht mit eckigen Klammern und code,
sondern c.

Und Groß-/Kleinschreibung erhöht die Lesbarkeit.
So macht das Lesen jedenfalls keinen Spaß.

Ich habe keine besondere Lust, da jetzt Klammern zu zählen,
aber kann es sein, daß for(;;) eine Endlosschleife ist und
darin j nur erhöht wird und nie wieder kleiner wird?

Autor: overseer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hier die gewünschte senderoutine.
for(;;)
  {
    while(UCSRA ^ 0b00100000) {} //prüft ob USR "leer" ist
    UDR = '$';
    _delay_ms(5);
    
    while(UCSRA ^ 0b00100000) {}
    UDR = 'G';
    _delay_ms(5);
    
    while(UCSRA ^ 0b00100000) {}
    UDR = 'P';
    _delay_ms(5);
  
    while(UCSRA ^ 0b00100000) {}
    UDR = 'R';
    _delay_ms(5);

    while(UCSRA ^ 0b00100000) {}
    UDR = 'M';
    _delay_ms(5);

    while(UCSRA ^ 0b00100000) {}
    UDR = 'C';
    _delay_ms(5);
   }                                    



hier noch mal die empfangsroutine
for(;;)
{
  while(j<6)
    {      
      while((UCSRA & 0b10000000)-128) {}
      Out[j]=UDR;
      j++;
    }  
  
    if(j==6)
    {
      j=0;
      lcd_sendstring(Out);
      lcd_choporder(0x02);
      _delay_ms(500);
      _delay_ms(500);
      _delay_ms(500);
      _delay_ms(500);
      _delay_ms(500);
      _delay_ms(500);
      Out[j]=UDR;
    }
}

gruß

Autor: Sajuuk (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was sollen die ganzen delays????
Mal davon abgesehen das bei __delay_ms() ne Begrenzung gibt.
Soweit ich weiß ist di Maximale wartezeit 262/F_CPU.(F_CPU in MHz)
Soll heizen selbst wenn du einen internen Quarz mit 1 Mhz hast könntest 
du trotzdem nur maximal 262ms warten.
Hast du überhaupt die delay.h includiert?

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das ist aber kein vollständiger Quelltext?
Wo wird j initialisiert? Ist j ein sinnvoller Variablenname,
wenn die Variable über einen größeren Bereich benutzt wird?
Warum liest du erst in der while-Schleife sechsmal (falls j
mit 0 initialisiert wird), und dann nachher am Ende vom if noch
einmal?
Warum nimmst du statt der while-Schleife mit 6 Durchläufen
nicht eine for-Schleife?
Und wozu ist if(j==6) gut, wenn doch j nach dem while nie einen
anderen Wert als 6 haben kann?
Braucht lcd_sendstring nicht einen nullterminierten String?
Falls ja: wo wird der terminiert?

Autor: krishna (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Sajuuk, kann schon sein, ich glaube da wurde in der neuen Version was 
geändert. Ist aber egal, weil es hier keine Rolle spielt.

Aaalso:
Die for(;;) brauchst du nicht, überleg mal , warum (soll ja ne Übung 
sein, oder ? :-)

Frage: Wartest du in der Senderoutine auch lange genug, bevor du den 
ganzen Kram nochmal sendest ? Ansonsten geht nämlich (wenn die 500ms 
passen) 3 sekunden lang alles ins Nirwana.

Was heißt, es kommt in der falschen Reihenfolge ? Kannst du das mal 
genauer Beschreiben ?

Autor: krishna (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Huch

>Die for(;;) brauchst du nicht, überleg mal , warum (soll ja ne Übung
>sein, oder ? :-)

stimmt nicht.. sorry. hab mich verguckt. :-(

Autor: MeinerEiner (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Mal davon abgesehen das bei __delay_ms() ne Begrenzung gibt.

Sicher?
Ich hab in einigen Projekten auch _delay_ms(8000) am Laufen, was perfekt 
funktioniert.

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
m.W. ist _delay_ms ab einem bestimmten Wert nicht mehr genau,
funktioniert aber ansonsten trotzdem.

Autor: overseer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
schonmal danke für die zahlreichen antworten

>Braucht lcd_sendstring nicht einen nullterminierten String?
>Falls ja: wo wird der terminiert?

braucht sie nicht
habe es so eingestellt das sie 6zeichen ausspuckt

>Warum liest du erst in der while-Schleife sechsmal (falls j
>mit 0 initialisiert wird)

ja, j wird mit 0 initialisiert
der einzulesende string ist 6 zeichen lang



>Und wozu ist if(j==6) gut, wenn doch j nach dem while nie einen
>anderen Wert als 6 haben kann?

da hast du wohl recht...
das kommt davon wenn man den code x mal umbastelt...
schaden tut es hier denke ich nicht von daher ist das wohl nicht der 
grund meines problems
werde es aber logischerweise anpassen. danke für den hinweis


>Was sollen die ganzen delays????
>Mal davon abgesehen das bei __delay_ms() ne Begrenzung gibt.
>Soweit ich weiß ist di Maximale wartezeit 262/F_CPU.(F_CPU in MHz)

afaik wurde diese grenze aufgehoben
davon abgesehen funktionieren die delays...die anzeige ändert sich alle 
~3sek
die delays sind da nur damit ich lesen kann was auf dem display steht
(zur fehler findung)



gruß

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Welchen Sinn das "Out[j]=UDR;" im if-Block haben soll, hast du noch 
nicht erklärt.

Außerdem: Du hast keinerlei Synchronisierung zwischen Sender und 
Empfänger. Auch in der Zeit, in der der Empfänger 3 Sekunden lang 
wartet, sendet der Sender fleißig weiter. Logisch, dass der Empfänger 
nach den 3 Sekunden nicht beim "$" wieder einsteigt, sondern eben da, wo 
der Sender zu diesem Zeitpunkt gerade ist.

Autor: gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
wenn du es richtiger machen willst


empfangsinterrupt akivieren und zeichen immer empfangen
wenn ein $ kam weißt du ja das jetz dein gewollter sting kommt
kommst was anderes isses unwichtig

dann senden

>braucht sie nicht
>habe es so eingestellt das sie 6zeichen ausspuckt

wozu ?
was ist wenn du was anderes senden willst ? schreibte noch 20 neue 
sendefunktionen ?


terminiere den string und sende es richtig

Autor: overseer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
doch in meinem ersten post..aber arg kurz

macht aber nix

ich habe mir das so gedacht...

ich fülle ja mein array nacheinander mit UDR.
nachdem die letzte stelle meines arrays gefüllt ist, wird udr aber 
wieder mit dem nächsten datensatz gefüttert, da ich jetzt aber mit 
meinem zeithungrigen bildschirm füllen beschäftigt bin, kann ich UDR 
nicht mehr leeren somit ist UDR mit einer altlast gefüllt die ich aber 
beim nächsten einlese vorgang direkt in mein array[0] schreibe, denn das 
UDR voll flag ist ja gesetzt somit denkt das programm das verwertbare 
daten in UDR sind

da ich das logischerweise nicht möchte habe ich mir gedacht lese ich UDR 
einfach aus, dadurch wird das flag wieder auf null gesetzt und das 
programm wartet auf den nächsten richtigen datensatz und überspeichert 
das nicht gewollte ergebnis damit.

im klartext heißt Out[j]=UDR an der stelle ja Out[0]=UDR
das wird also zweimal hintereinander beschrieben einmal mit dem alten 
inhalt und einmal mit dem neuen richtigen

fazit: funktioniert so scheinbar nicht

ich bin mir aber 100% sicher das da der fehler liegt!

in der ausgegebenen zeichenkette ist immer die erste stelle falsch 
sprich Out[0]

gruß

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> ich bin mir aber 100% sicher das da der fehler liegt!

Dann ist ja alles in Ordnung!

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Deine Überlegung ist gar nicht mal so schlecht, aber du hast 2 Zeichen 
"Altlasten". In UDR und im Empfangs-Shift-Register.

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
und diese beiden Altlasten sollen sicher das Ende eines Strings
sein und direkt danach soll ein neuer anfangen?

Sowas ist nicht in einem Thread zu machen.
Ohne Interrupts, die im Hintergrund UDR bedienen, wird das doch
nichts.

Autor: gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
und noch mehr altlasten

- deine aktuelle vorgehensweise  !!

derµC rennt in einer schleife
und soll was tun wenn es was zu tun gibt

dann mach es so ..
und halte den nicht mit sinnlosen delays auf

programmierst du jetzt mal wichtiges rein ... is das gesammte timing für 
die füße

Autor: overseer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
nein nein nein so kompliziert müssen wir es nicht machen :)
wie gesagt das ganze ist erstmal zum ÜBEN
schlussendlich würde ich gerne ein gps modul auslesen wollen aber das 
ist noch ein bissl hin -zeitlich und wissenstechnisch :)-

hier der ablauf:

schritt eins: lesen von 6zeichen
schritt zwei: ausgeben der 6 zeicehn

schritt eins: lesen der nächsten 6zeichen (es ist egal wo er genau 
anfängt nur die reihenfolge sollte noch stimmen)
schritt zwei: ausgeben

das ich noch eine zweite altlast habe war mir nicht bewusst :/
was UDR ist, ist klar, aber was ist das Empfangs-Shift-Register? :?

ich kenne wohl noch den seperaten 9ten bit in UCSRB aber der ist hier 
eigentlich egal da ich mit 8bits arbeite.


gru´ß

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
overseer schrieb:

> das ich noch eine zweite altlast habe war mir nicht bewusst :/
> was UDR ist, ist klar, aber was ist das Empfangs-Shift-Register? :?

Das ist das Register, in dem die einzelnen empfangenen Bits gesammelt 
werden. Ist das Byte vollständig, wird es nach UDR übertragen. Und 
während es dort auf die Abholung wartet, werden im Shift-Register schon 
die nächsten Bits gesammelt. Ist wieder ein Byte vollständig und UDR 
nicht frei, verbleibt es erstmal im Shift-Register. Jedes weitere 
eintreffende Bit wird nicht mehr gespeichert, sondern erzeugt einen 
DOR-Fehler. Du hast also zwei "Altlasten". Das Byte in UDR, das darauf 
wartet von dir abgeholt zu werden, und das Byte im Shift-Register, das 
darauf wartet nach UDR transferiert zu werden.

Autor: overseer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
thanks alot

jetzt gehts :)

habs durch zweimaliges auslesen des UDR registers gelöst


was anderes das mich schon seit einiger zeit wurmt und letzlich auch mit 
diesem thema zusammenhängt ist,

die geschwindigkeit/ die leistung die ein uC bringen kann ist ja 
abhängig von seiner rechengeschwindigkeit und von der zeit die ihm zum 
arbeiten zuverfügung steht

nehmen wir dieses beispiel hier...
angenommen das senden dieser 6zeichen würde 500ms benötigen und ich 
würde sie im sek takt senden, dann bliebe dem prozessor nur noch 500ms 
arbeitszeit
wie löst man so ein problem in der praxis?

die einzige lösung die mir einfällt, ist die daten von diesem µC 
nochmals zu einem anderen µC zuschieben, aber in kürzerer zeit.


gruß

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
overseer schrieb:
>
> angenommen das senden dieser 6zeichen würde 500ms benötigen und ich
> würde sie im sek takt senden, dann bliebe dem prozessor nur noch 500ms
> arbeitszeit
> wie löst man so ein problem in der praxis?

Indem man die UART-Interrupts benutzt. Dann beschäftigt das Senden und 
Empfangen den Prozessor nur noch für einen kleinen Bruchteil dieser 
500ms.

Autor: overseer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
stimmt jetzt wo du es schreibst :/

ich hatte die interrupts zwar nicht vergessen...aber ich hatte gedacht 
das der uC während des empfangens trotzdessen voll ausgelastet 
ist...aber er ist natürlich nur beschäftigt wenn ein byte fertig ist.


gruß

Autor: uart (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
wer mit dem senden + emfangen von einer uart sollte den µC eigentlich 
nicht belasten
wie lange er brauch  kannse dir ausrechnen



und 500ms ... sind bei 1MHz  nch 500000 takte und quasi ideal 500000 
befehle
rechnen wir real und schenken ihm 250000befehle

wenn du deine uartroutinen optimierst ...
ist zwischen dem senden statt 500ms eben 900ms zum rechnen luft


denke wie gesagt drüber nach was wie ablaufens oll und hau die delays 
raus
mach es ohne ...
gewohn dir sowas erst garnicht an


delays innerhalbd er initialisierung .. ok ...
aber im programmablauf hat das ding nichts zu suchen

und schon garkeine 3s !!

Autor: overseer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>denke wie gesagt drüber nach was wie ablaufens oll und hau die delays
>raus
>mach es ohne ...
>gewohn dir sowas erst garnicht an


>delays innerhalbd er initialisierung .. ok ...
>aber im programmablauf hat das ding nichts zu suchen

>und schon garkeine 3s !!

die sind hier nur zur fehlersuche!!!

normalerweise benutze ich keine delays außer natürlcih beim 
initialisieren. man wirft ja praktisch sein geld damit aus dem fenster 
xD

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.