Forum: Mikrocontroller und Digitale Elektronik MEGA328P -> Timer1 Compare Match A


von TimerNoob (Gast)


Lesenswert?

Guten Nabend,

eine kleine Frage.. Bin noch relativ neu in dem Thema "Timer".

Wenn ich jetzt meinen Timer1_CompA so konfiguriere, dass er jede 
Millisekunde in die ISR läuft..
Wie folgt konfiguriert..:
1
/**< Waveform Generation Mode Bits */
2
#define _TMR0_MODE0          ( ! ( 1 << WGM00 | 1 << WGM01 ) ) // Normal
3
#define _TMR0_MODE2          ( 1 << WGM01 ) // CTC
4
5
#define _TMR1_MODE0          ( ! ( 1 << WGM13 | 1 << WGM12 | 1 << WGM11 | 1 << WGM10 ) ) // Normal
6
#define _TMR1_MODE4          ( 1 << WGM12 ) // CTC
7
8
#define _TMR2_MODE0          ( ! ( 1 << WGM21 | 1 << WGM20 ) ) // Normal
9
#define _TMR2_MODE2          ( 1 << WGM21 ) // CTC
10
11
/**< Prescaler Mode Group Position */
12
#define _PRESCALER_0        ( 0b001 << 0 )
13
#define _PRESCALER_8        ( 0b010 << 0 )
14
#define _PRESCALER_64        ( 0b011 << 0 )
15
#define _PRESCALER_256        ( 0b100 << 0 )
16
#define _PRESCALER_1024        ( 0b101 << 0 ) // Sind für alle Timer (0..2) gleich
17
18
{ .uiCnt = 124     , .uiCSxx = _PRESCALER_64   , .uiWGMxx = _TMR1_MODE4 }, // 1ms   @8MHz
19
20
TCCR1A  = psTab->uiWGMxx & 0x03;
21
TCCR1B  = psTab->uiWGMxx & 0x18;
22
TCCR1B  |= psTab->uiCSxx;
23
OCR1A  = psTab->uiCnt;

Sollte er jede Millisekunde in die ISR laufen.. Nun toggle ich eine LED 
und messe das ich eine Amplitude von ~520us habe..
Was verstehe ich falsch?

von Einer K. (Gast)


Lesenswert?

Was ist das für eine Sprache?

von TimerNoob (Gast)


Lesenswert?

Arduino Fanboy D. schrieb:
> Was ist das für eine Sprache?

Ich weiß nicht genau was es mit der Sprache zu tun hat.. Aber es ist "C"

von Hugo H. (hugohurtig1)


Lesenswert?

Arduino Fanboy D. schrieb:
> Was ist das für eine Sprache?

Die des Unwissenden.

von Stefan F. (Gast)


Lesenswert?

Seltsames Bitgefummel. Was da effektiv bei heraus kommt ist:

> TCCR1A = 0
> TCCR1B = 11  (WGM12, CS11, CS10)
> OCR1A = 124

Das ist der CTC Modus mit Prescaler 64.

> messe das ich eine Amplitude von ~520us habe..
> Was verstehe ich falsch?

Ja, Amplituden haben eine Höhe, nicht Zeit. Die meinst wohl eine 
Pulsbreite.

Bei 16 MHz dauert ein Timer-Takt 1/16000000*64 = 4µs

124 ∙ 4µs = 496µs

Das passt also ungefähr. Oder hast du eine andere Taktfrequenz als 
Systemtakt?

von Beo Bachta (Gast)


Lesenswert?

TimerNoob schrieb:
> und messe das ich eine Amplitude von ~520us habe

Eine Amplitude in Zeit gemessen, das ist was wirklich Innovatives.

von Hugo H. (hugohurtig1)


Lesenswert?

Hugo H. schrieb:
> Die des Unwissenden.

Dann als Nachtrag: Zusammen kopiert ohne jede Ahnung.

von S. Landolt (Gast)


Lesenswert?

> Bei 16 MHz dauert ein Timer-Takt 1/16000000*64 = 4µs
> 124 ∙ 4µs = 496µs
> Das passt also ungefähr.

Zum einen sind es 125, zum anderen kämen 16 MHz aus einem Quarz, wären 
also hinreichend genau.

von Stefan F. (Gast)


Lesenswert?

S. Landolt schrieb:
> Zum einen sind es 125

