hallo ich möchte ein programm in assembler schreiben für einen mega16. als eingang drei schaltstellungen eines drehschalters. als ausgang eine led in schaltstelung 1 soll die led alle 10sekunden (ca.) blinken in schaltstelung 2 soll die led alle 20sekunden (ca.) blinken in schaltstelung 3 soll die led alle 30sekunden (ca.) blinken vielen dank schon im voraus - alleine krieg ich das nicht auf die reihe und wenn ich eure beiträge so durchlese , ist mein problem für euch ja ein "klaks" mfg
> alleine krieg ich das nicht auf die reihe welchen Teil des Problems kriegst du alleine auf die Reihe? Kannst du mit einem Timer eine LED in den von dir geforderten Zeiten blinken lassen? Du möchtest das nach Möglichkeit so machen, dass die Blinkzeit zb in einem Register steht, so dass sie von anderen Programmteilen eingestellt werden kann. Wenn du das hinkriegst, dann hast du schon 70% des Problems gelöst. Der Rest ist Abfrage der Schalterstellung und davon abgeleitet dann die Änderung der Blinkparameter in diesem einen Register.
hallo erst mal danke für die schnelle reaktion ! bis jetzt hab ich es leider nur geschafft , dass die 3 schalter abgefragt werden, und jeweils die led PINB0 leuchtet .include "m16def.inc" .def schalter1 = r16 ;PIND0 .def schalter2 = r17 ;PIND1 .def schalter3 = r18 ;PIND2 .def led = r19 ;PINB0 ldi schalter1, 0x00 ;Eingang out DDRD, r16 ldi schalter2, 0x00 ;Eingang out DDRD, r17 ldi schalter3, 0x00 ;Eingang out DDRD, r18 ldi led, 0xFF ;Ausgang out DDRB, r19 loop1: sbis PIND, 0 rjmp loop2 sbi PORTB, 0 loop2: sbis PIND, 1 rjmp loop3 sbi PORTB, 0 loop3: sbis PIND, 2 rjmp loop1 sbi PORTB, 0 ende: rjmp loop1 ;Endlosschleife mach so ja noch nicht viel sinn - wie bekomme ich jetzt die verschiedenen zeiten ins programm hab schon was gelesen mit Timer Overflow bzw. Vorteiler aber wie setzt ich das jetzt um ? bitte nicht zuviel vorraussetzten bin ein absolut beginner und quereinsteiger danke mfg
Stefan Burger wrote: > hallo > erst mal danke für die schnelle reaktion ! > bis jetzt hab ich es leider nur geschafft , dass die 3 schalter > abgefragt werden, und jeweils die led PINB0 leuchtet Das ist aber keine gute Lösung, die du da hast. Du musst die Schalter in der richtigen Reihenfolge drücken um irgendetwas zu bewirken. Gut bei einem Drehschalter ist das kein wirkliches Problem aber bei Tastern ist das keine gute Vorgabe. Als nächstes würde ich mal die Schalter vergessen und mich an deiner Stelle nur um die Led kümmern. Ziel: die Led mit einem Timer zum Blinken bringen. > mach so ja noch nicht viel sinn - wie bekomme ich jetzt die > verschiedenen zeiten ins programm > hab schon was gelesen mit Timer Overflow bzw. Vorteiler aber wie setzt > ich das jetzt um ? Was davon hast du nicht verstanden? So ein Timer ist doch eine simple Sache: Der zählt so vor sich hin. Mit jedem Tick zählt er um 1 weiter. Solange bis er seinen Maximalwert erreicht hat, dann beginnt er wieder bei 0. Nicht sonderlich aufregend, oder? Interessant wird die Geschichte erst dadurch, dass man sich an dieses Rücksetzen hängen kann (den sog. Overflow) und sich einen Interrupt auslösen lassen kann. Dadurch hat man eine Möglichkeit, wie man in regelmässigen Zeitabständen gewisse Funktionalität ausführen lassen kann. Aber im Grunde steht das alles auch im Tutorial. Hast du da schon reingeschaut? Das wichtigste über Timer findet sich hier http://www.mikrocontroller.net/articles/AVR-Tutorial:_Timer Es lohnt sich aber auch die Tutorial Teile davor zu lesen.
Hallo Karl Heinz habs jetzt wenigstens mal geschafft , dass der pinb 3 erst nach einer gewissen zeitverzögerung kommt. schaus dir doch bitte mal an danke .include "m8def.inc" .def temp = r20 .def timer = r21 .org 0x0000 rjmp main ; Reset Handler .org OVF0addr rjmp timer0_overflow ; Timer Overflow Handler main: ldi temp, LOW(RAMEND) ; Stackpointer initialisieren out SPL, temp ldi temp, HIGH(RAMEND) out SPH, temp ldi temp, 0x00 ;Eingang out DDRD, temp ldi temp, 0xFF ;Ausgang out DDRB, temp loop1: sbis PIND , 0 rjmp loop2 ldi temp, 0b00000001 ; CS00 setzen: Teiler 1 out TCCR0, temp ldi temp, 0b00000001 ; TOIE0: Interrupt bei Timer Overflow out TIMSK, temp sei loop: rjmp loop timer0_overflow: ; ldi timer , 1 ; dec timer cpi timer , 0 brne timer0_overflow sbi portb , 3 ende: rjmp ende loop2: sbi portb , 4 mfg stefan
hallo jetzt blinkt die led , aber sobald der schalter einmal gestartet wurde und die led mit blinken begonnen hat stoppt das blinken nicht durch rückstellen des schalters? wie kann ich den timer "reseten" sobald an portA 0 kein signal mehr anliegt?? mfg .include "m16def.inc" .def temp1 = r17 .equ XTAL = 4000000 rjmp main1 main1: ldi temp1, 0b00100000 out DDRD, temp1 ldi r16 , 0x00 out DDRA ,r16 sbis PINA , 0 rjmp main1 ldi temp1, LOW(RAMEND) ; Stackpointer initialisieren out SPL, temp1 ldi temp1, HIGH(RAMEND) out SPH, temp1 ; ; Timer 1 einstellen ; ; Modus 14: ; Fast PWM, Top von ICR1 ; ; WGM13 WGM12 WGM11 WGM10 ; 1 1 1 0 ; ; Timer Vorteiler: 8 ; CS12 CS11 CS10 ; 1 0 0 ; ; Steuerung des Ausgangsport: Set at BOTTOM, Clear at match ; COM1A1 COM1A0 ; 1 0 ; ldi temp1, 1<<COM1A1 | 1<<WGM11 out TCCR1A, temp1 ldi temp1, 1<<WGM13 | 1<<WGM12 | 1<<CS12 out TCCR1B, temp1 ; ; den Endwert (TOP) für den Zähler setzen ; der Zähler zählt bis zu diesem Wert ; ldi temp1, 0b01110000 out ICR1H, temp1 ldi temp1, 0b01000000 out ICR1L, temp1 ; der Compare Wert ; Wenn der Zähler diesen Wert erreicht, wird mit ; obiger Konfiguration der OC1A Ausgang abgeschaltet ; Sobald der Zähler wieder bei 0 startet, wird der ; Ausgang wieder auf 1 gesetzt ; ldi temp1, 0b00111111 out OCR1AH, temp1 ldi temp1, 0b11110000 out OCR1AL, temp1 rjmp main1
Stefan Burger wrote: > hallo > jetzt blinkt die led , aber sobald der schalter einmal gestartet wurde > und die led mit blinken begonnen hat stoppt das blinken nicht durch > rückstellen des schalters? > wie kann ich den timer "reseten" sobald an portA 0 kein signal mehr > anliegt?? Ein Timer hört dann zu zählen auf, wenn du den Vorteiler wieder rausnimmst. > rjmp main1 Warum springst du hier wieder zurück nach main1? Bei main1 beginnt das ganze Programm. Dort finden alle Initialisierungen statt. Wenn das Programm an dieser Stelle angelangt ist, dann wurde bereits alles richtig initialisiert. Es gibt keinen Grund das alles noch mal durchzulaufen. Lass doch die Hardware arbeiten und hör auf das alles immer wieder neu zu initialisieren. Deine komplette Schalterabfrage muss also in die Hauptschleife, die du noch nicht hast: ; Programmanfang ... nimm alle Initialisierungen vor: ... Stackpointer aufsetzen ... Timer in seinen Grundwerten einstellen (aber noch nicht starten) ... sonstiges loop: ; hier beginnt dann die Hauptschleife .... Wenn am PortA das Bit 0 gesetzt ist, dann schalte .... denn Timer ein, indem ihm ein Vorteiler gesetzt wird .... Ist besagtes Bit nicht gesetzt, dann schalte den Timer .... aus, indem der Vorteiler wieder auf 0 gesetzt wird rjmp loop
hallo danke - jetzt kann ích das blinken auch wieder ausschalten!! wie bringe ich es jetzt noch fertig eine zweite schaltstellung mit einem anderen blink interval zu programmieren ? aber hier erst mal der jetzige stand: .include "m16def.inc" .def temp1 = r17 .equ XTAL = 4000000 rjmp init1 init1: ldi temp1, 0b00100000 out DDRD, temp1 ldi r16 , 0x00 out DDRA ,r16 ldi temp1, LOW(RAMEND) ; Stackpointer initialisieren out SPL, temp1 ldi temp1, HIGH(RAMEND) out SPH, temp1 ;ldi temp1, 0b01110000 ;out ICR1H, temp1 ;ldi temp1, 0b01000000 ;out ICR1L, temp1 ldi temp1, 0x01ff out OCR1AH, temp1 ldi temp1, 0xffff out OCR1AL, temp1 main1: sbis PINA , 0 ; überspringe nächste wenn 1 rjmp main2 ldi temp1, 1<<COM1A1 | 1<<WGM11 out TCCR1A, temp1 ldi temp1, 1<<WGM13 | 1<<WGM12 | 1<<CS10 out TCCR1B, temp1 main2: sbic PINA , 0 ; überspringe nächste wenn 0 rjmp main1 ldi temp1, 0b00000000 out TCCR1A, temp1 ldi temp1, 0b00000000 out TCCR1B, temp1 rjmp main1 viele Dank mfg stefan
Stefan Burger wrote: > hallo > > danke - jetzt kann ích das blinken auch wieder ausschalten!! Aber du kannst es nicht wieder einschalten :-) > wie bringe ich es jetzt noch fertig eine zweite schaltstellung mit einem > anderen blink interval zu programmieren ? Wer oder was ist für das Blinkintervall zuständig? (Frage an Dich) Wenn du das identifiziert hast, dann musst du einen zweiten Schalter abfragen und je nach Schalterstellung einmal den einen Parametersatz in die entsprechenden Timer Register laden bzw. den anderen Parametersatz laden. Aber programmier erst mal dein jetztiges Beispiel fertig, so das du das Blinken nach belieben ein und ausschalten kannst.
hallo 1. also zumindest in der avr studio simulation kann ich den schalter schon wieder einschalten (falls ich das richtig mache? auto start mit gesetztem pin A - dann stoppe ich den Ablauf in dem ich auf pause drücke - jetzt nehm ich den pin A raus und geh wieder auf auto start - daselbe nochmal beim wiedereinschalten) 2. für die Dauer des Blinkintervalls ist folgender Absatz verantwortlich ldi temp1, 0b01110000 out ICR1H, temp1 ldi temp1, 0b01000000 out ICR1L, temp1 ldi temp1, 0x01ff out OCR1AH, temp1 ldi temp1, 0xffff out OCR1AL, temp1 richtig?? danke mfg stefan
hallo nochmal ich meine zwar immer noch, wie oben beschrieben , dass der icr1 bzw. der ocr1a wert für die dauer des intervalls verantwortlich ist , aber egal wie ich die werte änderte - es ändert sich nicht viel beim simulieren !? hat das etwas mit den einstellungen bei TCCR1A und TCCR1B zu tun ?- soweit ich das aus dem Datenblatt des atmega16 erkenne wird hier eingestellt, welche Werte miteinander verglichen werden und was dann passieren soll. z.b. clear OS1A , set output to low lever usw. danke stefan
Stefan Burger wrote: > hallo > 1. > also zumindest in der avr studio simulation kann ich den schalter schon > wieder einschalten (falls ich das richtig mache? auto start mit > gesetztem pin A - dann stoppe ich den Ablauf in dem ich auf pause drücke > - jetzt nehm ich den pin A raus und geh wieder auf auto start - daselbe > nochmal beim wiedereinschalten) Mein Fehler. Ich hab mich bei den ganzen rjmp verlesen. So wie du das gemacht hast ist das schon in Ordnung. Das ist schon fast die Programmstruktur zu der ich dich bringen wollte, bevor ich meinen Fehler bemerkt habe. Anzumerken bleibt noch: Es ist innerhalb der Hauptschleife nicht notwendig, so wie hier > ldi temp1, 1<<COM1A1 | 1<<WGM11 > out TCCR1A, temp1 > > ldi temp1, 1<<WGM13 | 1<<WGM12 | 1<<CS10 > out TCCR1B, temp1 jedesmal TCCR1A bzw. TCCR1B komplett zu setzen, bzw. zu löchen. (Einmal, ganz am Anfang musst du das natürlich machen, aber das machst du ohnehin). Wenn du willst, dass der Timer stehen bleibt, dann genügt es vollauf, wenn du das CS10 Bit im Register TCCR1B auf 0 setzt. Um den Timer wieder einzuschalten, wird dieses Bit (und nur dieses Bit) wieder gesetzt. Warum wäre es besser sich nur auf dieses Bit zu kontentrieren. Ganz einfach: Weil an dieser Stelle es dann völlig egal ist, welche anderen Bits in diesen Registern gesetzt wurden. Damit wird diese ein/ausschalt - Sequenz aber völlig unabhängig davon in welchem Modus der Timer gerade läuft. Den Modus (Zähler, CTC Modus, PWM Modus, etc) stellst du an anderer Stelle ein, der muss und soll hier nicht interessieren. Hier geht es einzig und alleine den Timer an sich über den Vorteiler ein und auszuschalten. Mehr nicht. Also sollte der Code an dieser Stelle auch nicht mehr machen! Wie kannst du ein Bit setzen. Ganz einfach du holst dir den Inhalt des TCCR1B Registers in eines der Univeralregister, so dass du es manipulieren kannst. Mit einem ODER (einer logischen Operation) wird dann das Bit gesetzt und der neue Wert wieder nach TCCR1B ausgegeben. Um ein Bit zu löschen, benutzt man eine Maske und die UND Operation. Die Maske enthält an allen Bitpositionen eine 1 die unverändert bleiben soll und nur dort eine 0, wo auch im Ergebnis eine 0 auftauchen soll. http://www.mikrocontroller.net/articles/AVR-Tutorial:_Logik
1 | main1: |
2 | sbis PINA , 0 ; überspringe nächste wenn 1 |
3 | rjmp main2 |
4 | |
5 | in temp1, TCCR1B ; setzte CS10 in TCCR1B |
6 | ori temp1, 1<<CS10 |
7 | out TCCR1B, temp1 |
8 | |
9 | main2: |
10 | |
11 | sbic PINA , 0 ; überspringe nächste wenn 0 |
12 | rjmp main1 |
13 | |
14 | in temp1, TCCR1B |
15 | andi temp1, ~(1<<CS10) |
16 | out TCCR1B, temp1 |
17 | |
18 | rjmp main1 |
anstelle der ganzen in ori/andi out Sequenz müsste, glaub ich, auch ein sbi/cbi funktionieren. > 2. > für die Dauer des Blinkintervalls ist folgender Absatz verantwortlich > > ldi temp1, 0b01110000 > out ICR1H, temp1 > ldi temp1, 0b01000000 > out ICR1L, temp1 > > ldi temp1, 0x01ff > out OCR1AH, temp1 > ldi temp1, 0xffff > out OCR1AL, temp1 > > richtig?? Im Prinzip ja. Wenn wir hier in der Schule wären, würde ich die Antwort trotzdem nicht gelten lassen, weil sie mir nicht zeigt, dass du verstanden hast, was du tust. Das ist so, wie wenn ich dich frage wodurch eigentlich in einem Auto die Kraftentwicklung passiert und du deutest auf den Motorblock und sagst: irgendwo da drinnen. Klar hast du schon recht, aber ich wollte eigentlich auf die Zündkerzen, Benzin, Brennraum, Kolben, etc hinaus. Im gegenständlichen Fall, arbeitet ja der Timer in einem bestimmten Modus. Diesen Modus hast du mit den WGM Bits eingestellt. Dieser Modus bestimmt, wie und woher der Timer seinen Endwert nimmt. Um also die Frequenz zu verändern, muss dieser Endwert verändert werden. In welchem Register dieser Endwert steht, hängt vom Modus ab. Weiters benutzt du den Timer in einem Modus, in dem du das Blinken völlig eigenständig entsteht. Und genau das kannst du ja bereits: Je nach Schalterstellung Register zu verändern. Mit dem Datenblatt musst du jetzt nur noch das Zusammenspiel von ICR1 und OCR1A herausfinden.
hallo bin jezt mal vom timer1 auf timer0 umgestiegen , hier kann man das intervall viel einfacher progammieren ! so funktionierts jetzt auch mal ldi temp1, 0b00111111 ;bei 00001111 ist das intervall kürzer out OCR0, temp1 main: ldi temp1, 0<<COM01 | 1<<COM00 | 1<<WGM01 | 1<<CS01 out TCCR0, temp1 rjmp main hier kann man die led jedoch nur kurz blinken lassen . um die led z.b. 10sek aus - 3sek. ein - 10sek. aus usw. blinken zu lassen muss ich wohl wieder den timer1 benutzen -richtig ?? mfg stefan
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.