Forum: Mikrocontroller und Digitale Elektronik timer Probleme ctc OCRA/B


von franz (Gast)


Lesenswert?

Mega2560 , ich kapiers einfach nicht.
 Ich möchte timer1 wie folgt haben,
 OCR1B sollte 9x getriggert werden und dann einmal OCR1A um eine
 Messung mit 50 oder 60HZ sowie 20HZ zu realisisern.
 Leider bekomme ich folgendes Pattern angezeigt.

ISR(TIMER1_COMPA_vect) gibt 'A' aus, hingegen
ISR(TIMER1_COMPB_vect) gibt 'B'-'K' usw aus,
Aus welchem Grund wird A zweimal aufgerufen ? hat da jemand eine idee ?

ok(856,1) init

MILLIS =  0
BACDEFGHIJKABACDEFGHIJKABACDE
MILLIS =  580
FGHIJKABACDEFGHIJKABACDEFGHIJKAB
MILLIS =  1220
ACDEFGHIJKABACDEFGHIJKABACDEFGHIJKAB
MILLIS =  1940
ACDEFGHIJKABACDEFGHIJKABACDEFGH
MILLIS =  2560
IJKABACDEFGHIJKABACDEFGHIJKAB
MILLIS =  3140
ACDEFGHIJKABACDEFGHIJKABACDEFGHIJKAB
MILLIS =  3860
ACDEFGHIJKABACDEFGHIJKABACDEFGHIJ
MILLIS =  4520
KABACDEFGHIJKABACDEFGHIJKABACD
MILLIS =  5120
EFGHIJKABACDEFGHIJKABACDEFGHIJKAB
MILLIS =  5780
ACDEFGHIJKABACDEFGHIJKAB


1
// initialize timer, interrupt and variable
2
void timer1_init()
3
{
4
  cli();
5
  // Clear registers
6
  TCCR1A = 0;
7
  TCCR1B = 0;
8
  TCNT1 = 0;
9
        OCR1A  = 50000-1; //Vergleichswert A    - 200ms
10
        OCR1B  = 5000;
11
        TCCR1B = 013;   // div64 -- ctc
12
13
        TIMSK1 |= (1<<OCIE1A); //Interrupt an Kanal A aktivieren
14
        TIMSK1 |= (1<<OCIE1B); //Interrupt an Kanal B aktivieren
15
        TIFR1  = 0xFF;
16
        putch('#');
17
  sei();
18
}
19
20
volatile uint64_t millis_;
21
uint64_t millis() { CRITICAL_SECTION_START; uint64_t m=millis_; CRITICAL_SECTION_END; return m; }
22
23
ISR(TIMER1_COMPA_vect){
24
        TOGGLE(LED_PIN);
25
        read_thermoR(0);
26
        read_thermoC();
27
        millis_+=HZ60?18:20;
28
        putch('A');
29
}
30
31
32
ISR(TIMER1_COMPB_vect){
33
        static byte n; byte m=++n;
34
        word w = HZ60?4166+(n&1):5000;
35
        putch('A'+n);
36
        if(n>=(HZ60?12:10)) n=0,OCR1B=w;
37
        else OCR1B  = w*n;
38
        millis_+=HZ60?16+(m&1):20;
39
        read_thermoR(m);
40
}

von Mitdenk Versager (Gast)


Angehängte Dateien:

Lesenswert?

franz schrieb:
> Mega2560 , ich kapiers einfach nicht.

Wenn du es schon nichst schaffst dich so auszudrücken dass
der Leser es einfach versteht dann wirst du es selbst auch
nicht verstehen bzw. verstanden haben.

Erster oberflächlicher Eindruck: putc() in der ISR, das
kann schwierig werden ....

read_thermoR(m) in der ISR ist auch sehr verdächtig ...

Dann noch das im Bild: beachte die Regeln.

Die Tabulation ist katastrophal.

Du meinst die main() vestecken zu müssen?

von S. Landolt (Gast)


Lesenswert?

>        TCCR1B = 013;   // div64 -- ctc

Dreizehn?

von Stefan F. (Gast)


Lesenswert?

S. Landolt schrieb:
> 013

Das ist eine Oktalzahl. In Dezimal übersetzt ist das eine 11.

von S. Landolt (Gast)


Lesenswert?

Tatsächlich, stimmt.

von S. Landolt (Gast)


Lesenswert?

Also ich hätte die COMPB-ISR nicht mit 'A' anfangen lassen, falls, warum 
auch immer, n mal 0 sein sollte. 'f' wäre doch schön gewesen, oder?

von c-hater (Gast)


Lesenswert?

S. Landolt schrieb:
>>        TCCR1B = 013;   // div64 -- ctc
>
> Dreizehn?

