Frage : solls ne exakte Sekunde sein oder reichts in so etwa, also von 0,7 bis 1,3 oder so???
MfG
Hallo AVR-Freunde.
Eine beliebte Aufgabenstellung in Programmier-Kursen ist es (oder war es immer ) ein Problem mit möglichst wenig Code zu lösen.
Die Aufgabe hier ist: Ein AVR soll eine LED im Sekundentakt blinken, und zwar mit möglichst wenig Maschinen-Befehlen!
Welche Programmiersprache ihr dazu verwendet ist egal, aber das Maß der Dinge sind die Assembler-Befehle bzw. Maschinen-Instruktionen, die "hinten" rauskommen.
Am besten geht so was natürlich direkt in Assembler. Mit Sprachen wie BASIC oder C hat man da eh keine Chance...
Lange Rede, kurzer Sinn: Wer schafft es, das kürzeste Assembler-Programm zu schreiben, um einen AVR im Sekundentakt einen Port zwischen LOW und HIGH wechseln zu lassen?
Nebenbei kann man durch das kleine Programm natürlich seinen AVR besser kennen lernen.
Die Aufgabe gilt als gelöst, wenn es jemand mit weniger als den magischen 10 Instruktionen schafft.
Noch ein Tip: Wenn man einen Lösungsvorschlag hat, kann man den so hinschreiben :
Dadurch sehen andere Leder beim Durchblättern nicht den Lösungsansatz und verlieren nicht die Lust am Mittüfteln.Code:Lösung: ...
Viel Spaß!
Disclaimer: none. Sue me.
Frage : solls ne exakte Sekunde sein oder reichts in so etwa, also von 0,7 bis 1,3 oder so???
MfG
So gaaanz genau muss es nicht sein, aber bis auf 2-3% sollte es schon stimmen.
+/- 30% Fehler ist aber entschieden zu viel.
Disclaimer: none. Sue me.
Nagut,
is ein 3-Zeiler und hat nen fehler von 4,8% laut Simulator.
habs auch noch nicht in Wirklichkeit ausprobiert, aber geht im SimulatorCode:.include "m8def.inc" ;gedacht für nen Mega-8 sbi DDRB,7 ;Port als Ausgang für die LED inc R16 ;R16 um eins erhöhen out PORTB,R16 ;R16 ausgeben
Taktfrequenz 1 Mhz
der Portbin muß immer die DDR*,7 sein
kleiner gehts wohl nicht, genauer aber
MfG
@Rofo88
Und was pasiert nach dem letzten Befehl??? Wir gehen in den Wald...
Zur Taktfrequenz: Die kann als bekannte Konstante angenommen werden. Der Code sollte also für 1MHz ebenso gehen wie für 12MHz (evtl mit neuem Übersetzen nach Anpassung der Konstanten in der asm-Quelle).
Disclaimer: none. Sue me.
@SprinterSB
Jeb da gehts ab ins nichts... das ist richtig, da steht dann FFFF womit der AVR nicht anfangen kann und das macht er bis zum ende des Speichers ( also ne pause ohne eine Codezeile, stant ja nirgendwo das ich den ganzen Flash nicht nutzen darf sollte nur wenig Code sein)
is nicht sehr elegant aber funzt...
zur Taktfrequenz : da brauche ich dann wohl mehr Flash \/
Fazit : nicht ganz sauber aber unheimlich klein...
MfG
Hi,
super Idee, muss natürlich mitmachen....
Und zwar bring ich einfach mal die Standard Methode....
Sind 13 Befehle...Code:.include "m16def.inc" sbi DDRB, 2 main: ldi r16, 1 ldi r17, 145 ldi r18, 3 loop: dec r16 brne loop dec r17 brne loop dec r18 brne loop com r20 out PortB, r20 rjmp main
Damits nicht bei der Unglückszahl bleibt hier nur 12:
Code:.include "m16def.inc" sbi DDRB, 2 main: ldi r17, 145 ldi r18, 3 loop: dec r16 brne loop dec r17 brne loop dec r18 brne loop com r20 out PortB, r20 rjmp main
Kann sein das die Zeit nicht 100% stimmt, müste aber halbwegs in der Toleranz sein.
Gruß,
Mehto
-
@Mehto: Das sieht doch schon mal gut aus! Hart an den "weniger als 10"
@Rofo88: [-X Deine Lösung verwendet neben den 3 Befehlen noch 8186 Bytes des Flash (ATmega also insgesamt 8192 Bytes. Nicht gerade kurz die Lösung...Code:Kannst du noch 3 Befehle sparen? Bei den Werten für die Zählschleife komm ich auf ca. 335000 Zyklen, was auf einen Takt von 1/3 MHz passen würde.
Disclaimer: none. Sue me.
erfüllt aber voll deine Aufgabenstellung
und zwar mit möglichst wenig Maschinen-Befehlen!mit weniger als den magischen 10 Instruktionen
ok gebs ja zu, es ist ein Hintertürchen
ok, hab noch eins, zwar nicht kleiner, sondern mit 13 Befehlen, dafür aber mit Timer
Was mich wirklich wundert ist, ist das es funktioniert, Simulieren klappt bei mir nicht.
Allerding ist die Sekunde doch ein wenig zu schnell (0,9536743 Sekunden, bei einem Quarz von 1,048576MHZ wären es genau 1sek) und nicht für einenen anderen Quarz anpasspar...
(erst wieder bei einem Quarz von 8,388608MHZ wieder genau, oder bei einem mit 33,554432MHZ oder 134,21773MHZ *g*)
Wüste sonst leider gerade nicht wie man das ganze kleiner machen könnte, die Idee von Rofo88 war eigentlich schon recht gut, man sollte aber noch schauen ob das überhaupt richtig funktioniert.Code:.include "m16def.inc" .org 0x01E rjmp TIM1_OVF ;Timer1 Overflow Handler start: sbi ddrb, 2 ;PinB 2 als Ausgang ldi r16, (1<<INT0) ;Int0 aktivieren out GICR, r16 ldi r16,0b00000010 ;Vorteiler auf 8 out tccr1b,r16 ldi r16,(1<<toie1) ;auf overflow stellen out timsk,r16 sei ;Interupts aktivieren ende: rjmp ende TIM1_OVF: com r18 out PortB, r18 reti
Kommt halt drauf an wie man es sieht, eigentlich stehen im Code ja noch über 8000 Nop's anderseits kann man sich die bei einem neuen µC sparen.
Aber wie ist das bei einem gebrauchten?
Der Flash wird ja nicht jedesmal komplett gelöscht, oder?
Sobald also ein älteres größeres Programm vorher drin stand dürfte der Code nicht meher funktionieren.
Aber ich denke mit nur drei Befehlen kann man nur irgendwie tricksen, anderst ist das gar nicht möglich...
Gruß,
Mehto
-
Lesezeichen