PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : [ERLEDIGT] Clock-Einstellungen am Atmega32U2 mit AVR Studio 4



pweyrich
04.12.2019, 18:02
Hallo Forum,

ich habe ein Problem mit einem Atmega32U2 (Breakout Board von ehajo, 16MHz-Quartz, Flip als Bootloader). Ich hatte ihn bereits mit BascomAVR programmiert möchte aber auf AVR Studio 4 umsteigen. Die Anleitung hab ich von Stefan Frings.
Das einfache Blink-Programm läuft auf dem µC, aber die erwarteten Zeiten stimmen nicht, anstatt 8s braucht die Hauptschleife 8x solange. Das Timing ist mir sehr wichtig, denn ich will später noch einen virtuellen Com-Port auf dem Chip betreiben.
Im AVR-Studio hab ich 16MHz und Atmega32U2 eingestellt.

Hier der Code:


#include <avr/io.h>
#include <stdint.h>
// #define F_CPU 2000000UL // <- damit komm ich auf die 8s
#include <util/delay.h>

int main(){
CLKSEL0 |= (1 << EXTE); // CKSEL0.EXTE = 1; // Enable_external_clock();
while ( (CLKSTA & (1 << EXTON)) == 0 ){} // while (CLKSTA.EXTON != 1); // while (!External_clock_ready());
CLKSEL0 |= (1 << CLKS); // CLKSEL0.CLKS = 1; // Select_external_clock();
CLKPR = 0b10000000; // Unterschiedliche Einstellungen des Prescalers wirken sich nicht aus.
uint8_t aPLLCSR = PLLE;
aPLLCSR |= PLLP0; // Damit sollten die 16MHz halbiert werden-
PLLCSR |= aPLLCSR; // PLLCSR.PLLE = 1; // Enable_pll();
CLKSEL0 &= ~(1 << RCE); // CLKSEL0.RCE = 0; // Disable_RC_clock();
while ( (PLLCSR & (1 << PLOCK)) == 0){} // while (PLLCSR.PLOCK != 1); // while (!Pll_ready());
USBCON &= ~(1 << FRZCLK); // USBCON.FRZCLK = 0; // Usb_unfreeze_clock();

DDRB=1;
while(1) {
for (uint8_t i=0; i<5; i++){ // 5x1s -> 5s
PORTB=0;
_delay_ms(500);
PORTB=1;
_delay_ms(500);
}
for (uint8_t i=0; i<30; i++){ // 30x 0,1s -> 3s
PORTB=0;
_delay_ms(50);
PORTB=1;
_delay_ms(50);
}
} // Insgesamt 8s, aber es dauert ca. 64s
}


Und die Compiler-Ausgabe:


