5 zeilen C code

Gast #2309957
Lesenswert?

Hallo Zusammen,

eine kurze Frage:
Ist es möglich den unten stehende C code einfacher zu schreiben ?
Oder so zu schreiben das er schneller vom µC abgearbeitet werden kann?

in der Schleife soll perm. der IO Pin 6.0 abgefragt werden und nach 
seinem Zustand (high / low) auf den IO Pin 1.2 gesetzt werden.

 while(UCA1IFG == 0x02) // mache solange , bis was im rx Puffer ist
  {
     if (P6IN & (1 << 0)) // ist 6.0 high
     {
        P1OUT |= 0x04; // dann setze 1.2 auf high
     }
     else
     {
        P1OUT &=~ 0x04;  // oder eben auf "low"
     }


vielen Dank

newbi
Gast #2309964
Lesenswert?

In C kannst du nicht wissen wie schnell der Code abgearbeitet wird, 
dafür bräuchstest du Assembler und wissen über die µC Type.

Vielleicht ist es schneller wenn du 3 while Schleifen hast und du somit 
nur ein if und kein else hast.

Das setzen des Bits ist soweit richtig, du kannst das so machen und 
musst nicht Toggeln.
Gast #2309971
Lesenswert?

ich will mich mit dem code (unter anderen) vorbereiten auf das nächste 
Semester.
hab mir dazu in der uni eine Evalboard von Ti ausgeliehen mit einem 
msp430f5506

@ Vlad Tepesch

ich will nicht toggeln, ich will den Zustand des pins 1.2 anhand des 
Zustands von pin 6.0 setzen

@ HenningW

kannst du das mit den 3 while schleifen skizzieren ?
#2309980
Lesenswert?

Tip:
wenn man portablen Code schreiben will, kapselt man Hardwarezugriffe.
Zb in eigene (inline) Funktionen.
Das hat den Vorteil, dass der Code auch viel verständlicher ist:
1
inline void StatusLedEin()
2
{
3
 P1OUT |= 0x04; // dann setze 1.2 auf high
4
}
5

6
inline void StatusLedAus()
7
{
8
 P1OUT &= ~0x04; // dann setze 1.2 auf high
9
}
10

11
inline bool isActive()
12
{
13
  return P6IN & (1 << 0);
14
}
15

16

17
...
18
     if (isActive())
19
     {
20
        StatusLedEin();
21
     }
22
     else
23
     {
24
        StatusLedAus()// oder eben auf "low"
25
     }
26
...
keine Angst, der Compiler optimiert das schon vernünftig
#2309982
Lesenswert?

newbi schrieb:
> Hallo Zusammen,
>
> eine kurze Frage:
> Ist es möglich den unten stehende C code einfacher zu schreiben ?
> Oder so zu schreiben das er schneller vom µC abgearbeitet werden kann?

Auf C Ebene ist das erst mal alles.
Jetzt kommt man in die Phase in der man sich die Frage stellt

* muss es schneller sein?
  wie schnell bin ich überhaupt? Welche Vorgaben habe ich, wie schnell
  ich sein muss?

* Was hat der Comiler da draus gemacht und habe ich alle meine
  Compileroptionen bereits ausgeschöpft?
  Ist zb der Optimizer eingeschaltet?

* Wie sieht der Assemblercode aus?
  Gibt es im Assemblercode noch Verbesserungspotential und wenn ja
  wie könnte ich das von C aus nutzen?

* Gehe ich die Sache vielleicht überhaupt falsch an?
  Welche anderen Möglichkeiten gibt es diese Funktionalität zu
  erreichen? Operationen aus der Schleife rausschaufeln? Interrupts
  nutzen?

* Reissen alle Stricke und muss ich vielleicht überhaupt auf
  Assembler ausweichen? Inline-Assembler?
Gast #2309985
Lesenswert?

vor while ersten zustand setzen
wenn erster zustand high
while(UCA1IFG == 0x02)
 while(UCA1IFG == 0x02 && pin aktiv){}
 if uca1fg == 2 pin low
 while(UCA1IFG == 0x02 && pin aktiv){}
 if uca1fg == 2  pin high
bei low analog dazu

Dann im Assemblercode prüfen obs mit weniger Takten abgearbeitet wird. 
Du kommst für solche Optimierungen und Zeitkritischen Sachen nicht an 
Assembler herum.
Gast #2310016
Lesenswert?

erstmal vielen Dank für die Tipps.

Ich arbeite mich seit einigen Tagen erstmal in C ein. Assembler ist mir 
seit dem zwar schon einige Male über den Weg gelaufen, aber parallel 
damit arbeiten und wirklich nutzen liegt noch in weiter ferne.

Wenn ich am Eingang (Pin 6.0 ) einen Taster anschließe und an Pin 1.2 
eine LED an und aus mache, spielt Zeit eher eine Nebenrolle

Ich versuche über einen Tongenerator (LVTTL Signal ist eingstellt) eine 
Frequenz bis 1MHZ einzuzspeisen und am Ausgang (Pin 1.2) zu messen.
Das klappt bis etwa 200 KHz
Testweise hatte ich vorher in der while Schleife den Ausgang getoggelt 
da habe  2,4 MHz gemessen.

In den code Beispielen Von TI tauchte immer wieder das hoch setzen der 
CLk bis 25 Mhz auf.
Wäre das nicht auch ein Lösung um mein Problem?
#2310028
Lesenswert?

newbi schrieb:
> In den code Beispielen Von TI tauchte immer wieder das hoch setzen der
> CLk bis 25 Mhz auf.
> Wäre das nicht auch ein Lösung um mein Problem?

Auch wenn TI das hin und wieder macht laeuft der uC ausserhalb seiner 
Specs. Sowas macht man nicht weil es nicht garantiert ist das er das 
unter allen Umstaenden (Temperatur , Spannung etc.) macht.
Die Beispiele von TI sind nicht das verbindliche Datenblatt und nur was 
dort drin steht wird auch garantiert.
Gast #2310036
Lesenswert?

ok, vielen Dank, das eval board sollte ich nicht kaputt machen, sonst 
gibts nen "duchgefallen" für die Prüfung und den Zorn des Profs.   ;-)