Stimmt, als exakt 500µs. Wie dem auch sei, es passt zum Messergebnis. 
Wenn Impulse im 1ms Abstand gewünscht sind, muss man OCR1A auf 255 
setzen.

von Hugo H. (hugohurtig1)


Lesenswert?

S. Landolt schrieb:
> Zum einen sind es 125, zum anderen kämen 16 MHz aus einem Quarz, wären
> also hinreichend genau.

Ja - interpretierst Du in saudummes Geschwätz z. B. auf der Wies'n auch 
immer etwas hinein?

von Stefan F. (Gast)


Lesenswert?

Hugo H. schrieb:
> Ja - interpretierst Du in saudummes Geschwätz z. B. auf der Wies'n auch
> immer etwas hinein?

Verstehe ich nicht, er hat doch absolut Recht!

von Stefan F. (Gast)


Lesenswert?

Stefan F. schrieb:
> Wie dem auch sei, es passt zum Messergebnis.
> Wenn Impulse im 1ms Abstand gewünscht sind, muss man OCR1A auf 255
> setzen.

Ich bin schon wieder halb am Schlafen. 2∙125-1 ist natürlich 249, nicht 
255.

von Hugo H. (hugohurtig1)


Lesenswert?

Stefan F. schrieb:
> Verstehe ich nicht, er hat doch absolut Recht!

TimerNoob schrieb:
> psTab->

Wo siehst Du das?

von Stefan F. (Gast)


Lesenswert?

Hugo H. schrieb:
> Wo siehst Du das?

psTab kann nur das sein
> { .uiCnt = 124     , .uiCSxx = _PRESCALER_64   , .uiWGMxx = _TMR1_MODE4 }

Ergibt sich aus dem Zusammenhang.

von Hugo H. (hugohurtig1)


Lesenswert?

Stefan F. schrieb:
> Ergibt sich aus dem Zusammenhang.

Nö - ist nicht bekannt (im Beispiel). Compiliere das mal und berichte 
über das Ergebnis.

Hugo H. schrieb:
> Arduino Fanboy D. schrieb:
>> Was ist das für eine Sprache?
>
> Die des Unwissenden.

: Bearbeitet durch User
von leo (Gast)


Lesenswert?

TimerNoob schrieb:
> #define _TMR0_MODE0          ( ! ( 1 << WGM00 | 1 << WGM01 ) ) // Normal

Die logischen NOT sind Absicht?

leo

von TimerNoob (Gast)


Lesenswert?

Stefan F. schrieb:
> Das passt also ungefähr. Oder hast du eine andere Taktfrequenz als
> Systemtakt?

Der Mega328 läuft mit 8MHz.

von S. Landolt (Gast)


Lesenswert?

Wie sieht die ISR aus?

von Hugo H. (hugohurtig1)


Lesenswert?

leo schrieb:
> Die logischen NOT sind Absicht?

Woher soll er das wissen?

von TimerNoob (Gast)


Lesenswert?

S. Landolt schrieb:
> Wie sieht die ISR aus?

Da ist wirklich nur nen Pin drin, der getoggelt wird.
Mehr nicht. Die main() ist auch leer..

Sehe ich das richtig das ich eigentlich eine "Pulsbreite" von einer 
Millisekunde haben müsste mit den Werten?

von S. Landolt (Gast)


Lesenswert?

Wenn die ISR falsch definiert sein sollte, ergäbe das ein fortlaufendes 
Reset, daraus könnten diese 520 us entstehen - deshalb frage ich.

von Einer K. (Gast)


Lesenswert?

TimerNoob schrieb:
> Die main() ist auch leer..
Der Timer wird also gar nicht initialisiert.


Ehy, sach mal...
Gibts irgend einen Grund, warum du nicht ein kompilierbares/lauffähiges 
Beispiel liefern willst?

von S. Landolt (Gast)


Lesenswert?

Ist doch spannender als Sudoku.

von TimerNoob (Gast)


Lesenswert?

Wie müsste denn die korrekt initalisierung aussehen für Timer1 & 
CompareMatchA @ 8MHz für 1ne Millisekunde?

von S. Landolt (Gast)


Lesenswert?

1
TCCR1B = (1<<WGM12) | (1<<CS11) | (1<<CS10);
2
OCR1A  = 125 -1;

von S. Landolt (Gast)


Lesenswert?

