So nun hat es mich auch in diese doofe Situation verschlagen :/ Ich möchte eine Sekunde ziemlich genau messen damit ich Ah ausrechnen kann. Ich habe einen 4,194304 Mhz Quarz im Einsatz mit einem Teiler von 256 komme ich genau auf 16384 Zyklen. Jedoch weiß ich nun nicht welchen Timer bzw. Interrupt ich wo und vor allem wie ansprechen muß das ich diese genaue Sekunde erhalten. :/ In meinem Programm habe ich bereits einen Timer2 Overflow, für meinen Drehimpulsgeber laufen, welcher jedoch bei jedem Drehimpuls eine Pause von 50ms einlegen muß (läßt sich leider bei der Bitabfrage des doofen Impulsgebers nicht anders ändern :/) Kann ich denn dann einen zweitern Timer nebenbei laufen lassen?! Oder sollte ich mir da tunlichst was anderes einfallen lassen?! Achja... µC ist ein Atmega32 und schreiben tue ich in MicroC - geht aber auch das normale AVR GCC... Vielen Dank für eure Hilfe!
In erster Näherung kannst du IMHO den Timer2 Overflow mitbenutzen (20 * exakt 50ms = exakt 1s). Genauer könnte man was dazu sagen, wenn man wüsste, aus welchen Messungen und wie du die Kapazität (Ah) berechenen willst.
Hallo was ist mit Timer 0? Ich würde nicht alle 256 Takte in die ISR hüpfen. Da diese ja selbst wenn du nur einen 8Bit Zähler hoch zählen willst etliche Takte benötigt und du so eine hohe Auslastung hast. (Gut bei einem Zähler geht's noch gerade so ;)
@ Draco (Gast) >So nun hat es mich auch in diese doofe Situation verschlagen :/ Ach du Aaaaaaarmer. >Ich möchte eine Sekunde ziemlich genau messen damit ich Ah ausrechnen >kann. Ich habe einen 4,194304 Mhz Quarz im Einsatz mit einem Teiler von >256 komme ich genau auf 16384 Zyklen. Und wo ist das Problem? Siehe AVR - Die genaue Sekunde / RTC >In meinem Programm habe ich bereits einen Timer2 Overflow, für meinen >Drehimpulsgeber laufen, welcher jedoch bei jedem Drehimpuls eine Pause >von 50ms einlegen muß (läßt sich leider bei der Bitabfrage des doofen >Impulsgebers nicht anders ändern :/) Unsinn. Im Interrupt wird NIE gewartet, schon gar nicht 50ms!!! Siehe Interrupt. Kann man alles anders programmieren, man muss nur wissen wie. Siehe auch Multitasking. > Kann ich denn dann einen zweitern >Timer nebenbei laufen lassen?! Oder sollte ich mir da tunlichst was >anderes einfallen lassen?! Ja, vergiss die Murksprogrammierung und lerne wie man es richtig macht. MFG Falk
Die 4,194304 MHz sind 2^22 Hz, daher kommt auch der Wert. Bei den Zählern gibt es daher die Möglichkeiten mit Overflow: 8 Bit-Zähler (2^8) mit Vorteiler 1024 (2^10) und eigener Zähler bis 16 (2^4), d.h. ein Zeitfenster von 62,5 ms. 16 Bit-Zähler (2^16) mit Vorteiler 64 (2^6) ergibt direkt 1 Sekunde. Wenn du statt deinen 50 ms mit den 62,5 ms leben kannst wäre das der beste Weg. AVR
Na die 50ms kommen nur dann zustande wenn der Impulsgeber eine Drehung vollführt.:
1 | void Timer2Overflow_ISR() org IVT_ADDR_TIMER2_OVF |
2 | {
|
3 | if (Button(&PINC, 2, 1, 1) && Button(&PINC, 4, 1, 0) && richtung == 0) { |
4 | richtung = 2; |
5 | delay_ms(50); |
6 | |
7 | } else if (Button(&PINC, 4, 1, 1) && Button(&PINC, 2, 1, 0) && richtung == 0) { |
8 | richtung = 1; |
9 | delay_ms(50); |
10 | |
11 | }
|
12 | }
|
13 | |
14 | |
15 | ....
|
16 | SREG_I_bit = 1; |
17 | TOIE2_bit = 1; |
18 | TCCR2 = 6; |
19 | ....
|
Ich messe die aktuelle Spannung einer (Solarzelle + Batterie - Verbraucher) via ADC alle 10sec und möchte mir die Ergebnisse einfach aufaddieren. Mir reicht es ja wenn ich erst nach 2-3h das Ergebniss sehe, das funktioniert ja auch soweit ganz gut :D Jedoch komme ich mit dem Timer nicht so ganz auf die Sekunde, weil mir fehlt entweder immer was oder ich bin nach 2-3 Minuten schon 2sec im vorraus.
Einen Delay im Timer Interrupt ? Aaaaaaaaaaaaaaaaaaahhhhhhhhhhhhhhhhh.
Hallo, ich meine, zu einer halbwegs genauen Zeit wirst Du erst kommen, wenn Du andersherum von Deiner Anforderung den Quarz berechnest. Also was ich meine: Bei 8 Bit Timer: z.B. per Software z.B. (50 x Interrupt und per Software zählen) x Hardware Teiler des Timers x Vorteiler => Quarz Da der 16 Bit Timer von Dir schon verwendet wird, schlage ich Dir den Timer 2 dafür vor, da kannst Du mit Überlauf Interrupt arbeiten. Den hat Timer0 nicht. (Hab mich damit leider vor einigen Tagen selbst auseinandersetzten müssen und mich viel Zeit gekostet). Wenn Du von einem Quarz ausgehst wie bisher, wirst Du vermutlich immer auf Teilerfaktoren kommen, die nicht ganzzahlig sind und dann wirds vermutlich ungenau. Viele Grüße Herbert
Ja und?! Momentan wurde der Timer auch ausschließlich für die Drehgeberabfrage genutzt. Es funktioniert wunderbar, das Programm war nicht zeitkritisch - also warum nicht?! Ist nicht schön, ich weiß. Aber das Ergebniss ist das Ziel - nicht der Weg. Das ich es nun umschreiben muß ist mir klar. Aber solche Postings bringen einen echt nicht weiter. Ich hab mir hierher gewandt weil ich ein Problem habe und ein Meister noch nie vom Himmel gefallen ist - auch ihr habt mal angefangen und Fehler begangen. Jemanden deswegen "dumm" zu machen sehe ich als falschen Ansatz in einem Forum wie diesem. Vielen Dank erstmal für die Hinweise, auch an Falk für die nützlichen Links. Werde mich da mal reinlesen.
Mensch.. so schnelle Antworten hier :D Herbert K. schrieb: > Hallo, > > ich meine, zu einer halbwegs genauen Zeit wirst Du erst kommen, wenn Du > andersherum von Deiner Anforderung den Quarz berechnest. > Also was ich meine: > Bei 8 Bit Timer: > z.B. per Software z.B. (50 x Interrupt und per Software zählen) > x Hardware Teiler des Timers x Vorteiler => Quarz > Da der 16 Bit Timer von Dir schon verwendet wird, schlage ich Dir den > Timer 2 dafür vor, da kannst Du mit Überlauf Interrupt arbeiten. Den hat > Timer0 nicht. (Hab mich damit leider vor einigen Tagen selbst > auseinandersetzten müssen und mich viel Zeit gekostet). > Wenn Du von einem Quarz ausgehst wie bisher, wirst Du vermutlich immer > auf Teilerfaktoren kommen, die nicht ganzzahlig sind und dann wirds > vermutlich ungenau. > Viele Grüße Herbert So wie ich mich gerade belesen habe im Datenblatt, ist der Timer2 einer der 8Bit Timer, also steht mir ja der 16Bit Timer (TCCR1) noch zur Verfügung. Dort passt mein Teiler ja wieder.
Hi >Timer 2 dafür vor, da kannst Du mit Überlauf Interrupt arbeiten. Den hat >Timer0 nicht. (Hab mich damit leider vor einigen Tagen selbst >auseinandersetzten müssen und mich viel Zeit gekostet). Alle Timer des ATMega32 haben einen Overflow-Interrupt. MfG Spess
Hallo, bitte um Entschuldigung - war noch ein wenig früh. ATmega32 hatte ich übersehen. Ich war vom ATmega8 ausgegangen. Aber ein Delay gehört eigentlich nicht in die ISR sondern das macht mann außerhalb der ISR - oder? Nach dem ich anfangs ähnliche Probleme hatte, habe ich mein Prg. geändert, so das in der ISR nur Zustände abgefragt / festgehalten werden und evt. Counter +1. Die Regelung / Steuerung mache ich dann außerhalb der ISR im normalen Programm, in dem die vorherigen Zustände einfach in einer Schleife abgefragt werden und da stört dann auch ein Delay nicht unbedingt. Seit dem läuft meine Uhr auch genauer. Viele Grüße Herbert
Hi >bitte um Entschuldigung - war noch ein wenig früh. ATmega32 hatte ich >übersehen. Ich war vom ATmega8 ausgegangen. Auch alle Timer des ATMega8 haben einen Overflow-Interrupt. MfG Spess
Hallo, Spess hat mich wieder mal auf einen Fehler hingewiesen: Ich meinte "Timer/Counter xx Compare Match" als ISR. Danke Spess. Viele Grüße Herbert
Aber wenn du in deinem einem Interrupt 50ms wartest. Verpasst du aber vielleicht den einen oder anderen Interrupt, da während eines Interrupt alle anderen gesperrt sind. Wen ein anderer Interrupt z.B alle 10ms kommt verpasst du ca. 4 mal den anderen. So kommst du nie auf eine genaue Sekunde.
Es ist egal, ob der Weg das Ziel ist oder nicht, denn Warteschleifen in Interrupts sind No-Gos. Sowas macht man nicht. Und wie du siehst hast du deswegen auch Probleme. Entprellung löst man anders als über Warteschleifen.
Gut gut, um nun mal ein wenig ruhe in den thread zu bringen hab ich die Tastenabfrage angepasst.:
1 | void Timer2Overflow_ISR() org IVT_ADDR_TIMER2_OVF |
2 | {
|
3 | if (Button(&PINC, 2, 0, 1) && Button(&PINC, 4, 0, 0) && richtung == 0 && zaehler >=29) { |
4 | richtung = 2; |
5 | zaehler = 0; |
6 | |
7 | } else if (Button(&PINC, 4, 0, 1) && Button(&PINC, 2, 0, 0) && richtung == 0 && zaehler >=29) { |
8 | richtung = 1; |
9 | zaehler = 0; |
10 | }
|
11 | |
12 | zaehler++; |
13 | }
|
Hab nun den 16Bit Timer mit 64iger Teilung genommen für meine sekunde, die Uhr läuft nun seit ca. 8h ohne eine sekunde abweichung, will sie dann morgen mal einen ganzen Tag neben einer Stopuhr laufen lassen. Danke für eure Hilfe!
Hallo, schön das wir Dir helfen konnten. Ich freue mich auch, das Du für andere die Änderung / Lösung hinterlassen hast. Viel Erfolg bei den weiteren Arbeiten am Projekt. Viele Grüße Herbert
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.