Guten Mittag meine Freunde, ich habe ein Problem:
Ich habe mir selbstverständlich alle gegebenen Anleitungen durchgelesen,
leider ist mir das mit dem Timer/Interrupt nicht ganz klar geworden.
ich habe 2 LEDS an meinen AtMega 8 angeschlossen (LED1 =^ PD6; LED2 =^
PD5)
sowie einen Taster (taster =^ PD2), nun mein Projekt:
Ich möchte, dass eine LED (PD6) leuchtet, sobald ich den Taster betätigt
habe. Damit beginnt auch der Timer zu laufen, der nach einpaar Stunden
(sagen wir 2) die andere LED (PD5) zum Leuchten bringt. Dann wieder 2
Stunden Pause, und die LED (PD5)soll wieder blinken. Währenddessen soll
die LED1 ununterbrochen die ganze Zeit leuchten.
Wie würdet ihr das in C schreiben? Ich bin damit leicht überfordert.
Ich bin erfreut über Tipps.
Vielen Dank
kopfkratz
Also wenn Du das Datenblatt nicht verstehst und dann noch die Tutorials
hier samt FAQ Timer von Karl-Heinz, dann solltest Du Dich entweder nach
einem anderen Hobby umsehen oder Deine Hausaufgabe mit dem Lehrer
besprechen :-P
Was Du brauchst:
1. Tastenentprellung (PeDa hilft da weiter)
2. Variable die den Tastendruck speichert
3. Timer der Dir die aktuelle Zeit in einer volatile Variable angibt
4. Hauptprogramm das beide Variablen entsprechend auswertet
Und nun ran an den Speck, egal ob in Assembler, BASIC, C, PASCAL oder
ZZZZZZZ :-P
kopfkratzer schrieb:> 2. Variable die den Tastendruck speichert
Okay, wieso muss der Tastendruck als solcher gespeichert werden?
Ich drücke den Taster, eine LED fängt an zu leuchten und der Timer geht
los. Ab da ist der Taster ja völlig uninteressant, da er nur einmal (zu
Anfang) betätigt wird/wurde.
> Vorteiler
Könntest du mir ne Beispielrechnung geben, wie ich die Maximaldauer
errechnen kann?
Danke
Oldie schrieb:> kopfkratzer schrieb:>> 2. Variable die den Tastendruck speichert>> Okay, wieso muss der Tastendruck als solcher gespeichert werden?> Ich drücke den Taster, eine LED fängt an zu leuchten und der Timer geht> los. Ab da ist der Taster ja völlig uninteressant, da er nur einmal (zu> Anfang) betätigt wird/wurde.>ROFLMAO
Gut dann ist es noch schlimmer als befürchtet.
Woher willst Du denn wissen das der Taster gedrückt wurde ?
Was soll denn passieren wenn während der 2 Stunden der Taster nochmal
gedrückt wird, wieder von vorne anfangen ?
Und jetzt erkläre mir mal bitte wie Du aus den beiden Timestamps die
zwei Stunden errechnen willst ?
Achja woher kommen die Timestamps ?
Besser nochmal beim Lehrer nachfragen ;-)
Oldie schrieb:> Ich drücke den Taster
Das denkst du, inwirklichkeit drückst du ihn mehrfach - ganz einfach
weil er prellt. Falls du über ein Speicher-Scope verfügst, kannst du den
elektrischen Part eines Tasterdrucks respektive Schalterbetätigung mal
ansehen. Du wirst dich wundern.
> Könntest du mir ne Beispielrechnung geben, wie ich die Maximaldauer> errechnen kann?
Man zählt mithilfe eines Timer eine Variable hoch und leitet davon die
tatsächlich gewünchte Zeit ab.
Oldie schrieb:> Okay, wieso muss der Tastendruck als solcher gespeichert werden?> Ich drücke den Taster, eine LED fängt an zu leuchten und der Timer geht> los.Oldie schrieb:> sowie einen Taster (taster =^ PD2), nun mein Projekt:> Ich möchte, dass eine LED (PD6) leuchtet, sobald ich den Taster betätigt> habe. Damit beginnt auch der Timer zu laufen, der nach einpaar Stunden> (sagen wir 2) die andere LED (PD5) zum Leuchten bringt. Dann wieder 2> Stunden Pause, und die LED (PD5)soll wieder blinken. Währenddessen soll> die LED1 {=PD6} ununterbrochen die ganze Zeit leuchten.
Grundzustand : Keine Taste gedrück, keine LED leuchtet (wahrscheinlich
ist das der Zustand nach dem Einschalten deines Controllers)
dann wird irgendwann die Taste gedrückt, Den Zustand "Taste ist
(verlässlich)gedrückt" bekommst du als Ergebniss deiner
Entprell-Routine. Das Betä#tigen der Taste führt zum sofortigen und
immerwährenden Leuchten von LED1, sowie zum "normalen Lampen-Geleuchte",
welche folgendes macht:
- abwarten, bis eine Zeit t1 abgelaufen ist
- am Ende der Zeit t1 die LED 2 statisch einschalten (so lese ich das
raus aus deinem post)
Wiederhole bis (unendlich)
- abwarten, bis eine Zeit t2 abgelaufen ist
- LED 2 ausschalten
- abwarten, bis eine Zeit t3 abgelaufen ist
- LED 2 blinkend einschalten
Ob oder was passiert wenn du die Taste nochmals drückst hast du nicht
angegeben. Daher wird diese hier auch nicht berücksichtigt
D. V. schrieb:> Man zählt mithilfe eines Timer eine Variable hoch und leitet davon die> tatsächlich gewünchte Zeit ab.
Ja, wenn ich jetzt den Vorteiler auf 1024 setze bei einem Takt von 1Mhz,
wie viel Zeit wäre das so "realZeit"?
kopfkratzer schrieb:> Und jetzt erkläre mir mal bitte wie Du aus den beiden Timestamps die> zwei Stunden errechnen willst ?
geht das nicht oder wie?
Wegstaben Verbuchsler schrieb:> Grundzustand : Keine Taste gedrück, keine LED leuchtet (wahrscheinlich> ist das der Zustand nach dem Einschalten deines Controllers)> dann wird irgendwann die Taste gedrückt, Den Zustand "Taste ist> (verlässlich)gedrückt" bekommst du als Ergebniss deiner> Entprell-Routine. Das Betä#tigen der Taste führt zum sofortigen und> immerwährenden Leuchten von LED1, sowie zum "normalen Lampen-Geleuchte",> welche folgendes macht:> - abwarten, bis eine Zeit t1 abgelaufen ist> - am Ende der Zeit t1 die LED 2 statisch einschalten (so lese ich das> raus aus deinem post)> Wiederhole bis (unendlich)> - abwarten, bis eine Zeit t2 abgelaufen ist> - LED 2 ausschalten> - abwarten, bis eine Zeit t3 abgelaufen ist> - LED 2 blinkend einschalten
Das ist es zu 100%. Genau das möchte ich erreichen! Also am besten wäre
es noch, wenn t4 existiert, und nach Ablauf dieser Zeitspanne wird die
LED 2 komplett abgeschaltet. Wenn ich den Taster nochmals drücke, soll
eigentlich nichts passieren (möglicherweise Reset des kompletten
Vorgangs, aber das ist kein Muss)
Oldie schrieb:> D. V. schrieb:>> Man zählt mithilfe eines Timer eine Variable hoch und leitet davon die>> tatsächlich gewünchte Zeit ab.>> Ja, wenn ich jetzt den Vorteiler auf 1024 setze bei einem Takt von 1Mhz,> wie viel Zeit wäre das so "realZeit"?>> kopfkratzer schrieb:>> Und jetzt erkläre mir mal bitte wie Du aus den beiden Timestamps die>> zwei Stunden errechnen willst ?>> geht das nicht oder wie?kopftisch
Was steht denn im Datenblatt des Mega8 bei Timer-OverFlow ?
Wie berechnet sich da die Frequenz ?
Nimm einen Taschenrechner und tippe da Deine aktuelle Frequenz und den
Vorteilerfaktor ein, was für einen Wert bei 1024 hast Du dann ?
Statt Dein angestrebtes Programm empfehle ich Dir erstmal Dich solange
mit Timer0 zu beschäftigen bis Du in der Lage bist EINE LED im
ungefähren Sekundentakt blinken zu lassen.
Dazu brauchst Du eine Zählervariable, besser nimm gleich drei für
Sekunden, Minuten und Stunden.
Du mußt mit der Formel im Datenblatt den ungefähren Sekundenwert
ausrechnen und dann eine volatile Variable damit in der ISR beschicken.
Die dann auf Minuten und Stunden umzubrechen ist in C trivial, wenn man
denn weiß wie es geht ...
Also besser in die nächste Bücherei und sich ein C-Buch holen um das
auch wirklich durchzuarbeiten.
Wenn dann der Groschen wegen modulo&Co. gefallen ist und Du außer "Hallo
Welt" auch z.B. den Verbrauch Deines Mopeds korrekt ausrechnen kannst
geht's weiter ;-)
Es führen zwar alle Wege nach Rom das wurde aber nicht an einem Tag
erbaut :-P
Also, ich habe eine angestrebte Periodendauer von t=7200s (2h)
Und bei einem Takt von 4Mhz und einem Vorteiler von 1024 wäre die
längstmögliche Periodendauer t0 = ca. 0,0655s.
Dann bruache ich von t0 insgesamt 101000 Perioden um meine 2 Stunden zu
erreichen, ist das richtig?
Aaalso, mein Problem ist folgendes: ich verstehe nicht, wie ich 2
Stunden im Timer erreiche. Ist es machbar, bei einem Takt von 4 MHZ
einen prescaler von 1024 zu benutzen und dann irgendwo mitzählen zu
lassen, wie oft ein Interrupt ausgelöst wurde? Also so: 4Mhz mit 1024er
Prescaler läuft, dann beginnt er wieder bei 0, wenn ein Durchlauf
vollbracht ist und simultan dazu wird in irgendeinem Register
mitgezählt, wie viele Durchläufe gemacht wurden. Und wenn die
Durchlaufanzahl einer vorher definierten entspricht, wird ein anderes
Ereignis ausgelöst. ist das möglich?
Oldie frug:
>ist das möglich?
Na freilich ist das möglich, aber die Ausgangswerte sind nicht so gut
gewählt, um 1Hz zu erzeugen.
Es geht mit hier mit 4MHz los, die vom Vorteiler durch 1024 geteilt
werden.
Das heißt, daß der eigentliche Zähler dann mit 3906,25 Hz getaktet wird.
Wenn Du Timer 0 benutzt, dann hat der (8-Bit Timer) 256 Zählschritte,
bevor er "einmal rum" ist.
Das heißt nun: Die 3906,25 Hz werden durch 256 geteilt. Das wären dann
15,25... Hz.
Das wird Mumpitz....
Besser ist es, ganzzahlige Verhältnisse zu schaffen: Nimm 256 als
Vorteiler.
Dann hast Du 4MHz/64= 62500 Hz.
Man muß im Interrupt dann eine Hilfsvariable die Anzahl der Interrupts
zählen lassen und wenn die entsprechende Zahle erreicht ist, eine Aktion
auslösen:
Hinweis, bevor hier wieder sinnloses Genöle kommt:
Man KANN den Timer auch im CTC-Modus betreiben und braucht ihn dann
nicht vor zu laden. Das dient hier nur zur besseren Verständlichkeit:
Danke! Nur habe ich folgende Fragen: wo kommen die 250 her? Also woher
weiß ich dass der Timer mit 250 Hz taktet?
Und: Wie funktioniert das mit dem Umlauf genau? Du hast ihn jetzt als
250 definiert, heißt das, dass er bis 250 zählt und dann ein Ereignis
auslöst? Danke
>Nur habe ich folgende Fragen: wo kommen die 250 her? Also woher>weiß ich dass der Timer mit 250 Hz taktet?
Die 250 kommen daher, daß der Timer vom Wert 6 (mit dem er vorgeladen
wurde) aufwärts bis zum Überlauf zählt. Er macht also nicht 256 Ticks,
sondern nur 250.
Warum 250?
Weil 250*250=62500 ist.
Jetzt brauchen wir noch einen "zweiten Mann", der auch bis 250 zählen
kann.
Das ist die Variable "Umlauf", die aber hier nicht aufwärts gezählt
wird,
sondern von 250 aus "runterwärts".
>Wie funktioniert das mit dem Umlauf genau? Du hast ihn jetzt als>250 definiert, heißt das, dass er bis 250 zählt und dann ein Ereignis>auslöst?
Im Interrupt wird die Variable "Umlauf", die zu Anfang auch auf 250
gesetzt
wurde, um 1 dekrementiert. Wenn Umlauf 0 ist, dann hat es 250 mal einen
Interrupt gegeben.
MfG Paul
Wir müssen hier fort, weil das die Codesammlung ist, die normalerweise
nicht zum Fragen-stellen erlaubt ist....
Oldie schrieb:> Danke! Nur habe ich folgende Fragen: wo kommen die 250 her? Also woher> weiß ich dass der Timer mit 250 Hz taktet?
Weil du dann im Zusammenspiel mit dem Vorteiler auf eine ganzzahlige
Zahl kommst, wie oft der Timer-Interrupt pro Sekunde ausgelöst wird. Die
250 hast du frei gewählt, weil das in der Nähe von 256 liegt und sich
mit einem der Vorteiler schön ausgeht.
> Und: Wie funktioniert das mit dem Umlauf genau? Du hast ihn jetzt als> 250 definiert, heißt das, dass er bis 250 zählt und dann ein Ereignis> auslöst?
Nein.
Von alleine löst da überhaupt nichts aus.
WEnn die ISR 250 mal in der Sekunde aufgerufen wird, dann zählt man eben
bei jedem Aufruf eine Variable um 1 hoch (oder runter). Ist die Variable
bei 250 angelangt (bzw bei 0, wenn runter gezählt wird), dann ist 1
Sekunde vergangen. Denn der Interrupt wird ja 250 mal in der Sekunde
ausgelöst.
Die Variable ist genau jene 'Umlauf'
Oldie schrieb:> Wenn ich den Taster nochmals drücke, soll> eigentlich nichts passieren (möglicherweise Reset des kompletten> Vorgangs, aber das ist kein Muss)
Überleg dir das gut!
Wenn bei einem weiteren Tastendruck nichts mehr passieren soll, hast du
Glück. Du brauchst keine Tastendruckerkennung samt Entprellung. Im
zweiten Fall benötigst du sie aber.
Auch solltest du mal darüber nachdenken, wie es dann eigentlich weiter
geht, wenn die Zeiten abgelaufen sind. Was passiert dann? Wie kommt die
Schaltung wieder in den Grundzustand?
Also, ich ersetze den Taster durch einen Schließer, sodass bei Drücken
des Schließers einfach der Stromfluss aktiviert wird. Das sollte alles
erleichtern.
Karl Heinz schrieb:> WEnn die ISR 250 mal in der Sekunde aufgerufen wird, dann zählt man eben> bei jedem Aufruf eine Variable um 1 hoch (oder runter). Ist die Variable> bei 250 angelangt (bzw bei 0, wenn runter gezählt wird), dann ist 1> Sekunde vergangen. Denn der Interrupt wird ja 250 mal in der Sekunde> ausgelöst.> Die Variable ist genau jene 'Umlauf'
Wenn bei 250 eine Sekunde vergangen ist, dann sind bei 900000 Interrupts
ja eine Stunde vergangen. Ich wollte am Anfang ja ein Auslösen eines
Ergebisses bei 1800000 Interrupts. Ich kann aber nicht einfach sagen,
dass bei 1800000 Interrupts ein Ergebnis ausgelöst werden soll, da der
Controller nur 255 mal zählen kann, richtig? Wie sorge ich jetzt dafür,
dass er 1800000 mal zählen kann? Danke
Oldie schrieb:> Wenn bei 250 eine Sekunde vergangen ist, dann sind bei 900000 Interrupts> ja eine Stunde vergangen. Ich wollte am Anfang ja ein Auslösen eines> Ergebisses bei 1800000 Interrupts. Ich kann aber nicht einfach sagen,> dass bei 1800000 Interrupts ein Ergebnis ausgelöst werden soll
Können tust du schon.
Musst halt für die Variable eine anderen Datentyp nehmen.
Aber ...
> , da der> Controller nur 255 mal zählen kann, richtig? Wie sorge ich jetzt dafür,> dass er 1800000 mal zählen kann? Danke
Wie machen wir es denn im täglichen Leben?
Wir zählen ja auch nicht die Sekunden seit Mitternacht. Sondern:
60 Sekunden sind 1 Minute
60 Minuten sind 1 Stunde.
Kein Mensch sagt, dass du Zeiten nur in einer einzigen Variablen zählen
darfst. Nimmst du halt 3 davon. Eine für Sekunden, eine für Minuten,
eine für Stunden.
(Wobei man Stunden eventuell nicht braucht. 120 Minuten geht gerade
noch, so dass sich jeder darunter 2 Stunden vorstellen kann)
Karl Heinz schrieb:> Kein Mensch sagt, dass du Zeiten nur in einer einzigen Variablen zählen> darfst. Nimmst du halt 3 davon. Eine für Sekunden, eine für Minuten,> eine für Stunden.
Hohoho, also schummel ich mich zu den 1800000 Interrupts? :D
Ungefähr so vom logischen:
Wenn 250 Interrupts (1s) ausgelöst, zähle irgendeine Variable (s) hoch
bis 60.
Wenn s = 60; gehe wieder zurück zu s = 0, aber setze Variable m + 1
Wenn m = 120; aktiviere LED an PortD
So vom logischen?
Oldie schrieb:> Karl Heinz schrieb:>> Kein Mensch sagt, dass du Zeiten nur in einer einzigen Variablen zählen>> darfst. Nimmst du halt 3 davon. Eine für Sekunden, eine für Minuten,>> eine für Stunden.>> Hohoho, also schummel ich mich zu den 1800000 Interrupts? :D
Was heißt da schummeln.
Jede Wald und Wiesen Nasenpopel Uhr arbeitet nach diesem Prinzip. So
funktinoniert nun mal unsere Zeitrechnug. Ich seh keinen Grund, warum
man dieses Prinzip nicht bernehmen soll. Hat sich seit über 2000 Jahren
bewährt.
Und nur weil du auf große Zahlen, wie 1.8 Mio Interrupts abfährst, muss
das nicht für jeden gelten. Ich stell meine Abfrage lieber auf 120
Minuten ein, als auf 1.8 Mio Interrupts. Das kommt auch besser, wenn man
mal statt 2 Stunden nur deren anderthalb braucht. Denn das kann ich im
Kopf rechnen, dass das 90 minuten sind. Wieviele Interrupts das sind,
ist mir hingegen völlig wurscht. Das ergibt sich sowieso von alleine,
bis dann irgendwann mal 90 Minuten erreicht sind.
brauchst du es noch länger? Ein paar Stufen mehr gingen noch, bis du auf
dem Alter des Universums bist.
Immerhin: wenn der letzte Dinosaurier auf den Knopf gedrückt hätte, dann
würde das klappen, das heute das Licht angeht. 65 Millionen Jahre sind
damit schon locker drinnen.
Muchas Gracias! Ich habe nun die Sache mit den Interrupts und der
Zeitrechnung verstanden. Nur stellt sich mir immer von Code-technisch
diese Frage: Ich habe nun definiert, nach 2 Stunden ein Ereignis
ausgelöst werden soll. wie stelle ich das dar?
Oldie schrieb:> Muchas Gracias! Ich habe nun die Sache mit den Interrupts und der> Zeitrechnung verstanden. Nur stellt sich mir immer von Code-technisch> diese Frage: Ich habe nun definiert, nach 2 Stunden ein Ereignis> ausgelöst werden soll. wie stelle ich das dar?
entweder so wie du schreibst, das du eben die Minuten mit 120
vergleichst, oder was ich immer gerne mache: ich dreh den Spiess um um
mach eine Countdownuhr, die von einer bestimmten Zeit auf 0 runter zählt
und dann eben schaltet, wenn 0 erreicht ist. Ist sicherlich
Geschmackssache, aber ich hab immer das Gefühl, dass ich bei einer
Countdown-Uhr besser mit mehreren Zeiten im Programm umgehen kann, weil
der Endpunkt des Countdowns ja immer 0 ist und ich einfach nur
unterschiedliche Startzeiten zuweisen muss.
1
volatileuint8_tMinuten;
2
volatileuint8_tSekunden;
3
4
ISR(...)
5
{
6
staticuint8_tsubCnt;
7
8
subCnt++;
9
if(SubCnt==250)
10
{
11
subCnt=0;
12
if(Sekunden>0)
13
Sekunden--;
14
15
else
16
{
17
Sekunden=59;
18
19
if(Minuten>0)
20
Minuten--;
21
22
else
23
// ... Schalte LED aus ...
24
PORT.....
25
}
26
}
27
}
28
29
intmain()
30
{
31
...
32
33
while(1)
34
{
35
if(Tastergedrückt&&Minuten==0)
36
{
37
// ... Schalte LED ein ...
38
PORT.....
39
40
// Countdownzeit setzen
41
cli();
42
Sekunden=0;
43
Minuten=120;
44
sei();
45
46
// jetzt läuft die Uhr und zählt die 120 Minuten runter
47
// sind die abgelaufen, dann wird die LED wieder abgeschaltet
48
}
49
}
50
}
Ob man jetzt den Schaltvorgang in der ISR macht oder im Hauptprogramm
hängt davon ab, wie kompliziert die abhängige Operation ist. Hier ist
das einfach, eine LED wird abgeschaltet. Das kann man genausogut in der
ISR machen. Bei komplizierteren Aktionen, setzt man sich dann eben ein
Flag, dass die Zeit abgelaufen ist und wertet das dann in der
Hauptschleife aus.
Dieses Grundrezept kann noch beliebig variiert werden. Zb mt mehreren
'Zählvariablen' können auch mehrere 'Countdownds' parallel laufen. Zb
ein 5 Sekunden Countdown, der eine andere LED gleichzeitig blinken
lässt. Oder mehrere Taster, die 'gleichzeitig' unterschiedliche
Zeiträume auf unterschiedlichen LEDs realisieren. etc. etc.
Wie gesagt: denk dir was aus! Wie würdest du das ganze mit Papier,
Bleistift und einem Summer machen, der im Sekundentakt einen Ton von
sich gibt. Der sekündliche Ton entspricht dem Teil in der ISR
1
ISR(...)
2
{
3
4
subCnt++;
5
if(subCnt==250)
6
{
7
subCnt=0;
8
9
....hieristderSekundentakt
10
11
}
12
}
und mit den gleichen Strategien, mit denen du in der Realität auch
operierst, operierst du auch hier. Das ist im wesentlichen nichts
anderes. Nur eben in einer Programmiersprache ausformuliert. Und geh
davon aus, dass du ein furchtbar schlechtes Gedächtnis hast. Alles was
du dir eigentlich merken müsstest (aber wegen des schlechten
Gedächntisses nicht kannst), musst du dir eben aufschreiben (daher
Papier und Bleistift). Im Programm ist das dann eben eine Variable. Und
ja, wenn das bedeutet, dass du dir am Papier notieren musst, ob die LED
jetzt blinken oder Dauerleuchten soll, dann bedeutet das eben das du das
'niederschreiben' musst, oder eben in einer Variablen festhalten, was
die LED jetzt eigentlich tun soll (0 ist blinken, 1 ist Dauerleuchten,
oder so) und du die Variable 'befragen' musst, was jetzt eigentlich
passieren soll.
Aber mach dir um Gottes Willen immer vorher die Strategie klar, die du
anwenden willst. Du kannst dir als 'Ideenlieferant' dich selber nehmen.
Denn du kannst das alles perfekt im wirklichen Leben. Einfach hinsetzen
und drauflosprogrammieren hingegen führt normalerweise ins Desaster. So
gut bist du noch nicht, dass das klappen würde. Erst mal brauchst du
immer einen Plan. Und am besten skizzierst du dir diesen Plan erst mal
in einfachen Worten.
Okay dann mach ich das erstmal komplett in Worten:
Es gibt:
LED1
LED2
Timer0
Schließer
Wenn Schließer aktiviert, dann leuchtet LED1 ununterbrochen.
Parallel dazu startet Timer0.
Der Takt von 4Mhz wird durch einen Prescaler von 64 geteilt.
Das bedeutet: 250 abgelaufene Interrupts ^= 1 Sekunde.
Wenn 1 Interrupts abgelaufen, dann inkrementiere Variable interrupts um
1.
Wenn Variable Interrupts bei 250, dann inkrementiere Variable Sekunde
UND
setze Variable Interrupts zurück auf 0, aber lass ihn weiterzählen.
Wenn Sekunde bei 60, setzte zurük auf 0 und inkrementiere Variable
Minute.
Wenn Minute = 120, dann leuchtet LED2 auf.
Wenn Minute = 140, dann beende leuchten von LED2 + Beende kompletten
Vorgang.
Ist das so richtig?
Achja uuund: Kann ich die eine LED dauerhaft leuchten lasse, indem ich
das einfach in den Code schreibe, oder muss ich das auch irgendwie immer
wiederholen?
Oldie schrieb:> Achja uuund: Kann ich die eine LED dauerhaft leuchten lasse, indem ich> das einfach in den Code schreibe, oder muss ich das auch irgendwie immer> wiederholen?
Die LEDs sind ja an einem auf "Ausgang" geschalteten Port angeschlossen.
Zum Ein- bzw. Ausschalten setzt man das entsprechende Port-Bit auf den
gewünschten Zustand. Der Zustand wird dort gespeichert und bleibt
solange erhalten, bis er vom Programm geändert (überschrieben) wird.
Wenn also das Programm am Port nicht "rummacht", ändert sich die LED
nicht.
Gruß Dietrich
Danke!
> Wenn Schließer aktiviert, dann leuchtet LED1 ununterbrochen.> Parallel dazu startet Timer0.> Der Takt von 4Mhz wird durch einen Prescaler von 64 geteilt.> Das bedeutet: 250 abgelaufene Interrupts ^= 1 Sekunde.> Wenn 1 Interrupts abgelaufen, dann inkrementiere Variable interrupts um> 1.> Wenn Variable Interrupts bei 250, dann inkrementiere Variable Sekunde> UND> setze Variable Interrupts zurück auf 0, aber lass ihn weiterzählen.> Wenn Sekunde bei 60, setzte zurük auf 0 und inkrementiere Variable> Minute.> Wenn Minute = 120, dann leuchtet LED2 auf.> Wenn Minute = 140, dann beende leuchten von LED2 + Beende kompletten> Vorgang.
Ist das richtig?
Oldie schrieb:> Danke!>>> Wenn Schließer aktiviert, dann leuchtet LED1 ununterbrochen.>> Parallel dazu startet Timer0.>> Der Takt von 4Mhz wird durch einen Prescaler von 64 geteilt.>> Das bedeutet: 250 abgelaufene Interrupts ^= 1 Sekunde.>> Wenn 1 Interrupts abgelaufen, dann inkrementiere Variable interrupts um>> 1.>> Wenn Variable Interrupts bei 250, dann inkrementiere Variable Sekunde>> UND>> setze Variable Interrupts zurück auf 0, aber lass ihn weiterzählen.>> Wenn Sekunde bei 60, setzte zurük auf 0 und inkrementiere Variable>> Minute.>> Wenn Minute = 120, dann leuchtet LED2 auf.>> Wenn Minute = 140, dann beende leuchten von LED2 + Beende kompletten>> Vorgang.>> Ist das richtig?
Du wirst nie weiter kommen, wenn du immer eine Tante zum lulu gehen
brauchst.
Du hast den µC vor dir, du hast deine Entwicklungsugebung vor dir.
Probiers aus. Nicht funktionierende Programme gehören genauso dazu, wie
runterfallen zum radfahr-lernen dazugehört.
Kaputt machen kannst du nichts. Im schlimmsten Fall funktionierts
einfach nicht. Arbeite in SChritten und setz erst mal kleinere Zeiten
an. Ob da letzten Endes 2 Minuten steht oder 120, das ist nur eine Zahl.
Aber 2 Minuten (oder noch kürzer) ist für dich in der Enwicklungsphase
erlebbar. 120 ist es nicht.
Und was soll dieses Konglomerat aus zusammenkopiertem Code sein?
Wo ist deine ISR?
Welcher Codeteil gehört in die ISR?
Du solltest wirklich erst mal mit was einfacherem anfangen. Das kann ein
Blinder greifen, dass du mit dieser Aufgabenstellung noch heillos
überfordert bist. Auch einfaches zusammenkopieren von Code will gelernt
sein. Solange man nicht versteht, was man da tut, wird das nichts.
Okay, also ich bin Schritt für Schritt vorgegangen:
Als erstes habe ich ganz stumpf versucht, eine LED leuchten zu lassen.
1
#define F_CPU 1000000UL /* 1MHz */
2
#include<avr/io.h>
3
// Defines:
4
#define LED1 (1<<PD5)
5
#define LED2 (1<<PD6)
6
intmain()
7
{
8
// LED-Pins als Ausgang definieren
9
DDRD|=LED1|LED2;
10
11
// LED1 einschalten
12
PORTD|=LED1;}
Hat funktioniert, ein Schritt nach vorne.
Das mit dem Timer habe ich mittlerweile auch begriffen, nur ist mir
folgendes immer noch ein Rätsel:
Was bedeutet dieses ISR? Mag nun plump erscheinen, aber diese Frage
quält mich.
Was hat es damit auf sich? Was macht man damit, bzw. wofür ist es gut?
Danke!
Oldie schrieb:> Was bedeutet dieses ISR?
- ISR = Interrupt Service Routine
- Interrupt: ein Hardware-Ereignis, dass den Programmablauf unterbricht
und die ISR anspringt. Am Ende der ISR kehrt der Prozessor wieder an die
Stelle zurück, wo das Hauptprogramm unterbrochen wurde.
- Bei der hier beschriebener Anwendung ist es der Timer (ein Stück
selbständig arbeitende Hardware innerhalb des Mikrocontollers), der z.B.
bei Überlauf den Interrupt auslöst.
- Der Timer wird also am Anfang des Hauptprogramms entsprechend
konfiguriert (durch Einträge in verschidenen Steuerregistern des
Timers), dass er z.B. jede Millisekunde eine Interrupt auslöst. Ab
diesem Zeitpunkt ist der Interrupt aktiv und die ISR wird jede
Millisekunde abgearbeitet - unabhängig vom Hauptprogramm.
Ansonsten solltest Du z.B. mal hier lesen:
http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Programmieren_mit_Interrupts
Gruß Dietrich
Okay Leute, ich habe eine Bitte an euch:
Vom Ding her habe ich das ganze jetzt mehr oder weniger verstanden, nur
bräuchte ich mal einen von euch, der, wenn er die Zeit findet und ein
bisschen Lust hat, mir diesen Code schreibt, damit ich das ganze
wirklich nachvollziehen kann, da ich noch Probleme damit habe, die
einzelnen Abfolgen richtig aufzuschreiben.
>> Atmega8>> Wenn Schließer aktiviert, dann leuchtet LED1 ununterbrochen.>> Parallel dazu startet Timer0.>> Der Takt von 4Mhz wird durch einen Prescaler von 64 geteilt.>> Das bedeutet: 250 abgelaufene Interrupts ^= 1 Sekunde.>> Wenn 1 Interrupts abgelaufen, dann inkrementiere Variable interrupts um>> 1.>> Wenn Variable Interrupts bei 250, dann inkrementiere Variable Sekunde>> UND>> setze Variable Interrupts zurück auf 0, aber lass ihn weiterzählen.>> Wenn Sekunde bei 60, setzte zurük auf 0 und inkrementiere Variable>> Minute.>> Wenn Minute = 120, dann leuchtet LED2 auf.>> Wenn Minute = 140, dann beende leuchten von LED2 + Beende kompletten>> Vorgang.
Also eben, dass von Anfang an LED1 (1<<PD5) leuchtet und dass dabei der
Timer läuft, der dann nach 2 Stunden (kann man dann ja noch ändern in
weniger) LED2 (1<<PD6) anfängt zu leuchten. Wenn es dann aber zu 140
Mintuen gekommen ist, geht LED2 wieder aus. LED1 leutet ununterbrochen.
Wie gesagt, wenn mir einer helfen würde, wäre ich extrem begeistert und
er wäre der netteste Mensch der Welt, ich bräuchte das einfach mal, um
es nachzuvollziehen. Bitte keine Kommentare á la "Mach's dir selbst du
BOB", VIELEN DANK!
Oldie schrieb:> Ist die LED jetzt nur bei minute == 2 an oder auch danach? Wie sag ich,> dass er die LED auch danach noch anlassen soll?
Aus deinen Vorstudeien solltest du eigentlich schon gelernt haben, dass
normale Output Port Pins nicht eigenmächtig ihren Zustand ändern.
Wenn du daher hier
1
PORTD|=LED2;
den Pin auf 1 schaltest, dann bleibt der auch auf 1, weil es im ganzen
Programm keine Anweisung gibt, die ihn wieder ausschalten würde.
Im übrigen hättest du dir die Frage ganz leicht selbst beantworten
können. D.h. der Mega hätte sie dir beantwortet. Brenn das Programm
rein, lass es laufen und sieh nach wie es sich verhält.
Genau deswegen schreibt dir das auch keiner, obwohl es für dir meisten
eine Kleinigkeit ist. Wir sind hier kein kostenloses Entwicklungsbüro.
In erster Linie eignest du dir die Kenntnisse an und schreibst das
Programm. Wenn es momentan noch zu schwer ist, dann schalt 3 Gänge
zurück und fang mit etwas einfacherem an. Dann erhebt sich auch die
Frage nicht mehr, ob und wie lange ein Portpin nach dem Setzen auf 1
auch auf 1 bleibt. Dann WÜSSTEST du nämlich, dass er das tut. Und zwar
so lange, bis eine Anweisung ausgeführt wird, die den Pin wieder auf 0
setzt. Gibt es keine, dann bleibt der Pin bis zum St. Nimmerleinstag auf
1.
Warum hast du denn jetzt noch Millisekunden eingebaut?
am besten fängst du jetzt mal an selbst zu Coden und nicht nur
unverstandenes zusammen zu kopieren.
und wenn es nicht klappt übst du erstmal ganz normale interrupts mit
LEDs und blinken mit nem Timer und dann geht's weiter.
Hallo,
ich habe mir den Code nur kurz überflogen:
kannst du mir sagen welchen wertebereich unsigned int hat?
(Tip die antwort wird nahe an deimen Problem liegen warum es nicht das
tutst was du dir gedacht hast.
Und ich schließe mich den anderen an, ganz langsam. Und am besten
anderen Quellcode nicht abkopieren sondern abschreiben (ich weiß man
kommt sich blöd vor) und wenn man eine Zeile nicht versteht in der C
referenz bzw. dem Datenblatt nachgucken.
Mfg
shee2e
>Und am besten anderen Quellcode nicht abkopieren sondern abschreiben
Ich möchte an dieser Stelle widersprechen. Das entscheidende ist nicht,
ob der Code nun kopiert oder abgeschrieben wird. Das entscheidende ist,
dass man einen Code, Ausdruck für Ausdruck, Zeile für Zeile, Schleife
für Schleife nachvollzieht. Unterläßt man das aber dann ist abschreiben
oder kopieren gleichermaßen sinnlos.
Der Rat, Code nicht einfach nur zu kopieren, bezieht sich demgemäß im
Besonderen auf solche Frager hier, die schon Code kopiert haben und das
Nachvollziehen unterlassen haben.
Man mag darüber verschiedener Meinung sein, ob nicht der Rat den Code
nachzuvollziehen sinnvoller sei. Aber es ist für den Leser dann sicher
einfacher einen Code anzusehen und zu erkennen ob der Code verstanden
worden ist, als die sprachlich an sich schon nicht einfache Beschreibung
des Fragers zu untersuchen. Deswegen ist der Rat Code lieber von Grund
auf selbst zu schreiben effektiver.
Hallo,
ja ok kopiert oder abgeschreiben ist eigentlich egal, aber nachvollzogen
sollte es werden. Da ist das abschreiben für mich besser da ich damals
das sicher jede Zeile durchgeganen bin und in dem Fall, dass ich es
nicht verstanden habe, sofort nachgeschlagen habe.
MfG
shee2e
Jon Doe schrieb:> sollte es werden. Da ist das abschreiben für mich besser
Ist bei mir ähnlich.
Wenn ich etwas abschreibe, dann bleibt es nicht aus, dass man sich
während des Schreibens bereits erste Gedanken macht. Und sei es nur,
dass man die generelle Struktur erkennt bzw. ganz nebenbei anfängt die
im Programm verwendeten Begriffe bzw. die Nomenklatur sich zu merken.
Den Code durchgehen ist zweifellos unabdingbar. Trotzdem ist abschreiben
(überhaupt bei so kurzen Programmen) zumindest bei mir in dieser
Hinsicht wesentlich effektiver als einfach nur kopieren mittels
Copy&Paste.
An sich liegt, zumindest meiner Ansicht nach, das Nachvollziehen sowieso
schon sehr nahe; meint: man sollte sowieso auf die Idee kommen das zu
tun.
Nun, ich wollte darauf hinaus, das jemand der Code kopiert hat und ihn
offensichtlich nicht verstanden hat, vermutlich dazu neigt, ihn auch
dann nicht nachzuvollziehen wenn er ihn abschreibt.
Das jemand wie Du, Karl-Heinz, den Code nachvollzieht, den er
abschreibt, bezweifle ich dagegen keinen Augenblick.
Das Tutorial auf dieser Seite ist imho wirklich sehr gut zum Lernen der
notwendigsten Dinge. Arbeite doch da erstmal los und du wirst erstaunt
sein, wie einfach dein Problem nach ein paar verstandenen Grundlagen
ist...