Berry
A PIC-based MP3 player: www.apic-bmp.nl.tt | Intresse in techniek? www.djoamersfoort.nl
Hallo,
ik ga een klein testprogrammatje maken. Daarbij moet ik 1 seconde timeout hebben. De pic loopt op 4MHz. Dan duurt 1 NOP instructie dus 0,25uS (1/4e6 = 0.25e-6) ? Dus dan heb ik voor 1 seconde pauze 4 miljoen NOP instructies nodig? Dus dan ziet mijn sleep functie er zo uit?
void sleep(unsigned int time)
{
unsigned int x;
for(x=0;x<=(4000000*time);x++)
{
asm("NOP");
}
};
Dat lijkt mij kloppen. Maar het rare vind ik dat ik in de code van een kennis van mij zie dat hij geen NOP gebruikt, maar CLRWDT(), waarom? Volgens hem duurt die CLRWDT() 10uS, terwijl die PIC ook op 4MHz draait (als het goed is...). Doe ik wat fout?
Jochem
If you want to succeed, double your failure rate.
ik heb er niet zo heel veel verstand van hoor, maar denk je eraan dat je op een gegeven moment misschien een beetje veel instructies hebt staan? 4 miljoen NOPjes gaat toch wel heel hard (qua beschikbaar geheugen voor je code)...
Xenobinol
Technology is dominated by two types of people: those who understand what they do not manage and those who manage what they do not understand
Een NOP instructie duurt 1us bij een kloksnelheid van 4MHz.
Dat komt omdat een NOP instructie 1 machinecyclus duurt.
En een PIC processor heeft 4 klokcyclus nodig voor het uitvoeren van 1 machinecyclus.
Daarnaast je C code, wil je werkelijk het getal 4 miljoen vermenigvuldigen met de unsigned int time.
Volgens mij moet je het hoofdstuk gegevenstype en hun bereik nog eens bestuderen.
Daarnaast duurt de uitvoer van deze C functie veel langer dan telkens 1 NOP instructie.
Er moet namelijk getest, gerekend en gesprongen worden, en dat gaat niet als je moet NOP-en in 1 enkele instructie.
Ik weet niet hoe de functie CLRWDT() werkt.
Maar het lijkt mij dat deze de WatchDogTimer CLeaRt.
Als je wilt weten hoe de watchdog werkt moet je ff de datasheet erbij pakken.
Maar in hoofdlijn komt het hier op neer, de watchdogtimer is een teller die met een vaste interval wordt verhoogd.
Op het moment dat deze zijn maximale waarde + 1 bereikt zal de processor worden gereset.
Het doel hiervan is te voorkomen dat als je programma vastloopt een einde te maken aan een mogelijke impasse of valse programma executie, dit omdat bij normale programma executie de watchdogtimer wordt gereset voordat deze de kans krijgt om de processor te resetten.
Berry
A PIC-based MP3 player: www.apic-bmp.nl.tt | Intresse in techniek? www.djoamersfoort.nl
ok, het komt voor mij niet zo precies, als ik maar even een sleep heb. Er komen trouwens geen 4 miljoen nopjes hoor, hij doet gewoon 4 miljoen keer een goto nop
Maar een goto neemt 2 cycles in, idd... Ff rekening mee houden. Het is trouwens niet zo belangrijk dat het precies komt, het is gewoon een blink a led je 
Het handigste vind ik nog gewoon de geneste wacht-loepjes.
de delay van het volgende voorbeeld is 1000000 machinecycles:
DELAY ;2 (call naar deze functie)
MOVLW 0x62 ;1
MOVWF COUNT0 ;1
DLY_LOOP0 MOVLW 0xD9 ; 1
MOVWF COUNT1 ; 1
DLY_LOOP1 MOVLW 0x0E ; 1
MOVWF COUNT2 ; 1
DLY_LOOP2 DECFSZ COUNT2,F ; 1
GOTO DLY_LOOP2 ; 2
DECFSZ COUNT1,F ; 1
GOTO DLY_LOOP1 ; 2
DECFSZ COUNT0,F ; 1
GOTO DLY_LOOP0 ; 2
NOP ;1
NOP ;1
RETURN ;2De formule is simpel af te leiden uit de code: ((3 * 0x0E + 5) * 0xD9 + 5) * 0x62 + 8 = 1000000
verander 0x0E, 0xD9 en 0x62 als je een andere delay wilt.
Dit simpele basic programmatje zoekt de 3 waarden voor je op: (voeg wel zelf nopjes toe als het niet helemaal uitkomt)
t = 1000000
max = 0
FOR a = 1 TO 256
FOR b = 1 TO 256
FOR c = 1 TO 256
d = ((3 * a + 5) * b + 5) * c + 6
IF d > t THEN EXIT FOR
IF d > max THEN
max = d
PRINT "((3 *"; a; "+ 5) *"; b; "+ 5) *"; c; "+ 6 ="; d
END IF
NEXT
NEXT
NEXTNog 1 ding: houd er wel rekening mee dat de code om de poort te laten blinken en in de mainloopt te blijven, ook tijd kost. Neem hierom altijd wat minder tijd in de delay loep als de nauwkeurigheid van de delay belangrijk is (zoals bij een stopwatch of klok)
Berry
A PIC-based MP3 player: www.apic-bmp.nl.tt | Intresse in techniek? www.djoamersfoort.nl
Jah leuk hoor zo'n assembly code, maar ik wil het eigenlijk volledig in C doen he... Ik had dus dit:
void sleep(unsigned int time)
{
unsigned long x;
for(x=0;x<=(time*333333);x++) // Een NOP + een GOTO = 3 Cycles
{ // 1000000uS/3 = 333333
asm("NOP"); // 1 Cycle
} // 2 Cycles
}maar die 333333 is veel te veel. Wat moet het dan zijn? Op gok lukte het met 3333 maar hoe bereken je dat?
In een hoge taal als c kun je dit heel lastig bepalen, of er moet in de handleiding van je compiler al staan hoeveel asm instucties je kwijt bent voor zo'n for loop. Ik heb geen idee hoe dat je compiler met zulke grote getallen omgaat, maar in asm is de hoogste waarde voor een var 255 (0xFF). Bestaat er trouwens niet gewoon al een standaard delay instructie?
Berry
A PIC-based MP3 player: www.apic-bmp.nl.tt | Intresse in techniek? www.djoamersfoort.nl
ik heb wat gevonden! In de samples directory zit dit voorbeeld:
#define DelayUs(x) { unsigned char _dcnt; \
_dcnt = (x)/((12MHZ)/(XTAL_FREQ))|1; \
while(--_dcnt != 0) \
continue; }
dan gebruik ik dit wel 