Ich werde alle Vorschläge jetzt durcharbeiten.
vielen Dank an alle
Gast #2310045
Lesenswert?

newbi schrieb:
> Oder so zu schreiben das er schneller vom µC abgearbeitet werden kann?

Wenn es schnell und unabhängig von Compilerumsetzung/-optimierungsstufe 
sein soll, wäre Inline-Assembler wohl die richige Wahl.
1
$asm (...)

Die Details hängen von deinem Prozessor und eingesetzten Assember ab.

Falls du die Problem, dass du ohne C nicht hättest, unbedingt in C lösen 
möchtest, solltest du einfach einen Blick in den erzeugten ASM-Code 
werfen, um zu gucken, was noch optimiert werden kann und so lange am C 
Code und der Oprimierung feilen, bis die gewünchte Assemblerzeile da 
steht.
Gast #2310082
Lesenswert?

@newbi

Dein Codebeispiel ist gut so: Kurz und übersichtlich und der Compiler 
hat die Möglichkeit, das optimal in Assambler umzusetzen. Ob er das 
wirklich tut hängt vom Compiler und den eingestellten Optionen (z.B. 
Optimierung) ab.


@HenningW
Die Version mit den While Schlaufen ist viel unübersichtlicher bzw. 
schwerer durchschaubar, sowas würde ich nicht empfehlen! Ich bin mir 
auch zimlich sicher, dass der Compiler dies weniger effizient übersetzen 
wird...
#2310131
Lesenswert?

1
void foo(void)
2
{
3
   while(UCA1IFG==0x02)
4
      {
5
         P1OUT=(P6IN&1)?0x04:(P1OUT&0xFB);
6
      }
7
}

Mag das jemand mal kompilieren? Hab gerade keinen Compiler zur Hand (vom 
nicht vorhandenen Header für den TI ganz abgesehen).

Würde selbst aber auch die Methode von Vlad anwenden.

Grüße,
Edson
#2310300
Lesenswert?

Meister Eder schrieb im Beitrag #2310292:
> Das ist nur die halbe Lösung, weil das Bit im Ausgangsregister P1OUT nie
> zurückgesetzt wird.

Verdammt du hast recht. Kleiner Denkfehler von mir.
1
while(UCA1IFG == 0x02) // mache solange , bis was im rx Puffer ist
2
    P1OUT = (P1OUT & 0xFB) | (P6IN << 2) & 0x04;
oder (wenn möglich)
1
int x = P1OUT & 0xFB;
2
while(UCA1IFG == 0x02) // mache solange , bis was im rx Puffer ist
3
    P1OUT = x | (P6IN << 2) & 0x04;
#2310489
Lesenswert?

Samuel K. schrieb:
> Meister Eder schrieb im Beitrag #2310292:
>> Das ist nur die halbe Lösung, weil das Bit im Ausgangsregister P1OUT nie
>> zurückgesetzt wird.
>
> Verdammt du hast recht. Kleiner Denkfehler von mir.

Danke fürs zitieren. Hab meinen Beitrag vorhin "aus Versehen" wieder 
gelöscht, wollte ihn eigentlich bearbeiten.

Deine Korrekturen passen, ich rate aber mal dass das Kompilat gegenüber 
der Inline-Deklaration keine Vorteile hat (genau wie mein Beispiel). 
Werds bei Zeiten mal prüfen.
Gast #2311440
Lesenswert?

einen Guten Morgen an alle

