Forum: Mikrocontroller und Digitale Elektronik Atxmega Timer Compare


von ATxmega_Fan (Gast)


Lesenswert?

Hallo,

versuche mich gerade an den Timern des Atxmega's. Ich möchte, das der 
Timer
frei läuft, und bei erreichen des jeweiligen Compare-Wertes einen 
Interrupt
auslöst, also keine PWM oder Frequenzy Mode. Nur kommen beide Led's 
zeitgleich und schalten auch gleich aus.

#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include "clksys_driver.h"

int main(void)
{
  /* konfiguriere Taktquelle */
  CLKSYS_XOSC_Config(OSC_FRQRANGE_12TO16_gc,false,OSC_XOSCSEL_XTAL_16KCLK_ 
gc);
  /* aktiviere Taktquelle */
  CLKSYS_Enable( OSC_XOSCEN_bm );
  /* konfiguriere PLL, Taktquelle, Faktor */
  CLKSYS_PLL_Config( OSC_PLLSRC_XOSC_gc, 2 );
  /* aktiviere PLL */
  CLKSYS_Enable( OSC_PLLEN_bm );
  /* konfiguriere Prescaler */
  CLKSYS_Prescalers_Config( CLK_PSADIV_1_gc, CLK_PSBCDIV_1_1_gc );
  /* warte bis takt stabil */
  do {} while ( CLKSYS_IsReady( OSC_PLLRDY_bm ) == 0 );
  /* wähle neue Taktquelle */
  CLKSYS_Main_ClockSource_Select( CLK_SCLKSEL_PLL_gc );
  /* deaktiviere internen Oszillator */
  CLKSYS_Disable( OSC_XOSCEN_bm );


  PMIC.CTRL |= PMIC_HILVLEN_bm |PMIC_MEDLVLEN_bm|PMIC_LOLVLEN_bm; 
//Interruptlevel freigeben
  sei();            // Interrupts freigeben
  PORTF.DIRSET = PIN0_bm;  //Ports als Ausgang
  PORTF.DIRSET = PIN1_bm;

  TCC0.CTRLB = 0b00000000; // Mode Normal,
  TCC0.PER = 0xFFFF; // Zähler Top-Wert
  TCC0.CCA = 1;
  TCD0_CCB = 1000;
  TCC0.INTCTRLA = 0b00000000;  //
  TCC0.INTCTRLB = 0b00001111;
  TCC0.CTRLA = TC_CLKSEL_DIV1024_gc;
  while (1)
    {
    }
}
ISR(TCC0_OVF_vect)
{

}

ISR(TCC0_CCA_vect)
{
  PORTF.OUTTGL=PIN0_bm;
}

ISR(TCC0_CCB_vect)
{
  PORTF.OUTTGL=PIN1_bm;
}

Hat jemand einen Tip, wo der Fehler liegt?

Gruß ATxmega_Fan

von Bastian W. (jackfrost)


Lesenswert?

Welcher Takt hat der xMega ?

Ausgehend von 32 MHz über die PLL ist der Versatz zwischen den LEDs 0,03 
Sekunden.

Gruß JackFrost

von Dieter F. (Gast)


Lesenswert?

ATxmega_Fan schrieb:
> TCD0_CCB = 1000;

Replace "D" with "C"

ATxmega_Fan schrieb:
> Nur kommen beide Led's
> zeitgleich und schalten auch gleich aus.

Nö, leicht versetzt - um die Ausführungszeit für die ISR des CCB. Der 
schlägt nämlich jeweils bei 0 (Initial-Wert) zu, vor CCA bei 1.

von ATxmega_Fan (Gast)


Lesenswert?

Hallo,

erstmal vielen Dank für die Antwort. Gut, der Tipp-Fehler ist schon
peinlich....

Hat aber daran gelegen. Nun habe ich das ganze erweitert, um lange 
Perioden abzuarbeiten. Dienen soll das ganze, um bei 2 Schrittmotoren 
die Drehzahl in 1-250 Upm vorzugeben.

#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include "clksys_driver.h"

static uint32_t Periode_M1;
static uint32_t Periode_M2;
volatile uint32_t Periode_Nachlade_M1;
volatile uint32_t Periode_Nachlade_M2;

