Forum: Mikrocontroller und Digitale Elektronik ATmega328 CLKDIV8 geht nicht


von Jch (Gast)


Lesenswert?

Hallo,

ich habe einen ATmega328 (Arduino Nano) und möchte diesen gerne auf 1MHz 
laufen lassen.
Mein Programm konnte unter den 16MHz vom Auslieferunszustand wunderbar 
den DS18B20 und das 1602LCD betreiben. Als ich den PID Regler von der 
Atmel Application Note 221 integrieren wollte, stand drin, dass man den 
PID Rechenzyklus auf ca. 1 Hz bringen soll.

Also den Timer Prescaler für den PID auf 1024 gesetzt und F_CPU auf 
1000000UL gesetzt und die Fuses für den Internen 8MHz Oszillator und 
CLKDIV8 aktiviert.

Jetzt geht gar nix mehr. Weder Display noch DS18B20.

Wenn ich die CKOUT Fuse aktiviere, kann ich an PB0 den 8MHz Tackt 
messen. Warum ändert sich dieser Tackt nicht, wenn ich die Fuse CLKDIV8 
aktiviere und deaktiviere?

Das müsste doch 100% Code-Unabhängig sein. Egal was ich da für einen 
Mist zusammengeschrieben habe. Weil wenn ich die CKOUT Fuse setze und 
resette, kann ich das ja sofort am Oszi messen. Warum geht das mit dem 
Tacktdividierer nicht?


Umgebung: AtmelStudio 7
Programmer: AVR Dragon über ISP

Kann mir jemand helfen?

Danke

von Stefan F. (Gast)


Lesenswert?

Laut Datenblatt sollte das gehen: "If the system clock prescaler is 
used, it is the divided system clock that is output. "

Hast du das Ding mal kurz Stromlos gemacht, nachdem du die Fuses 
geändert hast?

von Jch (Gast)


Lesenswert?

Danke Stefan, dass Du das genauso siehst.

Ja, ich habe sogar die verschiedenen Delaytimes bei den 8MHz Fuses 
ausprobiert und jedesmal einen Power-Reset gemacht.

Bringt leider nix. Der schwingt stur auf 8 Mhz.

Im DaBla konnte ich auch keinen Verweis finden, dass man noch andere 
Fuses o.ä. setzen muss?!

Grüße
Jch

von Einer K. (Gast)


Lesenswert?

Jch schrieb:
> PID Rechenzyklus auf ca. 1 Hz bringen soll.

Das  macht man auf anderem Wege, als den SystemTakt runter zu setzen.
Dafür verwendet man z.B. einen der Timer.

Jch schrieb:
> Warum ändert sich dieser Tackt nicht, wenn ich die Fuse CLKDIV8
> aktiviere und deaktiviere?
Muss es !

Also machst du was falsch.
Sicher, dass du nicht nur den Simulator befummelst?

von Jch (Gast)


Lesenswert?

Arduino Fanboy D. schrieb:
>> PID Rechenzyklus auf ca. 1 Hz bringen soll.
>
> Das  macht man auf anderem Wege, als den SystemTakt runter zu setzen.
> Dafür verwendet man z.B. einen der Timer.

Ähm ja. Aber bei 16 MHz und 8 Bit Timer und 1024er Prescaler komme ich 
leider nicht wirklich nahe an den 1Hz Tackt ran und warum sollte ich 
nicht den Systemtackt reduzieren dürfen? 1 MHz braucht weniger Leistung 
als 16 MHz und den Quarz brauche ich nicht für die Genauigkeit.

Wenn ich den 128 kHz Oszillator auswähle, geht mein Tackt auf die 128kHz 
runter, aber auch hier geht der CLKDIB8 nicht. Also auf 16kHz geht der 
Pin nicht runter.
Auch meine PWM Timer ändern ihren Tackt nicht, egal ob den DIV8 
aktiviere oder nicht.

Und der 1 MHz Tackt hätte noch den Vorteil, dass mein PWM MOSFET nicht 
so heiss werden würde, weil der für die Heizung keine besonders hohe 
frequenz schalten muss.

