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
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
Eine eigene Frage?
Dieser Thread ist über 18 Jahre alt.
Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.