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)