Det var kanske inte helt korrekt att använda ”förutfattade meningar” som beteckning på fenomenet i fråga. Jag förstår att i vissa fall kan det vara fördelaktigt att skriva i asm men för hobby och semi-professionell verksamhet är inlärningströskeln alldeles för hög för det stora flertalet.
Jag har själv hankat mig fram i 6502 miljö (”maskinkod”) på VIC20 tiden men när det finns genvägar (läs Basic) så kommer jag aldrig att gå bakåt i tiden igen! Varför åka hästskjuts när det finns jet? Naturligtvis finns det fällor att falla i men det uppväger ändå inte fördelarna och enkelheten i koden för att inte tala om hur mycket mindre man behöver skriva:
Exempel.
PicBasic Pro:
SERIN 0, N2400, ["A"] 'SERIN 0, N2400, ["A"] '
Wait for the ASCII character A on port-pin 0 at 2400 baud
ASM:
; SERIN port, pin, baud, polarity, bytes, filter
; Receives data serially at the specified rate and polarity via the specified
; port pin. Stores the data as a counted string starting at buffer-1 (buffer is
; the number of bytes in the string). An optional filter causes the routine to
; ignore data outside a range of ASCII character values set by filt_lo and
; filt_hi.
buffer = 31 ; String storage.
B2400 = 30 ; Bit delay for 2400 baud.
B1200 = 62 ; Bit delay for 1200 baud.
B600 = 126 ; Bit delay for 600 baud.
B300 = 255 ; Bit delay for 300 baud.
filt_lo = '0' ; Set filter for ASCII
filt_hi = '9' ; chars representing 0-9.
org 8
baud ds 1 ; Baud rate.
pin ds 1 ; Pin number (0-7).
port ds 1 ; Port number (0-2).
bytes ds 1 ; Number of bytes to receive.
temp1 ds 1 ; Temporary counter for Serin.
temp2 ds 1 ; Temporary counter for Serin.
temp3 ds 1 ; Temporary counter for delay.
ser_fl ds 1 ; Flags for serin switches.
polarity = ser_fl.0 ; Polarity: 0=true, 1=inverted.
filter = ser_fl.1 ; Range filter: 0=off, 1=on.
filt_1st = ser_fl.2 ; 1st filter byte passed?: 0=no, 1=yes.
aux = ser_fl.3 ; Temporary flag for filter comparisons.
; Device data and reset vector
device pic16c55,xt_osc,wdt_off,protect_off
reset start
org 0
; Table to convert pin number (0-7) into bit mask (00000001b to 10000000b).
Pinz jmp pc+w
retw 1,2,4,8,16,32,64,128
; Subroutine used by Serin to get a bit and delay for a number of loops
; set by temp3. Jumping into get_bit:loop provides the delay, but ignores the
; input bit.
get_bit mov fsr,port ; Point to port.
mov w,indirect ; IF Polarity = 0 THEN w = Port
snb Polarity ; ELSE w = NOT Port
mov w,/indirect
AND w,pin
snz ; IF w AND pin THEN carry = 1
clc ; ELSE carry = 0.
sz
stc
mov fsr,temp1 ; Point to buffer location.
rr indirect ; Rotate carry into msb of data byte.
:loop jmp $+1 ; Two-cycle nops.
jmp $+1
jmp $+1
jmp $+1
jmp $+1
djnz temp3,:loop
ret
; Main program start. Receives a single byte of data, filtered for numeric
; characters, and displays the data bits on LEDs connected to port RB.
start mov !ra, #15 ; All inputs.
mov !rb,#0 ; All outputs for LEDs.
clr rc ; Clear the LEDs.
clr ser_fl ; Clear serial flags.
mov bytes,#1 ; Receive 1 byte
clrb filter ; not filtered
setb polarity ; inverted polarity
mov baud,#B2400 ; at 2400 baud
mov pin,#2 ; via pin 2
mov port,#0 ; of port ra.
CALL SERIN ; Receive the data.
mov rb,buffer-1 ; Move byte to LEDs on RB.
jmp start ; Endless loop
; Body of the Serin routine. Expects the baud constant in baud, number of
; bytes to receive in bytes, the I/O port (0-2 for RA through RC) in port,
; the pin number (0-7) in pin, and the flag settings in ser_fl
SERIN clr buffer ; Clear buffer counter.
clrb filt_1st
ADD port,#RA ; Add offset for port RA.
mov w,pin
CALL Pinz ; Get bit mask from the table.
mov pin,w ; Put the mask into pin.
mov temp1,#buffer-1 ; Pointer for first data address.
:poll mov fsr,port
mov w,indirect ; IF Polarity = 0 THEN w = Port
snb Polarity ; ELSE w = NOT Port
mov w,/indirect
AND w,pin ; IF pin = 0 THEN receive data
jnz :poll ; ELSE poll
clc
mov w,>>baud ; LET temp3 = baud/2
mov temp3,w ; Set up 1/2 bit time delay.
CALL get_bit:loop ; Jump into delay of get_bit.
mov temp3,baud ; Set up full bit time delay.
CALL get_bit:loop ; Jump into delay of get_bit.
mov temp2,#8 ; Eight data bits.
:rcv mov temp3,baud ; Set up bit delay.
CALL get_bit ; Get the next data bit.
djnz temp2,:rcv ; Eight bits received?
:done mov temp3,baud ; Set up bit delay.
CALL get_bit:loop ; Wait for stop bit.
jnb filter,:skip ; IF filter=0 (off) THEN :skip
clrb aux ; LET aux = 0.
csae indirect,#filt_lo ; IF byte < filt_lo THEN aux=1
setb aux
csbe indirect,#filt_hi ; IF byte > filt_hi THEN aux=1
setb aux
jnb aux,:skip ; If aux = 0 (byte is within
snb filt_1st ; filter range) :skip. If byte is
ret ; out of range, but valid bytes have
jmp :poll ; been received, return. Else poll.
:skip setb filt_1st
DEC temp1 ; Decrement buffer pointer.
inc buffer ; Increment buffer counter.
djnz bytes,:poll ; More bytes to receive: poll.
ret
Jovisst, jag är lat! 