Geschwindigkeit einer Schleife

Gast #635185
Lesenswert?

Hallo,
ich bin grad beim Programmieren eines MSP430, habe eine while Schleife, 
die unendlich läuft und in welcher ich immer Daten auf meine serielle 
Schnittstelle ausgebe. Nun habe ich das Problem, dass wenn ich mit dem 
Debugger händisch arbeite, die Daten perfekt an meinem PC ankommen, wenn 
ich aber auf run klicke ( ==> soll heißen Programm läuft ) dann kommen 
nurmehr fetzen von Daten an.
Nun schließe ich daraus, dass die Schnittstelle mit dem Schreiben der 
Daten nicht mehr nachkommt und deshalb möchte ich irgendwie die 
Geschwindigkeit der Schleife bremsen. Doch habe ich noch nichts wirklich 
passendes finden können.
Nun wende ich mich an euch, in der Hoffnung, dass mir hier jemand helfen 
kann.

Danke

Stef
#635214
Lesenswert?

Stef wrote:

> Nun schließe ich daraus, dass die Schnittstelle mit dem Schreiben der
> Daten nicht mehr nachkommt

Auf einem µC hat die Serielle Schnittstelle ja normalerweise
eine Form von 'Ich arbeite noch'-Status. Wenn du also vor dem
Schreibvorgang diesen Status überprüfst, und solange wartest
bis die Schnitstelle 'frei' meldet, kann dieser Fall nicht
auftreten.
Gast #635243
Lesenswert?

Danke für die Tipps, ich versuche es im Moment aber mit einer zweiten 
while Schleife, die so lange verzögern sollte, bis die Schnittstelle 
wieder "frei" ist.
Ist zwar kein schönes programmieren, aber vielleicht klappt es.
Sonst werde ich euch noch um genauere Informationen bitten müssen.
Gast #635255
Lesenswert?

So, der Versuch mit meiner Schleife ist gescheitert, nun werde ich den 
Uart-Status abfragen müssen.
Ein paar Fragen dazu:
Wie genau sieht dieses Register aus:
Ist es: a) UART0 Interrupt Enable Register
        b) UART0 Interrupt Flag Register
        c) UART0 Module Enable Register
        d) keines von den oben genannten

Ich weiß nicht, welches dieser Register den Status enthält.


Wie sieht dieses Statusbit aus??

Danke


Stef
#635265
Lesenswert?

When the transmitter is enabled (UTXEx = 1), data should not be written 
to
UxTXBUF unless it is ready for new data indicated by UTXIFGx = 1. 
Violation
can result in an erroneous transmission if data in UxTXBUF is modified 
as it
is being moved into the TX shift register.
Gast #635288
Lesenswert?

Ich hab das nun so probiert, jedoch ohne Erfolg
( ja, wahrscheinlich ist es lächerlich, wie ich es probiert habe, aber 
ich
kenne mich noch nicht aus)

 if(UTXE0=1)
     {
          UTXIFG0=0;
          else
          UTXIFG0=1;
     }

Doch muss ersten bei If ein modifable value her, zweitens muss auch 
UTXIFG0 ein modifable value sein, und bei else erwartet mein Compiler 
ein Statement.


Kann mir nicht jemand ein Beispiel geben??

Danke

Stef
#635298
Lesenswert?

Stef wrote:
> Ich hab das nun so probiert, jedoch ohne Erfolg
> ( ja, wahrscheinlich ist es lächerlich, wie ich es probiert habe, aber
> ich
> kenne mich noch nicht aus)
>
>  if(UTXE0=1)
>      {
>           UTXIFG0=0;
>           else
>           UTXIFG0=1;
>      }
>

Du sollst nicht UTXIFG setzen, sondern abfragen ob es 0 oder 1
ist! Nur dann wenn es 1 ist, darfst du einen neuen Wert zur
Schnittstelle geben.

Irgendwas in der Art
1
   //
2
   // Warte in einer Schleife solange, bis UTXIFG0 zu 1 wird
3
   //
4
   while( UTXIFG0 != 1 )
5
     ;

Was ich jetzt nicht weiss ist, ob UTXIFG0 ein komplettes Register
oder nur ein Bit in einem Register ist.
Gast #635305
Lesenswert?

Hi Stef,

ohne jetzt Deinen Controller zu kennen und ungetestet!
1
while(1)
2
{
3
  while(UTXIFGx == 1);  //warten bis Schnittstelle fertig
4
  UxTXBUF = Daten;      //Daten ist das Byte, das übertragen werden soll
5
}

Dass du vorher die UART richtig initialisieren musst ist Dir klar, oder?

