Hiho, ich brauch einen Framebegrenzer für ein Pacman mit dem Atmega8. Also ich dachte mir sowas mach man sicher mit nem Timer oder nem Counter oder sowas. Aber wie kann man diesen unter WinAvr (also mit der Sprache "C") nutzen? Und wieviel Zeit darf denn dann so nen Frame haben? Ich glaube 40ms oder?
Die Dauer eines Frames hängt von der Bildwiederholrate ab. Aber was meinst Du mit einem Framebegrenzer?
Der sorgt dafür, dass nur 25 Bilder pro Sekunde gemalt werden. In meinem Fall ist das egal, aber es sollen halt auch die Berechnungen begrenzt werden. Also z.B. soll Pacman nur 25 mal pro Sekunde seine Position aktualisieren. Es soll eine Schleife da sein, die nur alle 40ms einmal durchläuft oder auch anders, da gibt es ja mehrere Möglichkeiten. Mich interessiert halt wie man die Timer nutzt oder ob das anders besser zu machen ist.
Timerinterrupt: 25Hz In diesem eine Variable auf 1 setzen, und irgendwo im Spielablauf dann die Abfrage: while (!wait40ms); wait40ms=0;
:) danke so in etwa hatte ich mir das auch gedacht, aber mein Problem ist eher wie man das auf nem Atmega8 in "C" Programmiert. Also wie man den Timer einstellt und aktiviert.
Daniel Kehr wrote: > :) danke so in etwa hatte ich mir das auch gedacht, aber mein Problem > ist eher wie man das auf nem Atmega8 in "C" Programmiert. Also wie man > den Timer einstellt und aktiviert. Sei mir nicht böse, aber ist dein Problem WIRKLICH das, dass du nicht weist, wie man in C den Timer etc. konfigurierst, oder ist es eher, dass du garnicht weist, wie man den Timer etc. konfiguriert?
Hmm, wo ist da der Unterschied? Ich programmier den Controller nunmal in C und da weis ich nicht wie das geht. Wie es in einer anderen Programmiersprache geht weis ich dementsprechend auch nicht.
>Hmm, wo ist da der Unterschied?
Ich könnte dir das z.B. nur in ASM und anhand des Datenblattes erklären
- C müsste ich mir zusammenkratzen.
Naja, Assembler ist doch auch schonmal was. Ich denke ich werd es schon halbwegs übersetzen können.
Wie jetz? Pacman für nen AVR gestrickt aber keine Ahnung von C? Datenblatt, AVR-Tutorials hier in der Artikelsammlung und ein Hauch Eigeninitiative. Mehr brauchts nicht.
Daniel Kehr wrote: > Hmm, wo ist da der Unterschied? Ich programmier den Controller nunmal in > C und da weis ich nicht wie das geht. Timer gehören nicht zum C-Sprachumfang und daher gibt es auch keine Timerfunktionen in C. Du hast auf dem AVR auch kein OS, welches Dir Systemcalls zur Verfügung stellt. Timer sind als Hardware im AVR ausgeführt, d.h. um sie anzusprechen, mußt Du das Datenblatt lesen und dann auf die entsprechenden IO-Register zugreifen. Peter
@Karl: Welchen Sinn hatte der Beitrag. Es gibt sicher auch SpamForen für solch nutzlose Beiträge. @Kai: Danke. Ich werde es mir mal anschauen. @Peter: Danke, dann brauch ich ja danach nichtmehr zu suchen. Gibt es denn keine INCLUDE-Datei für die Timer? Nagut, trotzdem danke.
Daniel Kehr wrote: > @Karl: Welchen Sinn hatte der Beitrag. Es gibt sicher auch SpamForen für > solch nutzlose Beiträge. Jaja, sei mal lieber nicht so frech ;) > Gibt es denn keine INCLUDE-Datei für die Timer? Nagut, trotzdem danke. Nein, das braucht es auch nicht. Wofür sollte es denn Funktionen/Datentypen/Macros/whatever für den Timer geben?
Warum fällt mir dazu immer der blöde Witz aus den 1950er Jahren ein: Mutter: "Fritzchen, was wünscht Du Dir zu Weihnachten?" Fritzchen: "OB!" ... Mutter: "Ja, warum das denn?" Fritzchen: "Weil man damit schwimmen und Schlittschuh laufen und Fahrrad fahren kann!" Q: "Warum willst Du C programmieren?" A: "Weil man damit PACMAN, Windows, Linux machen kann!" kopfschüttelnd Bernhard
:) Hätte ja sein können. Hab das mal grob überflogen, kann man denn den Vorteiler beliebig wählen oder muss der 1,8,64,256 oder 1024 sein?
Hallo, was ist eigentlich das Ziel? Hast du auf einem AVR Pacman programmiert? Oder willst du ein externes Gerät begrenzen? Sorry für die dumme Frage. Steffen.
Der Beitrag von Kai Giebeler war noch nicht da, als ich meinen geschrieben habe. Der Sinn des Beitrags: Die immer wieder auftauchende Frage nach Timer und Co. auf das Tutorial lenken, falls du das noch nicht kanntest. Dazu die Aufforderung, dir das Datenblatt durchzulesen. Da steht beinahe alles drin, was du wissen musst. Der Wink mit der Eigeninitiative sollte wohl die Frage verhindern, welchen wert du nun in welches Register zu welchem Zeitpunkt schreiben musst.
>Hab das mal grob überflogen, kann man denn den Vorteiler beliebig wählen >oder muss der 1,8,64,256 oder 1024 sein? Da ist es schon. Datenblatt!
@Bernhard Reichenbach: Also ein eigenes kleines Betriebssystem hab ich schon programmiert. Das ist ja nicht so extrem schwer. Warum programmierst du denn C? @Steffen: Naja, ich hab hier nen Display und den Mega8 verbunden und möchte ganz einfach wie bei jedem Spiel, welches ich bisher auf dem Rechner programmiert habe auch hier eine Framebremse.
Ein Betriebssystem programmiert ohne den Haus einer Ahnung wie man Hardware (Timer) anspricht. Das muss ein tolles System sein, oder meintest du "while(1){}" mit Betriebssystem ?? Mal Spass beiseite, wie willst du jemals auf dem Display was sehen können wenn du nicht mal die Hardware ansprechen kannst ? Alleine die Frage nach dem beliebigen Vorteiler disqualifiziert dich hier.... Leute gibt's (kopfschüttel....)
@Daniel Kehr: Hic Rhodos, hic salta! Bitte den Source-Code vom Betriebssystem! Und "Warum" fragen Kindergarten-Kinder.
Sorry, das ist der einzige Code den ich noch finden konnte, da ist allerdings einiges nicht von mir(alles was hinter dem Code noch kommentiert ist ist nicht von mir :) ). Es handelt sich dabei um die Interupt Routine 21. Ich weis nicht wo die Endversion hin ist, sorry. Bootloader und Kernel hab ich natürlich auch noch. So, hier:
1 | ;###Int 21h |
2 | int21h: |
3 | cmp ah,0h |
4 | JE pr_z |
5 | cmp ah,01h |
6 | JE pr_str |
7 | cmp ah,02h |
8 | JE rd_z |
9 | cmp ah,03h |
10 | JE rd_z_a |
11 | cmp ah,04h |
12 | JE rd_string |
13 | cmp ah,05h |
14 | JE rd_string_lenght |
15 | mov al,1 ;Fehlercode |
16 | int21h_e: |
17 | iret |
18 | ;###Int 21h Ende |
19 | |
20 | |
21 | |
22 | |
23 | ;### Zeichen ausgeben |
24 | pr_z: |
25 | mov ah,0eh |
26 | int 10h |
27 | iret |
28 | ;###Zeichenausgeben ende |
29 | |
30 | ;### Stringausgabe int 21h ah=01h begrenzungszeichen=ASCII 0 BX=OFFSET |
31 | pr_str: |
32 | lodsb ; Byte laden |
33 | or al,al |
34 | jz short putstrd ; 0-Byte? -> Ende! |
35 | mov ah,0x0E ; Funktion 0x0E |
36 | mov bx,0x0007 ; Attribut-Byte (wird nicht bentigt) |
37 | int 0x10 ; schreiben |
38 | jmp pr_str |
39 | putstrd: |
40 | iret |
41 | ;### Stringausgabe ende |
42 | |
43 | ;###Zeichen von Tastatur einlesen |
44 | rd_z: |
45 | mov ah,0 |
46 | int 16h |
47 | iret |
48 | ;### |
49 | |
50 | ;###Zeichen von Tastatur lesen und ausgeben |
51 | rd_z_a: |
52 | mov ah,0 |
53 | int 16h |
54 | mov ah,0eh |
55 | int 10h |
56 | iret |
57 | ;###Zeichen einlesen ende |
58 | |
59 | ;###String einlesen |
60 | ;#BX:Offset |
61 | rd_string: |
62 | mov cx,0 |
63 | push cx |
64 | mov [bx],cx |
65 | rd_str: |
66 | mov ah,0 |
67 | int 16h |
68 | cmp al,13 |
69 | JE rd_str_ende |
70 | cmp al,8 |
71 | jne rd_str_weiter |
72 | pop cx |
73 | cmp cx,0 |
74 | push cx |
75 | je rd_str |
76 | mov ah,3 |
77 | mov bh,0 |
78 | int 10h |
79 | mov ah,2 |
80 | mov bh,0 |
81 | dec dl |
82 | int 10h |
83 | mov al,0 |
84 | mov ah,0eh |
85 | int 10h |
86 | mov ah,2 |
87 | int 10h |
88 | pop cx |
89 | dec cx |
90 | push cx |
91 | dec bx |
92 | mov [bx],al |
93 | jmp rd_str |
94 | rd_str_weiter: |
95 | mov ah,0eh |
96 | int 10h |
97 | pop cx |
98 | inc cx |
99 | push cx |
100 | mov [bx],al |
101 | inc bx |
102 | xor ax,ax |
103 | mov [bx],al |
104 | jmp rd_str |
105 | rd_str_ende: |
106 | inc bx |
107 | mov cx, 0 |
108 | mov [bx], cx |
109 | pop cx |
110 | jmp int21h_e |
111 | ;###String einlesen ende |
112 | iret |
113 | |
114 | rd_string_lenght: |
115 | mov cx, 0 |
116 | rd_string_lenght_start: |
117 | ; Einen String ausgeben: |
118 | lodsb ; Byte laden |
119 | or al,al |
120 | jz short rd_string_lenght_ende ; 0-Byte? -> Ende! |
121 | inc cx |
122 | jmp rd_string_lenght_start ; Nchstes Byte |
123 | rd_string_lenght_ende: |
124 | iret |
125 | |
126 | |
127 | times 512-($-$$)-0 db 0 ; Dateilnge: 512 Bytes |
Des weiteren hab ich die komplette Ausgabe auf dem Display schon, ich will ganz einfach nur die Häufigkeit der Berechnungen begrenzen.
>ganz einfach nur die Häufigkeit der Berechnungen begrenzen.
Dann verwende das Zeitschlitzverfahren!
(Codeauzugaus einem meiner Projekte)
1 | // timer1 ovfl 14,7456MHz/65536 = 4,444ms (225Hz) ***************
|
2 | ISR ( TIMER1_OVF_vect ) |
3 | {
|
4 | //-- increase global timebase ---------------------------------
|
5 | u16TimeBaseTick++; |
6 | }
|
7 | void main ( void ) |
8 | {
|
9 | //-- local variables ----------------------------------------------
|
10 | uint16_t _u16TimeBaseTickLast = 0x0000; |
11 | uint16_t _u16TimeStampMode = 0x0000; |
12 | //-- initialisations ----------------------------------------------
|
13 | init_timebase (); |
14 | sei (); |
15 | //-- endless loop, call modes -------------------------------------
|
16 | while (1) |
17 | {
|
18 | //-- call modes every 4,44 ms ---------------
|
19 | if ( _u16TimeBaseTickLast != u16TimeBaseTick ) |
20 | {
|
21 | _u16TimeBaseTickLast = u16TimeBaseTick; |
22 | //-- fetch start time ---------------------
|
23 | _u16TimeStampMode = TCNT1; |
24 | //-- call mode routine --------------------
|
25 | taskaufruf1 (); |
26 | taskaufruf2 (); |
27 | ...
|
28 | //-- calculate procesing time -------------
|
29 | |
30 | }
|
31 | }
|
32 | }
|
So arbeiten auch SPS'en.. Die verschiedenen Tasks werden einfach alle x Millisekunden aufgerufen..
Sorry, aber das hätte ich hinbekommen, zwar hätte ich es ein bissle anders gemacht, aber es kommt aufs gleiche raus. Was mir fehlt ist nur der Teil, der sich hinter init_timebase (); verbirgt. Bei mir ist es halt der Timer0 und nicht der Timer1, aber ich nehm auch gerne den Timer1, hab ich nichts dagegen. Bei mir sieht das gerade so aus. Aber das funktioniert nicht so recht.
1 | .global init_Timer |
2 | init_Timer: |
3 | ldi temp, 0x04 ; CS00 setzen: Teiler 256 |
4 | out TCCR0, temp |
5 | |
6 | ldi temp, 0x01 ; TOIE0: Interrupt bei Timer Overflow |
7 | out TIMSK, temp |
8 | |
9 | ret |
sorry, hatte ich vergessen reinzukopieren:
1 | //** init timer1 in normal mode, overflow every 4,44ms **********************************
|
2 | void init_timebase ( void ) |
3 | {
|
4 | //-- set clk => 14,7456MHz in normal mode -------------------------
|
5 | TCCR1B |= (1<<CS00); |
6 | //-- enable overflow interrupt ------------------------------------
|
7 | TIMSK |= (1<<TOIE1); |
8 | }
|
Danke, aber er macht trotzdem nicht was er soll. Ich hab CS10 auf 1 gesetzt und lass immer eine Variable bis 240 Zählen und dann wird ein Ereignis aus ausgelöst. Mein Mega8 läuft auf 16 MHz. Somit sollte doch eigentlich rund jede Sekunde einmal dieses Ereignis ausgelöst werden, oder?
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.