und erstmal vielen Dank für eure Hilfe.
Ich bin gestern all eure Vorschläge, Tips und Denkanstöße durchgegangen.

rausgekommen ist dabei, dass eine If Abfrage schneller ist als ein 
ausrechnen
ala:

int x = P1OUT & 0xFB;
while(UCA1IFG == 0x02) // mache solange , bis was im rx Puffer ist
    P1OUT = x | (P6IN << 2) & 0x04;

der Controller braucht zwischen -Signal am Eingang-( Pin 6.0) bis 
-Signal am Ausgang ( Pin 1.2 ) bei If abfrage ca. 1 µs, bei ausrechnen 
ca. 1,6 µs

@ Helmut Lenzen

Die kuerzeste Version der inneren "if" Abfrage:
mit IAR Compiler

//  142   if(P6IN & 1)
        BIT.B   #0x1, &0x34
        JNC     ??main_1
//  143   {
//  144     P1OUT |= 0x04;
        BIS.B   #0x4, &0x21
        JMP     ??main_2
//  145   } else
//  146   {
//  147     P1OUT &= 0x04;
??main_1:
        AND.B   #0x4, &0x21
//  148   }
??main_2:

Ich würde deinen/diesen Code gerne mal probieren, wie kann an ich ihn 
benutzen/einfügen in meinen Code?
Ich benutze die IAR Kickstart.

Trotz all meiner Bemühungen gestern, schaffe ich es nicht das 
Eingangssignal bis auf 1MHz "hoch zu drehen" und es so Fehlerfrei am 
Ausgang zu messen.
z. Zeit ist die Grenze etwa 350 KHz.

Deshalb ist meine letzte Frage: Ist dies überhaupt möglich / 
Softwareseitig möglich ?
(Wie oben schon geschreiben: es ist ein Evalboard von TI mit einem 
f5506)
Ich möchte meine Helfer hier nicht von der wirklichen Arbeit abhalten


Gruß an alle
#2311460
Lesenswert?

newbi schrieb:
> Ich würde deinen/diesen Code gerne mal probieren, wie kann an ich ihn
> benutzen/einfügen in meinen Code?
> Ich benutze die IAR Kickstart.

Das ist das was der IAR Compiler daraus macht. Wenn du deinen C-Code mit 
dem IAR Compiler uebersetzt hast sollte er das daraus gemacht haben. Du 
kann es dir im C-Compiler Listing anschauen. Du must nur unter Options 
das Assemblerlisting einschalten.
Gast #2311501
Lesenswert?

Helmut Lenzen schrieb:
> Das ist das was der IAR Compiler daraus macht. Wenn du deinen C-Code mit
> dem IAR Compiler uebersetzt hast sollte er das daraus gemacht haben. Du
> kann es dir im C-Compiler Listing anschauen. Du must nur unter Options
> das Assemblerlisting einschalten.

mein Sie Options --> links category "Assembler" und rechts tab "List"
und dort Haken bei  "output list file" ?

wo befindedet sich das Assembler list file ?
#2311769
Lesenswert?

newbi schrieb:
> ok, vielen Dank, das eval board sollte ich nicht kaputt machen, sonst
> gibts nen "duchgefallen" für die Prüfung und den Zorn des Profs.   ;-)

Kauf dir halt das Launchpad für nen 5er. Da sind 2 kleine Prozessoren 
dabei mit ähnlicher Architektur. Du kannst selber was basteln und wenn 
ein Prozessor kaputt geht, geht ja immer noch der andere. Der Zorn des 
Professors belibt dir erspart :)

Was auch bei MSP430 interessant ist, sind die Videos von Prof. 
Lovisvcach, die aus hochschulinternen Praktika zur 
Mikrocontrollerprogrammierung entstanden sind. Hier das erste: 
http://www.youtube.com/watch?v=NKgXNXY9OSk

mfg mf
Gast #2311808
Lesenswert?

Es kann (theoretisch) auch billger sein den Pin einzulesen, zu maskieren 
(verunden) zu schieben und dann wieder auszugeben (mit oder). Wenn 
Sprünge auf dem µC teuer (langsam) sind kann dies beschleunigend wirken 
(muss aber nich).
Auf dem AVR lohnt sichs z.B. nicht, da dort ein Sprung sehr schnell 
geht, wie das beim MSP40 is weis ich nicht.
#2311822
Lesenswert?

Max schrieb:
> Auf dem AVR lohnt sichs z.B. nicht, da dort ein Sprung sehr schnell
> geht, wie das beim MSP40 is weis ich nicht.

