Hallo Kollegen, entschuldigt bitte die komplette Newbie-Frage. ich versuche die ganze Zeit eine Bytefolge mittel interrupt zu senden gleich nach dem letzten Byte möchte ich die TX_Interrupt ausschalten und auf RX_interrupt gehen. Leider empfange ich beim dem letzte Byte nur Schrott. ich habe mittel Osci festgestellt das ich nach dem letzten sendeByte eine kleine warte Zeit brauche, es gibt aber beim MSP430 die IDLE Frame transmitting, irgendwie schaffe ich es nicht diese Funktion zumlaufen zu bringen... ich möchte auch nicht eine Warte funktion mit dem TA generieren, es geht um LPM, und energie sparen... für weitere vorschlage vorschlage wäre ich Ihnen dankbar? MFG W
meine Routine sieht so aus: //USCI_A0 interrupt service routine : IrDa #pragma vector=USCIAB0TX_VECTOR __interrupt void USCIA0TX_ISR (void) { if(TX_Zaehler > RXData[1]+7) { if(TX_Zaehler > RXData[1]+8) { setBOF = false; IRDA_CTR_HIGH; // IrDA-High Pegel wait2s = true; TACCR0 = returnTAR()+32768; //sollte auf 2 seconden eingestelt // P1OUT |= BIT0; // P1OUT &= ~BIT0; //Wait(5); UCA0CTL1 &= ~UCTXADDR; IE2 &= ~UCA0TXIE; CACTL1 |= CAON; // Comparator_A einschalten UCA0CTL1 |= UCSWRST; UCA0CTL1 &= ~UCSWRST; // ~Set SW Reset IE2 |= UCA0RXIE; // Enable RX_IrDa (USCI) Interrupt TACCTL0 |= CCIE; } else { UCA0CTL1 |= UCTXADDR; UCA0TXBUF = 0x00; while (!(IFG2 & UCA0TXIFG)); // P1OUT |= BIT0; // P1OUT &= ~BIT0; } } else { //while (!(IFG2 & UCA0TXIFG)); UCA0TXBUF = RXData[TX_Zaehler]; // Send Charakter via IRDA-Interface while (!(IFG2 & UCA0TXIFG)); // USCI_A0 TX buffer ready? // P1OUT |= BIT0; // P1OUT &= ~BIT0; } TX_Zaehler++; }
hmmm, ich würde tippen, das du den uart ausschaltest, bevor die bits seriell rausgetaktet sind, daher das zerstörte letzte zeichen. nach dem schreiben in das tx-register wird dessen inhalt in das senderegister übertragen und von dort seriell rausgeschoben. das dauert je nach einstellung also nochmal 10-12 bitzeiten, in denen der uart nicht ausgeschaltet werden darf. kenne deinen uC nicht so gut aber deshalb haben die meisten uC's einen TX-complete UND einen TX-register empty interrupt. gruss, tom.
Hi Tom, genau das ist mein Problem, bei Ausschalten des Tx-interrupt ist die UART noch nicht fertig mit dem senden... Wait funktion dürfen nicht verwendet werden, naja... trotzdem danke für die schnelle Antwort. MFG
Ja. Der TxEmpty Interrupt kommt wenn der Buffer leer, das byte aber noch im Schieberegister ist. Daher muss man fuer das letzte Byte den TxComplete Interrupt verwenden. - So er denn existiert. Und auch dann wird das unter Umstaenden das Stopbyte abgeschnitten.
ok, @ hacky, das verwenden ich doch , siehe obere Quellcode mit dem befehl: ( while (!(IFG2 & UCA0TXIFG)); wie stellen Sie sich es vor? MFG
Ich seh genau einen Interrupt, den USCIA0TX_ISR , was auch immer der genau macht. Aber wo ist der TxComplete Interrupt ? .. while (!(IFG2 & UCA0TXIFG)); Was soll das in einem Interrupt ? Alles blockieren ? Es gibt keine while-loops in einem Interrupt ! Es gibt keine while-loops in einem Interrupt ! Es gibt keine while-loops in einem Interrupt ! Es gibt keine while-loops in einem Interrupt ! Es gibt keine while-loops in einem Interrupt !
Hi
>Aber wo ist der TxComplete Interrupt ?
Da ich den MSP auch nicht kenne habe ich mal ins Datenblatt nechgesehen.
Die scheinen keinen Complete-Interrupt zu haben.
MfG Spess
Hallo, die while (!(IFG2 & UCA0TXIFG)); verhindert Bytes collession, also das nächste byte darf erst gesendet nur wenn das verherige fertig ist. im interrupt Table vom uC msp430 siehe ich hier keine TxComplete interrupt vector. #define RESERVED0_VECTOR (0 * 2u) /* 0xFFC0 Reserved Int. Vector 0 */ #define RESERVED1_VECTOR (1 * 2u) /* 0xFFC2 Reserved Int. Vector 1 */ #define RESERVED2_VECTOR (2 * 2u) /* 0xFFC4 Reserved Int. Vector 2 */ #define RESERVED3_VECTOR (3 * 2u) /* 0xFFC6 Reserved Int. Vector 3 */ #define RESERVED4_VECTOR (4 * 2u) /* 0xFFC8 Reserved Int. Vector 4 */ #define RESERVED5_VECTOR (5 * 2u) /* 0xFFCA Reserved Int. Vector 5 */ #define RESERVED6_VECTOR (6 * 2u) /* 0xFFCC Reserved Int. Vector 6 */ #define RESERVED7_VECTOR (7 * 2u) /* 0xFFCE Reserved Int. Vector 7 */ #define RESERVED8_VECTOR (8 * 2u) /* 0xFFD0 Reserved Int. Vector 8 */ #define RESERVED9_VECTOR (9 * 2u) /* 0xFFD2 Reserved Int. Vector 9 */ #define RESERVED10_VECTOR (10 * 2u) /* 0xFFD4 Reserved Int. Vector 10 */ #define RESERVED11_VECTOR (11 * 2u) /* 0xFFD6 Reserved Int. Vector 11 */ #define RESERVED12_VECTOR (12 * 2u) /* 0xFFD8 Reserved Int. Vector 12 */ #define RESERVED13_VECTOR (13 * 2u) /* 0xFFDA Reserved Int. Vector 13 */ #define RESERVED14_VECTOR (14 * 2u) /* 0xFFDC Reserved Int. Vector 14 */ #define RESERVED15_VECTOR (15 * 2u) /* 0xFFDE Reserved Int. Vector 15 */ #define USCIAB1TX_VECTOR (16 * 2u) /* 0xFFE0 USCI A1/B1 Transmit */ #define USCIAB1RX_VECTOR (17 * 2u) /* 0xFFE2 USCI A1/B1 Receive */ #define PORT1_VECTOR (18 * 2u) /* 0xFFE4 Port 1 */ #define PORT2_VECTOR (19 * 2u) /* 0xFFE6 Port 2 */ #define RESERVED20_VECTOR (20 * 2u) /* 0xFFE8 Reserved Int. Vector 20 */ #define ADC12_VECTOR (21 * 2u) /* 0xFFEA ADC */ #define USCIAB0TX_VECTOR (22 * 2u) /* 0xFFEC USCI A0/B0 Transmit */ #define USCIAB0RX_VECTOR (23 * 2u) /* 0xFFEE USCI A0/B0 Receive */ #define TIMERA1_VECTOR (24 * 2u) /* 0xFFF0 Timer A CC1-2, TA */ #define TIMERA0_VECTOR (25 * 2u) /* 0xFFF2 Timer A CC0 */ #define WDT_VECTOR (26 * 2u) /* 0xFFF4 Watchdog Timer */ #define COMPARATORA_VECTOR (27 * 2u) /* 0xFFF6 Comparator A */ #define TIMERB1_VECTOR (28 * 2u) /* 0xFFF8 Timer B CC1-6, TB */ #define TIMERB0_VECTOR (29 * 2u) /* 0xFFFA Timer B CC0 */ #define NMI_VECTOR (30 * 2u) /* 0xFFFC Non-maskable */ #define RESET_VECTOR (31 * 2u) /* 0xFFFE Reset [Highest Priority] */ bitte beachten ich bin anfänger, vielleicht habe ich etwas übersehen oder nicht richtig verstanden...
Dann wird man einen Timer dafuer bemuehen muessen. Aus welchem Grund auch immer es etwas auszuschalten gibt.
Das naechste Byte kommt eh erst wenn das jetzige draussen ist. In einem Interrupt wird NIE gewartet, auf GAR NICHTS.
> Interrupt wird NIE gewartet, auf GAR NICHTS. genau dass darf ich nicht machen, kein Timer keine nop(), keine Waits, es soll energie sparend wie möglich sein!!!, ich habe aber nach geschaut, der msp430 unterstützt die Built-in idle-line and address-bit communication protocols for multiprocessor systems, man kann diese protocol verwenden um eine dummy byte zwischen Data zusenden, leider hat es bei mir nicht geklappt. > Dann wird man einen Timer dafuer bemuehen muessen. Aus welchem Grund > auch immer es etwas auszuschalten gibt. das warten schaffe ich in dem ich die while (!(IFG2 & UCA0TXIFG)); verwende, es geht um Tx_Interrupt Danke für die mühe und die schnelle Antwort. LG Wahib
> while (!(IFG2 & UCA0TXIFG));
ist aber warten. Dabei wird's nicht benoetigt. Zwischen zwei Bytes
braucht man sowieso nicht zu warten. Man saugt mit dem TxEmpty das
naechste Byte an und gut ist.
ok, ich bin damit einverstanden, aber in beiden fällen hat die while schleife damit nichts zu tun.
Wahib F. schrieb: > genau dass darf ich nicht machen, kein Timer keine nop(), keine Waits, > es soll energie sparend wie möglich sein!!!, Das ist aber nicht gleichbedeutend mit der Aussage, dass du nicht warten darfst. Timer anschmeissen, bis Interrupt pennen, gut is. Busy-Waiting ist das was du verhindern sollst. Und ja, jede WhiöeeSchleife ohne Body gehört da auf jeden Fall zu. In Interrupts erstmal grundsätzlich zu vermeiden um den normalen Programmablauf/andere Interrupts nicht zu beeinträchtigen.
Ein paar Fragen, die Du Dir stellen und beantworten solltest: Wann wird ein Tx-Interrupt ausgelöst? Und warum kann es im Tx-Interrupthandler NIE dazu kommen, daß ein im vorherigen Aufruf des Interrupthandlers gesendetes Datenbyte noch nicht fertig übertragen wurde? Eben. Was soll das Abschalten des TX-Interrupts nach Ende der Datenübertragung?
> Das ist aber nicht gleichbedeutend mit der Aussage, dass du nicht warten > darfst. Timer anschmeissen, bis Interrupt pennen, gut is. das stimmt, ich darf aber den Timer nicht verwenden weil ich keine zur verfuegung habe, also es gibt schon Ta und Tb im uC die sind aber als verbrauchte ressourcen. also mir stehen nicht zu, was ich natuerlich schade finde.
> Wann wird ein Tx-Interrupt ausgelöst? der TX-Interrupt soll gleich anfangen nach dem er Daten walidiert hat,und sie bereit zum senden sind. > Und warum kann es im Tx-Interrupthandler NIE dazu kommen, daß ein im > vorherigen Aufruf des Interrupthandlers gesendetes Datenbyte noch nicht > fertig übertragen wurde? einfach weil ich nachdem letzten sende byte sofort ausschalten muss, denn mein uC danach empfangsbereit stehen soll.
Hi >einfach weil ich nachdem letzten sende byte sofort ausschalten muss, >denn mein uC danach empfangsbereit stehen soll. Was hat denn das mitdem Empfangen zu tun? Das läuft doch getrennt und kann auch gleichzeitig erfolgen. MfG Spess
> Was hat denn das mitdem Empfangen zu tun? Das läuft doch getrennt und > kann auch gleichzeitig erfolgen. das wird auch so gebaut getrennt von einander... sowieso funktionert auch nur so. hat sich jemanden mit der idle Frame beschäftigt?
Wahib F. schrieb: >> Wann wird ein Tx-Interrupt ausgelöst? > der TX-Interrupt soll gleich anfangen nach dem er Daten walidiert > hat,und sie bereit zum senden sind. Du hast meine Frage nicht verstanden. Der TX-Interrupt wird wann und von wem ausgelöst?
Ja. Wie sendet man das erste Byte, und wie die Fogenden ? Man kann einen Timer Interrupt so ganz nebenbei mehrfach belegen. Eine Statusmaschine kann das.
> Du hast meine Frage nicht verstanden. Der TX-Interrupt wird wann und > von wem ausgelöst? der interrupt wird empfangsabgeschlossen der RX-interrupt aktiviert
> der interrupt wird empfangsabgeschlossen der RX-interrupt aktiviert ich habe einen Buffer der mit bytes ausgefühlt ist, die senden ich bis ich mein mein buffer.getlaenge erreicht habe, dann tx-Int ausschalten und Rx-int einschalten.... dabei kommt immer das letzte Byte nicht richtig an... ic habe weitere tests gemacht und stelle fest sobald ich den RX-interrupt aktiviere taucht dieses phenomen auf. >>IE2 |= UCA0RXIE; MFG
Wahib F. schrieb: >> Du hast meine Frage nicht verstanden. Der TX-Interrupt wird wann und >> von wem ausgelöst? > > der interrupt wird empfangsabgeschlossen der RX-interrupt aktiviert Du hast meine Frage immer noch nicht verstanden. Und solange Du nicht verstehst, was den TX-Interrupt auslöst, wirst Du auch die anderen Probleme nicht in den Griff bekommen.
Ihre Frage ist auch nicht wirklich klar, Sie fragen: Der TX-Interrupt wird wann und von wem ausgelöst? frage: wann --> Antwort: wenn das Receivebuffer in RX-ISR Complete ist. frage: von wem --> Antwort: von mir ;-).(spass bei seite also von dem RX-ISR)
Er meint, welche Hardware löst ihn in welcher Situation aus. ein TX-irq wird kaum bei einer RX Statusänderung ausgelöst
Wahib F. schrieb: > Ihre Frage ist auch nicht wirklich klar, Sie fragen: Der TX-Interrupt > wird wann und von wem ausgelöst? > > frage: wann --> Antwort: wenn das Receivebuffer in RX-ISR Complete ist. Eben das ist falsch. Der TX-Interrupt wird ausgelöst, wenn die UART-Hardware ein Byte versendet hat. Mit dem RX-Interrupt hat das gar nichts zu tun.
> Der TX-Interrupt wird ausgelöst, wenn die UART-Hardware ein Byte > versendet hat. > > Mit dem RX-Interrupt hat das gar nichts zu tun. nein nein, meine Rx-interrupt intialisiert alles vor und qualifiziert die zusendenden Bytes, das senden selber macht die TX-ISR()... ausserdem alles funktioniert bis auf das letzte byte der kommt nicht richt an und das wegen diese Quellcode abschnitt: UCA0CTL1 |= UCSWRST; UCA0CTL1 &= ~UCSWRST; //~Set SW Reset IE2 |= UCA0RXIE;
Hi >Der TX-Interrupt wird ausgelöst, wenn die UART-Hardware ein Byte >versendet hat. Der TX-Interrupt wird, wenn ich das Datenblatt nicht zu schnell überflogen habe, ausgelöst, wenn der interne TX-Puffer frei ist. Also wie UDRE beim AVR. Dem MSP scheint aber ein TX-Complete-Interrupt zu fehlen. MfG Spess
> Der TX-Interrupt wird, wenn ich das Datenblatt nicht zu schnell > überflogen habe, ausgelöst, wenn der interne TX-Puffer frei ist. der Interrupt wird ausgelöst wenn das TX-Puffer frei ist und nicht wenn die bits TX-Shift complete verlassen haben. > Dem MSP scheint aber ein TX-Complete-Interrupt zu fehlen. genau die ISR vermisse ich (TX-Complete-Interrupt). MFG Wahib
Eine so enge Kopplung zwischen senden und empfangen ist nicht wuenschenswert. Normalerweise empfaengt man, und wenn die ISR die Meldung komplet hat setzt sie ein Flag fuer das main(). Das main verarbeitet die Meldung und started das Senden. Gewartet wird nirgendwo ausser im main. Dort kann man zB auch in den sleep gehen oder was anderes mit der Zeit machen. Im TxEmpty Interrupt laedt man das naechste zu versendende Byte oder keins. Dann ist die Meldung beendet.
A...aha Soooo. schrieb: > Eine so enge Kopplung zwischen senden und empfangen ist nicht > wuenschenswert. Normalerweise empfaengt man, und wenn die ISR die > Meldung komplet hat setzt sie ein Flag fuer das main(). Das main > verarbeitet die Meldung und started das Senden. Gewartet wird nirgendwo > ausser im main. Dort kann man zB auch in den sleep gehen oder was > anderes mit der Zeit machen. Im TxEmpty Interrupt laedt man das naechste > zu versendende Byte oder keins. Dann ist die Meldung beendet. dafür hat TI eine Funktion gedacht, die sogenante IDLE-Line Multiprocessor Format. damit kann quasi don't care bits (11) generieren und so hat man ein Byte leerlauf zeit, damit könnte man diese enge Kopplung vermeiden bzw. umgehen, das war zu theorie. bei dem MSP430F4xxx und viele andere gibt es für die Funktion ein TXWAKE bit, damit kann man die don't care bits generieren, bei dem MSP430F2471 was ich jetzt verwenden gibt es diesen Registerbit nicht, dafür ein andere, der UCTXADDR heisst und es funktioniert nicht wie es beschrieben wurde... naja...
Moin moin, fählt niemenanden etwas ein? oder hat schon mal jemanden ein ähnliches Problem bekommen? hat vielleicht jemanden die IDLE-Line fomat in Betrieb genommen, die mit der UCTXADDR und nicht mit dem TxWAKE Register. MFG Wahib
Hallo, ich habe auch keine Alternative gefunden ausser mein uC ins LMP3 für 1ms zu senden. naja ich finde es unnötig aber .... Danke für die Zahlreiche Antworten und die Hilfe
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.