Operácie

Oneskorenia s AVR: Rozdiel medzi revíziami

Z SensorWiki

Riadok 1: Riadok 1:
ToDo: prelozit a poriadne sformulovat
 
 
  
 
== '''Poznámka k používaniu fukncie'''  _delay_ms() ==
 
== '''Poznámka k používaniu fukncie'''  _delay_ms() ==
  
  
void _delay_ms ( double  __ms )
+
Funkcia _delay_ms() pozdrží dobu vykonávania programu na čas zadaný argumentom funkcie. Aby funkcia správne fungovala na rozličných procesoroch v rozličných konfiguráciach, potrebuje vedieť, akou frekvenciou procesor pracuje. Robí sa to tak, že zadefinujeme makro F_CPU ako frekvenciu v Hz. Pre Arduino kompatibilné dosky je to
 
+
<source lang="cpp" style="background: LightBlue;">
 +
#define F_CPU 16000000UL
 +
</source>
  
Perform a delay of __ms milliseconds, using _delay_loop_2().
+
Niekedy je však výhodné použiť ten istý zdrojový kód programu aj viackrát a preto nie je dobré priamo vkladať frekvenciu do kódu. Dá sa to urobiť aj dodatočne, definovaním hodnoty v príkazoch pre prekladač.
 +
V Atmel Studio je prístup cez Project > (ProjectName) Properties > Toolchain > AVR/GNU C Compiler > Symbols, treba tam potom pridať takýto výraz
 +
F_CPU=16000000
 +
pozrite aj obrázok.
  
The macro F_CPU is supposed to be defined to a constant defining the CPU clock frequency (in Hertz).
+
<div style='text-align: center;'>
 +
[[Súbor:MIPS_AtmelStudioFCPU.png|300px]]<BR>
 +
''Vkladanie informácie o frekvencii procesora pre kompilátor.''
 +
</div>
  
The maximal possible delay is 262.14 ms / F_CPU in MHz.
+
Funkcia je deklarovaná nasledovne
  
Citovane z avr library documentation of delay.h http://www.nongnu.org/avr-libc/user-manual/group__util__delay.html
+
<source lang="cpp" style="background: LightBlue;">
 +
void _delay_ms (  double  __ms ) 
 +
// Perform a delay of __ms milliseconds, using _delay_loop_2()
 +
</source>
  
If you look at delay.h, you'll see the following comment:
+
Vyššie uvedená deklarácia funkcie, ktorá je predpripravená spolu s kompilátorom avr-gcc nám hovorí, že argumentom je počet milisekúnd oneskorenia, ktorým môže byť až  32-bitové celé čislo (double long int) alebo desatinné čislo s dvojitou presnosťou (double). Ktorá verzia je platná záleží na parametroch kompilátora (či zapneme aj používanie plávajúcej aritmetiky float, ktorá je default vypnutá, pretože zaberá veľa miesta).
 +
Zdalo by sa teda, že napríklad vytvoriť oneskorenie 1 sekunda je celkom jednoduché, stačí ako parameter vložiť číslo 1000.
  
    The maximal possible delay is 262.14 ms / F_CPU in MHz.
