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
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
Nein ich will keine interupt da ich mehrere unter programme hab die ich so ansteuern will
DEINE programm tuts auch nicht den TIFR register bit 2 bleibt nach einmalige ablauf bestehen da der interupt noch nicht beendet wurde
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
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
das hilft auch nicht ausserdem avr studio zeigt genau an der stelle sbi TIFR, 2 eine Fehler
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
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
Warum STS? - Es gibt doch OUT... Beim Rest kann ich nicht helfen, diesen Kauderwelsch kann ich leider nicht nachvollziehen...
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
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)
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...
Ach ne das ist nicht dein ernst oder lies doch mal Datenblatt genauer Timer Interrapt Flag Register
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.
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...
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...
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.