Forum: Mikrocontroller und Digitale Elektronik TImer Assembler


von Airbag (Gast)


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

von Airbag (Gast)


Lesenswert?

oder anstaat breq brne?

von Ingo Henze (Gast)


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

von Airbag (Gast)


Lesenswert?

Nein ich will keine interupt da ich mehrere unter programme hab die ich
so ansteuern will

von Airbag (Gast)


Lesenswert?

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

von Ingo Henze (Gast)


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

von Airbag (Gast)


Lesenswert?

Hilfeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee

von Airbag (Gast)


Lesenswert?

Hilfeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee ich flipp hier aus echt

von Andi (Gast)


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

von Airbag (Gast)


Lesenswert?

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

von Andi (Gast)


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

von Airbag (Gast)


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

von Airbag (Gast)


Lesenswert?

Danke Andy jetzt tuts vielen dank Peace

von ...HanneS... (Gast)


Lesenswert?

Warum STS? - Es gibt doch OUT...

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

von Andi (Gast)


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

von Airbag (Gast)


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)

von ...HanneS... (Gast)


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...

von Airbag (Gast)


Lesenswert?

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

von Airbag (Gast)


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.

von ...HanneS... (Gast)


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...

von ...HanneS... (Gast)


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...

von Airbag (Gast)


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,

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
Noch kein Account? Hier anmelden.