int main(void)
{
  /* konfiguriere Taktquelle */
  CLKSYS_XOSC_Config(OSC_FRQRANGE_12TO16_gc,false,OSC_XOSCSEL_XTAL_16KCLK_ 
gc);
  /* aktiviere Taktquelle */
  CLKSYS_Enable( OSC_XOSCEN_bm );
  /* konfiguriere PLL, Taktquelle, Faktor */
  CLKSYS_PLL_Config( OSC_PLLSRC_XOSC_gc, 2 );
  /* aktiviere PLL */
  CLKSYS_Enable( OSC_PLLEN_bm );
  /* konfiguriere Prescaler */
  CLKSYS_Prescalers_Config( CLK_PSADIV_1_gc, CLK_PSBCDIV_1_1_gc );
  /* warte bis takt stabil */
  do {} while ( CLKSYS_IsReady( OSC_PLLRDY_bm ) == 0 );
  /* wähle neue Taktquelle */
  CLKSYS_Main_ClockSource_Select( CLK_SCLKSEL_PLL_gc );
  /* deaktiviere internen Oszillator */
  CLKSYS_Disable( OSC_XOSCEN_bm );


  PMIC.CTRL |= PMIC_HILVLEN_bm |PMIC_MEDLVLEN_bm|PMIC_LOLVLEN_bm; 
//Interruptlevel freigeben
  sei();            // Interrupts freigeben
  PORTF.DIRSET = PIN0_bm;
  PORTF.DIRSET = PIN1_bm;

  TCC0.CTRLB = 0b00000000;
  TCC0.PER = 0xFFFF; // Zähler Top-Wert
  TCC0.CCA = 0;
  TCC0.CCB = 0;
  TCC0.INTCTRLA = 0b00000000;  //
  TCC0.INTCTRLB = 0b00001111;
  TCC0.CTRLA = TC_CLKSEL_DIV8_gc; //Timertakt 4Mhz
        // 1 Upm bei 1/8 Schritt
  Periode_Nachlade_M1=150000; // 4MHZ/((1*1600)/60)=1500000
  // 250 Upm bei 1/8 Schritt
        Periode_Nachlade_M2=600;    // 4MHZ/((250*1600)/60)=600

  while (1)
    {
    }
}

ISR(TCC0_CCA_vect)
{
  if(Periode_M1>0)
    {
    PORTF.OUTCLR=PIN0_bm;
    if(Periode_M1>50000)
      {
      TCC0.CCA=50000;
      Periode_M1-=50000;
      }
    else
      {
      TCC0.CCA=Periode_M1;
      Periode_M1=0;
      }
    }
  else
    {
    PORTF.OUTSET=PIN0_bm;
    Periode_M1=Periode_Nachlade_M1;
    }
}

ISR(TCC0_CCB_vect)
{
  if(Periode_M2>0)
    {
    PORTF.OUTCLR=PIN1_bm;
    if(Periode_M2>50000)
      {
      TCC0.CCB=50000;
      Periode_M2-=50000;
      }
    else
      {
      TCC0.CCB=Periode_M2;
      Periode_M2=0;
      }
    }
  else
    {
      PORTF.OUTSET=PIN1_bm;
      Periode_M2=Periode_Nachlade_M2;
    }
}

Leider kann ich die Frequenzen am Ausgang nicht testen, da das Meterman
anscheinend bei den kurzen Impulsen streikt. Daher meine nächste Frage,
funktioniert dies so oder geht es eleganter?

Gruß ATxmega_Fan

von Bastian W. (jackfrost)


Lesenswert?

Wenn du einen 16 Bit Timer mit F_CPU/8 laufen lässt, dann hast läuft 
dieser bei 32MHz CPU Frequenz alle 16,384 ms über. Dein CCA und CCB wird 
, sofern der Wert nicht geändert wird auch alle 16,384 ms ausgelöst. 
Egal ob CCA nun auf 1 oder 20000 liegt, die Zeit zwischen den 
Interrupten liegt bei 16,384 ms.

Du brauchst aber einen deutlich schnelleren Takt als diese ~61 Hz.

Du musst den Timer auf Frequenz stellen, aber dann geht nur noch CCA, da 
der Timer dann nur von 0x00 bis CCA zählt

Jenachdem welchen xMega du hast kannst du mit drei Timern das lösen ohne 
das die CPU viel rechnen muss.

Einen Timer lässt du mit F_CPU laufen und setzt CCA auf 15. Über das 
Eventsystem lässt du nun zwei weiter Timer im Frequenzmodus mit dem 
Überlauf vom ersten Timer als Quelle laufen.

