Sida 1 av 3

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

Postat: 4 juni 2006, 00:09:48
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.

Postat: 4 juni 2006, 00:24:12
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.

Postat: 4 juni 2006, 00:25:55
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.

Postat: 4 juni 2006, 00:32:09
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

Postat: 4 juni 2006, 00:34:53
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 ?

Postat: 4 juni 2006, 00:36:57
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).

Postat: 4 juni 2006, 00:44:42
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å.

Postat: 4 juni 2006, 00:55:46
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... :-)

Postat: 4 juni 2006, 01:07:46
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).

Postat: 4 juni 2006, 01:49:58
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.

Postat: 4 juni 2006, 07:42:52
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.

Postat: 4 juni 2006, 11:20:01
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.

Postat: 4 juni 2006, 11:29:41
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.

Postat: 4 juni 2006, 11:44:02
av Kalf
Jag fattar inte riktigt det här med ISR? Vad är det?

När du skriver 0X00 är det hexadecimalt då eller?

Postat: 4 juni 2006, 11:48:44
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.