Stránka 1 z 1
ATMEL 89S52 - zpoždění
Napsal: 26 kvě 2010, 21:45
od MirrA1
Dobrý večer
potřeboval bych trošku poradit a nakopnout jak vypočítat a naprogramovat zpoždění pro ATMEL 89S52, programuji v C v prostředí KEIL.
U procesoru 8051 jeden strojní cyklus (SC) zabere 12 taktů - takže při použitý krystalu 24MHz trvá jeden SC 500ns. Dejme tomu, že chci dosáhnout zpoždění 20us - což bude 40 SC.
Pro zpoždění jsem použil tento kód:
#include <REGX52.h>
#include <math.h>
delay(unsigned char y){
unsigned char i;
for(i=0;i<y;i++){;}
}
main(){
while(1){
delay(40);
P0_1 = 0;
delay(40);
P0_1 = 1;
}
}
který by měl pokud to dobře chápu fungovat tak, že i by se mělo inkrementovat do 40 a poté se vykoná další instrukce (rožnutí/zhasnutí LED). Dle logiky na začátku uvedeného výpočtu by mělo díky inkrementování do 40 dojít ke zpoždění 40 SC což by mělo být oněch 20us kterých chci dosáhnout.
Nicméně v praxi mi vychází dle osciloskopu doba zpoždění přesně 160us.
Nenapadá někoho čím to může být způsobeno? Moc díky za případné reakce.
Napsal: 26 kvě 2010, 21:53
od Andrea
Ten cyklus není jedna instrukce, tak jeden průchod trvá víc než 1 SC. Ani to volání procedury a návrat nejde zanedbat. Podívej se, jak je to přeložené do assembleru a uvidíš tu kupu instrukcí.
Napsal: 26 kvě 2010, 22:41
od procesor
Pre toto mám rád assembler, v tom cykle ti prefrčí aj cez 300 instrucií.
Napsal: 26 kvě 2010, 22:45
od MirrA1
NO tak je to tak. Když se kouknu do assembléru a odkrokuju si program v něm, tak mi dle počtu SC v simulátoru výjde přesný čas kterému odpovídá reálné chování.
Teď je ale otázka jak jednoduše spočítat kolik cyklů budu potřebovat pro požadované zpoždění protože to ještě závisí na tom jak si nadefinuji typ použitého čísla (v tomto případě: unsigned char )
Napsal: 26 kvě 2010, 22:50
od MirrA1
procesor píše:Pre toto mám rád assembler, v tom cykle ti prefrčí aj cez 300 instrucií.
Je to tak, zlatej assembler ve kterym si vsechno v procesoru manualne posilas kam zrovna chces

Napsal: 26 kvě 2010, 23:13
od procesor
40cyc....160us
x?cyc......20us
--------------------
x=800/160=5
Napsal: 27 kvě 2010, 00:07
od rnbw
A nie je tam v kniznici funkcia, ktora robi presne oneskorenie?
Napsal: 27 kvě 2010, 05:38
od MirrA1
procesor píše:40cyc....160us
x?cyc......20us
--------------------
x=800/160=5
no kéžby to bylo takhle jednoduše vypočitatelné, problém je v tom, že to není lineární.
čítání do 1 zabere 20 SC = 10us
čítání do 2 zabere 27SC = 13,5us
čítání do 3 zabere 35SC = 17,5us
Napsal: 27 kvě 2010, 05:41
od MirrA1
rnbw píše:A nie je tam v kniznici funkcia, ktora robi presne oneskorenie?
no právěže jediné zpoždění je dělané dle toho co jsem napsal - a to jsem prohledával i internet. Zpoždění jsou řešená jen dle této struktury, ale jak přesný čas vypočítat jsem nikde nenašel.
Druhou možností jak realizovat zpoždění je použít časovač - což je ale pro tak krátké časy nesmysl.
Napsal: 27 kvě 2010, 08:36
od Atlan
ides pokus omyl.... alebo vytvor kniznicu s oneskorenim v ASM, volanie tej knicnice uz by malo byt konstatne...
Napsal: 27 kvě 2010, 09:30
od AB1
Můžeš počítat takto:
unsigned char i;
Kód: Vybrat vše
for(i=0; i<n; i++) {} // n = (cykly-2)/3 5 <= n <= 769
Přidáme tolik nopů, kolik je zbytek po dělení.
Příklad:
delay 300 cyklů
(300-2)/3 = 99 ; zbytek=2
Kód: Vybrat vše
for(i=0; i<99; i++) {}
_nop_();
_nop_();
Při 12MHz je jeden instrukční cykl 1 mikrosekunda.
Napsal: 27 kvě 2010, 10:14
od Andrea
Dělat mikrosekundová zpoždění voláním nějaké funkce v C dost dobře nejde, jenom ta režie volání je nějakých 7us. Pokud to má být aspoň trochu přesné a stačí rozsah do 256us, tak by se asi dalo použít makro s parametrem a v makru vložený assembler. Instrukce DJNZ trvá při 24MHz právě tu jednu us.
Napsal: 27 kvě 2010, 11:17
od AB1
Souhlasím s Andreou.
Pokud některé překladače mají funkce delay(), tak stejně nebývají přesné.
Ani na kód, který jsem napsal výše nejde spolehnout, protože teď jsem zjistil že funguje přesně jenom při určité úrovni optimalizace.
Pokud je třeba přesný počet cyklů, je asi nejlepší použít čítač.