Pardon, es fehlte:
1
TIMSK1 = (1<<OCIE1A);
2
3
ISR (TIMER1_COMPA_vect)
4
...
5
...

von TimerNoob (Gast)


Lesenswert?

Also hier ist mal die Initalisierung die ich aufrufe
1
extern inline enum eTimerError Timer1CompAInit( const sTimer16Config_t *psTab , void (*pFncCallback)(void) )
2
{
3
  cli(); /**< Vorsichtshalber Interrupts global sperren */
4
5
  TCCR1A  = psTab->uiWGMxx;
6
  TCCR1B  = psTab->uiWGMxx;
7
  TCCR1B  |= psTab->uiCSxx;
8
  OCR1A  = psTab->uiCnt;
9
  
10
  if ( pFncCallback == NULL )
11
  {
12
    sei();
13
    return ERROR_TIMER_NO_ADDRESS;
14
  }else
15
  {
16
    pvTimerCallback[CALLBACK_TIMER1_COMPA] = pFncCallback;
17
  }
18
  
19
  _ENABLE_OCIE1A;
20
21
  sei();
22
  
23
  return ERROR_TIMER_OK;
24
}

Das ist die Konfiguration
1
const sTimer16Config_t sTimer1TovSettings[] = 
2
{
3
  #if (F_CPU == 1000000)
4
    { .uiCnt = 65535   , .uiCSxx = _PRESCALER_0    , .uiWGMxx = _TMR1_MODE0 }, // 1µS   @1MHz  
5
    { .uiCnt = 65526   , .uiCSxx = _PRESCALER_0    , .uiWGMxx = _TMR1_MODE0 }, // 10µS  @1MHz
6
    { .uiCnt = 65436   , .uiCSxx = _PRESCALER_0    , .uiWGMxx = _TMR1_MODE0 }, // 100µS @1MHz
7
    { .uiCnt = 65411   , .uiCSxx = _PRESCALER_8    , .uiWGMxx = _TMR1_MODE0 }, // 1ms   @1MHz
8
  #endif
9
10
  #if (F_CPU == 8000000)
11
    { .uiCnt = 65528   , .uiCSxx = _PRESCALER_0    , .uiWGMxx = _TMR1_MODE0 }, // 1µS   @8MHz
12
    { .uiCnt = 65456   , .uiCSxx = _PRESCALER_0    , .uiWGMxx = _TMR1_MODE0 }, // 10µS  @8MHz
13
    { .uiCnt = 65436   , .uiCSxx = _PRESCALER_8    , .uiWGMxx = _TMR1_MODE0 }, // 100µS @8MHz
14
    { .uiCnt = 65411   , .uiCSxx = _PRESCALER_64   , .uiWGMxx = _TMR1_MODE0 }, // 1ms   @8MHz
15
  #endif
16
17
  #if (F_CPU == 16000000)
18
    { .uiCnt = 65520  , .uiCSxx = _PRESCALER_0    , .uiWGMxx = _TMR1_MODE0 }, // 1µS   @16MHz
19
    { .uiCnt = 65376  , .uiCSxx = _PRESCALER_0    , .uiWGMxx = _TMR1_MODE0 }, // 10µS  @16MHz
20
    { .uiCnt = 65336  , .uiCSxx = _PRESCALER_8    , .uiWGMxx = _TMR1_MODE0 }, // 100µS @16MHz
21
    { .uiCnt = 65286  , .uiCSxx = _PRESCALER_64   , .uiWGMxx = _TMR1_MODE0 }, // 1ms   @16MHz
22
  #endif  
23
};

von Stefan F. (Gast)


Lesenswert?

Wir wollten etwas compilierbares haben. Keine Lust mehr, weiter zu 
raten.

Wie hast du denn verifiziert, ob dein Mikrocontroller wirklich auf 8MHz 
läuft?

von TimerNoob (Gast)


Lesenswert?

Stefan F. schrieb:
> Wir wollten etwas compilierbares haben. Keine Lust mehr, weiter zu
> raten.
>
> Wie hast du denn verifiziert, ob dein Mikrocontroller wirklich auf 8MHz
> läuft?

Was bringt Dir ausführbarer Code wenn Du ihn nicht testen kannst? Ich 
habe genau diese Routine genutzt um den Timer zu initalisieren. Mehr 
steht nicht drin.

Den Takt habe ich in den Fuses nachgeschaut. Dort ist auch kein DIV8 
etc. aktiviert.

