[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
;
;                                 Device : 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_t1        ;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

srm_source.zip
srm_hex.zip