Hallo, ich bastle gerade ein Alarmierungssystem mit einem Atmega16 das 8 Schleifen überwacht und je nach dem bestimmte SMS über ein Handy verschickt. Jetzt möchte ich das Handy alle 30 Minuten nach dem Ladezustand fragen und entsprechend reagieren. Idee war es den 8bit Timer zu nutzen(da einfacher zu konfigurieren), bei Überlauf im der Interrupt-Routine eine 16bit Variable hochzählen zu lassen. Diese wird dann im Hauptprogramm mit einem einfachen if überprüft. Takt sind 16 MHz, Prescaler 1024 ergibt 15,625kHz. Bei 256 Zählschritten ergibt das alle 0,016384 s einen Überlauf. Macht das Sinn oder sollte ich den 16bit Timer nehmen, wobei ich auch hier immer noch die externe Zählvariable benötige. Gruß
Wenn das Handy den Rest der Zeit schläft auf jeden Fall einen 16-Bit-Timer nutzen, je seltener das Gerät aufwacht desto besser für den Akku. Mal nebenbei: 30*60/0,016384=~109000 > 2^16-1
Ich bin mir nicht sicher, ob du Murks gerechnet hast, oder ich einfach
nicht wach bin. Ich komme auf:
16 000 000 Hz Systemtakt
15 625 Hz Nach Prescaler von 1024
61 Hz Overflows
Eine in dem Overflow-Interrupt hochgezählte 8-Bit Zahl läuft also alle 4
Sekunden über.
Also alle 7 bis acht Overflows der eigenen Zählvariablen im Interrupt
die Aktion auslösen.
Oder?
42 schrieb: > Wenn das Handy den Rest der Zeit schläft Das sollte natürlich "der µC" heißen. Ich glaube der der nicht wach ist bin ich. :-(
Uh, ja, hab' nen Schritt im Kopf übersprungen. Ich habe also 61 Hz in der Interrupt Routine. Macht ca. alle 0,2 Sekunden. Hier zähle ich eine 8 bit Zahl hoch (meinetwegen temp1). 61Hz durch 256 macht ca. 4.4. Also habe ich alle 4.2 Sekunden einen "Überlauf" von "temp1". Wenn dem so ist, zähle ich "temp2" hoch. Wenn temp2 überläuft sind rund 18 Minuten vergangen. Das macht man zwei mal. Rund 30 Minuten. Wenn man das "T"-Flag noch nicht brauchte, kann man es nehmen, um die "zweite Rund temp2" anzuzeigen.
Wenn man die Register braucht, kann man die Zahlen, zwischendurch ins RAM schmeißen. Man braucht sie ja nur in der Interrupt-Routine.
42 schrieb: > Mal nebenbei: 30*60/0,016384=~109000 > 2^16-1 Hmm stimmt, das hab ich irgendwie beim Rechnen übersehen. :-) Den Controller einschlafen zu lassen ist momentan nicht geplant/umgesetzt. Bin gerade erst dabei micht in die Controllerprogrammierung einzuarbeiten. Der überprüft gerade in einer Endlosschleife die Eingänge. Momentanes Ergebnis der Diskussion: Benutze den 16bit Timer mit einer Zusatzvariablen. Wobei es doch dann eigentlich auch keinen Unterschied macht obe ich den 8 oder 16bit Timer benutzte, nur dass ich eben beim 8bit Timer eine größere Zusatzvariable zum Zählen benötige. Wichtig vielleicht noch, es ist nicht zwingend nötig die 30 Minuten einzuhalten. Ein paar Minuten hin oder her ist egal. Gruß
Ich hab hier mal die Timer1 Konfiguration eingestellt. Stimmt das dann so? Der Timer erzeugt dann alle 4 Sekunden ein Interrupt, der den zaehler1 um 1 erhöht. In der Hauptschleife frage ich zaehler1 ab. Bei zaehler1 größer gleich 449( was dann 4 Sekunden x 450 Zählschritten = 1800 Sekunden = 30 Minuten ergibt) wird der Ladezustand abgefragt.
1 | void main (void) |
2 | {
|
3 | ...
|
4 | uint8_t zaehler1=0; |
5 | TCCR1B |= (1<<WGM12); // CTC Modus einschalten, Vergleichen mit OCR1A |
6 | TCCR1B |= (1<<CS00) | (1<<CS02); // Prescaler 1024 |
7 | OCR1A=62499; //Vergleichszahl für Timer1 |
8 | TIMSK |= (1<<OCIE1A); // Compare Interrupt erlauben |
9 | |
10 | if (zaehler1>=449) |
11 | {
|
12 | zaehler1=0; //zaehler1 zurücksetzten |
13 | hier wird der Ladezustand abgefragt und entsprechend reagiert |
14 | }
|
15 | ...
|
16 | }
|
17 | |
18 | ISR (TIMER1_COMPA_vect) |
19 | {
|
20 | zaehler1++; |
21 | }
|
1) Wie soll denn der Interrupt eine lokale Variable verändern können? 2) Wie soll ein uint8_t jemals größer (oder gleich) 449 sein können? 3) Informiere dich über "volatile".
Oh man, manchmal hab ich echt Tomaten auf den Augen und nen Knoten im Hirn. Danke
Man sollte den Code dann doch kopieren und nicht einfach nochmal aus dem Kopf abschreiben... so siehts eigentlich aus:
1 | volatile uint16_t zaehler1=0; |
2 | |
3 | void main (void) |
4 | {
|
5 | ...
|
6 | TCCR1B |= (1<<WGM12); // CTC Modus einschalten, Vergleichen mit OCR1A |
7 | TCCR1B |= (1<<CS00) | (1<<CS02); // Prescaler 1024 |
8 | OCR1A=62499; //Vergleichszahl für Timer1 |
9 | TIMSK |= (1<<OCIE1A); // Compare Interrupt erlauben |
10 | |
11 | if (zaehler1>=449) |
12 | {
|
13 | zaehler1=0; //zaehler1 zurücksetzten |
14 | hier wird der Ladezustand abgefragt und entsprechend reagiert |
15 | }
|
16 | ...
|
17 | }
|
18 | |
19 | ISR (TIMER1_COMPA_vect) |
20 | {
|
21 | zaehler1++; |
22 | }
|
zaehler1 ist außerhalb der main-Schleife mit volatile als uint16_t deklariert und sollte doch somit global verfügbar sein oder? Gruß
Eine Kleinigkeit noch, die aber vermutlich weiter keine Rolle spielt: wenn du den Zähler bei >=449 zurücksetzt, hast du nur 449 Zählschritte, keine 450.
Ja stimmt, Danke. Ich hab jetzt aber nochmal ein Problem. Der Compiler mault: 207: error: static declaration of '__vector_6' follows non-static declaration 207: error: previous declaration of '__vector_6' was here 260: error: expected declaration or statement at end of input und ich kann nichts damit anfangen. Kann mir nochmal jemand dabei helfen? Der Code ist angehängt. Danke
Ok nochmals Danke. Ich hör glaub am besten für heute auf und mach was anderes. ;-)
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.