von c-hater (Gast)


Lesenswert?

TimerNoob schrieb:

> Also hier ist mal die Initalisierung die ich aufrufe

> extern inline enum eTimerError Timer1CompAInit( const sTimer16Config_t
> *psTab , void (*pFncCallback)(void) )
[...]
>   TCCR1A  = psTab->uiWGMxx;
>   TCCR1B  = psTab->uiWGMxx;

Wer auch immer das verbrochen hat, es kann nur kompletter Bullshit 
sein...

von Stefan F. (Gast)


Lesenswert?

TimerNoob schrieb:
> Was bringt Dir ausführbarer Code wenn Du ihn nicht testen kannst?

Ich kann ihn doch testen!

von TimerNoob (Gast)


Lesenswert?

c-hater schrieb:
> TimerNoob schrieb:
>
>> Also hier ist mal die Initalisierung die ich aufrufe
>
>> extern inline enum eTimerError Timer1CompAInit( const sTimer16Config_t
>> *psTab , void (*pFncCallback)(void) )
> [...]
>>   TCCR1A  = psTab->uiWGMxx;
>>   TCCR1B  = psTab->uiWGMxx;
>
> Wer auch immer das verbrochen hat, es kann nur kompletter Bullshit
> sein...

Achja.. Warum?

von Stefan F. (Gast)


Lesenswert?

TimerNoob, deine Codefragmente sind immer noch unvollständig und 
widersprechen sich.

c-hater schrieb:
>>   TCCR1A  = psTab->uiWGMxx;
>>   TCCR1B  = psTab->uiWGMxx;
> Wer auch immer das verbrochen hat, es kann nur kompletter Bullshit
> sein...

Das kommt noch dazu.

TimerNoob schrieb:
> Achja.. Warum?

Weil man nicht in zwei unterschiedliche Konfigurationsregister den 
gleichen Wert schreiben will. Das kann so nicht beabsichtigt gewesen 
sein.

Weiter oben wurde psTab->uiWGMxx wenigstens noch mit unterschiedlichen 
Bitmasken gefiltert, was zwar funktioniert, aber auch sehr verwirrend 
ist. Merkt man auch daran, dass du deinen eigenen Code nicht verstehst. 
Das ist bei diesem Code kein Wunder.

Lege die Karten (den Quelltext) offen auf den Tisch oder höre auf, 
unsere Hilfsbereitschaft zu missbrauchen.

von S. Landolt (Gast)


Lesenswert?

"Vor Tische las man's anders":
1
TCCR1A  = psTab->uiWGMxx & 0x03;
2
TCCR1B  = psTab->uiWGMxx & 0x18;

Beitrag #6043633 wurde von einem Moderator gelöscht.
von TimerNoob (Gast)


Angehängte Dateien:

Lesenswert?

Anbei mal ein Foto.

von TimerNoob (Gast)


Lesenswert?

Ich bin den Hinweisen bzw. den Fragen zum Thema Quarz nochmal nach 
gegangen..

In den Fuses steht er auf 8MHz, wenn ich ihn auf den internen RC Oszi. 
schalte, läuft er deutlich langsamer und das mit den Timing von einer 
Millisekunde passt.. Das heißt im Endeffekt er steht bei den Fuses auf 
8MHz und wird übertaktet.. (ist ein China Arduino!)..
Auf dem Quarz kann man natürlich keine Frequenz ablesen.

von Beo Bachta (Gast)


Lesenswert?

TimerNoob schrieb:
> und wird übertaktet

Nein.

Übertakten bedeuted betreiben ausserhalb (oberhalb) der
spezifizierten Frequenzgrenze (die liegt beim 328P bei
16 MHz bzw 20 MHz).

Das bezweifle ich in deinem Fall sehr stark.

von Stefan F. (Gast)


Lesenswert?

TimerNoob schrieb:
> Anbei mal ein Foto.

Wo ist jetzt dein Problem?

Du hast 500µs Intervalle programmiert und sie auch bekommen. Das zeigt 
dein Oszilloskop an. immer abwechselnd 500µs LOW und 500µs HIGH.

TimerNoob schrieb:
> In den Fuses steht er auf 8MHz, wenn ich ihn auf den internen RC Oszi.
> schalte, läuft er deutlich langsamer