Da du bei jedem überlauf deinen Pin Toggelst musst du für deine 250 UpM 
den CCA wert vom zweitem Timer auf 150 stellen. Damit hast du dann eine 
Frequenz von 6,67 kHz. Mit CCA auf 37500 hast du eine Freuenz von 26,67 
Hz.

Wenn du das in Software machen willst, dann müsstest du in deinem mit 
deinen Takt vom Timer alle 16 Takte beide ISR durlaufen, damit ist die 
CPU nur noch in den ISRs. Da du aber nicht den Frequenz Modus gewählt 
hast, macht die CPU das zum Glück nur alle ~16 ms.
1
ISR(TCC0_CCB_vect)
2
{
3
  if(Periode_M2>0)
4
    {
5
    PORTF.OUTCLR=PIN1_bm;
6
    if(Periode_M2>50000)
7
      {
8
      TCC0.CCB=50000;
9
      Periode_M2-=50000;
10
      }
11
    else
12
      {
13
      TCC0.CCB=Periode_M2;
14
      Periode_M2=0;
15
      }
16
    }
17
  else
18
    {
19
      PORTF.OUTSET=PIN1_bm;
20
      Periode_M2=Periode_Nachlade_M2;
21
    }
22
}

Bei dem Block hast du über C&P auch noch die falschen Werte drinnen. Der 
Compiler hat das ziemlich gekürzt, da Periode_M2 immer nur 600 sein kann 
wird hier der Pin mit dem ~16 ms getoggelt. Damit hast du eine PWM mit 
~30 Hz und einem Duty cycle von 50 %.
1
ISR(TCC0_CCA_vect)
2
{
3
  if(Periode_M1>0)
4
    {
5
    PORTF.OUTCLR=PIN0_bm;
6
    if(Periode_M1>50000)
7
      {
8
      TCC0.CCA=50000;
9
      Periode_M1-=50000;
10
      }
11
    else
12
      {
13
      TCC0.CCA=Periode_M1;
14
      Periode_M1=0;
15
      }
16
    }
17
  else
18
    {
19
    PORTF.OUTSET=PIN0_bm;
20
    Periode_M1=Periode_Nachlade_M1;
21
    }
22
}

TCC0.CCA=50000 und TCC0.CCA=Periode_M1 sind beide 50000. Nach dem 
zweiten Durchlauf ist Periode_M1 nocht 50000 und damit wird im els Zweig 
nichts geändert. Der Interupt wird alle ~16 ms aufgerufen. Für drei 
Durchläuft ist dein Pin low und für einen high. Damit hast eine PWM mit 
~15 Hz und einem Duty cycle von 25 %.

Gruß JackFrost

von ATxmega_Fan (Gast)


Lesenswert?

Hallo


erstmal Danke für deine Erklärung. Wäre es dann nicht sinnvoller, den 
Frequency Mode zu nutzen? Da würde ich halt in der Berechnung den 
Vorteiler und PER Wert berechnen. Die Interrupt Last würde ja gen 0 
gehen. Und benötige ja eigentlich nur eine einstellbare Taktquelle.

Gruss ATxmega_Fan

von Dieter F. (Gast)


Lesenswert?

ATxmega_Fan schrieb:
> Dienen soll das ganze, um bei 2 Schrittmotoren
> die Drehzahl in 1-250 Upm vorzugeben.

Also variabel - je nach Input.

Ich würde da PWM nutzen. Machst Du sonst noch was damit (benötigst Du 
andere Timer für andere Zwecke?). Wäre schön, wenn Du Dein Projekt 
komplett anreisst, damit man sich etwas darunter vorstellen kann.

von ATxmega_Fan (Gast)


Lesenswert?

Hallo,

PWM bei Schrittmotoren? Da ist doch der Takt entscheidend und nicht die 
Pulseweite? Also die beiden Schrittmotoren sollen als Antrieb eines 
Roboters dienen. Mir gehts nur darum die Geschwindigkeit der Motoren zu 
regeln, in einem Bereich von 1-250Upm. Als Treiber dient für die Motoren 
der A4988.

Habe da jetzt mal mit dem Frequency Mode ein bissl gerechnet:

CCX= (F_CPU)/(2*N*((rpm*1600)/60))-1

CCX entspricht da den jeweilgen Compare-Register
N ist der entsprechende Vorteiler
rpm ist die Wunschdrehzahl

