AVR128DA Clock Teiler übersehen?!

#7454753
Lesenswert?

Guten Tag zusammen,

ich fange gerade mit den AVR128DA an. Strukturell sind die ähnlich zu den Tiny1 Serie (Tiny1614, Tiny3217) die ich schon viel im Einsatz habe. Allerdings habe ich aktuell Probleme mit der Clock.

Mein Code sieht so aus:

Meiner Auffassung nach, sollte ich da 24 Mhz CPU Clock haben. Wenn ich jetzt aber am Pin Messe, messe ich so genau 2Mhz lt. Osci Frequenz der Rechteckspannung.

1
CPU_CCP = 0xD8;
2
  CLKCTRL.MCLKCTRLA = CLKCTRL_CLKSEL_OSCHF_gc;
3
  CPU_CCP = 0xD8;
4
  CLKCTRL.MCLKCTRLB = 0;
5
  CPU_CCP = 0xD8;
6
  CLKCTRL.OSCHFCTRLA = CLKCTRL_FRQSEL_24M_gc;
7

8
  CPU_CCP = 0xD8;
9
  WDT.CTRLA = 0;
10
  
11

12
  PORTA.DIR = (1<<Pin3bp);
13

14

15
  while(1)
16
  {
17
    PORTA.OUT ^= (1<<Pin3bp);
18
  }

Weiterhin habe ich dann mal einen Timer initalisiert

1
TCD0.CMPBCLR = 150;
2
  TCD0.INTCTRL = TCD_OVF_bm;
3
  TCD0.CTRLB = TCD_WGMODE_ONERAMP_gc;
4
  TCD0.CTRLA = (TCD_CLKSEL_OSCHF_gc | TCD_CNTPRES_DIV32_gc | TCD_SYNCPRES_DIV1_gc | TCD_ENABLE_bm);

der sollte mir 5 khz interrupt bringen. Die ISR sieht so aus

1
ISR(TCD0_OVF_vect)
2
{
3
  PORTA.OUT ^= (1<<Pin3bp);
4
 TCD0.INTFLAGS = TCD_OVF_bm;
5
}

Statt 5khz messe ich nur 2,5 khz Rechteck mit dem Osci.

Ich habe oben als Define 24mhz F_CPU. Wenn ich 5ms delay_ms function in der While mache habe ich auch eher so 7ms statt 5ms. Wenn ich das F_CPU auf 20Mhz stelle habe ich exakt 5ms.

Irgendwie passt hier was nicht vom Timing? Was habe ich nur übersehen !? Bitte um Hilfe.

#7454935
Lesenswert?

Hallo,

meine Initialisierung für den AVRxDB mit 16MHz sieht wie folgt aus.

1
void initInternal16MHzOscillator (void)
2
{    
3
    CPU_CCP = CCP_IOREG_gc;
4
    CLKCTRL.OSCHFCTRLA = (
5
          CLKCTRL_FRQSEL_16M_gc     // default 4MHz
6
        | CLKCTRL_RUNSTDBY_bm       // Run standby: enabled
7
    );
8
  
9
    // wait internal oscillator is stable
10
    while(!(CLKCTRL.MCLKSTATUS & CLKCTRL_OSCHFS_bm))
11
    { ; }
12

13
    // Select Internal Clock Source
14
    CPU_CCP = CCP_IOREG_gc;
15
    CLKCTRL.MCLKCTRLA = CLKCTRL_CLKSEL_OSCHF_gc;        
16
  
17
    // wait for system oscillator changing to finish
18
    while (CLKCTRL.MCLKSTATUS & CLKCTRL_SOSC_bm)
19
    { ; }
20
}

Auch wird ein Pin niemals mit CPU Freq getaktet werden können. Geht praktisch nicht. Für das Ein und AUS wird je ein Takt benötigt. Das heißt es findet eine Halbierung statt. Den halben CPU Takt schafft man nur mit einem Timer der ungestört von allen anderen sein Ding machen kann. In while() in Software kommen noch die benötigten Takte für die Programmabarbeitung hinzu.

Das schnellste Pin Takt in Software funktioniert nur mit Pin Toggle. Pin auf Ausgang konfigurieren und

1
VPORTA.IN = _BV(PIN3_bm);
#7454937
Lesenswert?

...24 Mhz CPU Clock ... messe ich so genau 2Mhz

