Hallo zusammen!
ich wollte alle z.b. 5 Sekunden eine Messung auslösen, dazu hab ich
einen 16 bit Timer gebraucht, welcher jedoch ständig ca. 2 Sekunden
daneben liegt, dass heisst, statt den gewünschten 5 Sekunden von Messung
zu Messung wird eine erneute Messung erst nach 7 Sekunden durchgeführt.
Übersehe ich etwas??
1
voidtimer_init(void){
2
// initialize Timer1
3
cli();// disable global interrupts
4
TCCR3A=0;// set entire TCCR1A register to 0
5
TCCR3B=0;// same for TCCR1B
6
7
// set compare match register to desired timer count:
8
OCR3A=15624;
9
// turn on CTC mode:
10
TCCR3B|=(1<<WGM12);
11
// Set CS10 and CS12 bits for 1024 prescaler:
12
TCCR3B|=(1<<CS10);
13
TCCR3B|=(1<<CS12);
14
// enable timer compare interrupt:
15
TIMSK3|=(1<<OCIE3A);
16
sei();// enable global interrupts
17
}
18
19
20
ISR(TIMER3_COMPA_vect)
21
{
22
sec++;
23
if(sec==10)
24
{
25
sec=0;
26
if(pos_messen==1){
27
messen();
28
return;
29
}
30
}
31
}
Ich verwende einen externen 16MHz Quarz und den ATMega25601.
und in messen() spielt es sich dann ab, inklusive Übrtragung auf LCD
und/oder UART. Oder wie?
Der Teil gehört in die Hauptschleife und nicht in die ISR.
Und ja, das kann dafür verantwortlich sein, dass dein Timing nicht
stimmt. Schliesslich sind die Interrupts deaktiviert und wenn du mehr
als 1 verpasst, dann summiert sich das.
Uwe schrieb:> Ja es müßten eigentlich 10 Sekunden sein wegen :> if (sec == 10)
Mein Fehler, habe es auch mit 10 Sekunden versuecht, Resultat: 12
Sekuneden!
Karl Heinz Buchegger schrieb:> und in messen() spielt es sich dann ab, inklusive Übrtragung auf LCD> und/oder UART. Oder wie?
genau, da werden die Sensoren eingelesen und das Resultat dargestellt.
Karl Heinz Buchegger schrieb:> Der Teil gehört in die Hauptschleife und nicht in die ISR.
Ich denke du meinst über ne Abfrage der Flags? Ist aber dann nicht der
Intervall der Auslösung unregelmässig?
Abgesehen davon, sollte doch der Timer direkt nach auslösen wieder
zurückgesetzt werden und von neuem beginnen zu zählen?!
1 Sekunde ist aber eine Ewigkeit, da kann man auch schon mal eine
(LCD-)Ausgabe aus einer ISR heraus machen, ohne daß da gleich Interrupts
verloren gehen.
Wenn die Funktion messen allerdings länger als eine Sekunde benötigt
(warum auch immer), dann ist eine Messung pro Sekunde halt nicht drin,
egal, von wo aus die Funktion aufgerufen wird.
Oliver
Oliver schrieb:> 1 Sekunde ist aber eine Ewigkeit, da kann man auch schon mal eine> (LCD-)Ausgabe aus einer ISR heraus machen, ohne daß da gleich Interrupts> verloren gehen.>> Wenn die Funktion messen allerdings länger als eine Sekunde benötigt> (warum auch immer), dann ist eine Messung pro Sekunde halt nicht drin,> egal, von wo aus die Funktion aufgerufen wird.>> Oliver
Alles klar! Es war wirklich der Messprozess (da über mehrere Messungen
nacheinander gemittelt wird) habe nun eifach ein Flag gesetzt und in der
Hauptschleife abgefragt und alles ist so wie es sein soll, danke euch
allen!
hier noch der Code:
1
voidtimer_init(void){
2
// initialize Timer1
3
cli();// disable global interrupts
4
TCCR3A=0;// set entire TCCR1A register to 0
5
TCCR3B=0;// same for TCCR1B
6
// set compare match register to desired timer count:
Rico H. schrieb:
Es war wirklich der Messprozess (da über mehrere Messungen
> nacheinander gemittelt wird)
Hm. In einer Sekunde auf einem 16MHz AVR lassen sich aber sehr viele
Daten mitteln. Da sürfte dann noch einiges im argen liegen...
Oliver
Oliver schrieb:> Hm. In einer Sekunde auf einem 16MHz AVR lassen sich aber sehr viele> Daten mitteln. Da sürfte dann noch einiges im argen liegen...
Es sind 13 Sensoren, welche je 16 Messungen durchführen, mitteln und
ausgeben;)
@ Rico H. (Firma: FHNW) (2she)
>Es sind 13 Sensoren, welche je 16 Messungen durchführen, mitteln und>ausgeben;)
Was bislang auch mal länger als 1s dauern kann, wenn man den Ansatz so
sieht. Das kann man prüfen, im Programm.
http://www.mikrocontroller.net/articles/Multitasking#Verbesserter_Ansatz_mit_Timer
Siehe auch Interrupt. Dennoch bleibt die Grundaussage. Solche Sachen
gehören nicht in die ISR, einen 1s Timer wird man in den meisten Fällen
so nicht machen, sondern eher einen 10ms Timer und dort eine Variable
bis 100 hochzählen. Denn die meisten Programme brauchen einen deutlich
schnelleren Grundtakt als 1s.
Falk Brunner schrieb:> Solche Sachen> gehören nicht in die ISR
welche Sachen? ich erhöhe ja jetzt nur noch die Variable sec um 1 und
setze pos_messen auf 1?!
@ Rico H. (Firma: FHNW) (2she)
>> Solche Sachen>> gehören nicht in die ISR>welche Sachen? ich erhöhe ja jetzt nur noch die Variable sec um 1 und>setze pos_messen auf 1?!
Ich war zu langsam, ich meinte die Messung in der ISR. Deine jetztige
Lösung ist OK.
Rico H. schrieb:> Oliver schrieb:>> Hm. In einer Sekunde auf einem 16MHz AVR lassen sich aber sehr viele>> Daten mitteln.> Es sind 13 Sensoren, welche je 16 Messungen durchführen, mitteln und> ausgeben;)
[ironie]
Werden die jeweils 16 Messwerte dann pro Sensor wenigstens auch
schnellstmöglich nacheinander gemacht, um einen Ausreisser nicht
herauszumitteln?
[/ironie]
>> Da sürfte dann noch einiges im argen liegen...
Das mit den 16 Messungen pro Sensor deutet in der Tat darauf hin. W
@Oliver:
Warum musst du da 16 mal messen? Was bringt das?
Lothar Miller schrieb:> Warum musst du da 16 mal messen? Was bringt das?
Es handelt sich um Temperaturmessungen, welche sehr genau sein sollen.
neues Problem, eher ein einfaches aber im Moment Blick ich nicht mehr
durch.
Ich möchte auf einen Tastendruck eine Messung starten und den Timer
starten, sodass die 2ten Messungen 10 sec danach starten. Die Funktion
wird mit dem Tastendruck ausgeführt was auch soweit funktioniert.
Resp. wie kann ich den CTC Timer reseten?!
1
voidSensoren()
2
{
3
timer_init();//selbe Initialisierung wie oben
4
pos_messen=0;
5
messen();//Erste Messung sofort starten
6
timer_init();
7
//TCNT3 = 0; //Timer zurücksetzen???=> funktioniert nicht
8
while(site==1100)
9
{
10
//hier werden die Timerinterrupts die Messungen starten
Rico H. schrieb:> Ich möchte auf einen Tastendruck eine Messung starten und den Timer> starten, sodass die 2ten Messungen 10 sec danach starten.
Also nicht mehr regelmässig, so wie bisher?
Ich mach das immer so:
Countdowntimer
1
volatileint8_tcountdown=-1;
2
3
ISR(TIMER3_COMPA_vect)
4
{
5
sec++;
6
if(sec==10)
7
{
8
sec=0;
9
pos_messen=1;
10
}
11
12
if(countdown>0)
13
countdown--;
14
}
15
16
....
17
18
while(1)
19
{
20
21
....
22
23
if(Tastendruck)
24
{
25
countdown=10;
26
messen();
27
}
28
29
if(countdown==0)
30
{
31
messen();
32
countdown=-1;
33
}
34
35
....
36
}
37
}
Vergiss den Quatsch
1
voidSensoren()
2
{
3
timer_init();//selbe Initialisierung wie oben
4
pos_messen=0;
5
messen();//Erste Messung sofort starten
6
timer_init();
Dein Timer läuft durch. Immer! Der startet mit dem Einschalten der
Stromversorgung und ab da läuft der. Dauernd. Ständig.
Arbeite mit den ISR Aufrufen und entsprechenden Zählvariablen, aber lass
den Timer in Ruhe!
Du stellst ja deine Armbanduhr auch nicht dauernd ab bzw. den
Sekundezeiger auf 0, nur weil du irgendwelche Zeiten abmessen willst.
Genau deshalb ist weiter oben auch gesagt worden, dass die meisten
Programme einen Basistakt haben, der meistens etwas schneller als 1
Sekunde ist. Irgendwas im Millisekundenbereich. Man setzt sich einen
Timer auf, so dass zb jede 1 Millisekunde eine ISR aufgerufen wird. Und
den Rest leitet man dann mit entsprechenden Zählern und Jobflags von
diesen 1 Millisekunden her. Aber der Timer tickt durch. Ständig. Der
Zeitfehler ist dann nicht größer als diese 1 Millisekunden, was
angesichts diverser Ausgaben völlig ausreichend ist.
Rico H. schrieb:> // turn on CTC mode:> TCCR3B |= (1 << WGM12);> // Set CS10 and CS12 bits for 1024 prescaler:> TCCR3B |= (1 << CS10);> TCCR3B |= (1 << CS12);
Ich Pfosten hab zwar die richtigen Register beschrieben, aber die
falschen Bits gesetzt....
so funzt es jetzt! THX an alle!!