Da bekomme ich, sofern ich da richtig aufgestellt habe, folgende Werte 
raus:
F_CPU=32MHz, Vorteiler=64

1rpm entspricht 26,67Hz, CCX=9372,82
250rpm entspricht 6,67kHz, CCX=36,498

Also rein theoretisch könnte ich mit dem Vorteiler von 64 den ganzen 
Drehzahlbereich abdecken. Als Pluspunkt wäre, das ganze wäre 
Interruptfrei.

Gruß ATxmega_Fan

von ATxmega_Fan (Gast)


Lesenswert?

Wobei gerade mal in Exel eingetippt, mit dem Vorteiler von 64 werd ich 
nicht ganz glücklich, da ab 100Upm die Werte sich teilweise nur hinter 
dem Komma ändern. Besser wäre ab 90rpm ein Vorteiler von 8.

von Dieter F. (Gast)


Lesenswert?

ATxmega_Fan schrieb:
> PWM bei Schrittmotoren? Da ist doch der Takt entscheidend und nicht die
> Pulseweite?

Ja - das geht auch bei PWM.

von ATxmega_Fan (Gast)


Lesenswert?

Bei den Schritttreibern ergibt jeder Impuls einen Schritt. Wenn ich nur 
die Pulseite ändere, bleibt die Schrittzahl gleich. Erhöhere ich aber 
die Frequenz, mehr Schritte pro Sekunde. Versteh nicht was mir PWM 
bringen soll...

von Dieter F. (Gast)


Lesenswert?

ATxmega_Fan schrieb:
> Versteh nicht was mir PWM
> bringen soll...

Habe auch nur geschrieben "geht auch mit PWM" - oder?

von ATxmega F. (Firma: None) (atxmega_fan)


Lesenswert?

So, nun auch registriert. Der Frequency Mode scheidet leider aus, da die
Impulse zu kurz für den A4988 sind.

Gruß ATxmega_Fan

von Bastian W. (jackfrost)


Lesenswert?

ATxmega F. schrieb:
> So, nun auch registriert. Der Frequency Mode scheidet leider aus, da die
> Impulse zu kurz für den A4988 sind.
>
> Gruß ATxmega_Fan

Welche Einstellungen hast du denn genutzt, für deine 250 UpM hast du ja 
6,67 kHz was einer high Zeit von ~74 µs entspricht. Laut Datenblatt muss 
die mindest Zeit für high und low am Step Eingang >= 1µs sein.

Gruß JackFrost

von ATxmega F. (Firma: None) (atxmega_fan)


Lesenswert?

Hi,

so sieht es momentan aus:
1
#include <avr/io.h>
2
#include <util/delay.h>
3
#include <avr/interrupt.h>
4
#include "clksys_driver.h"
5
6
void Setze_Geschwindigkeit_M1(int16_t rpm)
7
{
8
  uint16_t Timerwert=0;
9
  Timerwert=(uint16_t)((F_CPU/(2*64*(rpm*1600.0)/60))-1);
10
  TCC0.CCABUF=Timerwert;
11
}
12
13
void Setze_Geschwindigkeit_M2(int16_t rpm)
14
{
15
  uint16_t Timerwert=0;
16
  Timerwert=(uint16_t)((F_CPU/(2*64*(rpm*1600.0)/60))-1);
17
  TCC1.CCABUF=Timerwert;
18
}
19
20
int main(void)
21
{
22
  int16_t drehzahl=0;
23
  /* konfiguriere Taktquelle */
24
  CLKSYS_XOSC_Config(OSC_FRQRANGE_12TO16_gc,false,OSC_XOSCSEL_XTAL_16KCLK_gc);
25
  /* aktiviere Taktquelle */
26
  CLKSYS_Enable( OSC_XOSCEN_bm );
27
  /* konfiguriere PLL, Taktquelle, Faktor */
28
  CLKSYS_PLL_Config( OSC_PLLSRC_XOSC_gc, 2 );
29
  /* aktiviere PLL */
30
  CLKSYS_Enable( OSC_PLLEN_bm );
31
  /* konfiguriere Prescaler */
32
  CLKSYS_Prescalers_Config( CLK_PSADIV_1_gc, CLK_PSBCDIV_1_1_gc );
33
  /* warte bis takt stabil */
34
  do {} while ( CLKSYS_IsReady( OSC_PLLRDY_bm ) == 0 );
35
  /* wähle neue Taktquelle */
36
  CLKSYS_Main_ClockSource_Select( CLK_SCLKSEL_PLL_gc );
37
  /* deaktiviere internen Oszillator */
38
  CLKSYS_Disable( OSC_XOSCEN_bm );
39
40
41
  PMIC.CTRL |= PMIC_HILVLEN_bm |PMIC_MEDLVLEN_bm|PMIC_LOLVLEN_bm; //Interruptlevel freigeben
42
  sei();            // Interrupts freigeben
43
  
44
  PORTC.DIRSET = PIN0_bm;
45
  PORTC.DIRSET = PIN4_bm; // set as output
46
47
48
  //Vorteiler des Timers einstellen
49
  TCC0.CTRLA = TC_CLKSEL_DIV64_gc;
50
  //Frequenzausgabe auswählen und Compare Ausgang A aktivieren
51
  TCC0.CTRLB = TC_WGMODE_FRQ_gc | TC0_CCAEN_bm;
52
  //Vorteiler des Timers einstellen
53
  TCC1.CTRLA = TC_CLKSEL_DIV64_gc;
54
  //Frequenzausgabe auswählen und Compare Ausgang A aktivieren
55
  TCC1.CTRLB = TC_WGMODE_FRQ_gc | TC1_CCAEN_bm;
56
57
  while (1) 
58
    {
59
  if (drehzahl<250)
60
  {
61
    drehzahl++;
62
  } 
63
  else
64
  {
65
    drehzahl=0;
66
  }
67
  Setze_Geschwindigkeit_M1(drehzahl);
68
  Setze_Geschwindigkeit_M2(1);
69
  _delay_ms(500);
70
    }
71
}

