Hallo Leute,
zunächst einmal: Ich bin gerade ganz neu in diesem Forum, also verzeiht
es mir bitte, wenn mein erster Post nicht perfekt und evtl. etwas
unvollständig ist. Ich hoffe wircklich das ihr mir weiter helfen könnt,
denn ich habe schon sehr viel gutes von diesem Forum gehört und auch das
AVR-GCC-Tutorial dieser Seite hat mir schon oft geholfen :-)
Ich habe folgendes Problem:
Ich versuch gerade das erste Mal mit einem Mikrocontroller (ATtiny2313)
und einem Computer (HTerm) seriell zu kommunizieren. Ich benutze AVR
Studio 6 und habe folgendes Programm in den µC geladen (hier nur die
Datei in der mit dem UART gearbeitet wird, in der main werden diese
Funktionen nur aufgerufen):
while(!(UCSRA&(1<<UDRE))){}// Warten bis Senden möglich
29
30
UDR='3';// Zeichen senden
31
}
Am PC nutze ich, wie oben schon erwähnt HTerm. Am µC habe ich einen
externen 8MHz Quarz angeschlossen, welcher laut Oszilloskop auch richtig
arbeitet. Die Fuse-Bits für diesen Quarz sind gesetzt und das CKDIV8-Bit
ist nicht gesetzt.
Bei HTerm empfange ich jedoch nur Datenmüll. Ich habe auch schon ein
anderes Terminalprogramm namens Termite ausprobiert, mit demselben
Ergebnis.
Wenn ich allerdings bei Termite des Öfteren Disconnecte und dann wieder
Connecte kommt manchmal das richtige an.
Ich hoffe ihr hab nun alle Infos die ihr braucht, um mir evtl. zu
helfen, sitze nämlich nun schon seit 2 Tagen daran und würde nun gerne
mit dem Projekt fortfahren, dies sollten ja eigentlich nur
Vorbereitungen werden :-)
Ich habe die Initialisierungssequenzen für den -2313 nicht im Kopf, aber
ich habe die Erfahrung gemacht dass, wenn Datenmüll ankommt, was
verschickt wird. Da Du ein Oszi. hast, schau Dir mal die
Übertragungsrate am Ausgang an. Möglicherweise ist die Baudrate daneben.
P.S. Ich habe mal vor ein paar Jahren Probleme mit der seriellen
Datenübertragung, allerdings bei einem ATMega, gehabt. Die konnte ich
nur lösen indem ich mit 2 Stoppbits gearbeitet habe. Keine Ahnung warum.
Ist wohl irgendwie aus dem (Übertragungs-)Rahmen gefallen.
Wenn das alles ist was Du sendest könnte die Ursache hier liegen
http://www.mikrocontroller.net/articles/AVR-Tutorial:_UART
"Wenn man das nachfolgende Programm laufen lässt und Hyperterminal
startet, scheint es problemlos zu funktionieren. Wenn man aber das RS232
Kabel zwischenzeitlich abzieht und wieder ansteckt wird es oft
passieren, dass nur noch wirre Zeichen auf dem PC erscheinen. Das liegt
daran, dass der PC aus einem ununterbrochen Zeichenstrom nicht den
Anfang eines Zeichens erkennen kann. Darum muss in solchen Fällen
periodisch eine kleine Pause von der Länge mindestens eines Zeichens
eingelegt werden, damit der PC sich wieder synchronisieren kann. "
Füge mal eine Pause in den gesendeten Datenstrom aus lauter Dreien ein
damit der Empfänger eine Chance hat ein Anfang solide zu erkennen.
Ansonsten ist es Glückssache, daß die Verbindung synchron mit dem Begin
eines Zeichens zum passenden Zeitpunkt hergestellt wird, was zu deiner
Beschreibung passen würde.
Gruß
Carsten
Yeah!!!! Endlich funktioniert es. Ich habe einfach eine Pause mit
_delay_ms() von 500ms eingebaut und schon funktioniert alles
einwandfrei.n Ich danke euch für die schnellen und guten Ratschläge!
@amateur(Gast)
soweit ich weiß, berechnet doch der Compiler UBRRH_VALUE und UBRRL_VALUE
mit genau dieser Anweisung?
Jens Kathe schrieb:> Endlich funktioniert es. Ich habe einfach eine Pause mit> _delay_ms() von 500ms eingebaut und schon funktioniert alles> einwandfrei.
Du brauchst gar nicht eine Ewigkeit zu waren. Eine Millisekunde würde
bei 9600 Bd völlig reichen.
Stimmt, eine Millisekunde ist ausreichend. Kürzer sollte die Pause aber
nicht sein. Die benötigte Pause richtet sich nach der Symbolrate, ist
also konfigurationsabhängig.
Zum Beispiel hat ein Byte 8 Bit. Dazu kommen noch ein Start und ein
Stopbit. Das macht insgesamt 10 Bit. Man kann aber auch 5,6,7 oder 9 Bit
und zwei Stopbits, Parity etc. verwenden. Die Pause muß groß genug sein,
daß ein ganzes Frame reinpaßt. Damit wäre dann gewährleistet, daß Sie
zweifelsfrei als Idle und nicht durch angrenzende Pegelwechsel als
Symbol erkannt wird.
Bei einem 10 Bit Frame wie hier und 9600 Baud sind es dann 10/9600=1/960
Sekunden, also sehr knapp an einer Millisekunde. Ein Bit mehr im Frame
und es Funktioniert nur noch in 99% aller Fälle, was das Ganze schwer
reproduzierbar macht und dann die Fehlersuche erschwert. Große Frames
bei 2400 Baud brauchen 5 Millisekunden.
500 Millisekunden sind großzügig, aber umgekehrt muß man auch nicht
gerade auf Kante nähen solange es nicht erforderlich ist. Sonst erlebt
man bloß durch kleine Frame oder Baudratenänderungen böse
Überraschungen. Und wer hat dann schon solche Details im Hinterkopf? In
zeitkritischen Anwendungen kann man dann noch immer tunen. Dann ist man
wenigstens mit den Gedanken bei der Sache und man weiß dann, daß man
bewußt auf Kante näht und findet das grenzwertige Verhalten schneller.
Lieber etwas größere Pausen, man braucht sie eh nur selten.
Gruß Carsten
@Amateur:
Wo man die Pausen hinsetzt hängt davon ab was man wie überträgt. Es geht
eigentlich nur darum, daß unmittelbar bevor die interessanten Daten
kommen ein ausreichend langes Idle vorangeht. Sendet man nur
gelegentlich, braucht man das nicht, weil naturgemäß eine Pause
vorangeht.
Sendet man kontinuierlich, ist dies eine simple von mehreren
Möglichkeiten um eine Synchronisierung sicherzustellen. Dann kommt die
Pause zu Beginn eines Datensatzes, selten auch zwischendurch wenn der
Datensatz riesig ist oder die Verbindung nicht kontinuierlich besteht,
bzw gestört ist. Dann braucht man aber auch noch andere Mechanismen.
Carsten R. schrieb:> ...
so ein blödsinn!
man wartet, bis das vorherige byte draußen ist und schickt dann das
nächste hinterher.
irgendwelches geschätztes, gerundetes, aufgemöbeltes und dann wieder
vergessenes gewarte ist einfach nur mist!
lern einem anfänger nicht solches gestümpe.
die avrs haben extra ein status register mit einem flag für genau diesen
zweck.
wenn diese zeile hier stimmt, ist es genau die warte-methode, die man
anwendet.
> while(!(UCSRA & (1<<UDRE))){} // Warten bis Senden möglich
Michael H. schrieb:> so ein blödsinn!> man wartet, bis das vorherige byte draußen ist und schickt dann das> nächste hinterher.> irgendwelches geschätztes, gerundetes, aufgemöbeltes und dann wieder> vergessenes gewarte ist einfach nur mist!> lern einem anfänger nicht solches gestümpe.
Darum geht es doch bei diesem Warten überhaupt nicht. Es geht darum, für
einen Empfänger, der während einer laufenden Übertragung aufgeschaltet
wird, eine Pause im Datenstrom zu erzeugen, die lang genug ist, dass er
sicher auf das nächste Startbit synchronisiert. Eine solche Pause sollte
immer mal wieder eingestreut werden, am Besten zum Beispiel zwischen
einzelnen Datenpaketen.
das teil hängt an einem pc... und nicht an einem rechenschieber.
und das eröffnungsposting lässt auch nicht im geringsten auf einen
solchen fehler schließen.
Michael H. schrieb:> das teil hängt an einem pc...
Ach, und bei dem kann man nicht ein serielles Kabel im laufenden Betrieb
ab- und anstöpseln?
Michael H. schrieb:> und das eröffnungsposting lässt auch nicht im geringsten auf einen> solchen fehler schließen.
Erstens gibt es im Thread ja auch noch mehr Postings, und zweitens ist
das nun mal genau die Situation, auf die sich Carstens Beschreibungen
bezogen haben. Dein "so ein blödsinn!" war somit unangebracht, und deine
Kritik ging am eigentlichen Thema des Postings, auf das du dich bezogen
hast, komplett vorbei.
Stefan Ernst schrieb:> das nun mal genau die Situation, auf die sich Carstens Beschreibungen> bezogen haben.
nö.
denn wenn es so wäre, würde zufälliges an- und abstöpseln bei 3of5
decision nicht mal zu .5% der zeit funktionieren.
das ist schon ziemlich bescheidener zufall.
der fehler ist und bleibt woanders.
zusammenhangsloses rumgewarte kaschiert den fehler, behebt ihn aber
nicht. der tipp an einen anfänger ist und bleibt käse.
Meine Frage nach dem "wo" die Pause eingefügt wurde zielte auf folgende
Problematik:
>while(!(UCSRA & (1<<UDRE))){} // Warten bis Senden möglich
... bedeutet ja "die Bahn ist frei". - Zumindest auf Atmel-Seite.
Der Empfänger ein PC, schon seit Jahren im Gigaherzbereich laufend,
sollte doch eigentlich mit Verzögerungen, die sich aus Übertragungen im
9600-Baud-Bereich ergeben 0,0 Probleme haben.
Ja, wenn wir hier über unangekündigte Pakete im 100 MHz-Bereich reden
würden, würde ich die Problematik einsehen.
amateur schrieb:> Der Empfänger ein PC, schon seit Jahren im Gigaherzbereich laufend,> sollte doch eigentlich mit Verzögerungen, die sich aus Übertragungen im> 9600-Baud-Bereich ergeben 0,0 Probleme haben.>> Ja, wenn wir hier über unangekündigte Pakete im 100 MHz-Bereich reden> würden, würde ich die Problematik einsehen.
falsch... denn der pc weiß nicht, an welcher stelle im rahmen er
angesteckt wurde. in einer kontinuierlichen symbolkette kann er das
start-bit nicht von einem anderen symbol unterscheiden.
aber das ist hier nicht der fehler.
Michael H. schrieb:> nö.> denn wenn es so wäre, würde zufälliges an- und abstöpseln bei 3of5> decision nicht mal zu .5% der zeit funktionieren.> das ist schon ziemlich bescheidener zufall.
Zufälliges ab- und anstöpseln funktioniert nur deshalb fast immer, weil
ein "normaler" Datenstrom eben genau solche Pausen enthält. Entweder
weil absichtlich eingefügt, oder weil wegen des Protokolls eh vorhanden.
Außerdem geht es nicht nur um ab- und anstöpseln.
Ein anderes Szenario ist:
Wenn kein externer Pull-Up verwendet wird, ist die Sendeleitung bis zur
UART-Initialisierung hochohmig. Hier kann durchaus vom Empfänger eine
fallende Flanke gesehen werden, und er fängt an ein Byte zu empfangen.
Und mitten in diesem "Fake-Byte" fängt nun der Sender an, einen
kontinuierlichen Datenstrom zu senden. Auch dann ist der Empfänger nicht
synchron.
Stefan Ernst schrieb:> Außerdem geht es nicht nur um ab- und anstöpseln.> Ein anderes Szenario ist:> Wenn kein externer Pull-Up verwendet wird, ist die Sendeleitung bis zur> UART-Initialisierung hochohmig. Hier kann durchaus vom Empfänger eine> fallende Flanke gesehen werden, und er fängt an ein Byte zu empfangen.> Und mitten in diesem "Fake-Byte" fängt nun der Sender an, einen> kontinuierlichen Datenstrom zu senden. Auch dann ist der Empfänger nicht> synchron.
Genau - zum Beispiel.
Würdest du in einer anständigen Lösung jetzt irgendwie warten, oder
würdest du dich um einen Power-On-Zustand kümmern?
@Michael H.
"das teil hängt an einem pc... und nicht an einem rechenschieber.
und das eröffnungsposting lässt auch nicht im geringsten auf einen
solchen fehler schließen."
Das Problem war als genau dieses aus der Beschreibung erkennbar und es
wurde mit der beschriebenen Methode erfolgreich sofort behoben. Es
stimmt zwar daß für gewöhnlich ausreichende Sendepausen vorangehen, für
gewöhnlich. Ich habe selbst darauf hingewiesen daß dies bei
unterbrochenem Senden der Fall ist, nicht aber bei kontinuierlichen
Übertragungen. In diesem Szenario war das also nicht der Fall. Und
manchmal reicht "für gewöhnlich" nicht und man geht auf nummer Sicher.
Es ist kein Gestümpe einem Protokoll ein definiertes IDLE
voranzustellen. Wenn Du es dennoch für Gestümpe hältst, dann nenne doch
bitte eine bessere und eifachere Alternative um ein Sicheres Idle direkt
vor dem Datenpaket zu gewährleisten. Eine Data Register Empty Prüfung
reicht nicht.
Michael H.schrieb
>nö.>denn wenn es so wäre, würde zufälliges an- und abstöpseln bei 3of5>decision nicht mal zu .5% der zeit funktionieren.>das ist schon ziemlich bescheidener zufall.
Das ist ein Trugschluß. Eben wegen der erwähnten üblichen Pausen erfolgt
das Einstöpseln sehr oft in einer Idle Phase. Das geht in der Regel gut
solange man nicht gerade ein Masseproblem etc. hat. Kritisch ist das
Verbinden während einer laufenden Übertragung. Da ist dann nicht nur das
aktuelle Symbol Schrott (völlig logisch), sondern der Uart weiß nie wo
das nächste Symbol beginnt und das alte Endet. Das ergibt dann nur noch
Mist bis zur nächsten Sendepause. Dann geht es wieder.
Wie schnell der Gigamegasuperduper-PC ist ist völlig egal, denn der
steht am Ende der Verbindung. Dann kommt der Tranciever, die Leitung,
der andere Usart und dann der Mikrocontroller. Die U(S)arts laufen
autark und interessieren sich nur dafür, ob die Register voll oder leer
sind etc. Die übertragung erledigen sie eigenverantwortlich. Wenn man
Salat empfängt wurde entweder zu Begin nur Unfug versendet oder der
Fehler liegt in oder zwischen den U(S)arts. Der PC wird damit selten
überfordert.
Ach ja, es müssen nicht unbedingt Störungen oder Steckvorgänge sein. Es
kann auch sein daß der Empfänger auf der anderen Seite erst während des
laufenden Sendevorgangs durch die Software aktiviert wurde. Es gibt
viele möglichkeiten die schief laufen. Funktionieren tut es nur wenn
alles richtig läuft und nicht nur zu 99% richtig.
Ein Sleep mode kann da auch mal was durcheinanderbringen, denn bei den
tieferen Modes werden die Taktsignale für die Peripherie abgeschaltet.
Wer jetzt denkt, er weckt seinen Zielcontroller mit einem INT0 und
schickt dann gleich die Sendung vom Uart ab kann Spaß haben wenn die
Daten ankommen bevor der Watchdog das Einschwingen der Taktquelle
abgezählt hat und das Dornröschen an die Arbeit läßt. Dann hat man
wieder nur Grütze bis zu nächsten Sendepause. Und dann geht es plötzlich
wieder.
Komisch. Sporadische aussetzer. Hm, wackel mal am Kabel.
viele Grüße und gute Nacht
Carsten