2. New PIC program
LIST P=16F84 PORTA EQU 5 PORTB EQU 6 TRISA EQU 85H TRISB EQU 86H STATUS EQU 3 INTCON EQU 0BH OPTREG EQU 81H TMR0 EQU 1 RP0 EQU 5 TOIF EQU 2 ZF EQU 2 CY EQU 0 ; USER DEFINED BITS IR EQU 1 ULTRA EQU 0 LED_IR EQU 3 LED_US EQU 2 #DEFINE BANK0 BCF STATUS,RP0 ;SELECT BANK 0 #DEFINE BANK1 BSF STATUS,RP0 ;SELECT BANK 1 CBLOCK 0CH ;VARIABLE BLOCK
TIME ;THE TIME-DELAY BETWEEN IR AND US-IMPACT
MIRROR_TIME ;THE MIRRORED TIME (BECAUSE OF D/A-CONVERTER)
COUNTER ;NEEDED FOR MIRRORING
CNTMSEC ;MSEC COUNT REGISTER IN WAIT SUBROUTINE
CNTSEC_4 ;1/4 SEC REGISTER IN WAIT SUBROUTINE
ENDC
;**************************
;* MAIN PROGRAM ENTRY *
;**************************
ORG 0
BANK1 CLRF TRISB^80H ;PORTB ALL OUTPUTS MOVLW B'00000110' ;TIMER0 PRESCALE 1:128 MOVWF OPTREG^80H MOVLW B'00000011' ;CONFIGURE ONLY PORT A0 AND A1 AS INPUTS MOVWF TRISA^80H ; BANK0 MOVLW B'00000011'
ANDWF PORTA,F ;CLEAR PORTA, BUT DON'T AFFECT A0 NOR A1
CLRF PORTB ;CLEAR PORTB
MOVLW 0x0C ;12*250ms=3SEC
CALL NSEC_4 ;WAIT THESE 3 SEC on power-up
BSF PORTA,LED_IR ;LED_IR ON to indicate device is working
MOVLW 0xFA ;WAIT 250 MSEC
CALL NMSEC
BCF PORTA,LED_IR ;LED_IR OFF
;NOW WE CAN START WITH MAIN PROGRAM GOTO PING ;******************************************************************* ;THESE MICRO4 AND NMSEC SUBROUTINES I FOUND SOMEWHERE ON THE INTERNET
MICRO4 ADDLW 0xFF ;SUBSTRACT 1 FROM W!
BTFSS STATUS,ZF ;SKIP WHEN YOU REACH ZERO
GOTO MICRO4 ;MORE LOOPS
RETURN
NMSEC MOVWF CNTMSEC ;W TO MSEC COUNT REGISTER
MSECLOOP MOVLW 0xF8 ;ALLOW FOR 8 MICROSEC OVERHEAD
CALL MICRO4 ;248 * 4 + 2 = 994 HERE
NOP ;MAKE REST OF LOOP
NOP ;ADD UP TO 6 MICROSECONDS
DECFSZ CNTMSEC,F ;DECREMENT COUNT, SKIP WHEN ZERO
GOTO MSECLOOP ;MORE LOOPS
RETURN
NSEC_4 MOVWF CNTSEC_4 ;W TO QUARTER OF A SECOND COUNTER
FSECLOOP MOVLW 0xEA ;wait until device well powered
CALL NMSEC ;250 MSEC
DECFSZ CNTSEC_4,F ;DECREMENT COUNT,SKIP WHEN ZERO
GOTO FSECLOOP ;MORE LOOPS
RETURN
;**************************************************************
; WAIT FOR IR-PING PING BTFSS PORTA,IR ;SKIP IF HIGH=IR-IMPACT
GOTO PING ;DO THIS AGAIN AND AGAIN
CLRF TMR0 ;RESET TIMER
BCF INTCON,TOIF ;CLEAR OVERFLOW CONDITION IF EVER
BSF PORTA,LED_IR;LED_IR ON
PONG BTFSS PORTA,ULTRA ;SKIP IF HIGH = NO US-IMPACT
GOTO SEND ;SEND MESSAGES TO RCX
BTFSS INTCON,TOIF ;SKIP IF TIME OVERFLOW = OUT OF RANGE
GOTO PONG ;DO THIS OVER AGAIN UNTIL TIMER OVERFLOW
;WAIT A BIT THEN RECOVER FROM ERROR CONDITION
MOVLW 0x0A ;WAIT 10 MSEC CALL NMSEC BCF PORTA,LED_IR ;LED_IR OFF
GOTO PING ;START CYCLE AGAIN
;NOW SIGNAL IS OK, DEVICE MAY SEND VALUE TO D/A-CONVERTER SEND BSF PORTA,LED_US ;TURN ON LED_US
MOVF TMR0,W ;W=TMR0,CHECK TIME
MOVWF TIME ;STORE TIME
CLRF MIRROR_TIME ;CLEAR MIRROR_TIME MOVLW 0x08 ;COUNTER=8 MOVWF COUNTER MIRROR RLF TIME,F ;ROTATE LEFT
BTFSC STATUS,CY ;SKIP IF NO CARRY
BSF MIRROR_TIME,7 ;SET THE 7TH BIT
DECF COUNTER,F ;NOW DECREMENT
BCF STATUS,CY ;CLEAR CARRY!!!
BTFSS STATUS,ZF ;SKIP IF ZERO
RRF MIRROR_TIME ;NOW ROTATE RIGHT
BTFSS STATUS,ZF ;SKIP IF ZERO
GOTO MIRROR
MOVF MIRROR_TIME,W MOVWF PORTB ;SHOW VALUE ON PORT B MOVLW 0x64 ;WAIT 100 MSEC CALL NMSEC BCF PORTA,LED_IR ;LED_IR OFF BCF PORTA,LED_US ;LED_US OFF GOTO PING END |
Notes:
one distance measurement needs a little more than 100ms
if the PIC doesn't get any ultrasonic signal after an IR-signal within a delay of 255*0.128ms=32.64ms, the PIC waits another 10ms, then jumps to the wait-for-IR-signal (=PING) routine.
the PIC must mirror the 8-bit output signal for the D/A converter. This little problem could also have been solved by connecting the receiver to the converter in an inverted way. But the present program solution was a little didactical challenge. The mirroring takes only 0.1ms, so this doesn't matter.
example: the measured delay 7810 = 0x4E16 = 010011102 is put out as 01110010 in order to be correctly converted to a voltage by the D/A-converter.
the measured delays between the IR and ultrasonic signals are expressed in units of 0.128 ms. (Remember that this is due to the 4MHz-quartz and the TMR0-prescale of 1:128. The PIC's internal timer is incremented every microsecond at a prescale 1:1; thus at 1:128 one timer-step has a duration of 0.128ms)