Viele Grüße

P.S.: was die Zeile "if(UTXE0=1)" tut weißt Du aber schon auch, oder??
#635309
Lesenswert?

@ Stef (Gast)

>Doch muss ersten bei If ein modifable value her, zweitens muss auch
>UTXIFG0 ein modifable value sein, und bei else erwartet mein Compiler
>ein Statement.

Du solltest dir schnellstens eine gutes Buch über C besorgen.

>Kann mir nicht jemand ein Beispiel geben??

void putc(char data) {
    while(UTXIFG0 != 1);       // warte auf UART Transmitter
    U0TXBUF = data;            // Daten senden
}

MfG
Falk
Gast #635320
Lesenswert?

Danke für die zahlreiche Hilfe, aber es funktioniert immer noch nicht:

Hier ist ein Teil von meinem Code:


 while(i < 20 )   /* Schleife, um unsigned char auszugeben */
            {
              {
                while(UTXIFG0 == 1);  //warten bis Schnittstelle fertig
                TXBUF0 = answer1[i];      //Daten ist das Byte, das 
übertragen werden soll
              }
              i++;
            }




Und diese while(i<20) Schleife befindet sich in meiner Endlosschleife.


Danke für weitere Anregungen

Stef
#635327
Lesenswert?

Stef wrote:
> Danke für die zahlreiche Hilfe, aber es funktioniert immer noch nicht:
>
> Hier ist ein Teil von meinem Code:
>
>
>  while(i < 20 )   /* Schleife, um unsigned char auszugeben */
>             {
>               {
>                 while(UTXIFG0 == 1);  //warten bis Schnittstelle fertig

Denkst du eigentlich auch selber mit?

Falk hat weiter oben einen Ausschnitt aus dem Datenblatt
gepostet. Darin steht eindeutig, dass UTXIFG0 erst dann zu 1
wird, wenn die Schnittstelle fertig ist. Das heist aber auch
im Umkehrschluss, dass solange gewartet werden muss, solange
UTXIFG0 nicht 1 ist!

   while( UTXIFG0 != 1 )
     ;
Persönliche Seite #635342
Lesenswert?

UTXIFG0 kann man nicht einfach so abfragen. Das ist nur eine numerische 
Konstante, die den Wert eines Bits in einem Register beschreibt.

Es muss geprüft werden, ob dieses Bit im zugehörigen Register IFG1 
gesetzt ist.

Eine korrekte Abfrage davon sieht so aus:

    while (!(IFG1 & UTXIFG0));   // USART0 TX buffer ready?

bzw. so für die zweite UART:

    while (!(IFG2 & UTXIFG1));   // USART1 TX buffer ready?


Im Gegensatz zur hier im Forum und bei AVRs sehr verbreiteten 
Bitshift-Schreibweise ist es bei der MSP430-Programmierung üblich, daß 
eine ein Bit beschreibende Konstante wie UTXIFG0 nicht die Bitnummer, 
sondern den Bitwert enthält.

Wäre es die Bitnummer, würde die Abfrage so aussehen:

    while (!(IFG1 & (1 << UTXIFG0)));

Aber das ist bei den üblichen MSP430-Compilern und den damit gelieferten 
Headerdateien definitiv nicht so realisiert.


Auszug aus msp430x14x.h von Rowley Crossworks:

#define UTXIFG0             (0x80)

Auszug aus io430x14x.h von IAR Embedded Workbench

enum {
  ...
  UTXIFG0             = 0x0080,
  ...
};
Gast #635345
Lesenswert?

@Falk Brunner (falk)
Sag mal hast du den ein gutes Buch parat.
Habe auch grad angefangen mit c.
VHDL war meine erste sprache. geht schon ganz gut

Uart, adc ausgabe an pins bekomm ich schon hin.
habe nen Mega128 auf der Platine von Uhlrich Radig.
das Datenblatt von dem Mega hab ich ausgedruckt.
Sollte man auf alle Fälle rein schauen,
in meinem sind auch c schnipsel drinne.

Wäre also nett wenn du ein gutes buch kennst!
hab keine lust Bücher zu kaufen die schrott sind.
Danke.
#635360
Lesenswert?

@ MockUp (Gast)

>@Falk Brunner (falk)
>Sag mal hast du den ein gutes Buch parat.

Nein, aber schau dir mal die Buchempfehlungen an. Der Klassiker 
Kernigham und Ritchi sowie die diversen Ableger sind ganz OK. Ich hab 
hier "Programmieren in C" rumliegen, das reicht schon SEHR weit.

>Habe auch grad angefangen mit c.
>VHDL war meine erste sprache. geht schon ganz gut

VHDL ist aber was anderes.

Mfg
Falk
Gast #635438
Lesenswert?

So, es würde nun so weit funktionieren, nur noch , dass die einzelnen 
Zeichen meines Charakters einzeln vervielfacht werden:
1
 ggggeeeeeeewwwwwaaaaaaaeeeeeeeehhhllllltttttee
2
eeerrrrrr    Kaannnnnnnaaaaaaall::0



So sieht mein Code jetzt aus, vielleicht erkennt jemand von euch den 
Feher:

1
 while (i < 20)             
2
            {
3
            do
4
                {                  
5
                  TXBUF0 = answer1[i];
6
                  
7
                }
8
                  while (!(IFG1 & UTXIFG0));
9
              
10
              i++;
11
            }
12
            TXBUF0 = '0';


Es müsste doch schon laufen, oder habe ich wieder einen Bock 
abgeschossen?
#635444
Lesenswert?

Stef wrote:
> So, es würde nun so weit funktionieren, nur noch , dass die einzelnen
> Zeichen meines Charakters einzeln vervielfacht werden:
>
>
1
 ggggeeeeeeewwwwwaaaaaaaeeeeeeeehhhllllltttttee
2
> eeerrrrrr    Kaannnnnnnaaaaaaall::0
>
>
>
> So sieht mein Code jetzt aus, vielleicht erkennt jemand von euch den
> Feher:
>
>
>
1
 while (i < 20)
2
>             {
3
>             do
4
>                 {
5
>                   TXBUF0 = answer1[i];
6
> 
7
>                 }
8
>                   while (!(IFG1 & UTXIFG0));
9
> 
10
>               i++;
11
>             }
12
>             TXBUF0 = '0';
13
> 
14
>
>
>
> Es müsste doch schon laufen, oder habe ich wieder einen Bock
> abgeschossen?

Hast du.
Was ist eigentlich so schwer daran zu verstehen, dass man zuerst
abfragt, ob die Schnittstelle frei ist, und erst dann das Zeichen
auf den Weg bringt. Das sollte doch eigentlich klar wie
Klossbrühe sein.

Und wenn du dir endlich ein vernünftiges Einrückschema angewöhnen
würdest, dann würdest du auch sehen, dass du umgangssprachklich
ausgedrückt, folgendes programmiert hast:

  Sende ein Zeichen, solange die Schnittstelle nicht frei ist.
Persönliche Seite #635446
Lesenswert?

So schreibst Du immer und immer wieder den auszugebenden Wert in das 
TXBUF-Register ... und gibst diesen Wert dadurch auch immer wieder auf 
der seriellen Schnittstelle aus. Daß das UTXIFG-Bit überhaupt mal 
gesetzt wird, ist eher Zufall.

Du solltest ZUERST warten, bis das UTXIFG-Bit gesetzt wird und DANN erst 
das Zeichen ausgeben:
1
  while (!(IFG1 & UTXIFG0));
2
  TXBUF0 = c;

Baue Dir am besten eine putc-Routine und rufe die von den entsprechenden 
Stellen auf:
1
void putc(char c)
2
{
3
  while (!(IFG1 & UTXIFG0));
4
  TXBUF0 = c;
5
}


Deine Ausgabeschleife ließe sich dann so formulieren:
1
i = 0;
2
while (i < 20)
3
{
4
  putc(answer1[i++]);
5
}
6
putc('0');
Gast #635449
Lesenswert?

Danke für die Hilfe, habe meinen Fehler aber entdeckt:
Und zwar so müsste es nun endgültig richtig lauten:

1
while (i < 20)             
2
            {
3
            
4
              TXBUF0 = answer1[i];
5
            while (!(IFG1 & UTXIFG0));
6
              
7
              i++;
8
            }
9
            TXBUF0 = '0';



Die Reihenfolge von TXBUF0= ...
und der while-Schleife ist ausschlaggebend!!


An alle ein herzliches Dankeschön und bis zu meinem nächsten Problem

;-)
#635454
Lesenswert?

Stef wrote:
> Danke für die Hilfe, habe meinen Fehler aber entdeckt:
> Und zwar so müsste es nun endgültig richtig lauten:
>
>
>
1
> while (i < 20)
2
>             {
3
> 
4
>               TXBUF0 = answer1[i];
5
>             while (!(IFG1 & UTXIFG0));
6
> 
7
>               i++;
8
>             }
9
>             TXBUF0 = '0';
10
>
>
>

Nein. Das ist immer noch falsch. Liest du eigentlich, was
wir hier so von uns geben?

>
> Die Reihenfolge von TXBUF0= ...
> und der while-Schleife ist ausschlaggebend!!

Das ist richtig.
Aber du musst zuerst abfragen, ob die Schnittstelle bereit
ist und erst dann das Zeichen senden!

Oder benutzt du zunächst mal das Auto deines Vaters und fragst
erst danach um Erlaubnis?

Abfragen ob die Schnittstelle frei ist:
1
     while (!(IFG1 & UTXIFG0))
2
       ;

Zeichen auf den Weg bringen:
1
     TXBUF0 = answer1[i];

Im Verbund:
1
   // zuerst abfragen, ob die Schnittstelle für die
2
   // Uebertragung des naechsten Zeichens frei ist,
3
   // und solange zuwarten, bis sie es ist
4
   while (!(IFG1 & UTXIFG0))
5
     ;
6

7
   // und dann das Zeichen ausgeben
8
   TXBUF0 = answer1[i];
#635461
Lesenswert?

Stef wrote:
> Ok, ist ein viel besserer Programmierstil.

Das hat nichts mit besserem Programmierstil zu tun.
Das ist eine Frage der Logik

> Aber im Moment bin ich froh, dass es nun läuft.
Bis es dann übermorgen, nach der 120-ten Programmergänzung
plötzlich nicht mehr läuft, weil du dich nicht an die einfachste
Sache der Welt halten kannst:
  * Zuerst nachfragen, ob ein Gerät bereit ist einen
    Befehl auszuführen und gegebenenfalls darauf warten,
    dass es bereit wird.
  * Dann dem Gerät den Befehl geben
Gast #635489
Lesenswert?

Sorry, tut mir leid, aber meine Antwort hat sich auf Andreas Schwarz 
bezogen. Die Sachen mit den Programmierstil und so
Wenn ich aber so schreibe:
1
while (!(IFG1 & UTXIFG0)); 
2
              TXBUF0 = answer1[i];                          
3
              i++;

hänge ich bei meiner while Schleife endlos drinnen.
Deshalb habe ich veruschweise die while-Schleife hinter den TXBUF0 
gestellt und es hat danach funktioniert!!
Ich sehe es von der Logik schon ein, aber warum habe ich dann eine 
endlos Schleife, und andersherum nicht???
Nur aus den empirischen Resultaten habe ich die Struktur umgestellt.
Persönliche Seite #635545
Lesenswert?

> Wenn ich aber so schreibe:
>
1
> while (!(IFG1 & UTXIFG0)); 
2
> TXBUF0 = answer1[i];                          
3
> i++;
4
>
> hänge ich bei meiner while Schleife endlos drinnen.
> Deshalb habe ich veruschweise die while-Schleife hinter den TXBUF0
> gestellt und es hat danach funktioniert!!


Was soll die völlig nutzlose Einrückung des auf die while-Schleife 
folgenden Codes? Lass sowas sein, das fördert nicht die Lesbarkeit des 
Codes.

Wenn es sich tatsächlich so verhält, wie Du beschreibst, dann lässt das 
darauf schließen, daß Du möglicherweise die UART nicht korrekt 
initialisierst.

Wie genau machst Du das?
Gast #635564
Lesenswert?

Mhm, kann glaube ich auch nur das einzige sein


Hier, so hab ich das initialisiert:
1
P3SEL = 0x30;  // P3.4 und P3.5 als USART0 TXD/RXD
2
ME1 |= UTXE0 + URXE0;
3
.....
4
UCTL0 &= ~SWRST´
5
IE1 |= URXIE0 + UTXIE0;
6
IFG1 &= ~UTXIFG0;


Das wars eignetlich auch schon.
Was stimmt dann aber hier nicht?
#635611
Lesenswert?

Stef wrote:
> Mhm, kann glaube ich auch nur das einzige sein
>
>
> Hier, so hab ich das initialisiert:
>
>
1
> P3SEL = 0x30;  // P3.4 und P3.5 als USART0 TXD/RXD
2
> ME1 |= UTXE0 + URXE0;
3
> .....
4
> UCTL0 &= ~SWRST´
5
> IE1 |= URXIE0 + UTXIE0;
6
> IFG1 &= ~UTXIFG0;
7
>

Du löscht hier das UTXIFG0 Flag explizit.
Dadurch ist es natürlich nicht gesetzt, wenn du es das erste
mal abfrägst.
Gast #635621
Lesenswert?

Genau, jetzt endlich.
Das habe ich für eine andere Applikation vorher gebraucht, die jetzt 
nicht mehr benötig wird.
Jetzt kann ich es endlich ausbessern.


Nochmals danke an alle für die tatkräftige Hilfe


Stef

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