www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Seriell Data übertragung crash bei dem letzten Byte


Autor: Wahib F. (wahib_f)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Wahib F. (wahib_f)
Datum:

Bewertung
0 lesenswert
nicht 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++;
}

Autor: tom (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Wahib F. (wahib_f)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Zwölf Mal Acht (hacky)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Wahib F. (wahib_f)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ok,
@ hacky,

das verwenden ich doch , siehe obere Quellcode mit dem befehl:
( while (!(IFG2 & UCA0TXIFG));
wie stellen Sie sich es vor?

MFG

Autor: Zwölf Mal Acht (hacky)
Datum:

Bewertung
0 lesenswert
nicht 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 !

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Wahib F. (wahib_f)
Datum:

Bewertung
0 lesenswert
nicht 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...

Autor: Zwölf Mal Acht (hacky)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dann wird man einen Timer dafuer bemuehen muessen. Aus welchem Grund 
auch immer es etwas auszuschalten gibt.

Autor: Zwölf Mal Acht (hacky)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das naechste Byte kommt eh erst wenn das jetzige draussen ist. In einem 
Interrupt wird NIE gewartet, auf GAR NICHTS.

Autor: Wahib F. (wahib_f)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Zwölf Mal Acht (hacky)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> 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.

Autor: Wahib F. (wahib_f)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ok, ich bin damit einverstanden,
aber in beiden fällen hat die while schleife damit nichts zu tun.

Autor: Maxx (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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?

Autor: Wahib F. (wahib_f)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Wahib F. (wahib_f)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Wahib F. (wahib_f)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> 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?

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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?

Autor: Zwölf Mal Acht (hacky)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Wahib F. (wahib_f)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Du hast meine Frage nicht verstanden. Der TX-Interrupt wird wann und
> von wem ausgelöst?

der interrupt wird empfangsabgeschlossen der RX-interrupt aktiviert

Autor: Wahib F. (wahib_f)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Wahib F. (wahib_f)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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)

Autor: Maxx (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Er meint, welche Hardware löst ihn in welcher Situation aus.

ein TX-irq wird kaum bei einer RX Statusänderung ausgelöst

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Wahib F. (wahib_f)
Datum:

Bewertung
0 lesenswert
nicht 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;

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Wahib F. (wahib_f)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Zwölf Mal Acht (hacky)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Wahib F. (wahib_f)
Datum:

Bewertung
0 lesenswert
nicht 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...

Autor: Wahib F. (wahib_f)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Wahib F. (wahib_f)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.