2 x 3 macht 4 Widdewiddewitt und Drei macht Neune
Ja, ist richtig, hab' Deinen Code nochmal angesehen. Dann ist's nur das Sichern und der ISR-Einsprung was Du in der Messung nicht mitbekommst. Von der Auslösung bis der Port auf Low geht sind's ~38 Takte, von da bis zum erneuten Setzen auf High sinds >= 642 Takte, also eine Verteilung Gesamt 76,5% auf 4,3% und 72,2%, genau 70% kommt da immer noch nicht raus.Aber die Wiederherstellung geschieht doch noch wenn D0 low ist.
Inzwischen gibt´s eine print() für Strings und eine printInt() für Ganzzahlen in dezimalform.
Gibt es da wieder Tricks die ich noch nicht kenne um die printInt() zu beschleunigen?
Eine Fehlertoleranz ist nicht vorgesehen, schade um die Rechenleistung.
Das große Problem wird die Division und der Modulo-Operator sein, denke ich. Auf jeden Fall wird ein riesieger ASM-Code erstellt.
Code:void printInt(unsigned char xPos, unsigned char yPos, unsigned char length, int num)//32767 -> +32767 { unsigned char temp; unsigned int i=0; xPos+=length-1; if(num<0) { num--; //Zweierkompliment num=~num; do { num-=(temp=num%10); //letzte Stelle extrahieren num/=10; //num>>1 dezimal text[yPos][xPos-i++]=temp+0x30; //um auf passenden char zu kommen if(i==length-1)break; //damit Platz fürs Minus ist }while(num); text[yPos][xPos-i++]=0x2D; //Minuszeichen an erste stelle }else { do { num-=(temp=num%10); num/=10; text[yPos][xPos-i++]=temp+0x30; if(i==length)break; }while(num); } while(i<length) text[yPos][xPos-i++]=0x20; //Rest mit Leerzeichen auffüllen }
Der "Trick" nennt sich "effektiverer Code"
Warum glaubst Du besser als itoa() zu sein ? Noch dazu Du umständlich programmierst. Hast ja bemerkt dass Divisionen "teuer" sind, für Multiplikationen gibt's in manchen AVR's Unterstützung durch den MUL Opcode, Divisionen müssen immer per Code gemacht werden.
Hier führst Du gleich 2 Divisionen durch, wovon Du eine hättest sparen können.
Ein Modulo 10 enthält die gleiche Division wie num/=10, die Multiplikation und Differenzbildung als Modulo zu Fuß wär' wahrscheinlich billiger gewesen.Code:num-=num%10; num/=10;
Dein Code benötigt so ganze 2570 Takte mit printInt(0,0,6,29999).
Braucht noch 1370.Code:void printInt(unsigned char xPos, unsigned char yPos, unsigned char length, int num){ char buff[7]; unsigned char slen; unsigned char spccnt = 0; itoa(num, buff, 10); slen = strlen(buff); if (slen < length) { spccnt = length - slen; memset((void*)&text[yPos][xPos], ' ', spccnt); xPos += spccnt; length -= spccnt; } memcpy((void*)&text[yPos][xPos], (void*)&buff, length); } printInt(0,0,6,29999);
Der noch 540.Code:const int idiv[6] PROGMEM = {0, 1, 10, 100, 1000, 10000}; void printInt(unsigned char xPos, unsigned char yPos, unsigned char length, int num){ unsigned int idx = 5; char lz = 1; char prlz; char chval; char isminus = 0; unsigned char *txtptr = &text[yPos][xPos]; if (num < 0) { num = 0 - num; length--; isminus = 1; } else *txtptr++ = ' '; while ((idx) && (length--)) { chval = '0'; prlz = lz; while (num >= pgm_read_word(&(idiv[idx]))) { num -= pgm_read_word(&(idiv[idx])); chval++; lz = 0; } if ((prlz != lz) && (isminus)) { prlz = lz; *txtptr++ = '-'; } idx--; if ((lz) && (idx)) chval = ' '; *txtptr++ = chval; } } printInt(0,0,6,29999);
Das einzig Lästige dabei ist, durch das Alignement des Fonts kommt const int idiv[6] PROGMEM auf $D00 zu liegen, der Compiler aligned für den darauffolgenden Code nochmals und verhaut damit knapp 240 Bytes Flash, aus der .map-Datei:
Code:0x00000d00 idiv 0x00000e00 . = ALIGN (0x2)
Weil ich itoa() zu bis eben noch nicht kannte
Kam mir zu speziell vor,als das es dafür eine Funktion gibt.
Danke, dass Du so geduldig mit mir bist
Ich kämpfe zur Zeit mit inhomogenen Differenzialgleichungen 2. Grades, sobald das verstanden wurde, werde ich mich an Deinen Code setzen.
Nochmal danke für die Arbeit.
Soo, die Prüfungen sind so gut wie fertig, bis auf eine, aber die hat noch Zeit
Wie gesagt, verwende ich ein neues Display(WINTEK WD-H3224V). Link
Verbaut sieht das dann so aus:
Bild hier
Der Touchscreen wurde inzwischen auch in Betrieb genommen. Ich habe ihm gleich noch eine Fehlerbetrachtung verpasst. Sollten zwei Folgewerte zu weit auseinander liegen, wird dies als Fehler betrachtet. Der 2. Wert wird aber trotzdem aufgenommen und mit der nächsten Messung verglichen. Wenn alles passt wird der Wert in in die Hauptvariable gepackt und ein "touched" Flag wird 1 gesetzt, bis wieder zwei Folgewerte zu stark voneinander abweichen u.s.w.
Der Sinn dahinter ist, dass die Ausgangsspannung sehr nervös ist, wenn man nicht richtig draufdrückt. So wird ein ein Verreißen des Ergebnisses verhindert.
Jetzt muss das Ergebnis nur noch aufbereitet werden, das heißt möglichst schnell/effizient auf 320x240 runterrechen, zurzeit sind es nur die zugeschnittene Werte des ADC.
Außerdem kam eine cls() und eine fillScr() hinzu, sie sind eigendlich beide gleich, bis auf die Kleinigkeit, dass cls() das Textarray mit Leerzeichen füllt, bei fillScr() kann man sich das Zeichen aussuchen.
Die PrintInt() von MagicWSmoke arbeitet nicht so wie sie soll, beim festlegen der Ausgabelänge wird der hintere Teil abgeschnitten, nicht der vordere. Das wird meine nächste Aufgabe.
Lesezeichen