Hallo, ich versuche seit einiger Zeit, mir eine Methode ausdenken, wie man die Auslastung der CPU mit einfachen Mitteln (sprich wenigen Befehlen) ermitteln kann. Aber irgendwie stehe ich bei diesem Problem auf dem Schlauch. Ich denke mir zur Zeit, in einer Hintergrundaufgabe einen Zähler hochzuzählen und diesen Zähler dann zu vergleichen. Aber womit vergleichen? Was wäre die Basis für die Ermittlung der Auslastung? Vielleicht hat ja jemand eine Idee, um mir auf die Sprünge zu helfen. Beim Suchen im Internet bin ich bis jetzt nur auf Methoden gestossen, die sich recht kompliziert angehört haben und IMHO selber bereits reichlich Rechenzeit verbrauchen. Das wollte ich eigentlich vermeiden :-) Gruß Thorsten
Ich mach das bei mir so: In der Haupschleife schicke ich den µC in den sleep, daraus wird er 128 mal in der Sekunde geweckt und dann fährt der Controller mit dem Programm fort. Jetzt setze ich vor dem Sleep einen Portpin auf low, nach dem Sleep einen Portpin auf High. Dann mess ich mit dem Oszi das Portsignal, High heisst dann er rechnet, low er schläft. Man kann auch eine LED dranhängen und sieht an der Helligkeit wann er grad wieviel rechnet. Bei einzelnen routinen kann man es genauso machen.
Hallo Fritz, danke für die schnelle Antwort. Für die Laufzeitmessung einzelner Programmteile habe ich diese Methode auch schon eingesetzt. Funktioniert einwandfrei. Leider kann ich den µC nicht zum "Schlafen" schicken da er auch in der Hauptschleife einiges zu tun hat und damit permanent arbeiten muss. Ich dachte eigentlich mehr an eine Berechnung, bei der hinten eine Zahl zwischen 0 und 100 (oder was auch immer) rauskommt. Diese Zahl könnte ich dann weiterverarbeiten. Oder habe ich immer noch ein Brett vorm Kopf, dass mir der Zusammenhang nicht auffällt? Gruß Thorsten
also wenn er in der hauptschleife auch die ganze zeit was abarbeitet, dann hat er meiner meinung nach 100% cpu auslastung :)
Ich würde auch sagen(wie Thomas K.) das die CPU 100% last hat. Wenn du jedoch in der hauptschleife nichts hast könntest du ja da einen zähler hoch zählen lassen, und mit einem timer immer wieder auf 8 setzt. Der Stand des zählers ist die prozesslast da ja die Interrupts die Hauptschleife unterbrechen und die so nicht weiter zählen kann. so müsstest du annähernd an 0-100% kommen. Nachteil: Hauptschleife muss frei sein, ein timer wird benötigt. aber im prinzip müsste es funktionieren, ohne oszi, ohne externer hardware, oder irre ich micht? mfg Azrael
@all Danke für die Antworten. Ich habe gerade festgestellt, dass es gar nicht so leicht die richtige Frage zu stellen. Ihr habt recht: Die Auslastung ist 100% bei der Fragestellung!!!!! Daher noch ein Versuch: Ich habe zwei zyklische Tasks per Timer-Interrupt (eine schnell(50µs); eine langsam (20ms)). Dazu kommen noch azyklische Interrupts von verschiedenen Kommunikationen (USART, TWI, SPI). Ausserdem gibt es Hintergrundaufgaben in der Hauptschleife. Und jetzt die Frage: Wie kann ich die Zeit messen (in %), die die Hintergrundaufgaben von der CPU-Zeit zur Verfügung haben? Ich hoffe, die Frage diesmal richtig gestellt zu haben. @Azrael Ich denke du hast die geleiche Idee wie ich schon hatte: Einen Zähler hoch zählen lassen und dann vergleichen. Aber womit vergleichen?!?! Gruß Thorsten
int main(void){
while(1){
count++;
}
}
SIGNAL(SIG_OVERFLOW1){
prozent = (count/typ_count)*100
count=0;
}
Ich hab das so gemeint.
In der Schleife im main zählst du den counter immer nach oben. Wenn
niemand etwas in der zwischenzeit macht, sollte immer der selbe wert
beim timer_interrupt sein(das währe typ_count) dieser Wert würde 100%
entsprechen. wenn jetzt andere interrupts rechenzeit verbrauchen sinkt
der count Wert. -> niedrigere cpu-last.
wenn immer irgend ein interrupt rechenzeit verbraucht kommt 0%raus(da
ja nie die Schleife abgearbeitet werden kann.
Ich habs noch nie ausprobiert, aber wenns funktioniert währe ich an dem
sourcecode interessiert, für ein paar benchmarks ;)
mfg Azrael
Ich denke, der Zähler müsste genau anders herum funktionieren. Wenn Maximum erreicht dann 0% Auslastung, da ja nichts anderes abgearbeitet wird. Wenn dauernd ein Interrupt ansteht dann wird der Zähler nicht mehr hoch gezählt und die CPU 100% Auslastung. Deine Rechnung würde ergeben wieviel Prozent CPU-Zeit noch verfügbar ist. Eigentlich sind beide Ergebnisse brauchbar. Ich denke mir auch das ein Zähler (count) benötigt wird. Dieser wird dann mit einem Vergleichswert (typ_count) verglichen. Kommt jetzt die Frage worauf basiert der Vergleichswert? Ich sehe zur Zeit 2 Möglichkeiten: 1. Taktzeit der CPU: Jeder Takt, der nicht für den Zähler verwendet wird, wird dabei als verbrauchte Rechenzeit gewertet. => inc count & nop würden bereits eine Auslastung von 50% ergeben (ich programmiere in Assembler :-) kann aber auch C lesen). => Dabei bereits 50% Auslastung: Ergebnis unbrauchbar. 2. Durchlaufzeit der Hintergrundaufgabe: Die Durchlaufzeit der Hintergrundaufgabe würde als Basis für den Vergleichswert dienen. Dadurch würde die Hauptschleife (while(1)) nicht gewertet. => Unabhängig von der Hauptschleifenlänge ergibt sich eine Prozentzahl die irgendwo zwischen 0-100% liegen müsste: Ergebnis schon weitaus brauchbarer, nur es wird halt nicht die Hintergrundaufgabe bewertet. Muss die eigentlich miteingerechnet werden oder darf man das vergessen? Vielleicht hat ja jemand noch eine Idee, wie dieser Vergleichswert ermittelt werden kann. @Azrael Wenn jemals brauchbarer Code herauskommt, kann ich ihn gerne posten :-) Gruß Thorsten
Also ich würde sagen, man hat einen Zähler der durch einen Timer
hochgezählt wird, und immer die CPU in eine Funktion wo sie arbeiten
muss hüpft steht am anfang der Befehl TImer Stopp, und am Ende Timer
an. Wenn bereits ein Timer verwendet wird kann das ganze über ein flag
realisiert werden. Man muss also nur wissen welche funktionen als
Arbeit gelten und Welche nicht. Der Zähler hat dann die Zeit die die
CPU nicht mit Arbeit verwendet hat. Um jetzt die AUslastung zu kriegen
kann man jetzt
a) einen weiteren zähler hochzählen lassen der immer hochzählt und dann
teilen
b) am Anfang der Hauptschleife, den Arbeitlosenzähler entsprechend
auswerten
Es könnte wie folgt aussehen
char flagarbeitlos;
unsigned int timer_arbeitlos,timer_gesamt;
unsigned char cpuaus;
void InitLastAusgabe()
{
timer_arbeit=timer_gesamt=0;
cpuaus=0;
}
void timer_isr()
{
if(!flagarbeitlos)
timer_arbeitlos++;
timer_gesamt++;
if(timer_gesamt==1000)
cpuaus in %
cpuaus=timer_arbeitlos/10; //cpuaus=timer_arbeitlos*100%/1000
}
unsigned char GetCPUAus()
{
return cpuaus;
}
//eine Funktion Arbeit kann wie folgt aussehen
//dabei kann das eine INterruptroutien oder ... sein hauptsache
flagarbeitlos wird gesetzt
void FktArbeit()
{
// oft auch erst die Frage nach gibt es arbeit
//nein return
//ja
flagarbeitlos=0;
//Arbeit
flagarbeitlos=1;
}
//WIchtig ist aber allerdings das flagarbeitlos immer gelöscht und
wieder gesetzt wird
//um auf nummer sicher zu gehen kann in bereichen die nicht als Arbeit
defeiniert sind immer wieder mal
//flagarbeitlos=0; stehen
oh hab ich grad übersehen in der timer_isr bei
if(timer_gesamt==1000)
{
cpuaus in %
cpuaus=timer_arbeitlos/10; //cpuaus=timer_arbeitlos*100%/1000
timer_arbeitslos=timer_gesamt=0; //muss natürlich wieder aus null
gestetzt werden
}
diese abfrage könnte man auch in die Hauptschleife stellen
jedoch dann mit
if(timer_gesamt>1000)
{
cpuaus=timer_arbeitslos*100/timer_gesamt;
timer_arbeitlos=timer_gesamt=0;
}
Ist der CPU nicht immer voll ausgelastet? Ich meine, der macht doch
durchgehend was, selbst wenn der keine Aufgabe hat:
while(1)
{
}
Selbst dabei hat der dann doch durchgehend (Sprung-)befehle.
Ist aber nur ne Vermutung :)
ja klar aber interesant ist ja ob er nur Sprungbefehle macht, oder ob er was "rechnet"
wenn er nur sprungbefehle mach weiss ich ich kann ihn noch mehr mit aufgaben belasten
@JOchen Wenn ich das ganze richtig verstanden habe, dann wird flagarbeitlos am Anfang einer Routine gesetzt und am Ende wieder rückgesetzt. Damit ergibt sich aber doch dass z.B. in einer ISR das flag gesetzt und wieder rückgesetzt wird ohne das die Timer-ISR überhaupt etwas davon mitbekommt, da ja ein neuer Interrupt erst abgearbeitet wird, wenn der aktuelle fertig ist. So habe ich das mit den Interrrupts bis jetzt jedenfalls verstanden. Damit würde timer_arbeitlos jedoch niemals hochgezählt und die Auslastung wäre immer 0% und das wäre dann nicht richtig. Wenn mir bei dieser Überlegung etwas entgangen ist, lass es mich bitte wissen. Aber mit dem flag könnte man z.B. einen Timer starten und stoppen und mit einem Vergleichstimer vergleichen und so die Auslastung bestimmen. Kostet halt einen Timer. Frage in dem Zusammenhang: Kennt jemand eine Möglichkeit, den Zählerstand des Watchdog-Timers bei einem AVR auszulesen? Ich denke, damit würde es relativ einfach werden, habe aber dazu noch nichts gefunden. @Jan wie JOchen schon sagte, die CPU hat immer was zu tun. Muss auch so sein. Es geht nur darum, zwischen "sinnlosen" Befehlen (mit Hilfe von Sprüngen warten in der Hauptschleife) und "sinnvollen" Befehlen (z.B. abarbeiten eines Interrupts) zu unterscheiden. Siehe auch weiter oben. Gruß Thorsten
Ja stimmt schon das erst der Interrupt vom timer wieder abgearbeitet wird wenn dieser interrupt fertig ist. Jetzt hast du 3 möglichkeiten: 1.Wenn der µC es zulässt kannst du mit unterschiedlichen interrupt prioritäten arbeiten, d.h. timer hat eine hohe was natürlich bei sehr zeit kritischen int's probleme macht da diese dann öfters unterbrochen würden(kommt bei dir Thorsten ja nicht in frage) 2.Am ende einer interrupt routine die als arbeit gilt den zähler für gesamtzeit um einen wert erhöhen, der der zeit entspricht die die cpu zum abarbeiten der Interrupt routine braucht, dazu musst du die zeit durch das T des Timers teilen, hier braucht man dann das flag nicht setzten und löschen. nur interessant wenn der INT fkt nicht komplex ist d.h. mal ist arbeit dann wieder nicht, mal nur 100µs mal 1ms 3.Interrupts einfach ignorieren, da allg. die zeit die die CPU in einer int fkt ist eh so kurz wie möglich sein soll->wenn jedoch zu lang siehe 2. (kommt ja auch nicht in frage weil du ja nur in den Timer ints steckst) naja wenn du die mainloop, und die tasks mal hier rein stellst kann ich dir mehr helfen, hab aber biss jetzt nicht so vorstellen wie den dein Code aussieht den biss jetzt wurd ich sagen das man ein timer einsparen kann, wenn mann beide task durch einen Timer steuert. und man kann die task auch so ablaufen lassen, das sie nicht als interrupts ausgeführt werden Gruß Jochen
Ich würde den Timer einfach laufen lassen. Es gibt dann eine globale
Variable die die Ticks des Timers zählt die als Arbeits-ISR's
abgearbeitet wurden. Dazu muß am Anfang jeder ISR der Timer ausgelesen
werden und am Ende auch. Die Differenz dieser Zählerstände wird
ermittelt und auf die globale Variable addiert. Man hat also in der
globalen Variable die Anzahl an Timer Ticks die in den ISRs verbraucht
wurden. Nun, in der Timer ISR, die ja exakt in einem festen Intervall
relativ zur MCU Taktfrequenz läuft, kann man nun die insgesammt
verbrauchten Timer Ticks ermitteln. Anteilmäßig davon stehen in der
globalen Variable die Anzahl der Ticks die in den Arbeits-ISR
verbraucht wurden. Es entsteht eine simple Verhältnissgleichung, mit
der man entweder Prozentual die Auslastung errechnen kann, oder aber
sogar das Verhältnis in Taktzyklen.
static int32_t ISR_Ticks = 0;
signal Arbeits_ISR() {
ISR_Ticks -= TCCNT0;
... bla bla bla
ISR_Ticks += TCCNT0 + Ticks_benötigt_für_Overhead_Berechnung;
}
static uint8_t Percent = 0;
signal Timer0_Overflow() {
Percent = (Percent + 100 * (256 + TCCNT0) / ISR_Ticks) / 2;
ISR_Ticks = 0;
}
Das funktionert weil auf AVR's normalerweise nur einen IQR Level
existiert. D.h. ISR's sind nicht verschachtelt sondern sequentiell.
Gruß Hagen
@JOchen Bevor ich das ganze Programm poste, möchte ich eine kleine Zusammenfassung geben. Es besteht zur Zeit aus 4 .asm Files mit zusammen 64kB Dateigröße und ca. 2000 Zeilen. Dazu kommt noch ein Makro-File mit 12kB. Das generierte .hex-File ist dann noch 13kB groß. Dazu kommt noch, dass das ganze Projekt noch nicht fertig ist, d.h. einige Stellen sind zwar angefangen aber funktionieren noch nicht. Wenn du trotzdem einen Blick reinwerfen möchtest, kann ich es gerne reinstellen. Übersicht über das Projekt: Aufgabe: Steuerung einer Eisenbahnanlage µC: ATMega16 (zur Zeit betrieben mit internen 8MHz, um den Quarz zu sparen :-), ist also noch was rauszuholen) geplante Kommunikation: TWI zur Kommunikation mit weiteren AVR's, SPI zur Porterweiterung (siehe WIKI) geplante Tasks: 1. Timer1-ISR mit ca. 30-50µs (ergibt sich dann aus der CPU-Auslastung) für SW-PWM mit 16 Kanälen (HW-PMW hat der µC ja leider "nur" 4). Laufzeit dieser ISR ca. 20µs 2. Timer2-ISR mit 10ms, die dann über weitere Untersetzungen verschiedene Aufgaben (z.B. Rampenberechnungen) zyklisch starten soll. Laufzeit z.Z. unbekannt. 3. SPI-ISR. Ich denke im Moment an eine Frequenz von ca. 100kHz was einen Interrupt alle ca. 100µs auslöst. Laufzeit der ISR selber ca. 2µs, die nachfolgende Auswertung ca. 20µs. 4. Hauptschleife. Als erstes wird das Interrupt-Flag vom TWI abgefragt. Da ich bis jetzt noch nicht in der Lage war eine vernünftige ISR dafür zu schreiben, muss ich das Flag halt abpollen. ISR kommt dann später mal :-) Aber damit das funktioniert muss halt recht hochzyklisch abgefragt werden. Ausserdem werden noch verschiedene andere Aufgaben ausgeführt, die aber dann keine große Priorität haben. Aus diesen Angaben ergibt sich bereits eine rechnerische Auslastung allein aus 1. und 3. von 60% (bei Timer1-ISR=50µs) bis 87% (bei Timer1-ISR=30µs). Daher kam dann die Frage nach der Online Berechnung der CPU-Auslastung. Ich hoffe, du kannst dir jetzt ein besseres Bild von der ganzen Sache machen. Und wie gesagt, wenn du noch willst, kann ich den Code gerne reinstellen . @Hagen Die Idee mit dem Timer gefällt mir eigentlich auch ganz gut. Ich fürchte zur Zeit nur, dass es nicht mehr funktioniert, wenn ich auch die Auslastung einer Hintergrundaufgabe mitmessen will. Irgendwann unterbricht die ISR diese Aufgabe und die Berechnung der Timer-Ticks kommt durcheinander. Sehe ich das richtig? Wenn nur ISR's gemessen werden sollten, müsste es funktionieren. Entschuldige wenn ich mich nicht klar ausgedrückt habe. @all Danke für die ganzen Anregungen und Ideen. Gruß Thorsten
Mein Erfahrung mit internen Osz. sind sehr schlecht, da sie meist nur aus R&C bestehen und somit sehr temp. Abhängig sind.
Hallo Frankl, stimmt schon dass die internen Schwingkreise nicht besonders gut sind. Aber solange alles synchronisiert läuft (TWI, SPI) und auch sonst keine Probleme auftreten, warum nicht? Z.B. beim USART-Betrieb sollte man schon einen Quarz spendieren. Kann dann einige "unerklärliche" Probleme vermeiden. Hab es selber erfahren müssen. :-) Gruß Thorsten
Ok, dann bleibt dir nur eines übrig:
In deimem Program MUSS es ja eine Hauptschleife geben. Diese pollt
verschiedene Ereignisse solange bis diese eintreffen. Nun, beim Start
dieses Pollen wird der aktuelle Timer ausgelesen und gespeichert.
Sobald nun ein Ereignis beim Pollen zutrifft wird wiederrum der Timer
ausgelesen und mit dem Startwert zu einer Differenz subtrahiert. Da du
aber ganz exakt die Taktzyklen die das Pollen benötig ausrechnen
kannst, und den Prescaler des Timers kennst, hast du nun die
Möglichkeit exakt auszurechnen wie lange deine ISR zum Zeitpunkt des
Pollens benötigt haben. Die anderen Task, die ja durch das Pollen
angesprungen werden, würden in dieser Rechnung mit einfließen können,
je nachdem wie du dir das wünscht.
Wichtig ist eben nur eines, der Timer muß laufen, egal ob ISR oder
Hauptschleife. Nur mit hilfe des Timers hast du eine sichere Taktzyklen
basierte Methode.
Zb.
// Hauptschleife
uint16_t TimerWert = TCCNT0;
while (1) do {
uin16_t r,t = TCCNT0;
r = t;
if (r <= TimerWert) r +=256;
r -= TimerWert;
TimerWert = t;
uint16_t Percent = (t - X) / 256 * 100;
if (Polled) {
}
}
Nun, wichtig ist oben das X, es gibt an wieviele Ticks das Pollen samt
Timer auslesen in der Schleife dauert. Sollte zB. der PreScaler vom
Timer0 auf 1 stehen, so würde X exakt die Taktzyklen angeben. In t muß
also immer mindestens die Dauer in Ticks die für das Pollen in der
Hauptschleife benötigt wird stehen. Dies wären dann 0 Prozent. Sobald
aber t größer ist als X heist dies das entweder eine ISR ausgeführt
wurde oder aber eine Unterfunktion aus der Hauptschleife heraus
aufgerufen wurde. In diesem Falle ist t > X und somit Percent > 0.
Mit dieser Methode würdest du die Gesamtauslastung der MCU messen, je
kleiner Percent um so häufiger wurde die Hauptschleife durchlaufen im
gleichem Zeitraum.
Ein andere Methode wäre den Timer0 auf Zb. exakt 1 Sekunde
einzustellen. Nahc dieser Sekunde wird in der Timer ISR ein Zähler
ausgewertet. Etwa so
uint16_t Counter = 0;
uint16_t Percent = 0;
signal Timer0() { // alle 1 Sekunde
Percent = (Percent + Counter / MaxCounter * 100) / 2;
Counter = 0;
}
void Main() {
while (1) {
Counter++;
if (Polled) {
bla bla...
}
}
}
MaxCounter musst du nun so berechnen das dort die Anzahl an
Schleifendurchläufen pro 1 Sekunde drinnensteht die die Mainloop
MAXIMAL durchlaufen kann. Diese ließe sich von Hand berechnen oder aber
du deaktivierst ALLE ISR's bis auf den Timer0 und rufts un Mainkloop
keine Unterfunktionen auf. Daraus ergibt sich also die Maximale Anzahl
an Aufrufen von Counter++ in der Mainloop pro Sekunde, wenn NICHTS
anderes durch die MCU ausgeführt wird.
Gruß Hagen
>Diese ließe sich von Hand berechnen oder aber >du deaktivierst ALLE ISR's bis auf den Timer0 und rufts un Mainkloop >keine Unterfunktionen auf. Da könnte man doch eigentlich auch eine init-Unterroutine aufrufen, die den Timer inkl. Interrupt aktiviert und eine fest definierte Schleife durchlaufen. Am Ende der Routine wird der Zählerstand des Timers ausgelesen und weis, wie viele Durchläufe pro festgelegtem Zeitraum überhaupt möglich sind. In der Hauptschleife kann man diesen Wert dann als Referenz verwenden.
@OldBug, korrekt.
Man könnte aber auch den Wert von MaxCounter abhänig vom Counter
ermitteln. Etwa so
uint16_t Counter = 0;
uint16_t MaxCounter = 1;
uint16_t Percent = 0;
signal Timer0() { // alle 1 Sekunde
if (Counter > MaxCounter) {
MaxCounter = Counter;
Percent = 100;
}
Percent = (Percent + Counter / MaxCounter * 100) / 2;
Counter = 0;
}
void Main() {
while (1) {
Counter++;
if (Polled) {
bla bla...
}
}
}
Nun würde das System schon während der Laufzeit die eigenen Schranken
ermitteln. Nach wenigen Sekunden hätte sich MaxCounter so stabilisert
das er die größt mögliche Dauer angibt die in der Main Loop ohne
weiterem zusätzlichen Code verbracht wurde. Dieses System würde sich
selbst kalibrieren.
Percent gibt natürlich hier den Prozentsatz an in dem die MCU nichts
tut. D.h. 100% bedeutet die Freizeit die die MCU hat, bei 0% ist die
MCU voll ausgelasstet.
Gruß hagen
Vorteile der obigen Methode liegen auf der Hand. Ob man den 8 oder 16
Bit Timer benutzt oder in welchem Interval die Timer ISR aufgerufen
wird ist fast egal. Wichtig ist nur das im Durchschnitt Counter++ in
der Mainloop häufiger aufgerufen wird als die Timer ISR.
Nachteil ist allerdings das die Timer ISR durch höherpriveligierte ISR
blockiert werden kann. D.h. gerade zum zeitpunkt wenn ein Timer OVR
eintritt wird eine längrdauernde ISR ausgeführt. In diesem Moment würde
eine Verfälschung entstehen. Man könnte das kompensieren indem man
TCCNT0 abfragt in der Timer ISR.
Desweiteren wird auch durch das Sperren der IQR's mit CLI die Methode
verfälscht. Man kann dies durch eine andere Methode verhindern:
void Main() {
uint16_t Ticks, Percent, MinTicks = 0xFFFF, WaitCount = 0;
Ticks = TCCNT0;
while (1) {
if (++WaitCount = 100) {
WaitCount = 0;
Ticks = TCCNT0 - Ticks;
if (Ticks == 0) Ticks += 256;
if (Ticks < MinTicks) {
MinTicks = Ticks;
Percent = 100;
}
Percent = (Percent + MinTicks / Ticks * 100) / 2;
}
if (Polled) {
bla bla...
}
}
}
Vereinfacht dargestellt und als ungetesteter Vorschlag. Hier benötigen
wir keine Timer ISR mehr.
Gruß Hagen
@all Danke für alle Amregungen und Ideen. Ich versuche mich jetzt mal an der Realisierung der Auslastungsberechnung. Wie versprochen werde ich das Ergebnis dann hier posten. Gruß Thorsten
Hallo allerseits, im Anhang ist das Ergebnis der Diskussion. Es ist das komplette Testprogramm für die Routine der Auslastungsberechnung. Funktioniert eigentlich ganz gut. Ich hoffe es ist ausreichend kommentiert. Meine Makros habe ich drin gelassen. Dadurch sollte die Lesbarkeit erhöht werden. Getestet im AVR-Studio 4.08 auf ATMega16-Plattform mit verschiedenen Frequenzen. Außerdem verschiedene Belastungen und Berechnungszyklen eingestellt. Das Ergebnis sah plausibel aus. Es sollten nicht mehr allzu viele "Leichen" drin sein:-) Wer mag, viel Vergnügen. Thorsten PS: Eingestellte Tab-Breite = 2.
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.