+
Nie je to však také jednoduché. Dokumentácía k prekladaču<ref group="REF">AVR Library [http://www.nongnu.org/avr-libc/user-manual/group__util__delay.html documentation of 'delay.h'].</ref> sa píše doslova
 
+
The maximal possible delay is (262.14 ms/F_CPU) where F_CPU is in MHz.  
So, running at 16 MHz, the maximum delay with _delay_ms is 16 milliseconds.
+
Podobná poznámka je aj priamo v delay.h a pre frekvenciu 16 MHz to znamená, že maximálne oneskorenie, ktoré vieme touto funkciou vygenerovať je '''16 milisekúnd'''! Preto si musíme napísať vlastnú funkciu,  
 
+
ktorá bude volať _delay_ms() s nejakým rozumným parametrom (1ms alebo 10ms) a tak dosiahneme potrebné dlhšie oneskorenia.  
 
+
 
+
<source lang="cpp" style="background: LightBlue;">
Tried this from scratch, compiled with -O1 on WinAVR 20060421 for an ATmega8, Frequency to 8 MHz, set up on AVR Studio 4.12 SP2 build 472, and it includes the full math library. Recompiling with -O2 the math library isn't included.GCC 3.4.6 doesn't optimize the FP math away with
+
// this wrapper function calls _delay_ms with a known value of 1
only -O1. It does with -Os though (which is IMHO the most
+
// if you call _delay_ms(variable) then the floating point library
recommendable optimization level for the AVR anyway).
+
// is going to be included and your output file gets much larger
Alternatively, add -fgcse, and it will optimize them as well.
 
 
 
Interestingly enough, GCC 4.1.0 optimizes these even with -O1.
 
  
void delay_1s(void)
+
void delay_1ms(uint16_t ms)  
 
{
 
{
  uint8_t i;
+
    uint16_t i;
  for (i = 0; i < 100; i++)
+
    for(i=0;i<ms;i++)  
       _delay_ms(10);
+
       _delay_ms(1);
 
}
 
}
 +
</source>
 +
 +
A na záver ešte jedna poznámka, že hodnota oneskorenia by mala byť kompilátoru známa v čase prekladu, aby mohol daný výraz vyhodnotiť a nahradiť ho výsledkom. V opačnom prípade je na počet cyklov použitý výpočet, ktorý vyvolá potrebu použitie kniznice pre pracu s reálnymi číslami math.h čím veľkosť programu vzrastie o viac ako 2kB.
  
Alebo
 
  
// this wrapper function calls _delay_ms with a known value of 1
+
Celkom na záver pozorovanie, ktoré sme však zatiaľ neoverovali, že ak kompulátor optimalizuje preklad s prepínačom -O1, pribalí aj celú math knižnicu, ale už -O2 ju vynechá. Podobne je to pre -Os.
// if you call _delay_ms(variable) then the floating point library
 
// is going to be included and your output file gets much larger
 
void delay_1ms(uint16_t ms) {
 
    uint16_t i;
 
    for(i=0;i<ms;i++) _delay_ms(1);
 
}
 
  
A tu je este poznamka, ze hodnota musi byt znama v case prekladu, takze kompilator moze vyraz vyhodnotit a nahradit ho vysledkom. V opacnom pripade je na pocet cyklov pouzity vypocet, ktory  vyvola pouzitie kniznice pre pracu s realnymi cislami math.h cim program vzrastie o viac ako 2kB.
 
  
The functions in this header file are wrappers around the basic busy-wait functions from <util/delay_basic.h>. They are meant as convenience functions where actual time values can be specified rather than a number of cycles to wait for. The idea behind is that compile-time constant expressions will be eliminated by compiler optimization so floating-point expressions can be used to calculate the number of delay cycles needed based on the CPU frequency passed by the macro F_CPU.
 
  
Note
 
    In order for these functions to work as intended, compiler optimizations must be enabled, and the delay time must be an expression that is a known constant at compile-time. If these requirements are not met, the resulting delay will be much longer (and basically unpredictable), and applications that otherwise do not use floating-point calculations will experience severe code bloat by the floating-point library routines linked into the application.
 
  
The functions available allow the specification of microsecond, and millisecond delays directly, using the application-supplied macro F_CPU as the CPU clock frequency (in Hertz).
 
  
  
 
[[Category:AVR]][[Category:MIPS]]
 
[[Category:AVR]][[Category:MIPS]]

Verzia zo dňa a času 10:26, 8. február 2021

Poznámka k používaniu fukncie _delay_ms()

Funkcia _delay_ms() pozdrží dobu vykonávania programu na čas zadaný argumentom funkcie. Aby funkcia správne fungovala na rozličných procesoroch v rozličných konfiguráciach, potrebuje vedieť, akou frekvenciou procesor pracuje. Robí sa to tak, že zadefinujeme makro F_CPU ako frekvenciu v Hz. Pre Arduino kompatibilné dosky je to

#define F_CPU 16000000UL

Niekedy je však výhodné použiť ten istý zdrojový kód programu aj viackrát a preto nie je dobré priamo vkladať frekvenciu do kódu. Dá sa to urobiť aj dodatočne, definovaním hodnoty v príkazoch pre prekladač. V Atmel Studio je prístup cez Project > (ProjectName) Properties > Toolchain > AVR/GNU C Compiler > Symbols, treba tam potom pridať takýto výraz

F_CPU=16000000

pozrite aj obrázok.

MIPS AtmelStudioFCPU.png
Vkladanie informácie o frekvencii procesora pre kompilátor.

Funkcia je deklarovaná nasledovne

 void _delay_ms 	(  	double  	__ms 	 )  	
 // Perform a delay of __ms milliseconds, using _delay_loop_2()

Vyššie uvedená deklarácia funkcie, ktorá je predpripravená spolu s kompilátorom avr-gcc nám hovorí, že argumentom je počet milisekúnd oneskorenia, ktorým môže byť až 32-bitové celé čislo (double long int) alebo desatinné čislo s dvojitou presnosťou (double). Ktorá verzia je platná záleží na parametroch kompilátora (či zapneme aj používanie plávajúcej aritmetiky float, ktorá je default vypnutá, pretože zaberá veľa miesta). Zdalo by sa teda, že napríklad vytvoriť oneskorenie 1 sekunda je celkom jednoduché, stačí ako parameter vložiť číslo 1000.

Nie je to však také jednoduché. Dokumentácía k prekladaču[REF 1] sa píše doslova

The maximal possible delay is  (262.14 ms/F_CPU) where F_CPU is in MHz. 

Podobná poznámka je aj priamo v delay.h a pre frekvenciu 16 MHz to znamená, že maximálne oneskorenie, ktoré vieme touto funkciou vygenerovať je 16 milisekúnd! Preto si musíme napísať vlastnú funkciu, ktorá bude volať _delay_ms() s nejakým rozumným parametrom (1ms alebo 10ms) a tak dosiahneme potrebné dlhšie oneskorenia.

// this wrapper function calls _delay_ms with a known value of 1
// if you call _delay_ms(variable) then the floating point library
// is going to be included and your output file gets much larger

void delay_1ms(uint16_t ms) 
{
    uint16_t i;
    for(i=0;i<ms;i++) 
      _delay_ms(1);
}

A na záver ešte jedna poznámka, že hodnota oneskorenia by mala byť kompilátoru známa v čase prekladu, aby mohol daný výraz vyhodnotiť a nahradiť ho výsledkom. V opačnom prípade je na počet cyklov použitý výpočet, ktorý vyvolá potrebu použitie kniznice pre pracu s reálnymi číslami math.h čím veľkosť programu vzrastie o viac ako 2kB.


Celkom na záver pozorovanie, ktoré sme však zatiaľ neoverovali, že ak kompulátor optimalizuje preklad s prepínačom -O1, pribalí aj celú math knižnicu, ale už -O2 ju vynechá. Podobne je to pre -Os.
Chyba citácie Značky <ref> pre skupinu „REF“ sú prítomné, ale nebola nájdená zodpovedajúca značka <references group="REF"/>