Seriell Data übertragung crash bei dem letzten Byte

OP #1902445
Lesenswert?

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
OP #1902452
Lesenswert?

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++;
}
Gast #1902500
Lesenswert?

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.
#1902657
Lesenswert?

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 !
OP #1902680
Lesenswert?

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...
OP #1902700
Lesenswert?

> 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
Gast #1902753
Lesenswert?

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.
OP #1902781
Lesenswert?

> 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.
OP #1902788
Lesenswert?

> 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.
Gast #1902855
Lesenswert?

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
OP #1902998
Lesenswert?

> 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
Persönliche Seite #1903052
Lesenswert?

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.
OP #1903093
Lesenswert?

> 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;
Gast #1903097
Lesenswert?

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
OP #1903102
Lesenswert?

>  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
#1903239
Lesenswert?

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.
OP #1903264
Lesenswert?

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...

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren