Forum: Mikrocontroller und Digitale Elektronik AVR128DA Clock Teiler übersehen?!


von Markus M. (atmelfreak100)


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.

von Peter B. (gast_123)


Lesenswert?

Setze zusätzlich das Bit7 "Main Clock Out" im MCLKCTRLA Register.
Danach kannst Du am Port PA7 "CLKOUT" den Systemtakt nachmessen.

von Veit D. (devil-elec)


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);

von S. L. (sldt)


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

von S. L. (sldt)


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)

von Georg M. (g_m)


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
}

von Veit D. (devil-elec)


Lesenswert?

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;

: Bearbeitet durch User
von S. L. (sldt)


Lesenswert?

an Veit Devil:
Danke für den Hinweis, aber das hatte ich bereits probiert: sowohl auf 
dem AVR128DA28 als auch dem AVR128DB28 kommen da immer nur 4 MHz auf A7 
- ich hatte die 24 erwartet. Oder verstehe ich das Datenblatt falsch?

von S. L. (sldt)


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
}

von Veit D. (devil-elec)


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

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