Nö, das ist eine typische C-Falle. 013 ist nicht etwa 13 dezimal, wie 
heute jeder Normaldenkende annehmen würde, sondern 13 oktal, wie es 
möglicherweise mal in der Steinzeit der Computerei sinnvoll war, aus 
welcher dieser ganze unsägliche C-Dreck stammt.

Meint also $d bzw. 0xd Hex oder 13 dezimal in allen richtigen Sprachen. 
Die zeichnen sich allesamt nämlich sinnvollerweise dadurch aus, dass 
eine zusätzliche führende Null im Literal am Wert der Zahl nichts 
ändert. Denn das ist eine universelle Regel, die mathematikweit für 
jegliches denkbare Zahlensystem gilt. Nur halt nicht in C...

von S. Landolt (Gast)


Lesenswert?

Ja, danke für die Aufklärung. Ich erinnere mich dunkel, schon einmal 
darauf hereingefallen zu sein.

von franz (Gast)


Lesenswert?

Mitdenk Versager schrieb:
> franz schrieb:
>> Mega2560 , ich kapiers einfach nicht.
>
Ja, ich komme aus der Pic Welt und wollte ein kleines Projekt, ca 2000 
Zeilen Code, mit der Arduino Umgebung bewerkstelligen, aber es scheint 
so
dass ich den Timer nicht verstehe.

> Wenn du es schon nichst schaffst dich so auszudrücken dass
> der Leser es einfach versteht dann wirst du es selbst auch
> nicht verstehen bzw. verstanden haben.
>
> Erster oberflächlicher Eindruck: putc() in der ISR, das
> kann schwierig werden ....
Ja, wurde für das debugging eingefügt, vom Timing unproblematisch.

>
> read_thermoR(m) in der ISR ist auch sehr verdächtig ...
Vom timing kein Problem, aber ich habe natürlich als erstes diese 
Aufrufe auskommentiert mit demselben Ergebniss.
>
> Du meinst die main() vestecken zu müssen?
nein, für den Test wird nur Initialisiert, Pins + timer1 and dann ist
folgende Zeile eingefügt worden:
1
  for(;;delay(1000)) p0(PSTR("\nMILLIS = "),(word)millis()),nl();

p0 verwendet atoi der AVR lib Delay ist wie folgt definiert:
1
 void delay(word ms) { while(ms--) _delay_loop_2(3999); }

Ausserhalb von Timer1 gibt es auch keine Interrupts.

S. Landolt schrieb:
>>        TCCR1B = 013;   // div64 -- ctc
>
> Dreizehn?
Ja, ist octal , in hex wäre es 0xb , ist dasselbe als:
   TCCR1B = (1 << WGM12) | (1 << CS10) | (1<<CS11) ;

Was ich absolut nicht verstehe ist der zweimalig Aufruf von COMPA.
Ich habe dat putch('A') auskommentiert und es kommt wirklich nur vom A 
interrupt.

von Stefan F. (Gast)


Lesenswert?

c-hater schrieb:
> das ist eine typische C-Falle

Nicht nur in C, das ist ebenso in Java, Perl, Python, JavaScript, ...

von franz (Gast)


Angehängte Dateien:

Lesenswert?

Hier nun ein minimales Beispiel als C source.
Der Output ist folgender:
Die Frae ist, wieso wird CompareA Interrupt zwei mal aufgerufen.
#
BaCDEFGHIJKaBaCDEFGHIJKaBa
CDEFGHIJKaBaCDEFGHIJKaBaCDEFGHIJKa
BaCDEFGHIJKaBaCDEFGHIJKaBa
CDEFGHIJKaBaCDEFGHIJKaBaCDEFGHIJKa
BaCDEFGHIJKaBaCDEFGHIJKaBa
CDEFGHIJKaBaCDEFGHIJKaBaCDEFGHIJKa
BaCDEFGHIJKaBaCDEFGHIJKaBa
CDEFGHIJKaBaCDEFGHIJKaBaCDEFGHIJKa
BaCDEFGHIJKaBaCDEFGHIJKaBa
CDEFGHIJKaBaCDEFGHI

Franz

von S. Landolt (Gast)


Lesenswert?

> Die Frae ist, wieso wird CompareA Interrupt zwei mal aufgerufen.

Nachdem in der COMPB-ISR 'B' ausgegeben wurde, mit n=1, wird OCR1B ein 
neuer Wert zugewiesen, der kleiner oder gleich dem vorherigen ist, 
sodass also der Timer bis zu OCR1A durchläuft.
  Wie das zugeht, weiß ich nicht, da ich dieses "HZ60?4166+(n&1):5000" 
nicht kenne.

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
Noch kein Account? Hier anmelden.