Sida 1 av 2
Mindre än 1? (ASM)
Postat: 4 mars 2007, 15:04:58
av squiz3r
Hej, Jag har en kod som gör att en variabel (time) blir en siffra. Sen vill jag att om denna sifran är mindre än 35 så ska den gå till "label1", så då tänkte jag att man kan göra såhär:
Kod: Markera allt
movfw time
sublw 35
btfsc STATUS, Z
goto label1
Men sen kom jag på att Z "biten" reagerar väll bara om det blir 0, men jag vill att det ska reagera om det blir Tex. -6 också. dvs. allting som är noll eller under.
Hur gör jag då?
Tack på förhand!
//Daniel A
Postat: 4 mars 2007, 15:15:54
av Marta
Använd carry istället före zero.
Postat: 4 mars 2007, 15:25:46
av squiz3r
Okej. men carry sätts väll inte fören det blir under noll, vilket betyder att jag måste kolla zero också eller har jag fattat fel?
Då kan jag väll skriva koden såhär:
Kod: Markera allt
movfw time ;W = time - 35
sublw 35
btfsc STATUS, Z ; om W = 0 gå till label1
goto label1
btfsc STATUS, C ; om W är mindre än 0 gå till label 1
goto label1
........ ; förtsätt här....
........
Postat: 4 mars 2007, 15:30:39
av sodjan
Ladda ner " Instruction Set - PICmicro Mid-Range MCU Family"
http://ww1.microchip.com/downloads/en/D ... 31029a.pdf
Där finns det fler exempel än i databladet. T.ex för SUBLW finns
just det fall som du frågar om (d.v.s "resultat mindre än noll").
> Okej. men carry sätts väll inte fören det blir under noll,
Dra av 36 istället för 35...
Dessutom, väldigt viktigt !!!!!!!
Skriv *aldrig* "sublw 35 ", utan "sublw d'35'" (om du menar 35 decimalt)
eller "sublw h'35'" (om du menar 35 hexadecimalt) !!
Ange *alltid* radix på *alla* konstanter !
Postat: 4 mars 2007, 15:50:54
av squiz3r
Så nu har jag laddat ner den, den verkar ju ha bra exempel
>Dra av 36 istället för 35...
hmm... hur kunde jag låta bli o tänka på det?
Okej då ska jag skriva d'36' i stället
Tack så mycket!
//Daniel A
Postat: 4 mars 2007, 17:26:58
av sodjan
En liten "side-note" om att ange radix i koden...
Man ser ofta ett HEX-värde skrivet som t.ex 0x3B.
Detta format är i och för sig OK i MPASM, men personligen
föredrar jag formatet h'3B'. Anledningen är att detta format
kan användas till alla radix :
a'A' : ASCII tecken.
d'98' : decimalt.
h'3B' : hexadecimalt.
o'26' : oktalt.
b'00010000' : binärt.
Det finns ingen motsvarighet till "0x" formatet i de andra radix'en...
På så sätt får man ett konsekvent skrivsätt oavsett radix.
Snyggare tycker jag...
Postat: 4 mars 2007, 18:11:17
av squiz3r
Sodjan: Okej, då får jag ta och fixa till det där jag har skrivit det också
Men nu har jag skrivit ihop en kod som inte vill fungera som jag vill

:
Kod: Markera allt
; Assign your microcontroller
LIST P=16F628A
; This include file makes programming more understandeble
include <P16F628A.INC>
__CONFIG _CP_OFF & _DATA_CP_OFF & _BODEN_OFF & _MCLRE_ON & _PWRTE_ON & _WDT_OFF & _INTRC_OSC_NOCLKOUT & _LVP_OFF
; save on free ram in bank0
delay_var1 equ 20h
delay_var2 equ 21h
delay_var3 equ 22h
pause_var1 equ 23h
time equ 24h
;define pinouts
#define alarm PORTA,2
#define sw1 PORTB,2
#define sw2 PORTB,3
#define G_LED PORTA,1
#define R_LED PORTA,0
#define sens1 PORTB,5
#define sens1_off PORTB,4
#define keypad PORTB,0
;startadres of the controller
org 0x0000
; For using A0-A3 as digital I/O
movlw D'7' ;
movwf CMCON ; Comparators off, all pins digital I/O
; Reset Port values
clrf PORTA
clrf PORTB
; define your pin direction (input/output)
portb5_out
bsf STATUS, RP0 ; Switch to bank 1
movlw b'00000000' ;
movwf TRISA ; PORTA = 0,1,2,3,4,5,6,7 out,
movlw b'00000000' ;
movwf TRISB ; PORTB = b5 out
bcf STATUS, RP0 ; Switch to bank 0
goto step_1
portb5_in
bsf STATUS, RP0 ; Switch to bank 1
movlw b'00000000' ;
movwf TRISA ; PORTA = 0,1,2,3,4,5,6,7 out,
movlw b'00100000' ;
movwf TRISB ; PORTB = b5 in
bcf STATUS, RP0 ; Switch to bank 0
goto step_2
; main loop
watch_resistans
goto portb5_out
step_1
bsf sens1
call delay
bcf sens1
movlw 0h
movwf time
movlw 1h
goto portb5_in
step_2
addwf time,f
bsf G_LED
call pause
bcf G_LED
call pause
btfsc sens1
goto step_2
goto step_3
step_3
bsf R_LED
call pause
bcf R_LED
call pause
decfsz time,1h
goto step_3
goto portb5_out
button1
bsf R_LED
call delay
goto watch_resistans
; Delay routine
; This code uses about 5 x 99975 instructions. At 4Mhz this is approx 500 milliseconds.
pause movlw 0xFF
movwf pause_var1
pause2 decfsz pause_var1,1 ; is placed in the file
goto pause2
return
delay movlw 0x5
movwf delay_var3
delay1 movlw 0x5
movwf delay_var2
delay2 movlw 0xFF
movwf delay_var1
delay3 decfsz delay_var1, f
goto delay3
decfsz delay_var2, f
goto delay2
decfsz delay_var3, f
goto delay1
return
END
Den läser av ett motstånd med hjälp av "RC-TIME", när Jag har mätt i oscyloscopet så blinkar den den den gula leden (G_LED) 4ggr.
då den borde väll R_LED blinka lika många gånger som den gula? För att efter att den gula har blinkat fyra gånger blinkar den röda 29ggr