Gruß ATxmega_Fan

von Bastian W. (jackfrost)


Lesenswert?

Wenn du über das CCABUF Register gehst musst über das CCABV Bit 
mitteilen das die Daten im Puffer ok sind und dann werden sie 
übernommen(Datenblatt xMega A Seite 168) . Alternativ nutz einfach das 
CCA Register.

Lass die Werte für CCA einfach mal mit einfachen Intertegerwerten 
durchlaufen. Du hast in in deiner Berechnung einen Float und ggf 
überschreitest du den Bereich von uint16_t. Ist dein F_CPU ein 
32000000UL ?

Für die Geschwindigkeiten würde ein einfacher LuT im Flash reichen, dann 
musst du die Werte nicht immer neu rechnen.

Gruß JackFrost

von ATxmega F. (Firma: None) (atxmega_fan)


Lesenswert?

Also von Hand gerechnet passt alles in ein uint16_t, wird auch gecasted.
Mit CCA direkt hatte ich probiert, da liefen die Motoren, geräuschlich 
rauher.

Was meinst du mit Lut?

Gruß ATxmega_Fan

von Bastian W. (jackfrost)


Lesenswert?

Wenn eines deiner Zwischenergebnisse größer als uint16 ist dann wird das 
ja abgeschnitten. Bei CCA wird dann aktualisiert wenn du den Wert 
reinschreibst beim Buf erst wenn der Timer auf 0 steht. Du musst halt 
dann das Bit setzen für das die Werte richtig sind.

Lut = Look up table. Du hast die Ergebnisse deiner Rechnungen in nem 
Array im Flash und dann musst du nur im Array den Wert holen.

Gruß JackFrost

von Bastian W. (jackfrost)


Lesenswert?

Bei einem Vorteiler von 64 hast du bei den oberen Geschwindigkeiten 
starke Sprünge, da die Werte sich hier nicht mehr in einem Integer 
abbilden lassen. Ab 101 UpM kommen Werte für das CCA Register immer 
doppelt vor. Unt später dann drei- oder vierfach.