Grüße
Jch

von Jch (Gast)


Lesenswert?

Arduino Fanboy D. schrieb:
> Jch schrieb:
>> Warum ändert sich dieser Tackt nicht, wenn ich die Fuse CLKDIV8
>> aktiviere und deaktiviere?
> Muss es !

das denke ich auch, aber was mache ich falsch? Gibts da geheime 
Hinterürchen?

Arduino Fanboy D. schrieb:
> Sicher, dass du nicht nur den Simulator befummelst?

Nein, ansonsten könnte ich ja weder mit den 8MHz und 128 kHz am Oszi 
spielen, noch würde ich mit dem CLKOUT Pin rumspielen können.

Und man kann auf dem Display den RESET beim flashen erkennen.

Grüße
Jch

von Jch (Gast)


Angehängte Dateien:

Lesenswert?

Hier noch die Fuses im Detail

von Jch (Gast)


Lesenswert?

Problem gelöst. Ob das die Ursche war, möchte ich Bezweifeln.

Ich habe einen Chip Erase gemacht und einfach nochmal mit den Fuses 
gespielt. Nach dem Chip Erase konnte ich einfach so zwischen CLKVIV8 und 
nicht-CLKDIV8 wechseln und am Oszi tut sich auch was.

Sehr merkwürdig. Ich dachte der Code auf dem Chip ist hierfür 
irrelevant.

Sobald ich wieder den Code auf den µC hochlade, bin ich wieder bei 8 
MHz.
Irgendwer überschreibt mir die Fuses. Kann das an den Toolchain 
Compilereinstellungen liegen?

Wenn ja, wo muss ich da suchen? Bzw. nach was muss man da Googlen? Das 
ist komplettes Neuland für mich
1
-x c -funsigned-char -funsigned-bitfields -DDEBUG  -I"C:\Program Files (x86)\Atmel\Studio\7.0\Packs\Atmel\ATmega_DFP\1.4.351\include" -I"../Config" -I"../include" -I"../utils" -I"../utils/assembler" -I".."  -O1 -ffunction-sections -fdata-sections -fpack-struct -fshort-enums -g2 -Wall -mmcu=atmega328p -B "C:\Program Files (x86)\Atmel\Studio\7.0\Packs\Atmel\ATmega_DFP\1.4.351\gcc\dev\atmega328p" -c -std=gnu99 -MD -MP -MF "$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -MT"$(@:%.o=%.o)"

von Hugo H. (hugohurtig1)


Lesenswert?

Jch schrieb:
> Mein Programm

Sehe ich das hier irgendwo?

von Stefan F. (Gast)


Lesenswert?

Jch schrieb:
> Irgendwer überschreibt mir die Fuses.

Ich tippe eher darauf, dass dein eigenes Programm den Prescaler CLKPR 
verändert und dadurch die Fuse unwirksam macht.

von Holger L. (max5v)


Lesenswert?

Jch schrieb:
> Sehr merkwürdig. Ich dachte der Code auf dem Chip ist hierfür
> irrelevant.

GCC power.h -> 
https://www.nongnu.org/avr-libc/user-manual/group__avr__power.html

Der Bootloader wird anscheinend auch immer mit programmiert?

Jch schrieb:
> Irgendwer überschreibt mir die Fuses. Kann das an den Toolchain
> Compilereinstellungen liegen?

Wird die .elf Datei oder die .hex hochgeladen?

von Jch (Gast)


Lesenswert?

Stefan ⛄ F. schrieb:
> Jch schrieb:
>> Irgendwer überschreibt mir die Fuses.
>
> Ich tippe eher darauf, dass dein eigenes Programm den Prescaler CLKPR
> verändert und dadurch die Fuse unwirksam macht.

Tatsächlich im Init vom PID-Code wird der CLKPR auf Prescaler 1 gesetzt. 
Somit muss ich mein Verständnis über fuses nochmal updaten. Ich dachte 
Fuses sind mächtiger als der Code. Somit habe ich nicht im Code danach 
gesucht.