Sedan satte jag på ett 2K (innan var det 10Kohm) motstånd i stället, då blinkade den gula 1ggr. o den röda 32ggr. Är det jag som har fattat något fel, eller?
//Daniel A
Postat: 4 mars 2007, 18:42:29
av sodjan
> Men nu har jag skrivit ihop en kod som inte vill fungera som jag vill
Kommentera koden så att det går att veta *vad* det är du vill...
Postat: 4 mars 2007, 19:30:24
av squiz3r
Här kommer koden med komentarer. Hoppas att dem är tydliga nog.
Kod: Markera allt
; Assign your microcontroller
LIST P=16F628A
; This include file makes programming more understandeble
include <P16F628A.INC>
__CONFIG _CP_OFF & _DATA_CP_OFF & _BODEN_OFF & _MCLRE_ON & _PWRTE_ON & _WDT_OFF & _INTRC_OSC_NOCLKOUT & _LVP_OFF
; save on free ram in bank0
delay_var1 equ 20h
delay_var2 equ 21h
delay_var3 equ 22h
pause_var1 equ 23h
time equ 24h
;define pinouts
#define alarm PORTA,2
#define sw1 PORTB,2
#define sw2 PORTB,3
#define G_LED PORTA,1
#define R_LED PORTA,0
#define sens1 PORTB,5
#define sens1_off PORTB,4
#define keypad PORTB,0
;startadres of the controller
org 0x0000
; For using A0-A3 as digital I/O
movlw D'7' ;
movwf CMCON ; Comparators off, all pins digital I/O
; Reset Port values
clrf PORTA
clrf PORTB
; define your pin direction (input/output)
portb5_out
bsf STATUS, RP0 ; Switch to bank 1
movlw b'00000000' ;
movwf TRISA ; PORTA = 0,1,2,3,4,5,6,7 out,
movlw b'00000000' ;
movwf TRISB ; PORTB = b5 out
bcf STATUS, RP0 ; Switch to bank 0
goto step_1
portb5_in
bsf STATUS, RP0 ; Switch to bank 1
movlw b'00000000' ;
movwf TRISA ; PORTA = 0,1,2,3,4,5,6,7 out,
movlw b'00100000' ;
movwf TRISB ; PORTB = b5 in
bcf STATUS, RP0 ; Switch to bank 0
goto step_2
; main loop
watch_resistans
goto portb5_out ;gör sens1 (portb5) till utgång
step_1
bsf sens1 ;ladda upp kondensatorn
call delay
bcf sens1
movlw 0h ;nollställ "time"
movwf time
movlw 1h ;lägg 1hex i W registret
goto portb5_in ;ändra sens1 (portb5) till ingång
step_2
addwf time,f ;time = time + 1 (lägg till 1h till "time")
bsf G_LED ;tändgul status LED
call pause ;pausa
bcf G_LED ;släck den igen
call pause ;pausa
btfsc sens1 ;kolla om kondensatorn fortfarande är uppladdad.
goto step_2 ;om den är det gå till step_2 o lägg till 1 till i variablen m.m.
goto step_3 ;annars gå till step_3
step_3 ;visa hur många gånger den loopade i "step_2" loopen.
bsf R_LED ;tänd röd LED
call pause ;pausa
bcf R_LED ;släck den igen
call pause ;pause igen
decfsz time,1h ;visa hur stor variablen är genom att köra denna loopen lika många gånger
goto step_3 ;om variablen fortfarande innehåller något gå till baks till "step_3"
goto portb5_out ;annars kör hela processen igen....
button1 ;********************************************
bsf R_LED
call delay ;Detta används inte nu....
goto watch_resistans ;*********************************************
pause movlw 0xFF ;*************************************
movwf pause_var1 ;gör en kort pause
pause2 decfsz pause_var1,1 ;
goto pause2 ;
return ;*************************************
delay movlw 0x5 ;*************************************
movwf delay_var3 ;
delay1 movlw 0x5 ;
movwf delay_var2 ;gör en lång pause
delay2 movlw 0xFF ;
movwf delay_var1 ;
delay3 decfsz delay_var1, f ;
goto delay3 ;
decfsz delay_var2, f ;
goto delay2 ;
decfsz delay_var3, f ;
goto delay1 ;
return ;**************************************
END
//Daniel A
Postat: 4 mars 2007, 20:41:31
av Maalobs
sodjan skrev:En liten "side-note" om att ange radix i koden...
Man ser ofta ett HEX-värde skrivet som t.ex 0x3B.
Detta format är i och för sig OK i MPASM, men personligen
föredrar jag formatet h'3B'. Anledningen är att detta format
kan användas till alla radix :
a'A' : ASCII tecken.
d'98' : decimalt.
h'3B' : hexadecimalt.
o'26' : oktalt.
b'00010000' : binärt.
Det finns ingen motsvarighet till "0x" formatet i de andra radix'en...
Jo, för oktalt finns det ju det, nämligen "0".
Fast jag vet inte om det är med i Microchips värld, och det var kanske i det sammanhanget du menade att det inte existerar något liknande.
Ett exempel med Perl one-liners:
Kod: Markera allt
$ perl -we "print 011"
9
$ perl -we "print 11"
11
$ perl -we "print 0x11"
17
Om jag minns rätt kommer det här från standard c.lib, så resten av världen funkar mestadels så här.
Postat: 4 mars 2007, 21:46:20
av sodjan
> Fast jag vet inte om det är med i Microchips värld,
Hela resonemanget rör naturligtsvis vad som accepteras av MPASM,
d.v.s assembler för PIC's. Se tablell 3-3 på sidan 42 i MPASM manualen.
> Ett exempel med Perl...
Perl är (ö-) känt för att acceptera nästan vad som helst...

