; pin assignments
; portB 0-7 = USB D0-D7 normally inputs, switched to outputs when
; writing to usb
; portC.7 = output USBWR normally low - pulse high to write
; portC.6 = input USBTXF low means ok to write
; portC.5 = output USBRD normally high - pulse low to read
; portC.4 = input USBRXF low means ok to read
; portC.3 = output SRF1Trigger normally low
; portC.2 = input SRF1Echo - time high pulse following trigger
; portC.1 = output SRF2Trigger
; portC.0 = input SRF2Echo
; pulse trigger hi for 10usec to start conversion
; Echo duration 100usec to 36000usec
; divide by 58 for millimeters or 148 for inches
; range of 1(1.7) to 620 cm = 0(0.67) to 243 inches
; portA.3 = output IR1Clock pulse hi 10usec to start conversion
; portA.2 = input IR1Data - time high pulse following trigger
; portA.1 = output IR2Clock
; portA.0 = input IR2Data
; drop clock low to start conversion and wait for data
; to go high (about 70 milliseconds
; set clock high for 2 usec then low and read Data bit,
; after 2usec set clock high again
; repeat for 7 additional bits
; end with clock high.
list P=16F872
#include <p16f872.inc>
;=====================
; Declaration
#define USBWR PORTC,7
#define USBTXF PORTC,6
#define USBRD PORTC,5
#define USBRXF PORTC,4
#define SRF1Trigger PORTC,3
#define SRF1Echo PORTC,2
#define SRF2Trigger PORTC,1
#define SRF2Echo PORTC,0
#define USBData PORTB
#define IR1Clock PORTA,3
#define IR1Data PORTA,2
#define IR2Clock PORTA,1
#define IR2Data PORTA,0
#define LED1 PORTA,5
#define LED2 PORTA,4
;start general purpose registers
N equ 0x20 ;simple counter counts 1 second periods
T equ 0x21 ;counts 4 ms periods for the 1 second counter
U equ 0x22 ;stores value read from USB port
I equ 0x23 ;general purpose temp variable
J equ 0x24 ;general purpose temp varaible
org 0x0000
goto Init
org 1ch
Init
movlw 0x10
movwf T1CON ;Timer1 - prescale 1:2, oscillator disabled, internal
clock, not running,
;set for 1 usec. rate
clrf INTCON ; Disable all interrupts and clear T0IF
clrf PORTA ;set all outputs low
clrf PORTB
clrf PORTC ;except...
bsf USBRD ;normally high
bsf IR1Clock ;normally high
bsf IR2Clock ;normally high
bsf STATUS, RP0 ; Bank1
movlw 0xc4 ; PortB pull-ups are disabled
movwf OPTION_REG ; Interrupt on rising edge of RB0 - interrrupts
are not enabled
; Timer0 increment from internal clock
; with a prescaler of 1:16 - will count at 8usec rate.
; wdt will timeout at 18msec.
movlw 0x06
movwf ADCON1 ;port A is all digital i/o - no a/d
movlw b'11000101' ;1,3,4 and 5 are outputs
movwf TRISA
movlw b'11111111'
movwf TRISB
movlw b'01010101' ;1,3,5 and 7 are outputs
movwf TRISC
bcf STATUS, RP0 ; Bank0
bsf USBRD ;normally high
bcf USBWR ;normally low
bsf IR1Clock ;normally high
bsf IR2Clock ;normally high
bcf SRF1Trigger ;normally low
bcf SRF2Trigger ;normall low
clrf N ;start at 0
clrf T
clrf U
;*******************************************************************
;main program loop here
;output sequence will be 0,0,SRF1Hi,SRF1Lo,IR1,SRF2Hi,SRF2Lo,IR2,
repeat...
;can synchronize by waiting for two zero values in fast succession,
;less than 1ms apart
Loop
movlw 0
call WriteUSB
movlw 0
call WriteUSB
call ReadSRF1 ;returned in Timer1 - 1 to 36 ms
movfw TMR1H
call WriteUSB
movfw TMR1L
call WriteUSB
call ReadIR1 ;returned in W - 70 ms
call WriteUSB
call ReadSRF2 ;returned in Timer1 - 1 to 36 ms
movfw TMR1H
call WriteUSB
movfw TMR1L
call WriteUSB
call ReadIR2 ;returned in W - 70 ms
call WriteUSB
goto Loop
;*******************************************************************
ReadUSB ;if USBRXF is low, read usb port to W
btfsc USBRXF
goto ReadUSBDone
bcf USBRD ;RD low
nop
nop ;pause a little
movf USBData,W ;data from USB
movwf U ;save it in U
bsf USBRD ;RD back to high
ReadUSBDone
return
;*******************************************************************
WriteUSB ;if USBTXF is low, write W to usb port
btfsc USBTXF
goto WriteUSBDone ;if USBTXF is high, skip writing
movwf USBData ;W to data port
bsf STATUS,RP0
movlw 0x00
movwf TRISB ;data port to output mode
bcf STATUS,RP0
bsf USBWR ;WR high
nop ;pause just a little
nop
bcf USBWR ;WR low
bsf STATUS,RP0
movlw 0xff
movwf TRISB ;data port back to input mode
bcf STATUS,RP0
WriteUSBDone
return
;*******************************************************************
;Reads IR1 Sensor, returns value in W, takes about 70 milliseconds
;uses temp variables I and J
;set clock low
;wait for data to go low
;set clock high then low
;read data bit - rotate bit into J
;repeat for rest of 8 bits
;set clock high
ReadIR1
bcf IR1Clock
btfsc IR1Data
goto $-1 ;wait for IR1Data low
clrwdt ;keep watch dog happy
btfss IR1Data
goto $-2 ;wait for IR1Data high
movlw .8
movwf I ;counter for 8 bits
ReadIR1Loop
bsf IR1Clock ;set clock high
nop
nop ;pause a little
bcf IR1Clock ;set clock low
nop
nop ;pause a little
bcf STATUS,C ;clear carry bit
btfsc IR1Data
bsf STATUS,C ;if data is high, set carry bit
rlf J ;shift carry bit into J
decfsz I
goto ReadIR1Loop ;repeat for all 8 bits
movfw J
bsf IR1Clock ;set clock high again
return
;*******************************************************************
ReadIR2
bcf IR2Clock
btfsc IR2Data
goto $-1 ;wait for IR2Data low
clrwdt ;keep watch dog happy
btfss IR2Data
goto $-2 ;wait for IR2Data high
movlw .8
movwf I ;counter for 8 bits
ReadIR2Loop
bsf IR2Clock ;set clock high
nop
nop ;pause a little
bcf IR2Clock ;set clock low
nop
nop ;pause a little
bcf STATUS,C ;clear carry bit
btfsc IR2Data
bsf STATUS,C ;if data is high, set carry bit
rlf J ;shift carry bit into J
decfsz I
goto ReadIR2Loop ;repeat for all 8 bits
movfw J
bsf IR2Clock ;set clock high again
return
;*******************************************************************
;set SRF1Trigger high
;wait at least 10us
;set SRF1Trigger low
;wait for SRF1Echo to go high
;time until SRF1Echo goes low (100 to 36000 usec.)
ReadSRF1
bsf SRF1Trigger ;set trigger high
movlw .7
movwf I
decfsz I
goto $-1 ;delay 11.5 usec.
bcf SRF1Trigger ;set trigger low
bcf T1CON,0 ;stop timer1
clrf TMR1H
clrf TMR1L ;and set it to zero
clrwdt ;keep watch dog happy
btfsc SRF1Echo
goto $-2 ;wait for echo low
;echo is now high
bsf T1CON,0 ;start timer1
clrwdt
btfss SRF1Echo
goto $-2 ;wait for echo low again
bcf T1CON,0 ;stop timer1
;timer1 contains echo pulse in usec.
return
;*******************************************************************
ReadSRF2
bsf SRF2Trigger ;set trigger high
movlw .7
movwf I
decfsz I
goto $-1 ;delay 11.5 usec.
bcf SRF2Trigger ;set trigger low
bcf T1CON,0 ;stop timer1
clrf TMR1H
clrf TMR1L ;and set it to zero
clrwdt ;keep watch dog happy
btfsc SRF2Echo
goto $-2 ;wait for echo low
;echo is now high
bsf T1CON,0 ;start timer1
clrwdt
btfss SRF2Echo
goto $-2 ;wait for echo low again
bcf T1CON,0 ;stop timer1
;timer1 contains echo pulse in usec.
return
;*******************************************************************
SetLED1 ;turns LED1 on or off according to low bit of N
btfsc N,0
goto SetLED1On
SetLED1Off
bcf LED1
return
SetLED1On
bsf LED1
return
;*******************************************************************
SetLED2 ;turns LED2 on or off according to low bit of U
btfsc U,0
goto SetLED2On
SetLED2Off
bcf LED2
return
SetLED2On
bsf LED2
return
;*******************************************************************
END