Definiere mal "sehr schnell". Es braucht mindestens 2 Zyklen, da erst 
der Programcounter auf dem Stack gesichert wird und dann der 
Programcounter mit der neuen Adresse geladen wird. Die Adressen sind 
allerdings 16bit lang. Müsste man in der Auflistung der Befehle 
nachsehen, zumal der AVR ja nur eine 8-Bit-Maschine ist(PC laden: atomic 
Operation von 2x 8 Bit laden??).
Dann macht es ja noch einen Unterschied, ob "weit" oder "kurz" 
gesprungen wird.

Beim MSP ist es, wie ich denke, anders. Der ist aber eine 
16-Bit-Maschine. Es könnte u.U. schneller gehen.

mfg mf
Gast #2311837
Lesenswert?

Hi

>Es braucht mindestens 2 Zyklen, da erst
>der Programcounter auf dem Stack gesichert wird und dann der
>Programcounter mit der neuen Adresse geladen wird.

Du beschreibst einen 'call' keinen 'jmp'.

MfG Spess
#2311862
Lesenswert?

Mini Float schrieb:
> Definiere mal "sehr schnell". Es braucht mindestens 2 Zyklen, da erst
> der Programcounter auf dem Stack gesichert wird und dann der
> Programcounter mit der neuen Adresse geladen wird. Die Adressen sind
> allerdings 16bit lang. Müsste man in der Auflistung der Befehle
> nachsehen, zumal der AVR ja nur eine 8-Bit-Maschine ist(PC laden: atomic
> Operation von 2x 8 Bit laden??).
> Dann macht es ja noch einen Unterschied, ob "weit" oder "kurz"
> gesprungen wird.

Bei AVRs braucht rjmp immer 2 Zyklen. Eigentlich braucht er nur einen, 
das Problem ist aber, dass der AVR den nächsten Befehl immer vorraus 
liest. Das funktioniert nach einem rjmp nicht und der µC braucht noch 
einen Takt um diesen zu lesen.

Übrigens kann der avr auch 2 Register gleichzeitig kopieren (movw) und 
braucht nur einen Takt, obwohl er ein 8bit µC ist.
Gast #2311868
Lesenswert?

Original Version:
1
while(UCA1IFG == 0x02) // mache solange , bis was im rx Puffer ist
2
  {
3
     if (P6IN & (1 << 0)) // ist 6.0 high
4
     {
5
        P1OUT |= 0x04; // dann setze 1.2 auf high
6
     }
7
     else
8
     {
9
        P1OUT &=~ 0x04;  // oder eben auf "low"
10
     }
11
  }


Das selbe kurz und genau so schnell:
1
while(UCA1IFG==0x02) P1OUT=(P6IN&0x01)?(P1OUT|0x04):(P1OUT&~0x04);



Gruss von mir...
Gast #2318292
Lesenswert?

Hallo Zusammen,

ich habe die letzte Zeit genutzt eure Vorschläge durch zuarbeiten und 
habe richtig dazugelernt.
Vielen Dank dafür

Leider schaffe ich es nicht ein Eingangssignal(Pin 6.0) mit 1MHz auf den 
Ausgang (Pin 1.2) zu "übergeben"
Ich habe auch schon ein TI samplescode genutz um die Frequenz auf 25 MHz 
zu erhöhen.

Ich fragte zwar schonmal, aber ist mein Vorhaben überhaupt möglich ?
Den Ausgang mit 2,5 Mhz zu toggeln auf jeden Fall Ja.


Grüße
Gast #2319681
Lesenswert?

Hallo Zusammen,

ich arbeite immernoch an den Problem von oben.
Anstatt einer IF abfrage kann ich doch perm. den Zustand vom Eingang 
setzen

so etwa:

 bool r ;
  while(1)
  {
    r = P6IN & BIT0; // 6.0 eingang
    P5OUT = r & BIT1; // 5.1 ausgang
  }

was ist daran falsch ?
#2319757
Lesenswert?

newbi schrieb:
> Ich fragte zwar schonmal, aber ist mein Vorhaben überhaupt möglich ?
> Den Ausgang mit 2,5 Mhz zu toggeln auf jeden Fall Ja.

Du musst schauen was der Comüpiler aus deinem C-Code macht. Ich kann 
jedoch nur Avrasm:
1
loop:
2
  sbic PINA, B
3
  rjmp h
4
  cbi PORTD, A
5
  sbic PINA, C
6
  rjmp loop
7
  rjmp end
8
h:
9
  sbi PORTD, A
10
  sbic PINA, C
11
  rjmp loop
12
end:

worst case 8 Takte (optimierbar auf 7 mit out), das sollte dein MSP auch 
schaffen.
Gast #2319927
Lesenswert?

Bin ich jetzt zu böld oder hab ich was verpasst?

/* P1_P2 als Ausgang konfigurieren */
DP1_P2 = 1;



<SCHLEIFE START>

/* aktuellen Zustand von P6_P0 auf P1_P2 setzen */
P1_P2 = P6_P0;

<SCHLEIFE ENDE>

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