www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik TImer Assembler


Autor: Airbag (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Freunde, Sieht euch mal dieses programm soll nach etwa 8sekunden
in den hauptprogramm zurück aber das tuts nicht, vielleicht ist die
Idee falsh. Wie kann ich den Assembler beibringen das er warten soll
bis der zähler überleuft. Das mit dem TIFR ist doch keine schlechte
Idee oder?
.include "m8def.inc"
.org 0x000
  rjmp main
sub1:
      ldi r16, 0b00000000
      out TCCR1A, r16
      ldi r16, 0b00000100
      out TCCR1B, r16
      ldi r16, 0b00000100
      out TIMSK, r16
while:
    ldi r17, 00000100
    andi r17, TIFR
    cpi r17, 00000100
    breq endwhile
    rjmp while
endwhile:
      ret



main:
   ldi r16, LOW(RAMEND)
   out spl, r16
   ldi r16, HIGH(RAMEND)
   out sph, r16
   ldi r16, 0b00001111
   out DDRB, r16
   ldi r16, 0xFF
   out PORTB, r16
   ldi r16, 0x00
   out DDRD, r16
   sei
   rcall sub1
weiter:
;   rcall sub2
   ldi r17, 0b00010000
   out PORTB, r17
rjmp main

Autor: Airbag (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
oder anstaat breq brne?

Autor: Ingo Henze (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Soweit ganz nett, aber Du solltest schon den TIFR Wert einlesen, also
sinngemäß:

while:
    in   r17, TIFR
    andi r17, 00000100
    cpi  r17, 00000100
    breq endwhile
    rjmp while
endwhile:

Wenn der uC wirklich nur die 8 Sekunden gar nix machen soll, würde sich
noch ein Timerinterrupt anbieten, der das Teil dann nach einem sleep
wieder aufweckt.
Spart eventuell sogar Strom :-)

Gruß
Ingo

Autor: Airbag (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nein ich will keine interupt da ich mehrere unter programme hab die ich
so ansteuern will

Autor: Airbag (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
DEINE programm tuts auch nicht den TIFR register bit 2 bleibt nach
einmalige ablauf bestehen da der interupt noch nicht beendet wurde

Autor: Ingo Henze (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Deshalb hab ich ja auch geschrieben sinngemäß, mir war nur
aufgefallen, das Du den Wert des TIFR überhaupt nicht einlieste. Dann
kannst Du natürlich auch das Falg nicht auswerten.
Was da nun genau zu machen ist, kann ich so aus dem Hut auch nicht
sagen.

Gruß
Ingo

Autor: Airbag (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hilfeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee

Autor: Airbag (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hilfeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee ich flipp hier aus echt

Autor: Andi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi!

Mag sein, das Du gleich ausrastest, aber ein paar Fehlerchen haben sich
schon eingeschlichen.
Du kannst nicht direkt eine AND-Verknüpfung mit dem Inhalt eines
Registers zur Aussenwelt machen:

    ldi r17, 00000100
    andi r17, TIFR

In Zahlen umgesetzt schaut das dann so aus:

    ldi r17, 00000100
    andi r17, 0x38 ($38 ist die Adresse von TIFR welche in der
m8def.inc mit .ecu definiert ist)

Mußt Du ändern in folgendes:

    in r17,TIFR
    andi r17, 0b00000100

Da fällt mir gerade auf, das Du 2 mal "0b" vor einer Binärzahl
vergessen hast.

Wenn Du willst, das Bit 2 nach dem Warten wieder zurückgesetzt wird muß
vor dem RET noch folgendes rein:

    sbi TIFR,2

Dadurch wird das Flag TOV1 zurück auf 0 gesetzt.
Lies Dir dazu mal in aller Ruhe im PDF-File für den ATMega 8 ab Seite
101 alles durch.
Der Rest schadet natürlich auch nicht.

Gruß
Andi

Autor: Airbag (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
das hilft auch nicht ausserdem avr studio zeigt genau an der stelle sbi
TIFR, 2 eine Fehler

Autor: Andi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sorry, mein Fehler!
Mit SBI/CBI/IN/OUT kann man, dank der AVR-Entwickler (nich bös
gemeint), nur die I/O-Register 0 bis 31 ansteuern.
Das macht das ganze dann etwas komplexer ;-)
Statt SBI dann:

    ldi r16,0b00000100
    sts TIFR+0x20,r16 ;I/O-Register 0 ist in echt bei Adresse 0x20!

Gruß
Andi

Autor: Airbag (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Oben ist irgend was falscht egal was ich mach er springt nicht raus
obwohl TIFR die 2 bit gesetzt wird danke für deine vorschlag aber die
Daten Blätter hab ich ganz genau studiert

Autor: Airbag (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke Andy jetzt tuts vielen dank Peace

Autor: ...HanneS... (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Warum STS? - Es gibt doch OUT...

Beim Rest kann ich nicht helfen, diesen Kauderwelsch kann ich leider
nicht nachvollziehen...

Autor: Andi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja, ja!
Hab erst nach her bemerkt, das IN/OUT von I/O-Reg. 0 bis 63 geht (0x00
bis 0x3F).
Also geht dann auch:
    ldi r16,0b00000100
    out TIFR,r16

Bei den ganzen verschiedenen Beschränkungen kommt man ein bißchen
durcheinander.

Gruß
Andi

Autor: Airbag (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja es sind schliesslich 303 Seiten man braucht einfach eine routine ich
wusste auch dass ich irgendwas mitt register Tifr und in gelessen zu
haben na ja Vielen dank es war sehr hilf reich vor allem ich hab nicht
gesehen wo ich irgend einzhal eingegben hab (anstaat 0b00000100 hab ich
eingegeben na ja Assembler in C wäre ja sowas kein Problem while
schleife)

Autor: ...HanneS... (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi...

Irgendwie verstehe ich nicht, was Ihr mit TIFR wollt.
TIFR wird von der Hardware durch ein INT-auslösendes Ereignis gesetzt
und löst einen Int aus, sofern das zugehörige Bit in TIMSK auch gesetzt
ist (für TIMSK ist der Programmierer zuständig) und natürlich das I-Flag
in SREG gesetzt ist (mit SEI). TIFR wird durch den Interruptaufruf
automatisch gelöscht.

Mit TIFR hat (im Normalbetrieb ohne Tricksereien) der Programmierer
überhaupt nix zu tun.

Man stellt die gewünschten Timer-Parameter ein (Vorteiler usw.), dann
in TIMSK die gewünschten Interrupts, und gibt mit SEI global Interrupts
frei. Das wars eigentlich schon.
Natürlich müssen die Int-Vektoren in den ersten Zellen des Flash
korrekt eingetrage werden und die zugehörigen Int-Handler ordentlich
mit RETI abgeschlossen sein. Es ist auch darauf zu achten, das die ISRs
möglichst kurz sind...

@Andi: Das mit den Einschränkungen geht leider nicht anders, bei nur 16
Bit für die Befehle reichen die Bits nicht, um alle Befehle mit allen
Registern bzw. I/O-Registern zu implementieren. Ich hätte auch gerne
Bit-Transfer per T-Flag mit dem I/O-Bereich (wäre schön bequem...),
aber man kann nicht alles haben... ;-((

Gruß...
...HanneS...

Autor: Airbag (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ach ne das ist nicht dein ernst oder lies doch mal Datenblatt genauer
Timer Interrapt Flag Register

Autor: Airbag (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja aber bei Overflow von Timer1 ist wird der in TIFR das 2 gesetzt so
kann der programmierer auch erkennen ob eine Interupt ausgelöst wurde.
Für den oberen Programm mach das natürlich kein sinn aber stell dir vo
du hättest mehrere unterprogramme wie Oben wie willst du es dann
machen? oder kennst du andre Möglichkeiten. Überleg dir wenn du wie du
oben behauptst einen Interrupt benutzen würdest dann konntest du nur
eine unterprogramm verwenden. Oder wenn du andre möglichkeiten kennst
dann hier damit.

Autor: ...HanneS... (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi Airbag...

Vorschlag:
Lies dir mal die Sektion Timer eines Datenblattes zu einem alten
Classic-AVR durch. Dort sind die reinen (normalen) Timerfunktionen
erklärt, ohne dass immer auf die Spezielfunktionen der neuen Features
(PWM usw.) verwiesen wird. Da versteht man das besser.

Zu deinem Programm kann ich dir derzeit keinen Tip geben, da ich noch
nicht nachvollziehen kann, was du eigentlich willst. Da ist zwar von
einem "Unterprogramm" die Rede, das nach 8 Sekunden fertig sein soll.
Ich sehe da keinen Sinn drin. Wenn ich eine Pause von 8s brauche, dann
stelle ich den Timer so ein, dass er nach 8s einen Interrupt auslöst
und schicke den AVR in den Sleep-Mode. In der ISR wird dann ein Flag
gesetzt (in einem der Register r16...r31, das ich "flags" nenne), was
von der Hauptschleife überprüft und nach Abarbeitung gelöscht wird.
Aber dieses Verfahren nutze ich selten, meine Programme laufen meist
total Timer-gesteuert. Da erzeugt ein Timer (meist Timer0) einen
regelmäßigen Aufruf seiner ISR, in der dann Register (als Zähler)
in/decrementiert werden und Flags für den Programmablauf der
Hauptschleife gesetzt werden. Wenn keine weiteren Ints genutzt werden,
mach ich auch gleich mal die gesamte Arbeit in der Timer-ISR. Ist die
Arbeit getan, schicke ich den AVR in den Sleep-Mode, er wird dann vom
nächsten Int geweckt...

...HanneS...

Autor: ...HanneS... (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi Airbag...

Mir ist da noch etwas aufgefallen.
In deinem Code (erstes Posting) endet die Routine "main" mit "rjmp
main". Damit beginnst du das Programm von vorn (mit allen
Initialisierungen). Vielleicht solltest du dir angewöhnen, einen
Anweisungsblock "reset" zu verwenden, in dem du alle
Initialisierungen erledigst. Darauf folgt dann "main" als
Hauptschleife, die mit "rjmp main" endet. Damit erreichst du, dass
die Initialisierungen nur beim Reset (Start, Watchdog) ausgeführt
werden. Wenn du nämlich mitten im Programm den Stackpointer neu
initialisierst, kann das böse Überraschungen bereiten.

Schau dir mal einige Programmbeispiele in anderen Threads an.

Gruß...
...HanneS...

Autor: Airbag (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Es geht hier nur drum um Portb Par sekunden lang in irgend eine zustand
zu halten. Das mit dem rjmp main hast du recht. Aber diese Programm
soll nur eine beispiel sein,

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.