rm -rf AVR_Test001.o AVR_Test001.elf dep/* AVR_Test001.hex AVR_Test001.eep AVR_Test001.lss AVR_Test001.map
Build succeeded with 0 Warnings...
avr-gcc -mmcu=atmega32u2 -Wall -gdwarf-2 -std=gnu99 -gstrict-dwarf -DF_CPU=16000000UL -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -MD -MP -MT AVR_Test001.o -MF dep/AVR_Test001.o.d -c ../AVR_Test001.c
avr-gcc -mmcu=atmega32u2 -Wl,-Map=AVR_Test001.map AVR_Test001.o -o AVR_Test001.elf
avr-objcopy -O ihex -R .eeprom -R .fuse -R .lock -R .signature AVR_Test001.elf AVR_Test001.hex
avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" --change-section-lma .eeprom=0 --no-change-warnings -O ihex AVR_Test001.elf AVR_Test001.eep || exit 0
avr-objdump -h -S AVR_Test001.elf > AVR_Test001.lss
Build succeeded with 0 Warnings...


Ich würd gern wissen wie es funktioniert, aber zur Not langt mir auch ein funtionierender Code-Schnipsel.

Danke im voraus.

Searcher
04.12.2019, 18:53
Das einfache Blink-Programm läuft auf dem µC, aber die erwarteten Zeiten stimmen nicht, anstatt 8s braucht die Hauptschleife 8x solange.

Hallo,
klingt danach, als wenn die CKDIV8 fuse programmed ist. Die teilt den Takt im Prescaler noch durch 8. Also Fuse Bit unprogrammen oder:

Im CLKPR Register kann man die, von der Fuse gesetzten CLKPS0 und CLKPS1 Bits wieder löschen. Allerdings muß man erst das CLKPCE Bit setzen. Hast Du schon richtig gemacht. Aber es fehlt das Löschen der CLKPCE Bits innerhalb von vier Taktzyklen nach setzen des CLKPCE Bits. Also einfach nochmal das gleiche "CLKPR = 0b10000000;" hinterher





#include <avr/io.h>
#include <stdint.h>
// #define F_CPU 2000000UL // <- damit komm ich auf die 8s
#include <util/delay.h>

int main(){
CLKSEL0 |= (1 << EXTE); // CKSEL0.EXTE = 1; // Enable_external_clock();
while ( (CLKSTA & (1 << EXTON)) == 0 ){} // while (CLKSTA.EXTON != 1); // while (!External_clock_ready());
CLKSEL0 |= (1 << CLKS); // CLKSEL0.CLKS = 1; // Select_external_clock();
CLKPR = 0b10000000; // Unterschiedliche Einstellungen des Prescalers wirken sich nicht aus.
CLKPR = 0b10000000;
uint8_t aPLLCSR = PLLE;
aPLLCSR |= PLLP0; // Damit sollten die 16MHz halbiert werden-
PLLCSR |= aPLLCSR; // PLLCSR.PLLE = 1; // Enable_pll();
CLKSEL0 &= ~(1 << RCE); // CLKSEL0.RCE = 0; // Disable_RC_clock();
while ( (PLLCSR & (1 << PLOCK)) == 0){} // while (PLLCSR.PLOCK != 1); // while (!Pll_ready());
USBCON &= ~(1 << FRZCLK); // USBCON.FRZCLK = 0; // Usb_unfreeze_clock();

DDRB=1;
while(1) {
for (uint8_t i=0; i<5; i++){ // 5x1s -> 5s
PORTB=0;
_delay_ms(500);
PORTB=1;
_delay_ms(500);
}
for (uint8_t i=0; i<30; i++){ // 30x 0,1s -> 3s
PORTB=0;
_delay_ms(50);
PORTB=1;
_delay_ms(50);
}
} // Insgesamt 8s, aber es dauert ca. 64s
}



Auszug aus Datenblatt 7799E–AVR–09/2012 zum CLKPR Register im ATmega32U2:
• Bit 7 – CLKPCE: Clock Prescaler Change Enable
The CLKPCE bit must be written to logic one to enable change of the CLKPS bits. The CLKPCE
bit is only updated when the other bits in CLKPR are simultaneously written to zero. CLKPCE is
cleared by hardware four cycles after it is written or when CLKPS bits are written. Rewriting the
CLKPCE bit within this time-out period does neither extend the time-out period, nor clear the
CLKPCE bit.

Gruß
Searcher

pweyrich
05.12.2019, 09:56
Hallo Searcher,

es ist die CLKPR wie vermutet. Allerdings ist die Beschreibung des Datenblatts nicht sehr klar - ein Timing-Sheet wäre schön.
34551

Die Lösung geht aber ein wenig anders als du es gedacht hast.



// Vorteiler -> 1
CLKPR = 0b1000000; //Enable gesetzt und gleichzeitig alle anderen Bits auf NULL
CLKPR = 0b0000000; //Danach Enable wegnehmen und die gewünschte CLKPS setzen, hier Faktor 1 deshalb die letzten 4 Bits 0000.




// Vorteiler -> 4
CLKPR = 0b1000000; //Enable gesetzt und gleichzeitig alle anderen Bits auf NULL
CLKPR = 0b0000010; //Danach Enable wegnehmen und die gewünschte CLKPS setzen, hier Faktor 4 deshalb die letzten 4 Bits 0010.


Warum sehe ich die Taste für die Code-Formatierung nicht??!! -> Weil ich unten auf die Taste ERWEITERT klicken muss!

Ich stell den Beitrag noch nicht auf gelöst, denn ich will erst noch abwarten ob der virtuelle COM-Port auch funktioniert.
Damit mich nichts anderes stört hab ich alle anderen Clock-Settings auskommentiert.

Searcher
06.12.2019, 07:18
... es ist die CLKPR wie vermutet. ...
Die Lösung geht aber ein wenig anders als du es gedacht hast. ...
Ich hatte vor einiger Zeit auch mit der Taktumstellung experimentiert. Konnte mich aber nur sicher an das zweimalige Schreiben innerhalb einer gewissen Zeit erinnern. Schön, daß es wenigstens zur richtigen Richtung gereicht hat.

Gruß
Searcher

pweyrich
07.12.2019, 17:31
Hallo Forum,

ich hab jetzt den virtuellen COM-Port mit LUFA und AS4 zum Laufen bekommen - hat ein bißchen gedauert, aber jetzt läufts. Ich hab dann zusätzlich den Blinker in die Hauptschleife gesetzt um zu die Blinkfrequenz zu testen und siehe da, durch den ganzen LUFA-Source brauch ich gar nichts mehr einzustellen.

So jetzt will ich das Thema noch auf gelöst stellen.

Habt nochmal Dank für Eure Hilfe, ganz besonders Searcher.

PS: Wie kann ich das Thema als gelöst, erledigt oder ähnliches stellen??

Manf
07.12.2019, 19:48
Das Erledigt gibt es in der Kopfzeile unter Themen Optionen

34552