Sida 1 av 2
Räkna ner i (Mikro)Basic ?
Postat: 21 september 2005, 04:46:40
av JimmyAndersson
Har stött på ytterligere ett problemi MikroBasic.
Jag vill göra en nedräkning från 3 till 0 med en FOR-loop, men när jag kör koden i PIC18LF1320 så hoppar den över nedräkningsloopen. (Se kommentarerna i koden.)
Koden nedan är lite modifierad med några "blinka fyra/två LED" för att se när nedräkningen kommer.
Här är koden. Något omständig men, som sagt det är bara för test:
Kod: Markera allt
program PimEget
dim vilkena as byte
dim vilkenb as byte
TRISB = 0 ' Utgångar på B
PORTB = 0 ' Stäng av alla
do
for vilkena = 0 to 3
SetBit (PORTB,vilkena)
delay_ms(200)
ClearBit (PORTB,vilkena)
delay_ms(5)
next vilkena
PORTB = $0F <----BLINKAR FYRA LED BARA FÖR ATT SE
delay_ms(50)
PORTB = $00
delay_ms(50)
PORTB = $0F
delay_ms(50)
PORTB = $00
delay_ms(200)
for vilkenb = 3 to 0 step -1 <-----HÄR ÄR PROBLEMET. DEN HOPPAR ÖVER HÄRIFRÅN
SetBit (PORTB,vilkenb)
delay_ms(200)
ClearBit (PORTB,vilkenb)
delay_ms(5)
next vilkenb <------OCH HIT.
PORTB = $06 <-----BLINKAR LED 2 OCH 3.
delay_ms(200)
PORTB = $00
delay_ms(200)
loop until 0 = 1
end.
Det går ju att lösa genom att räkna uppåt och minska med tre. Ungefär såhär: (Ingen korrekt PIC-kod, bara exempel)
For tal = 0 to 3
ner = 3 - tal
print ner
next tal
Det skulle ju ge utskriften:
3
2
1
0
...men nog borde man kunna göra en FOR-loop som går neråt? Det går ju i "vanliga" Basic...
Postat: 21 september 2005, 07:19:38
av Icecap
Nu är BASIC ju ett hat-ämne för mig men varför inte räkna 0 -> 3 och indexera med (3 - vilkenb)?
Postat: 21 september 2005, 10:35:29
av sodjan
> "...men nog borde man kunna göra en FOR-loop som går neråt? Det går ju i "vanliga" Basic..."
Och vad säger TFM om det ???
Postat: 21 september 2005, 16:04:32
av JimmyAndersson
Sodjan:

Både TFM och Google säger att koden stämmer, dvs att det är samma syntax för FOR i MikroBasic som i 19385st andra Basic-former. Men i debuggern ser man att den inte räknar ner den FOR-loopen. 'vilkenb' sätts bara till 3 och sedan hoppar den ner till raden under "next vilkenb".
Icecap: Jo det får nog bli så. Det blir ju lite extra kod, men det fungerar iallfall.
Postat: 21 september 2005, 16:28:17
av sodjan
Kolla hur asm koden ser ut för en FOR loop med negativ "step".
Det kanske ger någon ledtråd kring vad som händer...
Postat: 21 september 2005, 20:06:20
av JimmyAndersson
Har jämfört looparna i asm-koden. Tyvärr har jag inte hittat någon lösning, men det ser nästan ut som om den missar att den ska "minska med ett".
Så FOR-loopen avslutas eftersom 'vilkenb' är större än slut-talet (dvs noll).
(Om allt varit som det skulle, så hade loopen avslutats om 'vilkenb' varit mindre än slut-talet.)
Nåväl, det får bli en positiv FOR-loop som minskas med 3. Åtminstone tills det löser sig.
Postat: 21 september 2005, 21:22:13
av speakman
MikroBasic kanske inte stöder STEP alls? Har du testat med en positiv räkning med STEP 2 t.ex.? Eller ta bort STEP helt från den negativa?
Mvh
speakman
Postat: 21 september 2005, 21:44:01
av JimmyAndersson
Jodå, i 'manualen' står STEP med. Det står även att den ska klara negativa tal: "Note that parameter step_value may be negative, allowing you to create a countdown". FOR-loopar ser förresten ut såhär i MikroBasic-hjälpen:
for counter = initial_value to final_value [step step_value]
statements
next counter
Det som står inom [ och ] betyder att det är "valfritt"...
I alla exempel-koder jag kollat så stämmer det med det jag skrivit.
Om jag kör: for talet = 1 to 10 step 2
så stegar den: 1, 3, 5 osv..
Om jag kör: for talet = 10 to 1
UTAN step alltså, så går den bara förbi loopen.
Om jag kör: for talet = 10 to 1 step -2
så går den också förbi loopen.
Postat: 21 september 2005, 21:54:49
av speakman
Tragisk BASIC-tolk..

