www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Framebegrenzer mit Atmega8


Autor: Daniel Kehr (Firma: keine) (minotaurus)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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?

Autor: Mathi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die Dauer eines Frames hängt von der Bildwiederholrate ab.

Aber was meinst Du mit einem Framebegrenzer?

Autor: Daniel Kehr (Firma: keine) (minotaurus)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Daniel Kehr (Firma: keine) (minotaurus)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Keiner eine Idee?

Autor: Benedikt K. (benedikt) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Timerinterrupt: 25Hz
In diesem eine Variable auf 1 setzen, und irgendwo im Spielablauf dann 
die Abfrage:
while (!wait40ms);
wait40ms=0;

Autor: Daniel Kehr (Firma: keine) (minotaurus)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
:) 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.

Autor: Christian L. (lorio)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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?

Autor: Daniel Kehr (Firma: keine) (minotaurus)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Kai G. (runtimeterror)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>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.

Autor: Daniel Kehr (Firma: keine) (minotaurus)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Naja, Assembler ist doch auch schonmal was. Ich denke ich werd es schon 
halbwegs übersetzen können.

Autor: Kai G. (runtimeterror)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Schau dir das mal an:
AVR-Tutorial: Timer

Fehlt dir da noch was für die Umsetzung?

Autor: Karl (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Daniel Kehr (Firma: keine) (minotaurus)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@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.

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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?

Autor: Bernhard R. (barnyhh)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Daniel Kehr (Firma: keine) (minotaurus)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
:)
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?

Autor: Steffen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Karl (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Karl (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>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!

Autor: Daniel Kehr (Firma: keine) (minotaurus)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@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.

Autor: Bj (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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....)

Autor: Bernhard R. (barnyhh)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Daniel Kehr:
Hic Rhodos, hic salta!
Bitte den Source-Code vom Betriebssystem!

Und "Warum" fragen Kindergarten-Kinder.

Autor: Daniel Kehr (Firma: keine) (minotaurus)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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:
;###Int 21h
int21h:
cmp ah,0h
JE pr_z
cmp ah,01h
JE pr_str
cmp ah,02h
JE rd_z
cmp ah,03h
JE rd_z_a
cmp ah,04h
JE rd_string
cmp ah,05h
JE rd_string_lenght
mov al,1 ;Fehlercode
int21h_e:
iret
;###Int 21h Ende




;### Zeichen ausgeben
pr_z:
mov ah,0eh
int 10h
iret
;###Zeichenausgeben ende

;### Stringausgabe int 21h ah=01h begrenzungszeichen=ASCII 0 BX=OFFSET
pr_str:
lodsb             ; Byte laden
or al,al
jz short putstrd  ; 0-Byte? -> Ende!
mov ah,0x0E       ; Funktion 0x0E
mov bx,0x0007     ; Attribut-Byte (wird nicht bentigt)
int 0x10          ; schreiben
jmp pr_str
putstrd:
iret
;### Stringausgabe ende

;###Zeichen von Tastatur einlesen
rd_z:
mov ah,0
int 16h
iret
;### 

;###Zeichen von Tastatur lesen und ausgeben
rd_z_a:
mov ah,0
int 16h
mov ah,0eh
int 10h
iret
;###Zeichen einlesen ende

;###String einlesen
;#BX:Offset
rd_string:
mov cx,0
push cx
mov [bx],cx
rd_str:
mov ah,0
int 16h
cmp al,13
JE rd_str_ende
cmp al,8
jne rd_str_weiter
pop cx
cmp cx,0
push cx
je rd_str
mov ah,3
mov bh,0
int 10h
mov ah,2
mov bh,0
dec dl
int 10h
mov al,0
mov ah,0eh
int 10h
mov ah,2
int 10h
pop cx
dec cx
push cx
dec bx
mov [bx],al
jmp rd_str
rd_str_weiter:
mov ah,0eh
int 10h
pop cx
inc cx
push cx
mov [bx],al
inc bx
xor ax,ax
mov [bx],al
jmp rd_str
rd_str_ende:
inc bx
mov cx, 0
mov [bx], cx
pop cx
jmp int21h_e
;###String einlesen ende
iret

rd_string_lenght:
mov cx, 0
rd_string_lenght_start:
; Einen String ausgeben:
lodsb                ; Byte laden
or al,al
jz short rd_string_lenght_ende     ; 0-Byte? -> Ende!
inc cx
jmp rd_string_lenght_start ; Nchstes Byte
rd_string_lenght_ende:
iret


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.

Autor: Matthias Lipinsky (lippy)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>ganz einfach nur die Häufigkeit der Berechnungen begrenzen.

Dann verwende das Zeitschlitzverfahren!
(Codeauzugaus einem meiner Projekte)
// timer1 ovfl 14,7456MHz/65536 = 4,444ms (225Hz) ***************
ISR ( TIMER1_OVF_vect )
{
  //-- increase global timebase ---------------------------------
  u16TimeBaseTick++;
}
void  main  (  void  )
{
  //-- local variables ----------------------------------------------
  uint16_t  _u16TimeBaseTickLast  = 0x0000;
  uint16_t  _u16TimeStampMode     = 0x0000;
  //-- initialisations ----------------------------------------------
  init_timebase  ();
  sei  ();
  //-- endless loop, call modes -------------------------------------
  while  (1)
  {
    //-- call modes every 4,44 ms ---------------
    if ( _u16TimeBaseTickLast  != u16TimeBaseTick )
    {
      _u16TimeBaseTickLast = u16TimeBaseTick;
      //-- fetch start time ---------------------
      _u16TimeStampMode  =  TCNT1;
      //-- call mode routine --------------------
      taskaufruf1 ();
      taskaufruf2 ();
      ...
      //-- calculate procesing time -------------

    }
  }
}

So arbeiten auch SPS'en..
Die verschiedenen Tasks werden einfach alle x Millisekunden aufgerufen..

Autor: Daniel Kehr (Firma: keine) (minotaurus)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.
  .global init_Timer 
init_Timer:
        ldi     temp, 0x04      ; CS00 setzen: Teiler 256
        out     TCCR0, temp
 
        ldi     temp, 0x01      ; TOIE0: Interrupt bei Timer Overflow
        out     TIMSK, temp
 
        ret

Autor: Matthias Lipinsky (lippy)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
sorry, hatte ich vergessen reinzukopieren:
//** init timer1 in normal mode, overflow every 4,44ms **********************************
void init_timebase ( void )
{
  //-- set clk => 14,7456MHz in normal mode -------------------------
  TCCR1B |= (1<<CS00);
  //-- enable overflow interrupt ------------------------------------
  TIMSK |= (1<<TOIE1);
}

Autor: Daniel Kehr (Firma: keine) (minotaurus)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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?

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.