microbasic: variabel i delay_us(), hur gör jag?
microbasic: variabel i delay_us(), hur gör jag?
Hej jag håller på och kodar lite i mikrobasic och vill sätta in en variabel i delay_us(1000) istället för 1000, hur gör jag? Det skall ju vara en constant där igentligen.
> och vill sätta in en variabel i delay_us(1000) istället för 1000
Går inte, ska vara en konstant (alltså ett känt värde vid kompileringen)
> Det skall ju vara en constant där igentligen.
Ja men då så, du har ju redan svaret själv !!
*Varför* det inte går med en variabel är inte så konstigt igentligen.
Går inte, ska vara en konstant (alltså ett känt värde vid kompileringen)
> Det skall ju vara en constant där igentligen.
Ja men då så, du har ju redan svaret själv !!
*Varför* det inte går med en variabel är inte så konstigt igentligen.
- Greve Hamilton
- EF Sponsor
- Inlägg: 544
- Blev medlem: 4 september 2004, 15:03:35
- Ort: GBG
Gör en loop. Nu minns jag inte riktigt BASIC-syntaxen, men det borde bli ungefär såhär:
Ett varv i loopen tar ett visst antal instruktionscykler, säg 5 st. Om du kör med 20 MHz exekveras 5 klockcykler per us, dvs din delay är gjord! Du behöver bara kompensera delay för initeringen av loop-variabler osv.
För att få reda på hur många cykler loopen tar kan du simulera eller kolla på assemblerkoden.
Behöver du ändra till fler/färre cykler/per loop får du lägga in fler/färre NOP eller göra om till en GOTO-loop (om det ska gå ännu snabbare).
Kod: Markera allt
FOR delay = 999 DOWN TO 0
NOP()
NEXT delay
För att få reda på hur många cykler loopen tar kan du simulera eller kolla på assemblerkoden.
Behöver du ändra till fler/färre cykler/per loop får du lägga in fler/färre NOP eller göra om till en GOTO-loop (om det ska gå ännu snabbare).
En FOR loop är sannolikt den sämsta tänkbara lösningen.
Väldigt stelbent och snårigt att underhålla applikationen.
Processorn kan inte heller göra något annat under tiden,
vilket man i 99% av fallen har behov av.
Nej, precis som det har sagts i en annan tråd, så finns det en
anledning till att konstruktörerna av processorerna har lagt till timers.
Använd hårdvaran så långt det går, det gör koden enklare, renare
och smidigare att underhålla i framtiden.
> men jag var lat...
Brukar väldigt sällan hjälpa...
Väldigt stelbent och snårigt att underhålla applikationen.
Processorn kan inte heller göra något annat under tiden,
vilket man i 99% av fallen har behov av.
Nej, precis som det har sagts i en annan tråd, så finns det en
anledning till att konstruktörerna av processorerna har lagt till timers.
Använd hårdvaran så långt det går, det gör koden enklare, renare
och smidigare att underhålla i framtiden.
> men jag var lat...
Brukar väldigt sällan hjälpa...
Om det skulle vara en ersättare för delay_ms är det väl en ekvivalent lösning men med variabel längd? delay_ms tillåter väl inte processorn att jobba med annat?sodjan skrev:En FOR loop är sannolikt den sämsta tänkbara lösningen.
Om du tänker på att jag föreslog just FOR-loopen var det för att jag kände till syntaxen i BASIC bäst på den.
Nåväl, du verkar känna till mer om Kalf:s application än jag.
Alltså:
Att BASIC suger som strukturerat språk är en sak men rätt behandlat är det nog funktionsdugligt.
Preicis som sodjan säger finns det en anledning till att det finns timers med i processorstrukturen.
Jag såg i den andra tråden med samma ämne att timern är vald till Timer0 och jag undrar varför? Är det för att det inte finns en Timer1 eller är det av okännedom?
Man väljer helst en timer som kan "låsas" enkelt, alltså detta fibblande med att komma ihåg att ställa in nytt utgångsvärde i timern (TMR0 = x) ska bort så långt det bara går, det ger nämlig tids-jitter.
Jag brukar att (skissartat) ha 2 variabler, 1 med On-tid och en med Off-tid. Även i de fall då den totala cyklustid ska vara konstant, då kan jag utföra uträkningen utanför ISR'n och därmed spara ISR-tid.
Deta medför att main-delen av programmet ser till att ställa in On-Tiden och Off-Tiden i variablerna rätt kommer pulsen att bildas "helt automatisk", såklart ska man initiera timern osv.
Att BASIC suger som strukturerat språk är en sak men rätt behandlat är det nog funktionsdugligt.
Preicis som sodjan säger finns det en anledning till att det finns timers med i processorstrukturen.
Jag såg i den andra tråden med samma ämne att timern är vald till Timer0 och jag undrar varför? Är det för att det inte finns en Timer1 eller är det av okännedom?
Man väljer helst en timer som kan "låsas" enkelt, alltså detta fibblande med att komma ihåg att ställa in nytt utgångsvärde i timern (TMR0 = x) ska bort så långt det bara går, det ger nämlig tids-jitter.
Jag brukar att (skissartat) ha 2 variabler, 1 med On-tid och en med Off-tid. Även i de fall då den totala cyklustid ska vara konstant, då kan jag utföra uträkningen utanför ISR'n och därmed spara ISR-tid.
Kod: Markera allt
Timer-ISR:
Variabel Counter; // anges rätt enl. använd språk o max storlek
ISR:
Rensa interrupt-flaggan.
Counter = Counter - 1;
Om(Counter = 0)
{
Om(Pinnen_är_On)
{
Pinnen = off;
Counter = Off-Tiden;
}
annars
{
Pinnen = on;
Counter = On-Tiden;
}
}
Nu vet inte jag vara jag skall skriva detta men jag testar här:
Jag har gjort efter din modell icecap. Den var väldigt smart, men jag får inte min IF sats och fungera, någon som vet vad jag gjort för fel? Den går bara vidare till else även ifall portb sänder en etta.
Här är if satsten:
Och här är hela koden:
Jag har gjort efter din modell icecap. Den var väldigt smart, men jag får inte min IF sats och fungera, någon som vet vad jag gjort för fel? Den går bara vidare till else även ifall portb sänder en etta.
Här är if satsten:
Kod: Markera allt
if cnt = 0 then
if PORTB = 1 then
portb = 1
cnt = 200
else
PORTB = 0
cnt =50
end if
end if
Kod: Markera allt
program Tmr0
dim cnt as byte
sub procedure interrupt
cnt = cnt - 1 ' increment value of cnt on every interrupt
TMR0 = 96
INTCON = $20 ' set T0IE, claer T0IF
end sub
main:
OPTION_REG = $84 ' assign prescaler to TMR0
trisb = 0 ' designate portb as output
portb = $FF ' initialize portb
TMR0 = 96
INTCON = $A0 ' enable TMRO interrupt
do
if cnt = 0 then
if PORTB = 1 then
portb = 1
cnt = 200
else
PORTB = 0
cnt =50
end if
end if
loop until 0 = 1
end.
PORTB är nog inte en 1, om du använder bit 3 t.ex. kommer PORTB att vara antingen 0x00 eller 0x08....
På MikroC kan man använda PORTB.F3 för de enstaka bits....
Nu är det danska dålig programmeringsstil att bara räkna ner 'cnt' i ISR'n och känna av den i main-loopen. I detta fall kanske det fungerar men du kan mycket lätt får den att hinna utföra en timer-interrupt innan main-loopen "hinner med" och därmed hinner 'cnt' att räknas ner till -1 (= 255).
Antingen: if cnt < 0 then cnt = cnt -1
eller ha hela den sats i ISR'n, det sista är bäst om man inte har mycket specifika timingskrav.
På MikroC kan man använda PORTB.F3 för de enstaka bits....
Nu är det danska dålig programmeringsstil att bara räkna ner 'cnt' i ISR'n och känna av den i main-loopen. I detta fall kanske det fungerar men du kan mycket lätt får den att hinna utföra en timer-interrupt innan main-loopen "hinner med" och därmed hinner 'cnt' att räknas ner till -1 (= 255).
Antingen: if cnt < 0 then cnt = cnt -1
eller ha hela den sats i ISR'n, det sista är bäst om man inte har mycket specifika timingskrav.
