Forum: Mikrocontroller und Digitale Elektronik Wie kann man hier noch optimieren?


von Samuel (Gast)


Lesenswert?

Hallo zusammen

Ich messe mit einem Interrupt und einem Timer die Periodendauer und 
damit ja die Frequenz eines 50 Herz Signales. Dieses kann jedoch 
zwischen 45-65Hz variieren.

Dazu mache ich momentan folgendes in meinem Interrupt:
1
  unsigned long uiTemp = 0;
2
  cli();
3
  
4
  TCD0.CTRLA = TC_CLKSEL_OFF_gc;  //Clocksource von TCD0  off  
5
  
6
  uiTemp = TCD1.CNT;  
7
  ulPeriodendauer = (TCD0.CNT | (uiTemp << 16));    
8
  
9
  TCC1.PER = (ulPeriodendauer / 200) - 1;
10
  
11
  TCD1.CNT = 0;
12
  TCD0.CNT = 0;
13
  
14
  TCD0.CTRLA = TC_CLKSEL_DIV1_gc;  //Clocksource von TCD0  ist Sysclock mit 32MHz
15
  
16
  sei();

Nun die Frage, was könnte man hier noch Optimieren?
Denn grundsätzlich verilere ich ja Zählerstellen, sobald ich diesen im 
Interrupt deaktiviere bis dieser wieder aktiv ist.

Ich wollte zuerst folgenderweise ulPeriodendauer beschreiben:
1
  ulPeriodendauer = (TCD0.CNT | (TCD1.CNT<< 16));

Leider scheint das nicht zu funktionieren.
Der Compiler meldet immer dass shiften sei aufgrund inkompatibler grösse 
nicht möglich.

Wenn ich mit dem Debugger reinsehe erhält ulPeriodendauer auch nur den 
Weert von TCD0.CNT


Hoffe ihr könnt mir ein paar Tipps geben...

Danke!

von Samuel (Gast)


Lesenswert?

Ich muss dazu noch sagen, dass

TCD0 ist der low word zähler
TCD1 der high word zähler.

Beide zusammen ergeben einen 32Bit Counter. (AtXmega)

TCD1 wird bei einem overflow von TCD0 automatisch hochgezählt.

von Oliver (Gast)


Lesenswert?

Hat der AtXmega keinen ICP-Modus in einem der Timer?

Oliver

von Samuel (Gast)


Lesenswert?

Oliver schrieb:
> ICP-Modus

Was ist den ein ICP Modus?

von Samuel (Gast)


Lesenswert?

Ok habs nachgeschaut...

Hat der vermutlich schon, aber der Timer wird eben noch für andere Dinge 
gebraucht.

Deshalb ist dies nicht möglich.

von Werner (Gast)


Lesenswert?

Samuel schrieb:
> Ich wollte zuerst folgenderweise ulPeriodendauer beschreiben:
>   ulPeriodendauer = (TCD0.CNT | (TCD1.CNT<< 16));

würde ich so schreiben:

ulPeriodendauer = TCD0.CNT;
*(((uint16_t*)(&ulPeriodendauer)) + 1) = TCD1.CNT;

von Michael H. (michael_h45)


Lesenswert?

Samuel schrieb:
1
>   TCC1.PER = (ulPeriodendauer / 200) - 1;
Runden:
1
TCC1.PER = ((ulPeriodendauer + 100) / 200) - 1;


> Ich wollte zuerst folgenderweise ulPeriodendauer beschreiben:
>   ulPeriodendauer = (TCD0.CNT | (TCD1.CNT<< 16));
>
> Leider scheint das nicht zu funktionieren.
> Der Compiler meldet immer dass shiften sei aufgrund inkompatibler grösse
> nicht möglich.
Damit hat er ja auch Recht - eine 16-bit Zelle um 16 bit schieben ergibt 
nichts Vernünftiges. Wenn du TCD1.CNT erst in eine Variable ausreichnder 
Breite lädst, klappt das. Das kannst du auch dem Compiler überlassen, 
indem du castest:
[c]ulPeriodendauer = (TCD0.CNT | ((uint32_t)TCD1.CNT << 16));


Werner schrieb:
> ulPeriodendauer = TCD0.CNT;
> *(((uint16_t*)(&ulPeriodendauer)) + 1) = TCD1.CNT;
pfusch... sag nicht dem compiler, wie er es machen soll, sondern was 
er machen soll. ein compiler-bauer kann es nämlich im zweifelsfall 
besser.

: Bearbeitet durch User
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.