Holger L. schrieb:
> Der Bootloader wird anscheinend auch immer mit programmiert?

naja, das war noch eine Arduino-Leiche. Ich nutze keinen Bootloader.

Holger L. schrieb:
> Jch schrieb:
>> Irgendwer überschreibt mir die Fuses. Kann das an den Toolchain
>> Compilereinstellungen liegen?
>
> Wird die .elf Datei oder die .hex hochgeladen?

ich nehme die .hex. Würde die .elf einen Unterschied machen? Die ist 
doch nur dazu da um andere Einstellungen wie z.B.Fuses auch mit zu 
flashen oder?

Danke schonmal. Da wäre ich warscheinlich so schnell nicht draufgekommen

von Oliver S. (oliverso)


Lesenswert?

Jch schrieb:
> Somit muss ich mein Verständnis über fuses nochmal updaten. Ich dachte
> Fuses sind mächtiger als der Code.

Sind sie. Aber du solltest mal nachlesen, was die CLKDIV8-Fuse 
eigentlich tut.

Oliver

von Christian S. (roehrenvorheizer)


Lesenswert?

"388025I–AVR–02/09  ATmega48P/88P/168P/328P   Seite 38
The CKDIV8 Fuse determines the initial value of the CLKPS bits. If 
CKDIV8 is unprogrammed,the CLKPS bits will be reset to “0000”. If CKDIV8 
is programmed, CLKPS bits are reset to“0011”, giving a division factor 
of 8 at start up. This feature should be used if the selected 
clocksource has a higher frequency than the maximum frequency of the 
device at the present operat-ing conditions. Note that any value can be 
written to the CLKPS bits regardless of the CKDIV8Fuse setting. The 
Application software must ensure that a sufficient division factor is 
chosen ifthe selected clock source has a higher frequency than the 
maximum frequency of the device atthe present operating conditions. The 
device is shipped with the CKDIV8 Fuse programmed"

mfG

: Bearbeitet durch User
von Das nervt (Gast)


Lesenswert?

Jch schrieb:
> Tackt
> ...
> Tacktdividierer

Jch schrieb:
> 1Hz Tackt
> ...
> Systemtackt
> ...
> 1 MHz Tackt

von der nixwois (Gast)


Lesenswert?

@Jch

Hallo!
Ich habe hier auch den Arduino Nano V3 und hab mal nachgeschaut ob die 
1Mhz
für den Internen Oszilator überhaupt gibt. Leider Nein.

Aber vllt. hilft  dir das weiter:

Bei gestztem CLKDIV8 einfach mal F_CPU   8MHz, 4MhZ und 1Mhz
mit den Werten Spielen und beobachten was passiert.




#ifndef F_CPU            // kann auch im Makefile definiert sein
//#define F_CPU 16000000UL // Takt als LONG definieren, da zu groß für 
Integer
#define F_CPU 1000000UL // Takt als LONG definieren, da zu groß für 
Integer
#endif



#include <avr/io.h>     // Namen der IO Register
#include <util/delay.h> // Funktionen zum warten

// Achtung, damit delay richtig funktioniert muß mit Optimierung 
compiliert werden

int main(void)
{
    unsigned char test_c;

    // LED an Port PB0 ist Low Aktiv angeschlossen

    PORTB = 0x01;       // Nur Pin PB0 aktiv
    DDRB  = 0x01;       // PB0 als Ausgang definieren
    while (1)
    {

        PORTB &= ~(1<<PB0);
        _delay_ms(200);
        PORTB |= (1<<PB0);
        _delay_ms(200);
    }
}

von der nixwois (Gast)


Lesenswert?

@Jch

Was passiert wenn Bei gestztem CLKDIV8 und 16 Mhz mit dem Blinkprogramm?

Richtig! Die Blinkfrequenz wird langsammer.

Es dürfte deinem Ziel schon näher kommen!

Gute Nacht!

von MaWin (Gast)


Lesenswert?

