AVR128DA Clock Teiler übersehen?!

OP #7454753

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

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

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

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

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
}
#7455047

S. L. schrieb:

Hallo,

du gehst von Default aus das die interne Taktquelle verwendet wird. Kann man machen, auch wenn das nicht so schön lesbar ist. ;-) Aber he du C geschrieben. :-) :-)

Wegen ClockOut.

1
CLKCTRL.MCLKCTRLA = (CLKCTRL_CLKSEL_OSCHF_gc | CLKCTRL_CLKOUT_bm);  
2
oder bei Default nur 
3
CLKCTRL.MCLKCTRLA = CLKCTRL_CLKOUT_bm;
#7455065

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

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

Eine eigene Frage? Dieser Thread ist über 3 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.