Hallo, wie kann ich einen TimmerX auf 120sekunden einstellen. Ich habe eine Anweisung(siehe unten) wo ich jede 120s in die Anweisung rein möchte. if(Timerx > 120sec) (...) Fosc/4 = 1Mhz...Vorteiler auf 1/8..z.B Timer1(16Bit) 65536 sind es laut meiner Rechnung TMRx = [1MHz/(8*65536)] = 524ms Besten Dank JN
:
Verschoben durch Moderator
Kann hinkommen. Den Timer bekommst du prinzipiell nur auf einen gewissen Maximalwert gestellt (irgendwelche Millisekunden). Brauchst du größere Zeitabstände musst du in der ISR eine Variable hochzählen und das dann somit in Software machen. Auf diese Variable kannst du dann prüfen oder ein Flag setzen.
Dominik S. schrieb: > Kann hinkommen. > Den Timer bekommst du prinzipiell nur auf einen gewissen Maximalwert > gestellt (irgendwelche Millisekunden). > Brauchst du größere Zeitabstände musst du in der ISR eine Variable > hochzählen und das dann somit in Software machen. > Auf diese Variable kannst du dann prüfen oder ein Flag setzen. Kannst du das an einem Beispiel erläutern? Mfg
Naja... im einfachsten Fall:
1 | volatile uint16_t counter; |
2 | |
3 | ISR_100ms /* timer overflow interrupt, wird alle 100ms ausgelöst */ |
4 | {
|
5 | counter++; |
6 | }
|
7 | |
8 | int main(void) |
9 | {
|
10 | while(1) |
11 | {
|
12 | if(counter > 1200) /* sekunden mal 10, da 10 Interrupts pro Sekunde */ |
13 | {
|
14 | /* blub */
|
15 | counter = 0; |
16 | }
|
17 | }
|
18 | }
|
Den Timer so einstellen, dass du alle 100ms einen Überlauf hast. In der ISR hochzählen. counter/10 sind dann deine vergangenen Sekunden. Gibt natürlich noch diverse andere Umsetzungen. Du musst nur in irgend einer Form in deiner Software mitzählen wie oft der Timer schon übergelaufen ist (wie oft also schon 100ms vergangen sind).
Hi Dominik, danke für deine Hilfe, ich habe daraus so etwas wie unten ableiten können! Kannst du es mir eventuell korrigieren! :)) if(TMR0IE && TMR0IF) { counter++; if(counter==229) // 524ms * 229 = 120s { Schwellwert = ADCWert - offset;// Nach 120s neues Schwellwert counter=0; //Reset Counter } //Clear Flag TMR0IF=0; } } würde das so funktionieren? Mfg
Jesus Nvs schrieb: > würde das so funktionieren? Kann ich dir so direkt leider nicht sagen, da ich mich mit den PICs gar nicht auskenne. In die innere If-Bedingung schreib besser >= statt ==. Es sollte zwar nicht passieren (können) aber wenn counter jetzt irgendwie doch mal auf >230 rutscht verpasst du es nicht. Was die äußere If-Abfrage macht weiß ich natürlich nicht so genau ("TMR0IE && TMR0IF"). Ich würde vermuten außen rum muss statt der If-Abfrage eher eine ISR (Interrupt Service Routine), wie oben zu sehen. Diese wird angesprungen sobald ein Interrupt auf tritt. Kann aber natürlich sein, dass das Konstrukt was PIC-spezifisches ist.
Timer1 mit Quarz 32768 betreiben, maximaler Vorteiler, macht 2 Sekunden. Einen Zähler bis 60 zählen lassen ...
Ja geht, kommt natürlich in den Interrupt Code rein. vor counter solltest du "static char" machen. Und auch wenn es geht, wäre etwas anderes generell besser. if (!counter--) { /* code */ ; couner = 229 } In diesem Falle wird nähmlich der Wert nach dem ersten Überlauf oder Interrupt. Man kann einen Interrupt auch mittels das Setzen von TMR0IF selbst forzieren, ansonsten würde der Wert erst nach 120 Sekunden übernommen, was zu Kopfzerbrechen führen könnte. Bei mir kommt dieser Wert raus: 228,8818359375 Wenn du den genau haben möchtest, dann sollte counter eine 16bit Variable sein und du müsstes bei jedem Interrupt den Wert 286 zuzählen, sowie einen Startwert von 42 haben. Dann hast du keinen kummulativen Fehler. In diesem Falle solltest counter += 286; if (C) { /* code */ ; counter = 42; } Um dabei auch wieder gleich zu beginn eine Übername zu haben müsstest du sowas haben: static unsigned short counter = -286; // angenommen short = 16bit. Und C ist das Carry Flag vom Status Register, wegen Überlauf sollte es nicht bekannt sein.
Habe hier nur den Windows Taschenrechner und der streikt, wenn du es ganauer haben willst, schreib es und dann rechne es ich dir aus, die 16bit Rechnung oben stimmt nähmlich nicht.
#define cpu_clock 8000000/4 //--- OSCCON: OSCILLATOR CONTROL REGISTER OSCCONbits.IRCF = 0b111; OSCCONbits.SCS= 1; void pause_sek(uint16_t sek_temp) { while(sek_temp != 0) { pause_ms(1000); sek_temp--; } } void pause_ms(uint16_t ms_temp) { TMR0 = 0; uint32_t temp_1 = (((cpu_clock / 256) * ms_temp) / 1000); while(TMR0 < temp_1) {}; }
@pic Du schreibst ---wird nähmlich der Wert--- und ---stimmt nähmlich nicht--- Das ist ziemlich dämlich.
Tja passiert manchmal. Wie gesagt, das von dir gepostete sollte funktionieren, hat aber das Problem daß die ersten 120 Sekunden nichts passiert. Weiters brauchst du nur eine 8bit variable und keine 16bit, auch solltest du diese, wenn nicht extern gebraucht einfach als static in der Funktion definieren, ansonsten wenn du das Ram nicht löscht, dann ist der Variableninhalt undefiniert und du musst ihn explizit initieren. Dieses geht auch, und counter sollte eine 8bit statische variable sein. if (!counter--) { /* code */ ; counter = 229 } Mit beiden hast du einen Fehler welcher ca 45 Sekunden am Tag ausmacht. Auch diesen kann man korrigieren durch den Ansatz wie oben aufgezeigt. Nur mit dem Windowsrechner ist es blöd das ausrechnen, wenn du es brauchst, dann rechne ich es dir am Montag aus. Wenn es die Applikation aber nicht fordert, oder du den internen OSC verwendest, oder auch nur ein Resonator dann bringt diese Berichtigung nichts, da deine Taktquelle ein größere Fehler darstellt.
Jesus Nvs schrieb: > wie kann ich einen TimmerX auf 120sekunden einstellen. gar nicht wg. overflow, musst halt selbst die Sekunden zählen. Programme die die Registerwerte ausrechnen gibt es mit einer google suche: pic timer calculator
Falls du einen Timer hast, der auch im Sleepmode weiterläuft, kann man das eleganter lösen. Beispiel von einem 18F14K22:
1 | void Sleep100Ms(uint16_t delay) |
2 | { while(delay_multiplier) |
3 | { TMR3IE = 1; // enable Timer3 interrupt |
4 | TMR3H = 0x9E; // high byte, Timer3 counts upwards, -> 0xFFFF-0x61A8 = 9E57 |
5 | TMR3L = 0x57; // low byte, 8MHz/(8*4) -> 4 µsec * 25000 ~ 100 msec |
6 | T3CON = 0b11111101; // enable Timer3, clocked by Fosc/4, prescaler 1:8, 16 bit mode |
7 | sleep(); // sleep until Timer3 interrupt, reset TMR3IF in interrupt routine!!! |
8 | T3CON = 0; // disable Timer3 |
9 | delay--; |
10 | }
|
11 | }
|
TMR3IF muß in der Interruptroutine gelöscht werden.
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.