USART Interrupt ATMega

Hallo NG, ich habe folgendes Problem: in meiner Haussteuerung setze ich ATMega8 oder 16 (gleiches Problem) ein, die als Sensoren oder Aktoren =FCber einen RS485-Full-Duplex-Bus miteinander kommunizieren. Damit das Senden funktioniert, werden die RS485-SendeTreiber vor den Senden ein- und danach wieder ausgeschaltet, per Port-PIN ! Das Problem besteht darin, dass ich zum Ausschalten des Senders den Zeitpunkt wissen muss, nachdem das letzte Zeichen den Sendepuffer wirklich physisch verlassen hat. Gem=E4=DF meinem Speicherscope werden aber sowohl TX-Empty wie auch Tx complete Interrupt ausgel=F6st, bevor das Zeichen wirklich den Buffer verlassen hat. Damit wird der Sender zu fr=FCh disabled und das letzte gesendete Zeichen ruiniert. Mach' ich da was falsch, habe ich was =FCbersehen ?!? Ich bin dankbar f=FCr jede brauchbare Idee, denn ansonsten funktionieren meine Ringbufferroutinen wirklich astrein !

Gru=DF Thomas

Reply to
Thomas Mundhenke
Loading thread data ...

Thomas Mundhenke schrieb:

So als µC neuling würde das mit dem Holzhammer lösen indem ich per Timer einfach noch ein paar Takte abwarte, sofern der Timer nicht andersweitig benutzt wird. Wenn die Timer belegt sind, kannst du eventuell derweile erstmal eine Quadrahtwurzel ausrechnen.

Mir ist natürlich klar das das nicht gerade elegant gelöst wäre ;o))

bye uwe

--
AIM: hammernocker2000 ## ICQ: 115118874 ## www.pssgzudresden.de
Jürgen Gerkens in d.r.f. : "... gerade ein Polfilter ist als
Schutzfilter auch nicht viel schlauer, als die Frontlinse zum Schutz
vor Streulicht zu lackieren. ;-)"
Reply to
Uwe 'hammernocker' Roßberg

Also beim TX-Empty is das klar, weil ein neues Zeichen kann ja schon zum Senden ins Senderegister geladen werden, während das letzte gerade noch das Schieberegister am Verlassen ist. Aber beim TX complete sollte das IMO nicht sein.

Ich würde das per "Probieren" rausfinden: Bei fixer Baud-Rate weisst Du ja wie lange das Ausgeben des Zeichens braucht. Zwecks Test würde ich folgendes machen:

0) UART config ;) 1) Timer starten 2) zu sendendes Zeichen in TX schreiben 3) mit dem TXcomplete den Timer auslesen 4) Differenz zwischen IST und SOLL überprüfen

Alternativ geht das natürlich auch mit einem Port-Pin und einem Oszi (falls vorhanden). Ein Kanal (=Trigger) aufs Port-Bit, den zweiten auf den Seriellen Ausgang. Und damits einfach zum messen wird einfach eine Endlosschleife, in der Bytes auf die serielle ausgegeben werden.

Ich denke mal, dass du dir das Stop-Bit zerschiesst. Vielleicht ist die Idee aus dem zweiten Posting (Holzhammer-Methode) ja gar nicht sooo daneben. Einfach noch 10ms warten und dann erst den Treiber abschalten. Wenn sonst nix zu tun is kann das ja sogar eine simple "strohdumme" Loop sein. Sonst halt per Timer.

Heinz

Reply to
Heinz Liebhart

Erstmal danke f=FCr die Vorschl=E4ge, die Delay Methode nehme ich, wenns nicht anders geht. Da meine Software ohnehin Timergesteuert l=E4uft ist das kein Problem. Die Oszi-Messung mache ich ja schon wie beschrieben und es wird definitiv unabh=E4ngig von der Baudrate mitten im Zeichen, ungef=E4hrt bei Bit 3-5 der Interrupt ausgel=F6st. Was ich nicht verstehe, ist dass beide Interrupts das gleiche Resultat liefern ?!? Gru=DF Thomas

Reply to
Thomas Mundhenke

Thomas Mundhenke wrote: : Hallo NG, : ich habe folgendes Problem: : in meiner Haussteuerung setze ich ATMega8 oder 16 (gleiches Problem) : ein, die als Sensoren oder Aktoren über einen RS485-Full-Duplex-Bus : miteinander kommunizieren. Damit das Senden funktioniert, werden die : RS485-SendeTreiber vor den Senden ein- und danach wieder ausgeschaltet, : per Port-PIN ! Das Problem besteht darin, dass ich zum Ausschalten des : Senders den Zeitpunkt wissen muss, nachdem das letzte Zeichen den : Sendepuffer wirklich physisch verlassen hat. Gemäß meinem : Speicherscope werden aber sowohl TX-Empty wie auch Tx complete : Interrupt ausgelöst, bevor das Zeichen wirklich den Buffer verlassen : hat. Damit wird der Sender zu früh disabled und das letzte gesendete AFAIK sind TX-Empty oder Tx complete dafür gedacht, anzuzeigen, daß der Empfänger wieder aufnahmebereit ist. Meist sind die Empfängerregister gepuffert. Wenn Tx complete beim Stopbit ausgelöst wird, könnte es reichen,