der nixwois schrieb:
> // Takt als LONG definieren, da zu groß für
> Integer

Der Kommentar ist falsch!

von Einer K. (Gast)


Lesenswert?

Auf jeden Fall!
1. long ist auch ein Integer
2. long wird automatisch verwendet, wenn das Literal nicht in int passt
3. Das U könnte allerdings sinnvoll sein

von hab auch keinen Plan (Gast)


Lesenswert?

MaWin schrieb:
> Der Kommentar ist falsch!

Tut mir Leid ist aus einem anderem bsp. kopiert

von MaWin (Gast)


Lesenswert?

@Arduino Fanboy D.
Komm mal runter, ist ja wirklich schlimm mit dir. Es ist Entschleunigung 
angesagt. ;->

von Jch (Gast)


Lesenswert?

Oliver S. schrieb:
> Jch schrieb:
>> Somit muss ich mein Verständnis über fuses nochmal updaten. Ich dachte
>> Fuses sind mächtiger als der Code.
>
> Sind sie. Aber du solltest mal nachlesen, was die CLKDIV8-Fuse
> eigentlich tut.

ich habe es im DaBla nachgelesen, aber anscheinend anders interprätiert, 
als es gedacht ist.

Christian S. schrieb:
> Note that any value can be
> written to the CLKPS bits regardless of the CKDIV8Fuse setting.

ich habe das so verstanden, als ob man beim CLKPS z.B. ein Prescaler von 
8 einstellen kann und die CKDIV8-Fuse das nochmal dividiert, sodass man 
auf einen Prescaler von 64 kommt.

der nixwois schrieb:
> Hallo!
> Ich habe hier auch den Arduino Nano V3 und hab mal nachgeschaut ob die
> 1Mhz
> für den Internen Oszilator überhaupt gibt. Leider Nein.

danke dafür, aber wenn ich ein Oszi habe und den Clock direkt auf einen 
Pin herausführen kann, muss ich kein Blinklicht mitstoppen ;-)
Klar hat der 328 keinen echten 1 MHz Clock, sondern nur einen vom 8 Mhz 
RC welcher durch 8 geteilt wird durch die Fuse (oder durch andere Werte 
mit dem Höllenregister)


Ich habe doch schon in folgendem Beitrag die Lösung geschrieben:

Jch schrieb:
> Stefan ⛄ F. schrieb:
>> Jch schrieb:
>>> Irgendwer überschreibt mir die Fuses.
>>
>> Ich tippe eher darauf, dass dein eigenes Programm den Prescaler CLKPR
>> verändert und dadurch die Fuse unwirksam macht.
>
> Tatsächlich im Init vom PID-Code wird der CLKPR auf Prescaler 1 gesetzt.
> Somit muss ich mein Verständnis über fuses nochmal updaten. Ich dachte
> Fuses sind mächtiger als der Code. Somit habe ich nicht im Code danach
> gesucht.

Dieses Problem mit dem Takt ist gelöst, aber im Moment kämpfe ich noch 
mit den Rückgabewerten vom PID Regler. Aber das ist eine andere 
Geschichte...

von spess53 (Gast)


Lesenswert?

Hi

>ich habe das so verstanden, als ob man beim CLKPS z.B. ein Prescaler von
>8 einstellen kann und die CKDIV8-Fuse das nochmal dividiert, sodass man
>auf einen Prescaler von 64 kommt.

Nein. Es gibt nur einen Prescaler. Beim setzen der CKDIV8-Fuse wird 
dieser auf einen Teiler von 8 gestellt. Mit dem Setzen eines anderen 
Prescalers wird das überschrieben.

MfG Spess

von Christian S. (roehrenvorheizer)


Lesenswert?

>ich habe es im DaBla nachgelesen, aber anscheinend anders interprätiert, >als es 
gedacht ist.

>Christian S. schrieb:

>Note that any value can be
>written to the CLKPS bits regardless of the CKDIV8Fuse setting.

