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ß
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?
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?
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?
@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 ?
> 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.
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ß
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.
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
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ß
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.
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
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´ß
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.
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ß
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.
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ß
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 !!
>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