2 Stopbits zu verwenden.
Reply to
Peter Heitzer

Das kann/sollte auf keinen Fall so sein. Entweder hat Atmel ein Problem oder Du bei Deiner Messung :-). Da das aber eine extrem elementare Funktion ist, tippe ich auf Dich :-). Schreib doch mal, wie Du den Interrupt erkennst und nach außen reichst (für den Scope).

Gruß, Kurt

--
Kurt Harders
MBTronik - PiN - Präsenz im Netz GITmbH
mailto:news@kurt-harders.de
http://www.mbtronik.de
Reply to
Kurt Harders

Hallo,

kann es sein das du Transmit Compete Interrupt Enable (TXCIE) erst beim senden setzt und das TXCI Flag noch vom vorherigen Byte gesetzt ist und so der Interrupt sofort ausgelöst wird?

Gruß

Reply to
Benjamin Muckelbach

In der Xmit-Interruptroutine werden die By

Reply to
Thomas Mundhenke

warum liest Du nicht einfach beim Senden gleichzeitig mit ein, dann weißt Du a) ob irgendeiner, obwohl er nicht durfte, was zwischenreingefunkt hat b) alles von Deinem Krempel raus ist, weil nur dann das Receive Interrupt Flag gesetzt wird.

? Carsten

Reply to
Carsten Wenzler

Ich bin absolut der Meinung, dass es irgendwie gehen muss, nur ich komme immer wieder zum gleichen Resultat, dass beide Interrupts mitten im letzten Zeichen ausgel=F6st werden. Die vorgeschlagene Delaymethode klappt nat=FCrlich, aber geht nicht gibt's doch wohl nicht ? Quellcodeauszug wie folgt:

// TX Complete Interrupt Service void UART_TX_Interrupt( void ){ .=2E........ Behandlung Ringbuffer, wenns nicht das letzte Zeichen ist ! .=2E....... zum Schlu=DF // falls noch Zeichen im Ringbuffer sind if(TX_Counter){ // enable Transmit Complete Interrupt UCSRA |=3D (1

Reply to
Thomas Mundhenke

Hallo

Thomas Mundhenke schrieb:

Welchen IRQ meinst Du jetzt mit Xmit, den "USART Data Register Empty" oder "USART, Tx Complete"?

Ich verstehe das jetzt so: Du verwendest den UDRE-Interrupt um ein neues Byte in UDR zu legen. Beim letzten Byte aktivierst Du dann TXCIE um den "USART, Tx Complete" Irq zu bekommen und dann dort denn Treiber abzuschalten. Das TXC Bit was den Irq triggert wird jedoch auch gesetzt wenn du denn Interrupt nicht aktivierst. Wenn Du jetzt also den UDRIE Aktivierst ist TXC noch vom zuvor gesendeten Byte gesetzt und der Interrupt wird sofort ausgelöst (bzw. nach dem verlassen der UDRE Irq-Routine).

Bist Du sicher das es wirklich das letze Byte ist das abgeschnitten wird? Ich vermute hier ja eher ein timing oder zähl Problem, so wie ich das Datenblatt verstehe sollte Dein Vorhaben sonst mit dem TXC-Irq Funktionieren.

Gruß

Ben

Reply to
Benjamin Muckelbach

Hi,

welchen Compiler hast Du denn? bei mir (winavr) sehen die Aufrufe der IRQ-Funktionen anders aus.

Ich denke aber du musst auf jeden Fall die beiden IRQs tauschen.

sollte aufgerufen werden wenn das Byte draussen ist und

sollte aufgerufen werden wenn UDR frei ist, also das erste BIT des vorherigen Bytes gesendet wird.

dann gibt es aber noch das Problem Du das letzte Bit ins UDR schreibst und du dann das TXC vom vorherigen Byte bekommst (das ja zeitgleich raus gesendet wird). Der Controller sendet jetzt das nächste Byte und Du schaltest ab. Vielleicht solltest Du alles im TXC Irq machen, dann verlierst du zwar etwas Zeit zwischen den einzelnen Byte aber das zählen wird einfacher. oder zähl mal Probehalber die Bytes im TXC-Irq mit.

Gruß

Reply to
Benjamin Muckelbach

Hallo Thomas,

hier nochmal meine Meinung. Erst bei Atmel die Errata zum Chip runterladen und lesen. Wenn da alles in Ordnung ist, ist das sicherste:

1) alle Tx Interrupts ausschalten (bzw. auslassen)

2) die Daten in den Puffer schreiben

3) Treiber anschalten 4) UDREI setzen 5) im UDR-empty-Interrupt die Zeichen übertragen 6) nach dem letzten Zeichen - TXC löschen (dazu mußt Du das Bit setzen!) - TXCIE setzen 7) im TX-complete interrupt: - Treiber ausschalten - TXCIE löschen

Wenn das funktioniert kannst Du ein bißchen rumexperimentieren...

Viel Spaß Jan-Hinnerk

Reply to
Jan-Hinnerk Dumjahn

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.