>ich habe das so verstanden, als ob man beim CLKPS z.B. ein Prescaler von 8 
>einstellen kann und die CKDIV8-Fuse das nochmal dividiert, sodass man auf >einen 
Prescaler von 64 kommt."

Also liegt es am fremdländischen Englisch.
Der Satz heißt:

Beachte, daß jeder Wert in die clkps-Bits geschrieben werden kann, ohne 
Beachtung der/Rücksicht auf die Fuse-Einstellung.



Das bedeutet, daß die Fuse überschrieben werden kann. Sie stellt nur 
einen Anfangswert beim Start dar, der durch das Programm jederzeit 
geändert werden kann. Man kann es auch so verstehen, wie Du oben 
geschrieben hast. Das wäre eigentlich naheliegend, entspricht aber nicht 
dem Wortlaut des Autors.


MfG

: Bearbeitet durch User
von Rainer V. (a_zip)


Lesenswert?

spess53 schrieb:
> Nein. Es gibt nur einen Prescaler. Beim setzen der CKDIV8-Fuse wird
> dieser auf einen Teiler von 8 gestellt. Mit dem Setzen eines anderen
> Prescalers wird das überschrieben.

Hallo, ich arbeite mich auch gerade in die Clock/Timer-Geschichten ein 
und habe in der Docu gefunden, dass neben dem System-Clock-Prescaler 
Timer0/1 und Timer2 jeweils noch einen "eigenen" Prescaler haben 
(können). Verstehe ich das richtig?
Gruß Rainer

von Einer K. (Gast)


Lesenswert?

Der ADC UART TWI SPI haben auch noch Teiler!
Gibt also Mengen davon.

Alle diese hängen (meist) am Systemtakt.
Sind also dem CLKPS untergeordnet.

Rainer V. schrieb:
> dass neben dem System-Clock-Prescaler
Nicht neben, sondern unter, in der Hierarchie.

von Oliver S. (oliverso)


Lesenswert?

Rainer V. schrieb:
> Verstehe ich das richtig?

Tust du, das hat aber mit dem Thema des Threads wenig zu tun.

Oliver

: Bearbeitet durch User
von Jch (Gast)


Lesenswert?

Hallo,

ich bin gerade dabei den PID Regler einzubinden. Er funktioniert 
halbwegs, aber der Integrierer ist zu fleissig. Wie kann ich das 
Anti-Wind-Up einprogrammieren?

In der AVR221 AppNote 
(https://www.microchip.com/wwwAppNotes/AppNotes.aspx?appnote=en591227)
ist der Quellcode für den PID Regler. Wo sollte ich jetzt dem Integrator 
einen Strich durch die Rechnung machen?
1
 
2
// Calculate Iterm and limit integral runaway
3
  temp = pid_st->sumError + errors;
4
  if (temp > pid_st->255) {//maxSumError;
5
    i_term           = 255;//MAX_I_TERM;
6
    pid_st->sumError = pid_st->255;//maxSumError;
7
  } else if (temp < -pid_st->0) {//maxSumError;
8
    i_term           = 0;//-MAX_I_TERM;
9
    pid_st->sumError = -pid_st->0;//maxSumError;
10
  } else {
11
    pid_st->sumError = temp;
12
    i_term           = pid_st->I_Factor * pid_st->sumError;
13
  }

Die auskommentierten Werte sind die aus dem originalen Code und die 0 
und 255 kommt von mir.
Was mache ich falsch? Weil so funktioniert es nicht. Der C++ Code ist 
mir bisher noch nicht geläufig.
Ich will ja den Ausgang vom Regler auf 256 skalieren, weil es auf einem 
PWM Ausgang geht.


Grüße
Jch

von Rainer V. (a_zip)


Lesenswert?

Oliver S. schrieb:
> Tust du, das hat aber mit dem Thema des Threads wenig zu tun.

Ja, ich weiss, aber der TO hat die Timer-Prescaler wohl nicht auf dem 
Schirm und ich habe mich eben gefragt, ob ich da mit meinen 
"Erkenntnissen" ganz falsch liege. Sorry und danke :-)
Rainer

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.