Der Index in der Klammer sind die UpM, der Wert dahinter ist der Wert 
für das CCA Register.
1
[101]  91  unsigned int{data}@0x20ca
2
[102]  90  unsigned int{data}@0x20cc
3
[103]  90  unsigned int{data}@0x20ce
4
....
5
[162]  56  unsigned int{data}@0x2144
6
[163]  56  unsigned int{data}@0x2146
7
[164]  56  unsigned int{data}@0x2148
8
[165]  55  unsigned int{data}@0x214a
9
[166]  55  unsigned int{data}@0x214c
10
[167]  55  unsigned int{data}@0x214e
11
[168]  54  unsigned int{data}@0x2150
12
[169]  54  unsigned int{data}@0x2152
13
[170]  54  unsigned int{data}@0x2154
14
[171]  53  unsigned int{data}@0x2156
15
[172]  53  unsigned int{data}@0x2158
16
[173]  53  unsigned int{data}@0x215a
17
[174]  52  unsigned int{data}@0x215c
18
[175]  52  unsigned int{data}@0x215e
19
[176]  52  unsigned int{data}@0x2160
20
[177]  51  unsigned int{data}@0x2162
21
[178]  51  unsigned int{data}@0x2164
22
[179]  51  unsigned int{data}@0x2166
23
[180]  51  unsigned int{data}@0x2168
24
[181]  50  unsigned int{data}@0x216a
25
[182]  50  unsigned int{data}@0x216c
26
[183]  50  unsigned int{data}@0x216e
27
[184]  49  unsigned int{data}@0x2170
28
[185]  49  unsigned int{data}@0x2172
29
[186]  49  unsigned int{data}@0x2174
30
[187]  49  unsigned int{data}@0x2176
31
[188]  48  unsigned int{data}@0x2178
32
[189]  48  unsigned int{data}@0x217a
33
[190]  48  unsigned int{data}@0x217c
34
[191]  48  unsigned int{data}@0x217e
35
[192]  47  unsigned int{data}@0x2180
36
[193]  47  unsigned int{data}@0x2182
37
[194]  47  unsigned int{data}@0x2184
38
[195]  47  unsigned int{data}@0x2186
39
[196]  46  unsigned int{data}@0x2188
40
[197]  46  unsigned int{data}@0x218a
41
[198]  46  unsigned int{data}@0x218c
42
[199]  46  unsigned int{data}@0x218e
43
[200]  45  unsigned int{data}@0x2190
44
[201]  45  unsigned int{data}@0x2192
45
[202]  45  unsigned int{data}@0x2194
46
[203]  45  unsigned int{data}@0x2196
47
[204]  44  unsigned int{data}@0x2198
48
[205]  44  unsigned int{data}@0x219a
49
[206]  44  unsigned int{data}@0x219c
50
[207]  44  unsigned int{data}@0x219e
51
[208]  44  unsigned int{data}@0x21a0
52
[209]  43  unsigned int{data}@0x21a2
53
[210]  43  unsigned int{data}@0x21a4
54
[211]  43  unsigned int{data}@0x21a6
55
[212]  43  unsigned int{data}@0x21a8
56
[213]  43  unsigned int{data}@0x21aa
57
[214]  42  unsigned int{data}@0x21ac
58
[215]  42  unsigned int{data}@0x21ae
59
[216]  42  unsigned int{data}@0x21b0
60
[217]  42  unsigned int{data}@0x21b2
61
[218]  42  unsigned int{data}@0x21b4
62
[219]  41  unsigned int{data}@0x21b6
63
[220]  41  unsigned int{data}@0x21b8
64
[221]  41  unsigned int{data}@0x21ba
65
[222]  41  unsigned int{data}@0x21bc
66
[223]  41  unsigned int{data}@0x21be
67
[224]  40  unsigned int{data}@0x21c0
68
[225]  40  unsigned int{data}@0x21c2
69
[226]  40  unsigned int{data}@0x21c4
70
[227]  40  unsigned int{data}@0x21c6
71
[228]  40  unsigned int{data}@0x21c8
72
[229]  39  unsigned int{data}@0x21ca
73
[230]  39  unsigned int{data}@0x21cc
74
[231]  39  unsigned int{data}@0x21ce
75
[232]  39  unsigned int{data}@0x21d0
76
[233]  39  unsigned int{data}@0x21d2
77
[234]  39  unsigned int{data}@0x21d4
78
[235]  38  unsigned int{data}@0x21d6
79
[236]  38  unsigned int{data}@0x21d8
80
[237]  38  unsigned int{data}@0x21da
81
[238]  38  unsigned int{data}@0x21dc
82
[239]  38  unsigned int{data}@0x21de
83
[240]  38  unsigned int{data}@0x21e0
84
[241]  37  unsigned int{data}@0x21e2
85
[242]  37  unsigned int{data}@0x21e4
86
[243]  37  unsigned int{data}@0x21e6
87
[244]  37  unsigned int{data}@0x21e8
88
[245]  37  unsigned int{data}@0x21ea
89
[246]  37  unsigned int{data}@0x21ec
90
[247]  36  unsigned int{data}@0x21ee
91
[248]  36  unsigned int{data}@0x21f0
92
[249]  36  unsigned int{data}@0x21f2
93
[250]  36  unsigned int{data}@0x21f4
94
[251]  36  unsigned int{data}@0x21f6
95
[252]  36  unsigned int{data}@0x21f8
96
[253]  36  unsigned int{data}@0x21fa