Kann ja sein, je nachdem, wie der Compiler die while-Schleife gestaltet. Wenn Sie das nicht im lss-File nachsehen wollen, ist der Rat von Peter B. das Gegebene.

sollte mir 5 khz interrupt bringen ... messe ich nur 2,5 khz

Alles korrekt - 'what goes up must come down'.

#7455037
Lesenswert?

Dies hier bringt an A6 4.0 MHz - 1 Takt für das Toggeln des Pins (/sbi/, 2 Takte für das Springen (/rjmp/) im while: 24 MHz / ((1+2)*2) = 4 MHz.

1
#include <avr/io.h>
2
int main(void) {
3
    _PROTECTED_WRITE(CLKCTRL.OSCHFCTRLA,CLKCTRL_FRQSEL_24M_gc);
4
    VPORTA_DIR = 0x40; // A6 als Ausgang
5
    while(1)
6
      VPORTA_IN = 0x40;
7
    ;
8
}

(das mit 'Main Clock Out' an A7 bekomme ich gerade nicht zum Laufen, warum auch immer)

#7455045
Lesenswert?

Noch ein indirekter Nachweis von 24MHz: TCA Frequency Waveform Generation, (100kHz am PE0 vom AVR128DB48).

f = f_clock / (2 × TCA_Prescaler × (CMP0+1))

f = 24000kHz / (2 × 8 × (14+1)) = 100kHz

1
#include <avr/io.h>
2

3
int main(void)
4
{
5
  PORTMUX.TCAROUTEA = PORTMUX_TCA0_PORTE_gc;      // alternative pin positions
6
  PORTE.DIRSET = PIN0_bm;                         // PE0 output
7

8
  TCA0.SINGLE.CTRLB = TCA_SINGLE_CMP0EN_bm | TCA_SINGLE_WGMODE_FRQ_gc;
9
  TCA0.SINGLE.CMP0 = 14;
10
  TCA0.SINGLE.CTRLA = TCA_SINGLE_CLKSEL_DIV8_gc  | TCA_SINGLE_ENABLE_bm;
11

12
  _PROTECTED_WRITE(CLKCTRL.OSCHFCTRLA, CLKCTRL_FRQSEL_24M_gc);
13
 
14
  while(1)
15
  {
16
      
17
  }
18
}
#7455065
Lesenswert?

PS: ich sollte, auch wenn der Tag lang war, das Messgerät richtig bedienen; also nochmal - dies bringt an A7 24 MHz, an A6 4 MHz:

1
#include <avr/io.h>
2
int main(void) {
3
    _PROTECTED_WRITE(CLKCTRL.OSCHFCTRLA,CLKCTRL_FRQSEL_24M_gc);
4
    _PROTECTED_WRITE(CLKCTRL.MCLKCTRLA,CLKCTRL_CLKOUT_bm); // -> A7
5
    VPORTA_DIR = 0x40; // A6 als Ausgang
6
    while(1)
7
      VPORTA_IN = 0x40;
8
    ;
9
}
#7455067
Lesenswert?

Hallo,

der Code lässt auf meinem AVRxDB den ClockOut mit 24MHz takten. Wenn das nicht bei allen klappt wäre schon komisch. Wenn alles andere bei dir funktioniert sollte das eigentlich von alleine funktionieren.

1
void initInternal24MHzOscillator (void)
2
{    
3
    CPU_CCP = CCP_IOREG_gc;
4
    CLKCTRL.OSCHFCTRLA = CLKCTRL_FRQSEL_24M_gc;    // default 4MHz
5
  
6
    // wait internal oscillator is stable
7
    while(!(CLKCTRL.MCLKSTATUS & CLKCTRL_OSCHFS_bm))
8
    { ; }
9

10
    // Select Internal Clock Source and enable Pin Clock Out
11
    CPU_CCP = CCP_IOREG_gc;
12
    CLKCTRL.MCLKCTRLA = (CLKCTRL_CLKSEL_OSCHF_gc | CLKCTRL_CLKOUT_bm);        
13
  
14
    // wait for system oscillator changing to finish
15
    while (CLKCTRL.MCLKSTATUS & CLKCTRL_SOSC_bm)
16
    { ; }
17
}
18

19
int main(void)
20
{
21
    initInternal24MHzOscillator();
22
    
23
    while(1)
24
    {  }
25
}

Edit: Alles klar, in der Hitze des Gefechtes :-)

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren