delay afhankelijk van F_CPU in Atmel studio

Ik heb een printje ontworpen met een Atmega88PA, en ik zou de interne klok van deze microcontroller gebruiken.

Nu ben ik aan het programmeren aangekomen en merkte ik op dat bij het gebruiken van een delay van bijvoorbeeld 20 ms dit varieert samen met de ingestelde frequentie van de processor.

c code:


#define F_CPU 1000000UL //CPU 1Mhz

#include <avr/io.h>
#include <util/delay.h>

int main(void)
{
        DDRD = 0xFF; //PortD output
	
	PORTD = 0x01; //led aan
	_delay_ms(20); //20 ms delay
	PORTD = 0x00; //led uit
}

c code:


#define F_CPU 8000000UL //CPU 8Mhz

#include <avr/io.h>
#include <util/delay.h>

int main(void)
{
        DDRD = 0xFF; //PortD output
	
	PORTD = 0x01; //led aan
	_delay_ms(20); //20 ms delay
	PORTD = 0x00; //led uit
}

Bij de code met CPU frequentie 1Mhz blijft het ledje effectief 30 ms aan, bij de code met CPU frequentie 8Mhz blijft het ledje ongeveer 8x zo lang aan. Weten jullie hoe ik de delay met een CPU frequentie van 8Mhz toch juist kan krijgen?

Ik had ook in de library gelezen dat de maximum delay 262.14 ms / F_CPU in MHz is.
Voor 1Mhz -> 262,14 ms
Voor 8Mhz -> 32,7675 ms
Dit zou dan voor mijn delay van 20 ms geen probleem mogen geven.

Misschien is dit een erg simpel antwoord, maar toch: welke freq heeft die interne oscillator dan? Je moet het instellen zoals de werkelijke freq is.

"We cannot solve our problems with the same thinking we used when we created them" - Albert Einstein

code:

#define F_CPU 1000000UL //CPU 1Mhz

Vertelt alleen maar aan je compiler hoe snel je clock draait, je stelt hem daarmee niet in. Pas je wel de klokfrequentie aan (clkdiv bitje in je fuses, ander kristal/oscillator, clkdiv register)?

Zo goed als het vroeger was, is het nooit geweest.
Lucky Luke

Golden Member

Zo'n delay is een for-lusje waar je processor een aantal keer doorheen gaat om de gewenste hoeveelheid tijd te "verbranden" (Door de gewenste hoeveelheid klokcycli daarmee bezig te zijn).

Die define F_CPU vertelt je compiler hoe snel je CPU loopt, zodat uitgerekend kan worden hoeveel klokcycli die 20 milliseconden nu echt is.

Die moet je dus instellen op de frequentie waarop je CPU ook daadwerkelijk loopt. Althans, als je wilt dat die berekening blijft kloppen :)

Als je 'm 8 keer te hoog instelt, duren je delays uiteraard 8 keer zo lang... Je processor is dan 8 keer trager dan "de compiler" "denkt".

(aanhalingstekens wegens: het is de preprocessor en die rekent het uit, _delay_ms is afaik een macro. Maargoed, de geanthropomorfiseerde vermenselijkte versie daarvan is "dan de compiler denkt")

Eluke.nl | De mens onderscheid zich van (andere) dieren door o.a. complexe gereedschappen en bouwwerken te maken. Mens zijn is nerd zijn. Blijf Maken. (Of wordt, bijvoorbeeld, cultuurhistoricus)
buckfast_beekeeper

Golden Member

Welke IDE gebruik je? Je kan beter de frequentie in je settings zetten. Zo weet je dat die correct is voor alle programma delen die je include. Afhankelijk van je gebruikte IDE gebeurd dit op een andere plaats.

Uiteraard fuses aanpassen aan de reële situatie.

Van Lambiek wordt goede geuze gemaakt.
big_fat_mama

Zie Paulinha_B

Als je nu in c de functies sleep of microsleep gebruikt, dan zouden die (met vriendelijke hulp van de compiler of een van zijn inleidende stadia) dat toch allemaal transparent moeten maken?

Zo zegt toch deze niet_kenner, met meer hoop en vertrouwen dan kennis van deze concrete omgeving...

hoe beter de vraag geschreven, zoveel te meer kans op goed antwoord
buckfast_beekeeper

Golden Member

In Atmel studio 6 klok frequentie beschikbaar maken voor alle libraries.

Alt+F7 (project properties) en dan Toolchain->AVR/GNU C Compiler -> Symbols

http://users.skynet.be/buckfast_beekeeper/CO/ScreenShot037.png

Van Lambiek wordt goede geuze gemaakt.