measures the width of a pulse in 10-instruction-cycle units. Returns a 16-bit value and an error code.
Tachometers, duty-cycle meters, capacitor checkers, and precise interval timers can all be implemented with Pulsin.
To use Pulsin, you must set the desired pin to input and supply three arguments: the pulse direction in state (0 = 1-to-0, 255 = 0-to-1), the pin number (0 to 7) in pin, and the port number (0 = RA, 1 = RB, etc.) in w. When Pulsin returns, the 16-bit pulse width will be in hiB and lowB, and an error code in w. State and pin will have been modified by Pulsin for its own use, so your program should keep copies of these variables if needed.
The error codes returned in w are as follows:
Pulsin, like the other routines that accept pin and port arguments, requires the short table Pinz. Remember that tables must be located in the first 256 words of a 512-word program memory page. The same restriction applies if you decide to use a jump table (see Branch) to process the error code in w; the destinations of the calculated jumps must be in the first half of a program memory page.
One hint on using Pulsin: always assign the port number to w immediately before calling the routine. If you don't, some other instruction that uses w may change its contents, causing an error.
To see Pulsin in operation, connect the circuit below to an erasable PIC
or PIC emulator, such as the Parallax downloader. Assemble and run PULSIN.SRC.
When you adjust the function generator, the binary value displayed on the
LEDs will change.
; PULSIN port (in w), pin, state ; Measures the width of an input pulse in 10-cycle (10 us at 4 MHz) units. ; Returns a 16-bit (0 to 65,535) value. If no pulse occurs within ; 65,535 10-cycle intervals, the routine returns an error code in w. ; Routine is edge triggered. If the input pin is already in the target state ; when the routine begins, it will wait for the state to change, then wait ; for the specified edge. The routine waits 65,535 x 10 cycles for ; each edge, so it normally returns within 0.65535 seconds (4 MHz). ; However, if each transition is delayed by close to the full 65,535 x 10 ; cycles, the routine can take nearly 2 seconds to return (4 MHz). org 8 pin ds 1 ; Pin number to sample (0-7). state ds 1 ; Trigger: 255 = 0-to-1 transition. hiB ds 1 ; MSB of measurement. lowB ds 1 ; LSB of measurement. ; 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 start mov !rb,#0 ; Outputs to display result on LEDs. mov !rc,#0 mov !ra, #1111b ; All inputs mov state,#0 ; Negative pulse. mov pin,#2 ; Pin 2. mov w,#0 ; Port ra. call Pulsin mov rb,lowB ; Write Pulsin result to ports RB mov rc,hiB ; and RC for viewing on LEDs. jmp start ; Do it again. ; Upon entry, the desired pin must already be set up as an input. ; The w register contains a number representing the input port (0-2) for ; RA through RC. Variable pin contains the pin number (0-7). Variable state ; contains 255 for a 0-to-1 (positive) pulse, or 0 for a 1-to-0 (negative) pulse. ; Upon exit, the 16-bit count is in variables lowB and hiB. ; Variable pin contains the mask bit used by pulsin (not the pin number ; anymore, but a value with a 1 in the pin position), and state has been ; ANDed with pin. W contains the error code: 0= no error; 1= pin in ; already in target state when Pulsin was called--timeout waiting ; for transition; 2= timeout waiting for initial edge; 3= timeout waiting ; for final edge. Pulsin clr lowB ; Clear the 16-bit counter. clr hiB mov fsr,w ; Point to the port number. add fsr,#RA ; Add offset for port RA. mov w,pin ; Get bit mask from the table. call Pinz mov pin,w ; Put the mask into pin. AND state,w ; Mask extra bits out of state. :Hold mov w,indirect ; Sample the port. AND w,pin ; Mask off bits other than pin. XOR w,state ; Check pin against state. jnz :doneH ; If pin <> state, set up for edge. inc lowB ; Otherwise, lowB = lowB+1. snz ; Overflow in lowB? incsz hiB ; Yes: hiB=hiB+1, watch for overflow. jmp :Hold ; Sample the pin again. retw 1 ; Overflow in hiB? Timed out: return. :doneH clr lowB clr hiB :Edge1 mov w,indirect ; Sample the port. AND w,pin ; Mask off bits other than pin. XOR w,state ; Check pin against state. jz :doneE ; If pin = state, wait until change. inc lowB ; Otherwise, lowB = lowB+1. snz ; Overflow in lowB? incsz hiB ; Yes: hiB=hiB+1, watch for overflow. jmp :Edge1 ; Sample the pin again. retw 2 ; Overflow in hiB? Timed out: return. :doneE clr lowB clr hiB :Edge2 mov w,indirect ; Sample the port. AND w,pin ; Mask off bits other than pin. XOR w,state ; Check pin against state. jnz :done ; If pin <> state, we're done. inc lowB ; Otherwise, lowB = lowB+1. snz ; Overflow in lowB? incsz hiB ; Yes: hiB=hiB+1, watch for overflow. jmp :Edge2 ; Sample the pin again. retw 3 ; Overflow in hiB? Timed out: return. :done ret ; Done: pulsewidth in hiB, lowB.