Forum: Mikrocontroller und Digitale Elektronik uart probleme oder?


von overseer (Gast)


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ß

von overseer (Gast)


Lesenswert?

sorry für den code :/ hab einen slash vergessen :(

von Klaus W. (mfgkw)


Lesenswert?

und sorry dafür, daß er beswcheiden formatiert ist.

von Klaus W. (mfgkw)


Lesenswert?

es gibt keinen internen Quarz.
Siehe Tutorial.

von krishna (Gast)


Lesenswert?

zeig mal die senderoutine

von Klaus W. (mfgkw)


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?

von overseer (Gast)


Lesenswert?

hier die gewünschte senderoutine.
1
for(;;)
2
  {
3
    while(UCSRA ^ 0b00100000) {} //prüft ob USR "leer" ist
4
    UDR = '$';
5
    _delay_ms(5);
6
    
7
    while(UCSRA ^ 0b00100000) {}
8
    UDR = 'G';
9
    _delay_ms(5);
10
    
11
    while(UCSRA ^ 0b00100000) {}
12
    UDR = 'P';
13
    _delay_ms(5);
14
  
15
    while(UCSRA ^ 0b00100000) {}
16
    UDR = 'R';
17
    _delay_ms(5);
18
19
    while(UCSRA ^ 0b00100000) {}
20
    UDR = 'M';
21
    _delay_ms(5);
22
23
    while(UCSRA ^ 0b00100000) {}
24
    UDR = 'C';
25
    _delay_ms(5);
26
   }


hier noch mal die empfangsroutine
1
for(;;)
2
{
3
  while(j<6)
4
    {      
5
      while((UCSRA & 0b10000000)-128) {}
6
      Out[j]=UDR;
7
      j++;
8
    }  
9
  
10
    if(j==6)
11
    {
12
      j=0;
13
      lcd_sendstring(Out);
14
      lcd_choporder(0x02);
15
      _delay_ms(500);
16
      _delay_ms(500);
17
      _delay_ms(500);
18
      _delay_ms(500);
19
      _delay_ms(500);
20
      _delay_ms(500);
21
      Out[j]=UDR;
22
    }
23
}

gruß

von Sajuuk (Gast)


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?

von Klaus W. (mfgkw)


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?

von krishna (Gast)


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 ?

von krishna (Gast)


Lesenswert?

Huch

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

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

von MeinerEiner (Gast)


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.

von Klaus W. (mfgkw)


Lesenswert?

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

von overseer (Gast)


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ß

von Stefan E. (sternst)


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.

von gast (Gast)


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

von overseer (Gast)


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ß

von Klaus W. (mfgkw)


Lesenswert?

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

Dann ist ja alles in Ordnung!

von Stefan E. (sternst)


Lesenswert?

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

von Klaus W. (mfgkw)


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.

von gast (Gast)


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

von overseer (Gast)


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´ß

von Stefan E. (sternst)


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.

von overseer (Gast)


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ß

von Stefan E. (sternst)


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.

von overseer (Gast)


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ß

von uart (Gast)


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 !!

von overseer (Gast)


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

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.