mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Geschwindigkeit einer Schleife


Autor: Stef (Gast)
Datum:

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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

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

Autor: Labberer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Genauer gesagt muss es ein Uart statusregister geben, das ein bit 
enthaelt, das den TxReady zustand enthaelt. Das bit abfragen und warten. 
Ein Interrupt ist zwar praktischer

Autor: Stef (Gast)
Datum:

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

Autor: Stef (Gast)
Datum:

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

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Stef (Gast)

>So, der Versuch mit meiner Schleife ist gescheitert, nun werde ich den
>Uart-Status abfragen müssen.

Wohl wahr.

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

Schon mal das Datenblatt gelesen?

MFg
Falk

Autor: Falk Brunner (falk)
Datum:

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

Autor: Stef (Gast)
Datum:

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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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
   //
   // Warte in einer Schleife solange, bis UTXIFG0 zu 1 wird
   //
   while( UTXIFG0 != 1 )
     ;

Was ich jetzt nicht weiss ist, ob UTXIFG0 ein komplettes Register
oder nur ein Bit in einem Register ist.

Autor: Ampfing (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi Stef,

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

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

Autor: Falk Brunner (falk)
Datum:

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

Autor: Ampfing (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Oje, Text falsch gelesen...
Die Zeile "while(UTXIFGx == 1);" muss natürlich ein "while(UTXIFGx != 
1);" sein, sorry.

Viele Grüße

Autor: Stef (Gast)
Datum:

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

Autor: Stef (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Achso, jetzt bin ich zu langsam gewesen. Ok, ich probier gleich einmal 
die neuere Variante aus.


Danke


Stef

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

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

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

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

Autor: MockUp (Gast)
Datum:

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

Autor: Falk Brunner (falk)
Datum:

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

Autor: MockUp (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja weiß ich.
Ok werde mal schauen, wo ich eins von denen bekomme.
Danke
MockUp

Autor: Stef (Gast)
Datum:

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



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

 while (i < 20)             
            {
            do
                {                  
                  TXBUF0 = answer1[i];
                  
                }
                  while (!(IFG1 & UTXIFG0));
              
              i++;
            }
            TXBUF0 = '0';



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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stef wrote:
> So, es würde nun so weit funktionieren, nur noch , dass die einzelnen
> Zeichen meines Charakters einzeln vervielfacht werden:
>
>
 ggggeeeeeeewwwwwaaaaaaaeeeeeeeehhhllllltttttee
> eeerrrrrr    Kaannnnnnnaaaaaaall::0 
>
>
>
> So sieht mein Code jetzt aus, vielleicht erkennt jemand von euch den
> Feher:
>
>
>
 while (i < 20)
>             {
>             do
>                 {
>                   TXBUF0 = answer1[i];
> 
>                 }
>                   while (!(IFG1 & UTXIFG0));
> 
>               i++;
>             }
>             TXBUF0 = '0';
> 
> 
>
>
> 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.

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

Bewertung
0 lesenswert
nicht 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:
  while (!(IFG1 & UTXIFG0));
  TXBUF0 = c;

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


Deine Ausgabeschleife ließe sich dann so formulieren:
i = 0;
while (i < 20)
{
  putc(answer1[i++]);
}
putc('0');

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Stef (Gast)

Versuchs mal damit
for (i=0; i<20; i++) {
    while (!(IFG1 & UTXIFG0));
    TXBUF0 = answer1[i];
}

Erkennst du die Schönheit? Und vor allem dass es so funktioniert?

MFG
Falk

Autor: Stef (Gast)
Datum:

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

while (i < 20)             
            {
            
              TXBUF0 = answer1[i];
            while (!(IFG1 & UTXIFG0));
              
              i++;
            }
            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

;-)

Autor: Andreas Schwarz (andreas) (Admin) Benutzerseite Flattr this
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich wäre ja für das hier:
#define until(x) while(!(x))

for (i=0; i<20; i++) {
  until (IFG1 & UTXIFG0);
  TXBUF0 = answer1[i];
}

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stef wrote:
> Danke für die Hilfe, habe meinen Fehler aber entdeckt:
> Und zwar so müsste es nun endgültig richtig lauten:
>
>
>
> while (i < 20)
>             {
> 
>               TXBUF0 = answer1[i];
>             while (!(IFG1 & UTXIFG0));
> 
>               i++;
>             }
>             TXBUF0 = '0';
> 
>
>

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:
     while (!(IFG1 & UTXIFG0))
       ;

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

Im Verbund:

   // zuerst abfragen, ob die Schnittstelle für die
   // Uebertragung des naechsten Zeichens frei ist,
   // und solange zuwarten, bis sie es ist
   while (!(IFG1 & UTXIFG0))
     ;

   // und dann das Zeichen ausgeben
   TXBUF0 = answer1[i];

Autor: Stef (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ok, ist ein viel besserer Programmierstil.
Aber im Moment bin ich froh, dass es nun läuft.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

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

Autor: Stef (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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:
while (!(IFG1 & UTXIFG0)); 
              TXBUF0 = answer1[i];                          
              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.

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

Bewertung
0 lesenswert
nicht lesenswert
> Wenn ich aber so schreibe:
>
> while (!(IFG1 & UTXIFG0)); 
> TXBUF0 = answer1[i];                          
> 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!!


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?

Autor: Stef (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mhm, kann glaube ich auch nur das einzige sein


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


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

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

Bewertung
0 lesenswert
nicht lesenswert
Was soll das hier?
IFG1 &= ~UTXIFG0;

Wie sieht Dein Interrupthandler aus?

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

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

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

Autor: Stef (Gast)
Datum:

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

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.