microbasic: variabel i delay_us(), hur gör jag?

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
Användarvisningsbild
Kalf
Inlägg: 249
Blev medlem: 5 november 2005, 09:59:45

microbasic: variabel i delay_us(), hur gör jag?

Inlägg av Kalf »

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.
sodjan
EF Sponsor
Inlägg: 43266
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Inlägg av sodjan »

> 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.
Användarvisningsbild
Greve Hamilton
EF Sponsor
Inlägg: 544
Blev medlem: 4 september 2004, 15:03:35
Ort: GBG

Inlägg av Greve Hamilton »

Det finns något som heter Vdelay_ms(), där man kan stoppa in en variabel.

Dock inget för us, vad jag vet.
Användarvisningsbild
Kalf
Inlägg: 249
Blev medlem: 5 november 2005, 09:59:45

Inlägg av Kalf »

finns det något bra sätt då ifall jag vill kunna ändra på det vär det enkelt då? Vill ha det i us
sodjan
EF Sponsor
Inlägg: 43266
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Inlägg av sodjan »

Nej, du kan *inte* ändra värde på parametern till delay_us() i run-time,
var vi inte överens om det ?

Du får ändra design och koda på något annat sätt.
Vilket intervall gäller det ?
bearing
Inlägg: 11682
Blev medlem: 2 mars 2006, 01:01:45
Ort: Ängelholm

Inlägg av bearing »

Gör en loop. Nu minns jag inte riktigt BASIC-syntaxen, men det borde bli ungefär såhär:

Kod: Markera allt

FOR delay = 999 DOWN TO 0
NOP()
NEXT delay
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).
Användarvisningsbild
Kalf
Inlägg: 249
Blev medlem: 5 november 2005, 09:59:45

Inlägg av Kalf »

>Vilket intervall gäller det ?

Det är samma sak som vi pratade om igår, jag håller på med mitt servo, men jag var lat och gick tillbaka till min gamla kod, men då måste jag använda timer ifall jag vill kuna ändra läge på servot enkelt då.
sodjan
EF Sponsor
Inlägg: 43266
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Inlägg av sodjan »

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... :-)
sodjan
EF Sponsor
Inlägg: 43266
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Inlägg av sodjan »

Greve Hamilton:
> Det finns något som heter Vdelay_ms(), där man kan stoppa in en variabel.
> Dock inget för us, vad jag vet.

Se även delay_cyc() vilken tar en variabel (3..255).
bearing
Inlägg: 11682
Blev medlem: 2 mars 2006, 01:01:45
Ort: Ängelholm

Inlägg av bearing »

sodjan skrev:En FOR loop är sannolikt den sämsta tänkbara lösningen.
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?

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.
Användarvisningsbild
Icecap
Inlägg: 26736
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Inlägg av Icecap »

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.

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;
      }
    }
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.
Användarvisningsbild
Kalf
Inlägg: 249
Blev medlem: 5 november 2005, 09:59:45

Inlägg av Kalf »

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:

Kod: Markera allt

       if cnt = 0 then 
           	if PORTB = 1 then
			          portb  = 1
           		  cnt = 200
		        else
			          PORTB = 0
			          cnt =50
		        end if
       end if

Och här är hela koden:

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.
Användarvisningsbild
Icecap
Inlägg: 26736
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Inlägg av Icecap »

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.
Användarvisningsbild
Kalf
Inlägg: 249
Blev medlem: 5 november 2005, 09:59:45

Inlägg av Kalf »

Jag fattar inte riktigt det här med ISR? Vad är det?

När du skriver 0X00 är det hexadecimalt då eller?
Användarvisningsbild
Icecap
Inlägg: 26736
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Inlägg av Icecap »

Aha... ISR = Interrupt Service Routine = 'sub procedure interrupt'

Edit: Jepp, 0x.. är hexadecimal standart i C, PIC ASM och lite andra ställen.
Skriv svar