Hallo, schon lange her das ich mich mit AVRs beschäftigen musste. Ich habe ein Problem mit der Richtungsumkehr der Uart. Nach dem Empfang eines Frames soll auf diesen geantwortet werden. Die sende Routine alleine funktioniert aber nicht nach dem Empfang eines Paketes. Ich sehe das EN Bit was den Treiber umdreht und auch wo der Antwort Frame sein sollte aber es werden keine Daten auf den TX geschrieben. Folgende Bedingung sollten erfüllt sein. - UDRIEn 1 -> UDRx frei - UCSRxB TXENx 1 trotzdem hat das schreiben auf das Register UDRx keine Wirkung, als würde das UDRx nicht frei sein. Kann es sein das der RX durch den default Pegel des Treibers blockiert wird ? Also dieser immer weiter Daten einließt und mir deshalb den UDR nicht frei gibt? Was nicht unerwähnt sein sollte ich muss im Telegramm ein Break erzeugen mit umschalten der Baudrate.
:
Bearbeitet durch User
Ausser dem Namen fürs Datenrgister (UDRn) und und dem gleichen Baudratengenerator für beide haben Sender und Empfänger nichts miteinander zu tun. Und da es erwiesenermaßen bei anderen funktioniert, wird es wohl an deinem Programm liegen (den seltenen Fall eines Hardwaredefekts mal ausgeschlossen.
Ich bin auch ein Blödmann .... Also mal in die Referenz geschaut und zwischen den Zeilen gelesen. bevor man ins UDR schreibt muss man das TXCn im CSRnA erst löschen. Damit schaltet man das UDR Register um. Mit einer ISR wird dies automatisch erledigt. Es hat trotzdem nicht funktioniert -> ich Blödmann habe nicht erkannt das das Devices gar nicht antworten kann so lange der Master den TX oben hält wenn dieser im reinen DMX Mode läuft, kehrt der auch die Richtung nicht um. Steckt man ihn ab hängt das ganze in der Luft. Na ein paar kleinen Änderung die nicht ganz 8bit like waren hat das RDM Projekt sofort auf dem Atmel 32U4 funktioniert. Unten das mit der 15 in der UID ist der AVR ;) Vom Memory liege ich so bei 44% der 1k ;) wohl gemerkt 29 Parameter. Das lässt sich sicherlich noch optimieren. Subdevices sind aber auf Grund des mangeln Speichers problematisch. Der Sam3x auf dem das gebaut wurde hatte 100k ;)
Marco H. schrieb: > bevor man ins UDR schreibt muss man das TXCn im CSRnA erst löschen. > Damit schaltet man das UDR Register um. Nein, da hast Du irgendwas gründlich fehlinterpretiert.
Das steht aber so in der Referenz und ist auch logisch. Ich lösche das Bit -> schreibe ins UDR und warte bis es draußen ist. Dann kommt das nächste ... "Note that the TXCn Flag must be cleared before each transmission (before UDRn is written) if it is used for this purpose." "The TXCn Flag bit is automatically cleared when a transmit complete interrupt is executed, or it can be cleared by writing a one to its bit location. The TXCn Flag is useful in half-duplex communication interfaces (like the RS-485 standard), where a transmitting application must enter receive mode and free the communication bus immediately after completing the transmission."
Das ist so ähnlich wie das Ding mit dem Status Register beim lesen. Erst UCSRA auslesen und dann das UDR... Aber ich lasse mich gerne belehren wenn doch anderes ist ... Das mit dem Umschalten war ewt. nicht korrekt. Es sind ja zwei UDR Register die man über eine Adresse anspricht. Es wird wohl nach lesen bzw. schreiben selektiert.
:
Bearbeitet durch User
Trotzdem ist es eine Fehlinterpretation. Das UDR fasst zwei Register in einem zusammen, das Senderegister und das Empfangsregister. Die Auswahl des jeweiligen Registers erfolgt durch die Art des Zugriffs - das Senderegister kann nur beschrieben werden, das Empfangsregister hingegen kann nur gelesen werden. Das TXCn-Flag dient lediglich dazu, festzustellen, daß die UART das letzte geschriebene Byte bereits gesendet hat; wenn Du den Satz vor dem ersten von Dir zitierten Satz Dir auch angesehen hättest, sähest Du das auch: > The TXCn Flag can be used to check that the Transmitter has > completed all transfers (...) Das ist wichtig, wenn man ein Protokoll wie RS485 implementieren will, weil man den RS485-Treiber umschalten muss, wenn man mit dem Senden eines kompletten Datensatzes fertig ist. Dieses Bit hilft einem dabei, den entsprechenden Zeitpunkt festzustellen; Du kannst es entweder pollen (d.h. zyklisch abfragen), dann musst Du es selbst vor dem Senden zurücksetzen, oder aber Du kannst es einen Interrupt auslösen lassen, dann musst Du Dich um das Zurücksetzen nicht kümmern. In der ISR musst Du dann feststellen, ob der komplette Datensatz gesendet ist, und kannst dann die Steuerleitung für den RS485-Treiber entsprechend ansteuern. Aber das hat mit der UART selber nichts zu tun, sondern ist eine Protokollebene oberhalb dessen, was die UART macht.
1 | for(int i=0;i<length;i++){ |
2 | |
3 | UCSR1A|= (1<<TXC1); |
4 | UDR1 = data[i]; |
5 | while(!(UCSR1A&(1<<TXC1))); |
6 | }
|
1 | UCSR1A|= (1<<TXC1); |
entfernt man das schweigt das ganze... Ich rufe für das senden keine ISR auf, ich schalte auch alle ISRs aus da das antworten zeitkritisch ist.
Marco H. schrieb: > Also mal in die Referenz geschaut und zwischen den Zeilen gelesen. Das glaubst höchstens du. > bevor man ins UDR schreibt muss man das TXCn im CSRnA erst löschen. Unsinn. TXCn ist hyperfluid für den eigentlichen UART-Sendeverkehr. Der wird nämlich über UDREn als "Kontrollinstanz" abgewickelt. TXCn braucht man nur dann, wenn man aus irgendeinem Grunde die Sende-Hardware der UART mal explizit komplett ausleeren muss, ohne den Inhalt dessen zu beschädigen, was an Bits noch in der Hardware-Queue rumlungert, sondern sicherstellen will oder muss, dass auch diese noch komplett gesendet wird. Also eher selten... Eine typische Anwendung wäre allerdings irgendwas mit RS485, weil das nunmal simplex ist, d.h.: umschalten auf Empfang darf man erst, wenn die Sendung nachweislich komplett 'raus ist. Da darf und sollte man dann TXCn beschäftigen. Dein Problem ist offensichtlich, dass du die Funktionsweise der USART nicht wirklich kapiert hast...
Ich habe es schon verstanden was ihr meint, das Problem ist das es nicht funktioniert.
1 | for(int i=0;i<length;i++){ |
2 | |
3 | UDR1 = data[i]; |
4 | UCSR1A|= (1<<TXC1); |
5 | |
6 | while(!(UCSR1A&(1<<TXC1))); |
7 | }
|
kehrt man die Reihenfolge um funktioniert nur kurz dann ist Feierabend der code hängt dann in der schleife und der BUS wird durch den TX blockiert.
1 | for(int i=0;i<length;i++){ |
2 | |
3 | UDR1 = data[i]; |
4 | |
5 | while(!(UCSR1A&(1<<UDRE1))); |
6 | }
|
kommt es zu packet errors .. Auch wenn man auf das TXC1 wartet .. Das UDREn sagt ja das UDR ist frei, TXCn alle Daten sind raus ..
HI >while(!(UCSR1A&(1<<UDRE1))); Ob UCR frei ist prüft man vor dem >UDR1 = data[i]; Siehe Datenblatt. MfG spess
Das mache ich auch bevor ich in die sende Routine komme. Den timer brauche ich um das RX timeout festzustellen, ja das könnte man auch in der ISR aber den Timer brauche ich auch so das die Antwort min 176µ nach dem RX erfolgen muss. Man könnte auch den Überlauf checken ca 4ms oder den counter checken dann hat das erzeugen der Antwort zu lange gedauert, da lief dann etwas schief. So zerstört man kein DMX Paket vom Bus. Auch das berechnen der BAUD rate könnte man verbessern, aber beim break ist der Fehler ziemlich Wurst.
Ich habe die Routine nochmal verändert und zwar in der Hinsicht getrennte Buffer für RDM und DMX zu verwenden. Es gab eine Laufzeit abhängigen Fauxpas, der AVR war an einer stelle nicht flott genug die Daten weg zu kopieren. Das Signal wird jetzt auf Gültigkeit geprüft. -> kein geflacker mehr mit dem Finger in der Dose ;) usw. Dem Dimmer wurden folgende Modi hinzugefügt. - 8bit RGB Mode - 16bit RGB Mode - 8bit RGB Fader Mode -> 1 Channel ist Master - switch Mode wie immer alles steuerbar über RDM
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.