Postat: 5 mars 2007, 01:24:15
av Maalobs
Det har inte så mycket med egenskaper i Perl att göra, det är en ärvd egenskap av standard C libbet som den och alla andra program skrivna i C är länkade mot.
En googling hittade:
"leading 0X or 0x implies hexadecimal, leading 0 implies octal, otherwise decimal"
Under stdlib.h:
http://www.csse.uwa.edu.au/programming/ ... brary.html
Men som sagt, man använder ju inte direkt det kompletta ANSI C-biblioteket när man utvecklar mot mikrokontrollers, om man nu ens skulle få för sig att göra sådant i C.
Postat: 5 mars 2007, 11:44:34
av sodjan
> "leading 0X or 0x implies hexadecimal, leading 0 implies octal, otherwise decimal"
OK, visst...
*Problemet* är att man i MPASM kan ställa om "default radix", så att
ett värde helt utan prefix kan i princip betyda vad som helst (så länge
värdet i sig är giltigt så klart).
Min rekomendation kvarstår, ange alltid radix-prefix, och kör med det format
som ser likadant ut oavsett radix (för läsbarhetens och konsekvensens skull).
Och igen, detta gäller MPASM, I couldn't care less hur det ser ut i std-C...

Postat: 11 mars 2007, 18:20:08
av squiz3r
Ingen som kan se något fel i min kod? Jag har gått igenom den gång efter gång men som sagt så vill den inte....
Myckat tacksamföralla svar!
//Daniel A
Postat: 11 mars 2007, 21:34:29
av sodjan
Nja, jag vet inte vad som går fel, men ett par saker i alla fall...
PÅ ett ställe står det "; main loop" och sedan kommer labeln "watch_resistans".
Lite längre ner kommer "goto watch_resistans".
Så långt är det OK, detta borde alltså vara just "main loop".
**Men** i koden i denna loop så finns det "goto" till labels som
ligger **utanför** loopen (till "portb5_in" och "portb5_out").
Inte alls snyggt ! Alla anrop till kod som ligger *utanför* main-loop
borde ska vara call's till subrutiner.
Gör de två port5_xx rutinerna till subrutiner och avsluta med return istället.
Du får komplettera med en extra "goto step_1" efter det andra anropet
till portb5_out, men det blir i alla fall snyggare så.
Jag skulle föreslå att du städer upp strukturen i programmet.
Kanske att problemet som du ser försvinner på samma gång, vem vet.
>step_2
> addwf time,f ;time = time + 1 (lägg till 1h till "time")
Hur vet du att du lägger till just + 1 ?? Var kommer ettan från ???
> decfsz time,1h
Om det är "decfsz time, f" som avses så är det bättre att skriva så.
Använd alltid "w" eller "f" som "destination".