Moment mal. Der interne Oszillator hat 8 MHz. Mit der CLKDIV8 Fuse kann 
er der Takt (egal ob intern oder extern) durch 8 geteilt werden.

Wenn der Mikrocontroller mit dem internen Oszillator nur halb so schnell 
läuft, wie mit dem externen, dann hat der externe Oszillator 
logischerweise die doppelte Taktfrequenz, also 16 MHz.

16 MHz ist bei Arduino Modulen die übliche Bestückung. Meistens ist das 
bei den billigen Modulen übrigens nur ein Keramik Resonator - weniger 
genau als ein Quarz.

Und das passt zu deinem zuerst genannten Code und deinem Messergebnis.

Ergo: Da ist kein Problem. Wenn du andere Intervalle wolltest, musst du 
wie gesagt den Wert im OCR1A Register ändern.

von Einer K. (Gast)


Lesenswert?

TimerNoob schrieb:
> Ich bin den Hinweisen bzw. den Fragen zum Thema Quarz nochmal nach
> gegangen..
>
> In den Fuses steht er auf 8MHz, wenn ich ihn auf den internen RC Oszi.
> schalte, läuft er deutlich langsamer und das mit den Timing von einer
> Millisekunde passt.. Das heißt im Endeffekt er steht bei den Fuses auf
> 8MHz und wird übertaktet.. (ist ein China Arduino!)..
> Auf dem Quarz kann man natürlich keine Frequenz ablesen.
Die Fuses kann man nicht auf 8MHz extern einstellen.
5V Arduinos sind mit 16MHz Resonatoren ausgestattet.
Die billigen China Modelle auch mal mit Quarz.

von S. Landolt (Gast)


Lesenswert?

> Ergo: Da ist kein Problem.

Doch, er braucht eine Brille:

> und messe das ich eine Amplitude von ~520us habe..

von TimerNoob (Gast)


Lesenswert?

Wozu stellt man genau die CLK Fuses ein? Wenn man 8MHz eingestellt hat 
ihn dann aber auch mit 16MHz betreiben kann?
Was bewirken diese Einstellungen?

von S. Landolt (Gast)


Lesenswert?

Eine korrekte und vor allem vollständige Antwort würde umfangreich, 
sicher nicht viel kürzer als das, was im Datenblatt steht; also dort 
nachlesen.
  Von mir nur soviel: man wählt den Oszillator aus, diverse interne 
RC-Oszillatoren sowie Oszillatoren, die mit extern anzuschließendem 
Quarz (oder Resonator) betrieben werden; bei letzteren gilt es noch, 
hinreichend gut an die Frequenz anzupassen.

von elmo64 (Gast)


Lesenswert?

Beo Bachta schrieb:
> Übertakten bedeuted betreiben ausserhalb (oberhalb) der
> spezifizierten Frequenzgrenze (die liegt beim 328P bei
> 16 MHz bzw 20 MHz).

Die "Frequenzgrenze" ist Spannungsabhängig! Im DB befindet sich ein 
schönes Diagramm, das den sicheren Arbeitsbereich veranschaulicht. Die 
Maximal vom Hersteller spezifizierte Frequenz beträgt 20 Mhz. Die 16Mhz 
auf zB. sämtlichen Arduino-boards kann damit erklärt werden, dass viele 
ältere AVRs nur höchstens 16Mhz unterstützen.

TimerNoob schrieb:
> CLK Fuses [...] Was bewirken diese Einstellungen?

Datenblatt!
Vielleicht hilft dir auch eine Gui zum Fuses setzen, wie der im Atmel 
Studio weiter?

von Stefan F. (Gast)


Angehängte Dateien:

Lesenswert?

TimerNoob schrieb:
> Wozu stellt man genau die CLK Fuses ein? Wenn man 8MHz eingestellt hat
> ihn dann aber auch mit 16MHz betreiben kann?

Nochmal: Man kann nicht 8MHz einstellen.

Du kannst da drei Sachen einstellen:

1) Die Quelle, das ist entweder der interne 128 kHz Oszillator, oder der 
interne 8 MHz Oszillator oder eine externe Quelle.

2) Die Startup Time (SUT) gibt dem Oszillator Zeit, sich einzuschwingen.

3) Mit CLKDIV8 kann die Taktfrequenz (egal aus welcher Quelle) durch 8 
geteilt werden.

Guck Dir das mal im Engbedded Fuse Calculator an (Anhang).

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.