Ich möchte einem Programm schreiben, das alle x Sekunden einen Pin
rücksetzt, dieser Pin kann mit Tastendruck wieder auf 1 gesetzt werden:
Bis jetzt habe ich es wie folgt versucht (mit Codevision):
1
unsignedinti=0;
2
// Timer 0 overflow interrupt service routine
3
interrupt[TIM0_OVF]voidtimer0_ovf_isr(void)
4
{
5
// Place your code here
6
i=i+1;
7
if(i==6250)
8
{
9
i=0;
10
PORTA.1=0;
11
}
12
}
13
14
voidmain(void)
15
{
16
..Deklarationsteil
17
18
while(1){
19
if(TASTER)
20
{
21
delay_us(300);
22
#asm("CLI")
23
24
PORTA.1=1;
25
i=0;
26
#asm("SEI")
27
}
28
}
Das funktioniert ja soweit (prinzipiell). Doch eigentlich dachte ich
PORTA.1 müsste nachdem die Taste gedrückt wurde, immer x Sekunden lang 1
sein um dann auf 0 zu wechseln.
Wenn ich den Taster kurz drücke (aber länger als 300us) geht der Pin
gleich nach dem Loslassen wieder auf 0 zurück. Warum?
Irgendwie hast du etwas vom Programm unterschlagen.
Vielleicht willst du bei einer fallenden Flanke den IR auslösen, tust es
aber bei einer steigenden?
// Clock value: 1000,000 kHz
1000000/256=3906 mal pro sekunde wird dein timer0_ovf_isr aufgerufen,
i=i+1;
if(i == 6250)
6250/3906 = 1,6 sekunden sollte PORTA.1=1 sein.
Vielen Dank für den "volatile-Tipp"!
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
Ich wenn mit dem Ozsi nachmesse, komm ich darauf, dass meine
Interrupt-Routine alle 2ms aufgerufen wird.
Nur wie geht das rechnerisch?
1/(1 000 000 000Hz)*256=0.256us
Wie komme ich auf den Unterschied?
Ich verwende den internen Oszillatior, wobei
Das Fusebit CKDIV8 einen Hacken hat und SUT_CKSEL auf
"INTRCOSC_8MHZ_6CK_14CK_64MS" steht.
Zudem habe ich im Code den Clock-Teiler eingestellt:
// Crystal Oscillator division factor: 8
#pragma optsize-
CLKPR=0x80;
CLKPR=0x03;
#ifdef OPTIMIZE_SIZE
#pragma optsize+
#endif
Ich habe gemessen wenn ich einen Ausgang auf 1 schalte und wieder
zurück, so dauert es 2us, d.h. für jeden Schaltvorgang 1us = 1MHz.
Das wäre ja in Ordnung.
Martin schrieb:> Vielen Dank für den "volatile-Tipp"!>> //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +>> Ich wenn mit dem Ozsi nachmesse, komm ich darauf, dass meine> Interrupt-Routine alle 2ms aufgerufen wird.>> Nur wie geht das rechnerisch?>> 1/(1 000 000 000Hz)*256=0.256us
Ich denke nicht, dass dein µC mit 1Ghz getaktet wird.
... ist genau das, was ich im Codevision Wizard hasse. Um rauszukriegen,
was da tatsächlich eingestellt wird, muss man sich erst mal exzessiv
durchs Datenblatt wühlen um zu entschlüsseln, welche Bits da eigentlich
in den einzelnen Registern gesetzt werden und um dann weiter zu
ergründen, was sie bedeuten.
Eines ist ziemlich sicher: das hier
TCCR0B=0x02;
ist kein Vorteiler von 1. Ich bin allerdings auch zu faul rauszusuchen,
was das jetzt tatsächlich für ein Vorteiler ist.
Entschuldige, ich habe noch einen wichtigen Teil vergessen hier
anzugeben.
// Crystal Oscillator division factor: 8
#pragma optsize-
CLKPR=0x80;
CLKPR=0x03;
#ifdef OPTIMIZE_SIZE
#pragma optsize+
#endif
TIMSK=0x02;
Heißt nur, dass der Timer Interrupt aktiviert wird.
Martin schrieb:> TIMSK=0x02;> Heißt nur, dass der Timer Interrupt aktiviert wird.
Das weiß ich selber auch. Aber bei
TIMSK |= ( 1 << TOIE0 );
kann ich direkt im Code sehen, dass hier das '_T_imer _O_verflow
_I_nterrupt _E_nable bit vom timer _0_' gesetzt wird. Da steht also
(mehr oder weniger) im Klartext, das hier der Overflow freigegeben wird.
Es gibt nämlich im allgemeinen Fall auch noch andere Interrupts als nur
den Overflow, die von einem Timer ausgelöst werden können.
Ausserdem geht es nicht um die Freigabe des Overflows, sondern darum,
wie schnell eigentlich der Timer getaktet wird.
Dazu braucht man 2 Angaben
* die Taktfrequenz des µC
* welcher Vorteiler wird benutzt
aus diesen Angaben kann man errechnen, wie schnell der Timer getaktet
wird und damit, und dem Wissen wie weit er zählt, errechnet sich dann,
wie groß der zeitliche Abstand zwischen den Overflows ist.
Die µC Taktfrequenz musst du wissen. Welcher Vorteiler eingestellt ist,
ist hier
TCCR0B=0x02;
codiert.
Und ich hab jetzt keine Lust rauszusuchen, welche CS-Bits in TCCR0B
stecken und was sie bedeuten. Du bist der Programmierer, das ist dein
Job.
http://www.mikrocontroller.net/articles/FAQ#Timer
Eigentlich sagt dir der CV-AVR in Kommentaren wie schnell dein Timer
läuft,
vorausgesetzt du hast danach im "c" Text nichts verändert.
// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 1000,000 kHz
// Mode: 8bit top=FFh
// Clock value: 1000,000 kHz bedeutet, dass der Timer mit 1MHz betrieben
wird,das weiß der Compiler natürlich nur aus der Angabe des Systemtakts
und dem Teiler, also 8Mhz/8-Teiler =1MHz.
Natürlich kann der Compiler nicht wissen wie die Fuses eingestellt sind
und wie schnell der Quarz taktet, also bei 16Mhz Takt wäre der Timer mit
oberen Einstellungen mit 2MHz gelaufen also 2 mal schneller.
> Warum geht das Gerät meist bei Tastendruck aus?!?!
Das kann abartige Ursachen haben wie z.B. ein Kurzschluss durch die
Tasterbetätigung und dadurch einen Reset (Power, Brownout) deiner ganzen
Hardware. Denn nach dem Hochfahren des µC aus dem Reset heraus gilt ja
auch PORTA.1=0;... Um diesen Fall zu Debuggen könntest du einen weiteren
Portpin zu Beginn von main vor der while() Schleife schalten und mit
einem Oszi oder einer LED überwachen, ob der µC resettet.