[Menu]>[Guide to use the PIC]>[Circuits Gallery]>[Ultrasonic Range Meter]

Source code file of Ultrasonic Range Meter

    001
    002
    003
    004
    005
    006
    007
    008
    009
    010
    011
    012
    013
    014
    015
    016
    017
    018
    019
    020
    021
    022
    023
    024
    025
    026
    027
    028
    029
    030
    031
    032
    033
    034
    035
    036
    037
    038
    039
    040
    041
    042
    043
    044
    045
    046
    047
    048
    049
    050
    051
    052
    053
    054
    055
    056
    057
    058
    059
    060
    061
    062
    063
    064
    065
    066
    067
    068
    069
    070
    071
    072
    073
    074
    075
    076
    077
    078
    079
    080
    081
    082
    083
    084
    085
    086
    087
    088
    089
    090
    091
    092
    093
    094
    095
    096
    097
    098
    099
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    304
    305
    306
    307
    308
    309
    310
    311
    312
    313
    314
    315
    316
    317
    318
    319
    320
    321
    322
    323
    324
    325
    326
    327
    328
    329
    330
    331
    332
    333
    334
    335
    336
    337
    338
    339
    340
    341
    342
    343
    344
    345
    346
    347
    348
    349
    350
    351
    352
    353
    354
    355
    356
    357
    358
    359
    360
    361
    362
    363
    364
    365
    366
    367
    368
    369
    370
    371
    372
    373
    374
    375
    376
    377
    378
    379
    380
    381
    382
    383
    384
    385
    386
    387
    388
    389
    390
    391
    392
    393
    394
    395
    396
    397
    398
    399
    400
    401
    402
    403
    404
    405
    406
    407
    408
    409
    410
    411
    412
    413
    414
    415
    416
    417
    418
    419
    420
    421
    422
    423
    424
    425
    426
    427
    428
    429
    430
    431
    432
    433
    434
    435
    436
    437
    438
    439
    440
    441
    442
    443
    444
    445
    446
    ;********************************************************
    ;
    ;                 Ultrasonic Range Meter
    ;
    ;                                 Divice : PIC16F873
    ;                                 Author : Seiichi Inoue
    ;********************************************************

            list            p=pic16f873
            include         p16f873.inc
           __config _hs_osc & _wdt_off & _pwrte_on & _lvp_off

    ;****************  Label Definition  ********************
            cblock  h'20'
    s_count                         ;Send-out pulse count adr
    s_adj                           ;Adjustment data address
    s_adj_count                     ;Rotate value save adr
    s_digit                         ;Digit cont work address
    g_time1                         ;Guard timer address 1
    g_time2                         ;Guard timer address 2
    p_countl                        ;Propagation L cnt adr
    p_counth                        ;Propagation H cnt adr
    digit_cnt                       ;Digit counter head adr
    disp_ha                         ;Digit head address
    disp_u                          ;1st digit address
    disp_t                          ;10th digit address
    disp_h                          ;100th digit address
    seg7_ha                         ;7 segLED table head adr
    seg70                           ;Pattern 0 set adr
    seg71                           ;Pattern 1 set adr
    seg72                           ;Pattern 2 set adr
    seg73                           ;Pattern 3 set adr
    seg74                           ;Pattern 4 set adr
    seg75                           ;Pattern 5 set adr
    seg76                           ;Pattern 6 set adr
    seg77                           ;Pattern 7 set adr
    seg78                           ;Pattern 8 set adr
    seg79                           ;Pattern 9 set adr
    seg7a                           ;Pattern A set adr
    seg7b                           ;Pattern B set adr
            endc

    ra1     equ     h'01'           ;RA1 port designation
    ra2     equ     h'02'           ;RA2 port designation
    ra3     equ     h'03'           ;RA3 port designation
    ra5     equ     h'05'           ;RA5 port designation

    ccp1    equ     h'02'           ;CCP1(RC2) designation

    seg7_0  equ     b'01000000'     ;-gfedcba Pattern 0
    seg7_1  equ     b'01111001'     ;         Pattern 1
    seg7_2  equ     b'00100100'     ;         Pattern 2
    seg7_3  equ     b'00110000'     ;         Pattern 3
    seg7_4  equ     b'00011001'     ;         Pattern 4
    seg7_5  equ     b'00010010'     ;         Pattern 5
    seg7_6  equ     b'00000010'     ;         Pattern 6
    seg7_7  equ     b'01111000'     ;         Pattern 7
    seg7_8  equ     b'00000000'     ;         Pattern 8
    seg7_9  equ     b'00010000'     ;         Pattern 9
    seg7_a  equ     b'01111111'     ;         Detect error
    seg7_b  equ     b'00100011'     ;         Illegal int

    ;****************  Program Start  ***********************
            org     0               ;Reset Vector
            goto    init
            org     4               ;Interrupt Vector
            goto    int

    ;****************  Initial Process  *********************
    init

    ;*** Port initialization
            bsf     status,rp0      ;Change to Bank1
            movlw   b'00000001'     ;AN0 to input mode
            movwf   trisa           ;Set TRISA register
            clrf    trisb           ;RB port to output mode
            movlw   b'00000100'     ;RC2/CCP1 to input mode
            movwf   trisc           ;Set TRISC register

    ;*** Ultrasonic sending period initialization (Timer0)
            movlw   b'11010111'     ;T0CS=0,PSA=0,PS=1:256
            movwf   option_reg      ;Set OPTION_REG register
            bcf     status,rp0      ;Change to Bank0
            clrf    tmr0            ;Clear TMR0 register

    ;*** Capture mode initialization (Timer1)
            movlw   b'00000001'     ;Pre=1:1 TMR1=Int TMR1=ON
            movwf   t1con           ;Set T1CON register
            clrf    ccp1con         ;CCP1 off

    ;*** A/D converter initialization
            movlw   b'01000001'     ;ADCS=01 CHS=AN0 ADON=ON
            movwf   adcon0          ;Set ADCON0 register
            bsf     status,rp0      ;Change to Bank1
            movlw   b'00001110'     ;ADFM=0 PCFG=1110
            movwf   adcon1          ;Set ADCON1 register
            bcf     status,rp0      ;Change to Bank0

    ;*** Display initialization (Timer2)
            movlw   disp_u          ;Set digit head address
            movwf   disp_ha         ;Save digit head sddress
            movlw   h'0a'           ;"Detect error" data
            movwf   disp_u          ;Set 1st digit
            movwf   disp_t          ;Set 10th digit
            movwf   disp_h          ;Set 100th digit
            movlw   d'3'            ;Digit counter
            movwf   digit_cnt       ;Set digit counter
            movlw   seg70           ;Set 7seg head address
            movwf   seg7_ha         ;Save 7seg head address
            movlw   seg7_0          ;Set 7segment pattern 0
            movwf   seg70           ;Save pattern 0
            movlw   seg7_1          ;Set 7segment pattern 1
            movwf   seg71           ;Save pattern 1
            movlw   seg7_2          ;Set 7segment pattern 2
            movwf   seg72           ;Save pattern 2
            movlw   seg7_3          ;Set 7segment pattern 3
            movwf   seg73           ;Save pattern 3
            movlw   seg7_4          ;Set 7segment pattern 4
            movwf   seg74           ;Save pattern 4
            movlw   seg7_5          ;Set 7segment pattern 5
            movwf   seg75           ;Save pattern 5
            movlw   seg7_6          ;Set 7segment pattern 6
            movwf   seg76           ;Save pattern 6
            movlw   seg7_7          ;Set 7segment pattern 7
            movwf   seg77           ;Save pattern 7
            movlw   seg7_8          ;Set 7segment pattern 8
            movwf   seg78           ;Save pattern 8
            movlw   seg7_9          ;Set 7segment pattern 9
            movwf   seg79           ;Save pattern 9
            movlw   seg7_a          ;Set 7segment pattern A
            movwf   seg7a           ;Save pattern A
            movlw   seg7_b          ;Set 7segment pattern B
            movwf   seg7b           ;Save pattern B
            movlw   b'00011110'     ;OPS=1:4,T2=ON,EPS=1:16
            movwf   t2con           ;Set T2CON register
            bsf     status,rp0      ;Change to Bank1
            movlw   d'157'          ;157x64=10048usec
            movwf   pr2             ;Set PR2 register
            bsf     pie1,tmr2ie     ;TMR2IE=ON
            bcf     status,rp0      ;Change to Bank0

    ;*** Interruption control
            movlw   b'11100000'     ;GIE=ON,PEIE=ON,T0IE=ON
            movwf   intcon          ;Set INTCON register

    wait
            goto    $               ;Interruption wait

    ;***************  Interruption Process  *****************
    int
            movfw   pir1            ;Read PIR1 register
            btfsc   pir1,ccp1if     ;Capture occurred ?
            goto    capture         ;Yes. "Capture"
            btfsc   pir1,tmr2if     ;TMR2 time out ?
            goto    led_cont        ;Yes. "LED display"
            movfw   intcon          ;Read INTCON register
            btfsc   intcon,t0if     ;TMR0 time out ?
            goto    send            ;Yes. "Pulse send"

    ;***************  Illegal interruption  *****************
    illegal
            movlw   h'0b'           ;Set Illegal disp digit
            addwf   seg7_ha,w       ;Seg7 H.Adr + digit
            movwf   fsr             ;Set FSR register
            movfw   indf            ;Read seg7 data
            movwf   portb           ;Write LED data
            bcf     porta,ra1       ;RA1=ON
            bcf     porta,ra2       ;RA2=ON
            bcf     porta,ra3       ;RA3=ON
            goto    $               ;Stop

    ;************  END of Interruption Process **************
    int_end
            retfie

    ;***************  Pulse send-out Process ****************
    send
            bcf     intcon,t0if     ;Clear TMR0 int flag
            clrf    tmr0            ;Timer0 clear

    ;*** Received Pulse detection check
            movfw   portc           ;Read PORTC register
            btfsc   portc,ccp1      ;Detected ?
            goto    detect_off      ;Yes. Detected
            movlw   h'0a'           ;"Detect error" data
            movwf   disp_u          ;Set 1st digit
            movwf   disp_t          ;Set 10th digit
            movwf   disp_h          ;Set 100th digit

    ;*** Receive pulse detector off
    detect_off
            bcf     porta,ra5       ;Set detector OFF

    ;*** Capture start
            clrf    tmr1h           ;Clear TMR1H register
            clrf    tmr1l           ;Clear TMR1L register
            clrf    ccpr1h          ;Clear CCPR1H register
            clrf    ccpr1l          ;Clear CCPR1L register
            movlw   b'00000101'     ;CCP1M=0101(Capture)
            movwf   ccp1con         ;Set CCP1CON register
            bsf     status,rp0      ;Change to Bank1
            bsf     pie1,ccp1ie     ;CCP1 interruptin enable
            bcf     status,rp0      ;Change to Bank0
            bcf     pir1,ccp1if     ;Clear CCP1 int flag

    ;*** 40KHz pulse send ( 0.5 msec )
            movlw   d'20'           ;Send-out pulse count
            movwf   s_count         ;Set count
    s_loop
            call    pulse           ;Call pulse send sub
            decfsz  s_count,f       ;End ?
            goto    s_loop          ;No. Continue

    ;*** Get adjustment data
            bsf     adcon0,go       ;Start A/D convert
    ad_check
            btfsc   adcon0,go       ;A/D convert end ?
            goto    ad_check        ;No. Again
            movfw   adresh          ;Read ADRESH register
            movwf   s_adj           ;Save converted data

            movlw   d'5'            ;Set rotate value
            movwf   s_adj_count     ;Save rotate value
    ad_rotate
            rrf     s_adj,f         ;Rotate right 1 bit
            decfsz  s_adj_count,f   ;End ?
            goto    ad_rotate       ;No. Continue
            movfw   s_adj           ;Read rotated value
            andlw   b'00000111'     ;Pick-up 3 bits
            addlw   d'54'           ;(0 to 7) + 54 = 54 to 61
            movwf   s_adj           ;Save adjustment data

    ;*** Capture guard timer ( 1 milisecound )
            movlw   d'2'            ;Set loop counter1
            movwf   g_time1         ;Save loop counter1
    g_loop1 movlw   d'124'          ;Set loop counter2
            movwf   g_time2         ;Save loop counter2
    g_loop2 nop                     ;Time adjust
            decfsz  g_time2,f       ;g_time2 - 1 = 0 ?
            goto    g_loop2         ;No. Continue
            decfsz  g_time1,f       ;g_time1 - 1 = 0 ?
            goto    g_loop1         ;No. Continue

    ;*** Receive pulse detector on
            bsf     porta,ra5       ;Set detector ON

            goto    int_end

    ;***************  Pulse send-out Process ****************
    pulse
            movlw   b'00010000'     ;RC4=ON
            movwf   portc           ;Set PORTC register
            call    t12us           ;Call 12usec timer
            clrf    portc           ;RC4=OFF
            goto    $+1
            goto    $+1
            nop
            return

    ;***************  12 microseconds timer *****************
    t12us
            goto   $+1
            goto   $+1
            goto   $+1
            goto   $+1
            nop
            return

    ;******************  Capture Process ********************
    capture
            bcf     pir1,ccp1if     ;Clear CCP1 int flag

            clrf    p_countl        ;Clear L count
            clrf    p_counth        ;Clear H count
            clrf    ccp1con         ;CCP1 off

    division
            movfw   s_adj           ;Read adjustment data
            subwf   ccpr1l,f        ;Capture - adjust
            btfsc   status,z        ;Result = 0 ?
            goto    division2       ;Yes. "R = 0"
            btfsc   status,c        ;Result < 0 ?
            goto    division1       ;No. "R > 0"
            goto    division3       ;Yes."R < 0"

    division1                       ;( R > 0 )
            movlw   d'1'            ;Set increment value
            addwf   p_countl,f      ;Increment L count
            btfss   status,c        ;Overflow ?
            goto    division        ;No. Continue
            incf    p_counth,f      ;Increment H count
            goto    division        ;Jump next

    division2                       ;( R = 0 )
            movfw   ccpr1h          ;Read CCPR1H
            btfss   status,z        ;CCPR1H = 0 ?
            goto    division1       ;No. Next
            movlw   d'1'            ;Set increment value
            addwf   p_countl,f      ;Increment L count
            btfss   status,c        ;Overflow ?
            goto    digit_set       ;Jump to digit set
            incf    p_counth,f      ;Increment H count
            goto    digit_set       ;Jump to digit set

    division3                       ;( R < 0 )
            movfw   ccpr1h          ;Read CCPR1H
            btfss   status,z        ;CCPR1H = 0 ?
            goto    division4       ;No. Borrow process
            goto    digit_set       ;Jump to digit set

    division4
            decf    ccpr1h,f        ;CCPR1H - 1
            movlw   d'255'          ;Borrow value
            addwf   ccpr1l,f        ;CCPR1L + 255
            incf    ccpr1l,f        ;CCPR1L + 1
            goto    division1       ;Next

    ;****************  Digit Set Process ********************
    digit_set
            clrf    disp_u          ;Clear 1st digit
            clrf    disp_t          ;Clear 10th digit
            clrf    disp_h          ;Clear 100th digit

    ;*** 100th digit
    digit_h
            movlw   d'100'          ;Divide value
            subwf   p_countl,f      ;Digit - divide
            btfsc   status,z        ;Result = 0 ?
            goto    digit_h2        ;Yes. "R = 0"
            btfsc   status,c        ;Result < 0 ?
            goto    digit_h1        ;No. "R > 0"
            goto    digit_h3        ;Yes."R < 0"

    digit_h1                        ;( R > 0 )
            incf    disp_h,f        ;Increment 100th count
            goto    digit_h         ;Jump next

    digit_h2                        ;( R = 0 )
            movfw   p_counth        ;Read H counter
            btfss   status,z        ;H counter = 0 ?
            goto    digit_h1        ;No. Next
            incf    disp_h,f        ;Increment 100th count
            goto    digit_t         ;Jump to 10th digit pro

    digit_h3                        ;( R < 0 )
            movfw   p_counth        ;Read H counter
            btfss   status,z        ;H counter = 0 ?
            goto    digit_h4        ;No. Borrow process
            movlw   d'100'          ;Divide value
            addwf   p_countl,f      ;Return over sub value
            goto    digit_t         ;Jump to 10th digit pro

    digit_h4
            decf    p_counth,f      ;H counter - 1
            movlw   d'255'          ;Borrow value
            addwf   p_countl,f      ;L counter + 255
            incf    p_countl,f      ;L counter + 1
            goto    digit_h1        ;Next

    ;*** 10th digit
    digit_t

    ;*** Range over check
            movfw   disp_h          ;Read 100th digit
            sublw   d'9'            ;9 - (100th digit)
            btfsc   status,z        ;Result = 0 ?
            goto    digit_t0        ;Yes. "R = 0"
            btfsc   status,c        ;Result < 0 ?
            goto    digit_t0        ;No. "R > 0"
            movlw   h'0a'           ;"Detect error" data
            movwf   disp_u          ;Set 1st digit
            movwf   disp_t          ;Set 10th digit
            movwf   disp_h          ;Set 100th digit
            goto    int_end

    digit_t0
            movlw   d'10'           ;Divide value
            subwf   p_countl,f      ;Digit - divide
            btfsc   status,z        ;Result = 0 ?
            goto    digit_u         ;Yes. "R = 0"
            btfsc   status,c        ;Result < 0 ?
            goto    digit_t1        ;No. "R > 0"
            goto    digit_t2        ;Yes."R < 0"

    digit_t1                        ;( R > 0 )
            incf    disp_t,f        ;Increment 10th count
            goto    digit_t         ;Jump next

    digit_t2                        ;( R < 0 )
            movlw   d'10'           ;Divide value
            addwf   p_countl,f      ;Return over sub value
            goto    digit_u         ;Jump to 1st digit pro

    ;*** 1st digit
    digit_u
            movfw   p_countl        ;Read propagetion counter
            movwf   disp_u          ;Save 1st count

            goto    int_end

    ;****************  LED display control  *****************
    led_cont
            bcf     pir1,tmr2if     ;Clear TMR2 int flag

            movfw   digit_cnt       ;Read digit counter
            movwf   s_digit         ;Save digit counter
            decfsz  s_digit,f       ;1st digit ?
            goto    d_check1        ;No. Next
            bsf     porta,ra1       ;RA1=OFF
            bsf     porta,ra2       ;RA2=OFF
            bcf     porta,ra3       ;RA3=ON
            goto    c_digit         ;Jump to digit cont
    d_check1
            decfsz  s_digit,f       ;10th digit ?
            goto    d_check2        ;No. 100th digit
            bsf     porta,ra1       ;RA1=OFF
            bcf     porta,ra2       ;RA2=ON
            bsf     porta,ra3       ;RA3=OFF
            goto    c_digit         ;Jump to digit cont
    d_check2
            bcf     porta,ra1       ;RA1=ON
            bsf     porta,ra2       ;RA2=OFF
            bsf     porta,ra3       ;RA3=OFF

    c_digit
            decf    digit_cnt,w     ;Digit count - 1
            addwf   disp_ha,w       ;Digit H.Adr + count
            movwf   fsr             ;Set FSR register
            movfw   indf            ;Read digit
            addwf   seg7_ha,w       ;Seg7 H.Adr + digit
            movwf   fsr             ;Set FSR register
            movfw   indf            ;Read seg7 data
            movwf   portb           ;Write LED data

            decfsz  digit_cnt,f     ;Digit count - 1
            goto    int_end         ;Jump to interrupt end
            movlw   d'3'            ;Initial value
            movwf   digit_cnt       ;Set initial value
            goto    int_end         ;Jump to interrupt end

    ;********************************************************
    ;            END of Ultrasonic Range Meter
    ;********************************************************

            end