Maila å påpeka!
Mvh
speakman
Postat: 21 september 2005, 22:38:47
av sodjan
En sak...
Loop räknaren "vilkenb" är definierad som "byte".
"step" är alltså -1.
I manualen står det : "The initial_valueand final_valueshould be expressions compatible with the counter;"
Det kanske gäller "step" också, och i så fall undrar jag om "-1" är kompatiblent med "byte". Du kanske skulle prova att ändra "byte" (0...255) till "short" (-128...127) för att eventuellt göra loopvariablen kompatibel med step värdet.
speakman skrev : Tragisk BASIC-tolk..
"Basic-tolk" ??

Postat: 21 september 2005, 23:03:48
av JimmyAndersson
Precis, jag funderade också på det. Tyvärr hjälpte det inte att ändra "vilkenb" till 'short'.
Det verkar nästan som om STEP inte klarar att hantera negativa tal. Det kanske är en bugg..?

Postat: 21 september 2005, 23:42:56
av sodjan
Mycket möjligt, opch det skulla vara rellativt enkelt att kolla om man hade asm koden från ett litet exempel...
Postat: 22 september 2005, 00:36:34
av JimmyAndersson
Det går att ordna.
Först MikroBasic-koden för ett exempel:
Kod: Markera allt
program PimTest
dim vilkenb as short
TRISB = 0 ' Utgångar på B
PORTB = 0 ' Stäng av alla
do
for vilkenb = 3 to 0 step -1
SetBit (PORTB,vilkenb)
delay_ms(40)
ClearBit (PORTB,vilkenb)
delay_ms(1)
next vilkenb
loop until 0 = 1
end.
Sedan asm-varianten: (Har tyvärr inte fixa till den. Gjorde precis test-koden ovan. Hoppas det går att läsa asm-koden ändå..)
Kod: Markera allt
;// ASM code generated by mikroVirtualMachine for PIC - V. 3.0.0.0
; Date/Time: 2005-09-22 00:30:03
; Info: http://www.mikroelektronika.co.yu
;// ADDRESS OPCODE ASM
; ----------------------------------------------
$0000 $EF04 F000 GOTO PimTest_main
$0008 $ PimTest_main:
$0008 $ PimTest_main_main:
$0008 $6A93 CLRF TRISB, 0
$000A $6A81 CLRF PORTB, 0
$000C $ PimTest_L_1:
$000C $0E03 MOVLW 3
$000E $6E15 MOVWF main_global_vilkenb, 0
$0010 $ PimTest_L_2:
$0010 $6A01 CLRF STACK_1, 0
$0012 $80D8 BSF STATUS, C, 0
$0014 $BE15 BTFSC main_global_vilkenb, 7, 0
$0016 $D002 BRA PimTest_L_5
$0018 $5015 MOVF main_global_vilkenb, W, 0
$001A $5C01 SUBWF STACK_1, W, 0
$001C $ PimTest_L_5:
$001C $E33D BNC PimTest_L_4
$001E $ PimTest_L_3:
$001E $0E01 MOVLW 1
$0020 $1281 IORWF PORTB, F, 0
$0022 $0E03 MOVLW 3
$0024 $6E01 MOVWF STACK_1, 0
$0026 $0EFF MOVLW 255
$0028 $6E02 MOVWF STACK_2, 0
$002A $0EFF MOVLW 255
$002C $6E03 MOVWF STACK_3, 0
$002E $2E01 DECFSZ STACK_1, F, 0
$0030 $D001 BRA $+2
$0032 $D007 BRA $+8
$0034 $2E02 DECFSZ STACK_2, F, 0
$0036 $D001 BRA $+2
$0038 $D003 BRA $+4
$003A $2E03 DECFSZ STACK_3, F, 0
$003C $D7FE BRA $-1
$003E $D7FA BRA $-5
$0040 $D7F6 BRA $-9
$0042 $0E0B MOVLW 11
$0044 $6E01 MOVWF STACK_1, 0
$0046 $0EFF MOVLW 255
$0048 $6E02 MOVWF STACK_2, 0
$004A $2E01 DECFSZ STACK_1, F, 0
$004C $D001 BRA $+2
$004E $D003 BRA $+4
$0050 $2E02 DECFSZ STACK_2, F, 0
$0052 $D7FE BRA $-1
$0054 $D7FA BRA $-5
$0056 $0E1A MOVLW 26
$0058 $6E01 MOVWF STACK_1, 0
$005A $2E01 DECFSZ STACK_1, F, 0
$005C $D7FE BRA $-1
$005E $0000 nop
$0060 $0E01 MOVLW 1
$0062 $6E02 MOVWF STACK_2, 0
$0064 $1E02 COMF STACK_2, F, 0
$0066 $5002 MOVF STACK_2, W, 0
$0068 $1681 ANDWF PORTB, F, 0
$006A $0E0D MOVLW 13
$006C $6E01 MOVWF STACK_1, 0
$006E $0EFF MOVLW 255
$0070 $6E02 MOVWF STACK_2, 0
$0072 $2E01 DECFSZ STACK_1, F, 0
$0074 $D001 BRA $+2
$0076 $D003 BRA $+4
$0078 $2E02 DECFSZ STACK_2, F, 0
$007A $D7FE BRA $-1
$007C $D7FA BRA $-5
$007E $0EF3 MOVLW 243
$0080 $6E01 MOVWF STACK_1, 0
$0082 $2E01 DECFSZ STACK_1, F, 0
$0084 $D7FE BRA $-1
$0086 $0EFF MOVLW 255
$0088 $2615 ADDWF main_global_vilkenb, F, 0
$008A $0EFF MOVLW 255
$008C $6E15 MOVWF main_global_vilkenb, 0
$008E $0EFF MOVLW 255
$0090 $B0D8 BTFSC STATUS, C, 0
$0092 $0F01 ADDLW 1
$0094 $2615 ADDWF main_global_vilkenb, F, 0
$0096 $D7BC BRA PimTest_L_2
$0098 $ PimTest_L_4:
$0098 $D7B9 BRA PimTest_L_1
$009A $D7B8 BRA PimTest_L_1
$009C $ PimTest_L_6:
$009C $ PimTest_L_7:
$009C $D7FF BRA PimTest_L_7
Postat: 22 september 2005, 09:23:57
av speakman
sodjan: kompilator då... men bara för den här gången!
Mvh
speakman
Postat: 22 september 2005, 10:47:20
av sodjan
Alltså, tanken var att ha en *ENKEL* loop utan en massa onödigt som inte har med "FOR...STEP" att göra. Plocka bort allt utom något enkelt som går lätt att identifiera i asm koden, t.ex "PORTB = 0" eller liknande.
Måste man ha med do...until ?
Något i stil med :
Kod: Markera allt
program PimTest
dim vilkenb as short
for vilkenb = 3 to 0 step -1
PORTB = 0
next vilkenb
end.
Jag misstänker att SetBit och ClearBit skapar en hel del kod (som är ointressant i detta fall), eftersom det inte finns någon direkt motsvarighet i assembler till det...