Hallo,
ich hab ein kleines Problem mit dem Conuter eines ATmega 168A-PU.
Die Clocksource des Timer0 wurde auf Extern und fallende Flanke
eingestellt. Damit sollen die von einem Encoder produzierten Flanken
detektiert werden.
Timer2 stellt den Zeitbezug her um auf eine Drehzahl schließen zu
können.
Prinziepiell funktioniert das auch. Allerdings nur solange der Motor
nicht mit "Vollgas" fährt.
Sobal die Encoderpulsfrequenz einen Grenzwert (ca 41kHz) überschreitet
verweigert der Counter vollständig seinen Dienst. Die über die
Serielleschnittstelle eingelesenen Variablen bleiben 0.
Unterhalb der genannten Frequenz liefert der Counter zwar Werte,
allerdings sehen diese eher nach einer Alias-Frequenz aus. Das heisst
bei geringerer Geschwindigkeit zählt der Counter mehr Pulse als bei
höheren.
Soweit ich das im Datenblatt nachlesen konnte sollte die Grenzfrequenz
bei dem 1/2,5 fachen des CPU-Taktes liegen. Da die CPU über einen
externen Quarz mit 20MHz läuft, kann ich da kein Problem erkennen. Und
auch bei 8MHz wären 42kHz auch noch unter dem geforderten Wert.
Deshalb verstehe ich nicht wirklich wo das Problem liegt. Hat jemand
dazu eine Idee?
Quelltext(Auszug):
1
#define EXTCLK_FALING_EDGE 0x06
2
#define TIMER0_OVINT_ENABLED TIMSK0 |= (1<<TOIE0)
3
#define TIMER2_OVINT_ENABLED TIMSK2 |= (1<<TOIE2)
4
#define START_TIMER0 TCCR0B = EXTCLK_FALING_EDGE
5
#define START_TIMER2 TCCR2B = 0x07
6
7
intmain(void)
8
{
9
setup();//ruft unter Anderem timer() und counter() auf.
10
OVERFLOW=0;
11
OVERFLOW2=0;
12
13
while(1)
14
{
15
sei();
16
}
17
}
18
19
voidtimer()
20
{
21
START_TIMER2;
22
TIMER2_OVINT_ENABLED;
23
}
24
25
voidcounter()
26
{
27
START_TIMER0;
28
TIMER0_OVINT_ENABLED;
29
}
30
31
32
ISR(TIMER0_OVF_vect)
33
{
34
cli();
35
overflow_flag++;
36
if(overflow_flag==255)
37
{
38
overflow2_flag=1;
39
overflow_flag=0;
40
}
41
}
42
43
ISR(TIMER2_OVF_vect)
44
{
45
cli();
46
TICK_COUNT=TCNT0;
47
tick_sum=tick_sum+TICK_COUNT;
48
OVERFLOW=overflow_flag;
49
OVERFLOW2=overflow2_flag;
50
overflow_flag=0;
51
overflow2_flag=0;
52
}
Der gesamte Quelltext ist etwas zu umfangreich um ihn hier einzustellen.
(380 Zeilen + Header) Daher nur ein Auszug.
Um feinheiten, wie exakte Werte durch stoppen und wieder starten der
Timer und den genauen Prescaler des Timer2 habe ich mich noch nicht
gekümmert. Ich wollte erst einmal einen prinziepiell funktionierenden
Code.
Matthias schrieb:> Der gesamte Quelltext ist etwas zu umfangreich um ihn hier einzustellen.
Dann häng ihn eben an.
Schnipsel bringen garnichts.
Es werden eh nur immer die Schnipsel gepostet, an denen es garantiert
nicht liegt.
Oder die nichtmal dem Original entsprechen!
Und ja, man darf auch eigene Programme mit Kommentaren versehen, die die
Funktion beschreiben.
Nicht jeder kann in Deinen Kopf schauen.
Und Du hast nach einem Jahr vieles vergessen.
Sag mal was soll das cli(); / sei(); ?
ist doch dort wo es steht unnütz.
Auch die Angabe es AVR µC wäre hilfreich.
Einmal sei(); reicht.
Ich habe einen Frequenzzähler am laufen, der bei F_CPU = 20MHz noch bis
9,625MHz sicher zählt.
Das wäre der Wert für die Frequenzmessung, den ich ebenfalls (in etwa)
erwartet hätte.
Das cli(); steht da um eine Rekursivität auszuschlißen.
Da das ganze Programm über ISRs läuft war es zumindest denkbar das es zu
einem Stackoverflow kommt und so die seltsamen Werte produziert werden.
Deshalb werden erst nach beenden einer ISR mit sei(); die Interrups
wieder freigegeben.
Wohl richtig gemeint :-)
> Nun ein Interrupt kann NICHT ohne weiters eine schon laufende> Interruptbearbeitung unterbrechen.
darum ist cli(); unsinnig.
Matthias schrieb:> Deshalb werden erst nach beenden einer ISR mit sei(); die Interrups> wieder freigegeben.
Lies Dir nochmal im Datenblatt den Abschnitt Interrupthandling in Ruhe
durch.
Peter Dannegger schrieb:> Lies Dir nochmal im Datenblatt den Abschnitt Interrupthandling in Ruhe> durch.
Eventuell habe ich mich etwas undeutlich ausgedrückt.
Sei und Cli wurden erst eingefügt, nachdem ich merkte, dass Etwas nicht
stimmen kann. --> Ausschlussverfahren. Ich habe lieber eine, oder zwei
Assembleranweisungen zuviel im Code stehen als mir nicht 100% sicher zu
sein, dass es nicht doch daran liegen könnte.
Falls das ein Hinweis auf einen Fehler sein sollte kann ich ihn nicht
erkennen. Anderenfalls verstehe ich nicht, was es mit dem eigentlichen
Problem zu tun hat.
Matthias schrieb:> Anderenfalls verstehe ich nicht, was es mit dem eigentlichen> Problem zu tun hat.
Da wir nur deinen Quellcode(Auszug) kennen, sind vermutlich noch viel
mehr Maden im Speck.
Matthias schrieb:> Der gesamte Quelltext ist etwas zu umfangreich um ihn hier einzustellen.> (380 Zeilen + Header) Daher nur ein Auszug.
Nur 380 Zeilen? Da hast du vermutlich die ganzen Initialisierungen
vergessen?
Als Dateianhang fällt das nicht ins Gewicht.
Matthias schrieb:> Sei und Cli wurden erst eingefügt, nachdem ich merkte, dass Etwas nicht> stimmen kann.
Dann hast Du gemerkt, daran liegt es nicht, aber uns kannst Du die Gurke
ja ruhig andrehen?
Es gehört sich einfach nicht, überflüssigen Schrunz, der nichts mit dem
Problem zu tun hat, im Code drin zu lassen.
Damit schafft man sich keine Freunde.
Man sieht es leider oft, daß bei Problemen man irgendwas verwurschteltes
mit allen möglichen Trial&Error Codefragmenten unkommentiert vorgesetzt
kriegt.
Ich gebe Dir mein Wort, das hebt in keinster Weise die Motivation, zu
helfen.
Poste die erste Version, wo der Fehler zuerst aufgetreten ist und
kommentiere, welche Funktion Du von welchem Code erwartest.
Eine eigene Frage?
Dieser Thread ist über 13 Jahre alt.
Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.