Bei einem Vorteiler von 10, den du über einen Timer als Zeitbasis für 
die anderen beiden Timer nutzen kannst, gibt es zum für jede 
Geschwindwigkeit einen Integer Wert. Natürlich werden das dann nicht 
"ganze" UpM sein da hier ja auch Rundungen drinnen sind.
1
[0]  0  unsigned int{data}@0x2000
2
[1]  59999  unsigned int{data}@0x2002
3
[2]  29999  unsigned int{data}@0x2004
4
[3]  19999  unsigned int{data}@0x2006
5
[4]  14999  unsigned int{data}@0x2008
6
[5]  11999  unsigned int{data}@0x200a
7
[6]  9999  unsigned int{data}@0x200c
8
[7]  8570  unsigned int{data}@0x200e
9
[8]  7499  unsigned int{data}@0x2010
10
[9]  6665  unsigned int{data}@0x2012
11
[10]  5999  unsigned int{data}@0x2014
12
[11]  5453  unsigned int{data}@0x2016
13
[12]  4999  unsigned int{data}@0x2018
14
[13]  4614  unsigned int{data}@0x201a
15
[14]  4284  unsigned int{data}@0x201c
16
[15]  3999  unsigned int{data}@0x201e
17
[16]  3749  unsigned int{data}@0x2020
18
[17]  3528  unsigned int{data}@0x2022
19
[18]  3332  unsigned int{data}@0x2024
20
[19]  3156  unsigned int{data}@0x2026
21
[20]  2999  unsigned int{data}@0x2028
22
[21]  2856  unsigned int{data}@0x202a
23
[22]  2726  unsigned int{data}@0x202c
24
[23]  2607  unsigned int{data}@0x202e
25
[24]  2499  unsigned int{data}@0x2030
26
[25]  2399  unsigned int{data}@0x2032
27
[26]  2306  unsigned int{data}@0x2034
28
....
29
[222]  269  unsigned int{data}@0x21bc
30
[223]  268  unsigned int{data}@0x21be
31
[224]  266  unsigned int{data}@0x21c0
32
[225]  265  unsigned int{data}@0x21c2
33
[226]  264  unsigned int{data}@0x21c4
34
[227]  263  unsigned int{data}@0x21c6
35
[228]  262  unsigned int{data}@0x21c8
36
[229]  261  unsigned int{data}@0x21ca
37
[230]  259  unsigned int{data}@0x21cc
38
[231]  258  unsigned int{data}@0x21ce
39
[232]  257  unsigned int{data}@0x21d0
40
[233]  256  unsigned int{data}@0x21d2
41
[234]  255  unsigned int{data}@0x21d4
42
[235]  254  unsigned int{data}@0x21d6
43
[236]  253  unsigned int{data}@0x21d8
44
[237]  252  unsigned int{data}@0x21da
45
[238]  251  unsigned int{data}@0x21dc
46
[239]  250  unsigned int{data}@0x21de
47
[240]  249  unsigned int{data}@0x21e0
48
[241]  247  unsigned int{data}@0x21e2
49
[242]  246  unsigned int{data}@0x21e4
50
[243]  245  unsigned int{data}@0x21e6
51
[244]  244  unsigned int{data}@0x21e8
52
[245]  243  unsigned int{data}@0x21ea
53
[246]  242  unsigned int{data}@0x21ec
54
[247]  241  unsigned int{data}@0x21ee
55
[248]  240  unsigned int{data}@0x21f0
56
[249]  239  unsigned int{data}@0x21f2
57
[250]  239  unsigned int{data}@0x21f4
58
[251]  238  unsigned int{data}@0x21f6
59
[252]  237  unsigned int{data}@0x21f8
60
[253]  236  unsigned int{data}@0x21fa

Btw. bei deiner Rechnung gibt es keinen Überlauf zum nicht -O0 
Optimierung. Wenn du aber die 1600 nicht als Float hast stimmen die 
Werte nicht mehr.
Die Werte stammen aus dem Simulator vom Atmel Studio.

Gruß JackFrost

: 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.