int choosetable(){ if(startup==1){ allticks=15000; } uint32_t calcticks=allticks; if (allticks >= 3191) { if(allticks>= 11905 ){ coilon=allticks- (loadtime+((calcticks*(vorzuendung+zzp1[0]))/1800)); coiloff=coilon+loadtime; startup=0; return 0; }//253-1260 if(allticks>= 7075 ){ coilon=allticks- (loadtime+((calcticks*(vorzuendung+zzp1[2]))/1800)); coiloff=coilon+loadtime; return 0; }//1261-2120 if(allticks>= 5034 ){ coilon=allticks- (loadtime+((calcticks*(vorzuendung+zzp1[3]))/1800)); coiloff=coilon+loadtime; return 0; }//2121-2980 if(allticks>= 3906 ){ coilon=allticks- (loadtime+((calcticks*(vorzuendung+zzp1[4]))/1800)); coiloff=coilon+loadtime; return 0; }//2981-3840 if(allticks>= 3191 ){ coilon=allticks- (loadtime+((calcticks*(vorzuendung+zzp1[5]))/1800)); coiloff=coilon+loadtime; return 0; }//3841-4700 }else{ if(allticks>= 2698 ){ coilon=allticks- (loadtime+((calcticks*(vorzuendung+zzp1[6]))/1800)); coiloff=coilon+loadtime; return 0; }//4701-5560 if(allticks>= 2336 ){ coilon=allticks- (loadtime+((calcticks*(vorzuendung+zzp1[7]))/1800)); coiloff=coilon+loadtime; return 0; }//5561-6420 if(allticks>= 2060 ){ coilon=allticks- (loadtime+((calcticks*(vorzuendung+zzp1[8]))/1800)); coiloff=coilon+loadtime; return 0; }//6421-7280 if(allticks>= 1843 ){ coilon=allticks- (loadtime+((calcticks*(vorzuendung+zzp1[9]))/1800)); coiloff=coilon+loadtime; return 0; }//7281-8140 if(allticks>= 1667 ){ coilon=allticks- (loadtime+((calcticks*(vorzuendung+zzp1[10]))/1800)); coiloff=coilon+loadtime; return 0; }//8141-9000 } return 0; } Oben angefügt habe ich einen Codeabschnitt meines Programms mit dem ich leider so meine Probleme habe. Die If Schleifen brauchen im Worst-case 25µs bei 20 Mhz und die Rechnung für den Wert coilon leider 70 µs. Das Problem bei des Sache ist nur, dass es sich hier um eine zeitkritische Anwendung handelt bei der Werte für einen gesamten Durchlauf von 20-50 µs äußerst praktisch wären. Gibt es Möglichkeiten den Code zu optimieren um Zeit zu sparen ? Wenn ich oben calcticks als 16 bit Variable passiert spart es Zeit aber das Ergebniss wird zu ungenau. Dasselbe passiert wenn ich statt zu dividieren schieben um 11 benutze. Gibt es andere Möglichkeiten der optimierung ? Vor allem die IFs stören mich. Bitte helft mir ich hab schon masseenhaft Foren ergebnisslos durchsucht. mfg Manax
Hallo, http://if-schleife.de/ auch wenn ich mir Dein Problem noch nicht genauer anegschaut habe... Gruß aus Berlin Michael
Bitte poste den Code noch einmal als Anhang, dann stimmt sowohl die Einrueckung als auch das Code-Highlighting und man kann ihn viel besser lesen.
@Michael: lol... ist mir gar nicht aufgefallen. Jeder weis doch was er meint. Also jetzt sei nicht so kleinlich ;-). Ansonsten: Vielleicht ist eine "case-Schleife" schneller.
Schmeiss die Division mit dem konstanten Faktor 1800 raus. Warum schleppst Du das mit Dir rum? Läßt sich "vorzuendung+zzp1[x]" eventuell im Voraus berechnen?
Man kann es erstmal übersichtlicher schreiben:
1 | void choosetable( void ) |
2 | {
|
3 | uint8_t idx; |
4 | |
5 | if( startup==1 ) |
6 | allticks=15000; |
7 | |
8 | switch( allticks ){ |
9 | case 11905 ... 65535: idx = 0; startup = 1; break; |
10 | case 7057 ... 11904: idx = 2; break; |
11 | case 5034 ... 7056: idx = 3; break; |
12 | case 3906 ... 5033: idx = 4; break; |
13 | case 3191 ... 3905: idx = 5; break; |
14 | case 2698 ... 3190: idx = 6; break; |
15 | case 2336 ... 2697: idx = 7; break; |
16 | case 2060 ... 2335: idx = 8; break; |
17 | case 1843 ... 2059: idx = 9; break; |
18 | case 1667 ... 1842: idx = 10; break; |
19 | default: return; |
20 | }
|
21 | coilon = allticks - loadtime |
22 | - ((uint32_t)allticks*(vorzuendung+zzp1[idx]))/1800; |
23 | coiloff = coilon+loadtime; |
24 | }
|
Wenn Du mal in Worten beschreiben würdest, wozu das gut ist, könnte man wohl auch noch optimieren. Peter
> case 11905 ... 65535: idx = 0; startup = 1; break;
Man sollte sich aber bewußt darüber sein, daß das kein Standard-C,
sondern eine Erweiterung des gcc ist.
Das war mir schon klar, sonst hätte ich anders geantwortet. Ich find's nur trotzdem gut, solche Abhängigkeiten zu erwähnen.
Rolf Magnus schrieb: >> case 11905 ... 65535: idx = 0; startup = 1; break; > > Man sollte sich aber bewußt darüber sein, daß das kein Standard-C, > sondern eine Erweiterung des gcc ist. als Pseudocode betrachten, ist lesbarer. MfG
Manax schrieb: > Wenn ich oben calcticks als 16 bit Variable passiert spart es Zeit aber > das Ergebniss wird zu ungenau. Dasselbe passiert wenn ich statt zu > dividieren schieben um 11 benutze. Warum ist das zu ungenau ? Was sind das überhaupt für nen Haufen Werte? Sind das Konstanten, kannst Du doch beim Compilieren den Korrekturfaktor 2048/1800 einfach mit reinrechnen lassen. Die Division ist jedenfalls das mit Abstand teuerste. Und wenns ein ATmega ist, ist die Multipikation auch nicht so schlimm. Wenn "allticks" bei jedem Aufruf konstant hoch- oder runterzählt, dann kann man die Rechnung auf eine einzige Addition verkürzen. Die Tabelle enthält dann nicht mehr Faktoren, sondern die Schrittweite. Das ist dann am schnellsten. > Vor allem die IFs stören mich. Die stören vielleicht optisch, von der Rechenzeit her sind es Pinats. Was mich daran stört, ist das 10-fach Copy&Paste-Monster. Es wird doch fast immer das gleiche gemacht, als ab damit ans Ende und nicht 10-mal kopieren. Peter
Vielen dank für eure schnelle Hilfe. Der Hinweis mit dem case hat mich gerettet wusste gar nicht,dass das so funktioniert. (Spart mir schonmal 7µs ) macht die Sache übersichtlicher und vor allem erweiterbar. Assembler kann ich leider nicht programmieren. Ich würde die Division gerne rausziehen allerdings ist vorzuendung+zzp[idx] ein so kleiner Wert, dass die Rechnung viel zu ungenau wird.Allticks ist eine Variable. Zur grundsätzlichen Funktion des Programms: Dieser Programmteil soll die Zündverzögerung einer Zündung mit Verstellkurve errechnen. Der Wert in µs ist gesucht mit einem globalen Wert (in 0.2 Grad Schritten )und einem speziellen auf die Drehzahl abgestimmten Wert (in 0.2 Grad Schritten). mfg Manax
p.s. Ich bin fast verzweifelt bis ich den Fehler in der case gefunden habe. Ein arraywert wird übersprungen zzp[1]. mfg
Peter Dannegger schrieb: > Man kann es erstmal übersichtlicher schreiben: > void choosetable( void ) > { > uint8_t idx; > if( startup==1 ) > allticks=15000;> > switch( allticks ){ > case 11905 ... 65535: idx = 0; startup = 1; break; > case 7057 ... 11904: idx = 2; break; > case 5034 ... 7056: idx = 3; break; > case 3906 ... 5033: idx = 4; break; > case 3191 ... 3905: idx = 5; break; > case 2698 ... 3190: idx = 6; break; > case 2336 ... 2697: idx = 7; break; > case 2060 ... 2335: idx = 8; break; > case 1843 ... 2059: idx = 9; break; > case 1667 ... 1842: idx = 10; break; > default: return; > } Könnte mir jemand diese GCC Erweiterung erklären, da ich nur Standard c(++) behersche. Prüft der Switch ob sich Werte dazwischen befinden? z.B. zwischen 1667 ... 1842 und wenn ja, wird idx zu 10 gesetzt?
> Könnte mir jemand diese GCC Erweiterung erklären, da ich nur Standard > c(++) behersche. Das GCC-Handbuch kann das. > Prüft der Switch ob sich Werte dazwischen befinden? Nicht dazwischen, aber ob sie sich in dem angegebenen Bereich befinden, also inklusive den angegebenen Grenzwerten. > z.B. zwischen 1667 ... 1842 und wenn ja, wird idx zu 10 gesetzt? Ja.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.