inverts the state of an output pin.
In assembly language, inverting the state of a pin (or any bit, for that matter) is a matter of XORing the register with a value containing a 1 in the corresponding position. For example, to invert bit 2 of port RA, you would use the instructions XOR ra, #00000100b.
PBASIC's Toggle also changes the pin's data direction to output by putting a 0 in the appropriate bit of the tristate (TRIS) register. (In assembly, a 0 in TRIS means makes a pin and output; a 1 makes it an input. This is the opposite of the BASIC Stamp.) The assembly-language example here changes only the output latch, not TRIS.
Of course, if you use a literal number to toggle a pin's state with XOR, you cannot change the pin to be toggled while the program is running. The literal number is coded as part of the machine-language instruction. The accompanying program listing is a port- and pin-independent Toggle routine. Write the pin number to pin, the port number to w, and call Toggle.
To see Toggle in operation, either run the program with the PSIM simulator, or connect the circuit below to an erasable PIC or PIC emulator, such as the Parallax downloader. Assemble and run TOGGLE.SRC. When you apply power to the PIC, the LEDs connected to ports RB and RC will be inverted one-by-one, beginning with RB.0.
;
; ***************************************************************************
; *** Bubble Software Parallax to PIC Source Converter. Copyright 1999. ***
; *** http://www.bubblesoftonline.com email: sales@picnpoke.com ***
; ***************************************************************************
;
; TOGGLE port (in w), pin
; Toggles (inverts) the state of the specified port and pin.
; Device data and reset vector
P = pic16c55
#include <16c55.inc> ; processor assembler definitions
_CONFIG _xt_osc & _wdt_off & _protect_off
reset start
org 8
pin Res d'1' ; Pin number to set (0-7).
; Variables for the demo program--not required by Toggle.
p_index Res d'1' ; Copy of pin number, port number.
temp Res d'1' ; Temporary variables for time delay
temp2 Res d'1' ; between outputs.
org 0
; Table to convert pin number (0-7) into bit mask (00000001b to 10000000b).
Pinz ADDWF pcl
RETLW d'1'
RETLW d'2'
RETLW d'4'
RETLW d'8'
RETLW d'16'
RETLW d'32'
RETLW d'64'
RETLW d'128'
; The following demonstration code should show the value of being able to
; toggle a particular bit of a port based on a calculation performed while the
; program is running. As the variable p_index is incremented from 0 to 15,
; it is used to specify the pin and port to invert using Toggle.
start MOVLW d'0' ; All outputs on rb.
TRIS 6h
MOVLW d'0' ; All outputs on rc.
TRIS 7h
MOVLW b'10101010' ; Put a pattern of alternating lights
MOVWF 6h
MOVLW b'10101010' ; onto rb and rc.
MOVWF 7h
CLRF p_index ; Clear p_index.
start_loop MOVLW d'7' ; Copy three lsbs of p_index into
MOVWF pin
MOVF p_index ; variable pin.
ANDWF pin
MOVLW d'1' ; IF p_index.3 = 0
BTFSC p_index,d'3' ; THEN w = 1
MOVLW d'2' ; ELSE w = 2
CALL Toggle
CALL delay ; Wait a while between toggles.
INCF p_index ; Next pin/port.
BTFSS p_index,d'4' ; IF p_index < 15 (rc.7)
GOTO start_loop ; THEN :loop ELSE done
done GOTO $ ; Endless loop.
; To use the routine Toggle, put the pin number into the variable pin
; and the port number into w. Then call Toggle.
Toggle MOVWF fsr ; Point to the port number.
MOVLW 5h ; Add offset for port RA.
ADDWF fsr
MOVF pin,w
CALL Pinz ; Get bit mask from the table.
XORWF indirect ; Invert the selected bit
RETLW 0h
; Delay routine for demonstration. Not required by Toggle.
delay DECFSZ temp ; Time delay to provide spacing
GOTO delay
DECFSZ temp2 ; between highs.
GOTO delay
RETLW 0h
end
; TOGGLE port (in w), pin
; Toggles (inverts) the state of the specified port and pin.
org 8
pin ds 1 ; Pin number to set (0-7).
; Variables for the demo program--not required by Toggle.
p_index ds 1 ; Copy of pin number, port number.
temp ds 1 ; Temporary variables for time delay
temp2 ds 1 ; between outputs.
; 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
; The following demonstration code should show the value of being able to
; toggle a particular bit of a port based on a calculation performed while the
; program is running. As the variable p_index is incremented from 0 to 15,
; it is used to specify the pin and port to invert using Toggle.
start mov !rb, #0 ; All outputs on rb.
mov !rc, #0 ; All outputs on rc.
mov rb,#10101010b ; Put a pattern of alternating lights
mov rc,#10101010b ; onto rb and rc.
clr p_index ; Clear p_index.
:loop mov pin,#7 ; Copy three lsbs of p_index into
AND pin,p_index ; variable pin.
mov w,#1 ; IF p_index.3 = 0
snb p_index.3 ; THEN w = 1
mov w,#2 ; ELSE w = 2
call Toggle
call delay ; Wait a while between toggles.
inc p_index ; Next pin/port.
sb p_index.4 ; IF p_index < 15 (rc.7)
jmp :loop ; THEN :loop ELSE done
done jmp $ ; Endless loop.
; To use the routine Toggle, put the pin number into the variable pin
; and the port number into w. Then call Toggle.
Toggle mov fsr,w ; Point to the port number.
ADD fsr,#RA ; Add offset for port RA.
mov w,pin
call Pinz ; Get bit mask from the table.
XOR indirect,w ; Invert the selected bit
ret
; Delay routine for demonstration. Not required by Toggle.
delay djnz temp,delay ; Time delay to provide spacing
djnz temp2,delay ; between highs.
ret
See also:
Code: