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?
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ß
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 ?
Huch >Die for(;;) brauchst du nicht, überleg mal , warum (soll ja ne Übung >sein, oder ? :-) stimmt nicht.. sorry. hab mich verguckt. :-(
> 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.
m.W. ist _delay_ms ab einem bestimmten Wert nicht mehr genau, funktioniert aber ansonsten trotzdem.
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ß
> ich bin mir aber 100% sicher das da der fehler liegt!
Dann ist ja alles in Ordnung!
Deine Überlegung ist gar nicht mal so schlecht, aber du hast 2 Zeichen "Altlasten". In UDR und im Empfangs-Shift-Register.
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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.