-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathADC_to_7seg_16f887.s
464 lines (411 loc) · 11.9 KB
/
ADC_to_7seg_16f887.s
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
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
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
;TO ENABLE CORRECT OPERATION OF RESET AND INTERRUPT VECTORS: --HIGHLY IMPORTANT--
;under Project Properties, pic-as Linker, under Custom linker options, include a copy of the following line:
;"-PRES_VECT=0x00;-PINT_VECT=0x04"
PROCESSOR 16F887 ;Datasheet: https://ww1.microchip.com/downloads/en/devicedoc/41291d.pdf
; CONFIG1
CONFIG FOSC = INTRC_NOCLKOUT ; Oscillator Selection bits (INTOSCIO oscillator: I/O function on RA6/OSC2/CLKOUT pin, I/O function on RA7/OSC1/CLKIN)
CONFIG WDTE = OFF ; Watchdog Timer Enable bit (WDT disabled and can be enabled by SWDTEN bit of the WDTCON register)
CONFIG PWRTE = OFF ; Power-up Timer Enable bit (PWRT disabled)
CONFIG MCLRE = ON ; RE3/MCLR pin function select bit (RE3/MCLR pin function is MCLR)
CONFIG CP = OFF ; Code Protection bit (Program memory code protection is disabled)
CONFIG CPD = OFF ; Data Code Protection bit (Data memory code protection is disabled)
CONFIG BOREN = ON ; Brown Out Reset Selection bits (BOR enabled)
CONFIG IESO = ON ; Internal External Switchover bit (Internal/External Switchover mode is enabled)
CONFIG FCMEN = ON ; Fail-Safe Clock Monitor Enabled bit (Fail-Safe Clock Monitor is enabled)
CONFIG LVP = ON ; Low Voltage Programming Enable bit (RB3/PGM pin has PGM function, low voltage programming enabled)
; CONFIG2
CONFIG BOR4V = BOR40V ; Brown-out Reset Selection bit (Brown-out Reset set to 4.0V)
CONFIG WRT = OFF ; Flash Program Memory Self Write Enable bits (Write protection off)
#include <xc.inc>
CLONE EQU 0x20 ;value used to refer to memory store in interrupt routine
WAIT1 EQU 0x21 ;values used to refer to memory stores used in wait delays
WAIT10 EQU 0x22
WAIT100 EQU 0x23
WAIT1k EQU 0x24
ADCTEMP EQU 0x31 ;variables used to point to memory stores for the readadc routines
ADC0 EQU 0x32
ADC1 EQU 0x33
ADC2 EQU 0x34
BINARY_INPUT EQU 0x40
NUM_100s EQU 0x41
NUM_10s EQU 0x42
NUM_1s EQU 0x43
RPZERO EQU 0x05 ;refers to bit RP0 in the STATUS Register
INTFL EQU 0x01 ;interrupt 0 flag - INT0IF in INTCON
INTEN EQU 0x04 ;interrupt 0 enable - INT0IE in INTCON
GI EQU 0x07 ;global interrupt enable - GIE in INTCON
;NUM EQU abcdefg0B
NINE EQU 11011110B
EIGHT EQU 11111110B
SEVEN EQU 00001110B
SIX EQU 11111010B
FIVE EQU 11011010B
FOUR EQU 11001100B
THREE EQU 10011110B
TWO EQU 10110110B
ONE EQU 00001100B
ZER0 EQU 01111110B
;================================== RESET VECTORS =============================
psect RES_VECT,class=CODE,delta=2 ; PIC10/12/16
RES_VECT:
nop
goto start
PSECT INT_VECT,class=CODE,delta=2
INT_VECT:
movwf CLONE ;create a copy of the current working register
btfss INTCON,INTFL ;check interrupt has occured, skips if true
retfie ;set GI and RETURN in a single clock cycle
call your_interrupt
bcf INTCON,INTFL ;reset the interrupt flag
movf CLONE,0x00 ;return the saved working register back for use (working register address 0x00)
retfie
your_interrupt:
nop
return
psect code
wait1ms: ;@4MHz, the exe rate = 1MIP, t=1us. 1000 total instructions needed to make 1ms.
movlw 255 ;+1 instruction
movwf WAIT1 ;+1
loop1ms:
decfsz WAIT1,1 ;+1*255
goto loop1ms ;+2(255-1)
movlw 77 ;+1
movwf WAIT1 ;+1
loop1ms2:
decfsz WAIT1,1 ;+1*77
goto loop1ms2 ;+2(77-1)
nop ;+1
nop ;+1
return ;+2 = 1000 total instructions
wait10ms: ;requires 10,000 instructions
movlw 10 ;+1
movwf WAIT10 ;+1
loop10ms:
call wait1ms ;10*1000 instructions
decfsz WAIT10,1 ;+10
goto loop10ms ;+2*9
return ;+2 = 10,030 total
wait100ms: ;requires 100,000 instructions
movlw 100 ;+1
movwf WAIT100 ;+1
loop100ms:
call wait1ms ;+100*1000
decfsz WAIT100,1 ;+100
goto loop100ms ;+99*2
return ;+2 = 100,302
wait1000ms: ;requires 1,000,000 instructions
movlw 10 ;+1
movwf WAIT1k ;+1
loop1000ms:
call wait100ms ;+10*100,302
decfsz WAIT1k,1 ;+10
goto loop1000ms ;+2*9
return ;+2 = 1,003,052
readadc0:
movlw 00000001B ;PORTA,0
bsf STATUS,RPZERO
movwf ANSEL
bcf STATUS,RPZERO
movlw 01000001B ;01XXX001, three blank bits tell ADCON0 which analog input to check
movwf ADCON0
bsf ADCON0,1 ;start adc conversion
loopadc0:
clrwdt ;Pat the watchdog
btfsc ADCON0,1 ;check if conversion finished
goto loopadc0
movf ADRESH,w ;take result from ADRESH
movwf ADC0 ;move result to ADC0
return
readadc1:
movlw 00000010B ;PORTA,1
bsf STATUS,RPZERO
movwf ANSEL
bcf STATUS,RPZERO
movlw 01001001B ;01XXX001, three blank bits tell ADCON0 which analog input to check
movwf ADCON0
bsf ADCON0,1 ;start adc conversion
loopadc1:
clrwdt ;Pat the watchdog
btfsc ADCON0,1 ;check if conversion finished
goto loopadc1
movf ADRESH,w
movwf ADC1
return
readadc2:
movlw 00000100B ;PORTA,2
bsf STATUS,RPZERO
movwf ANSEL
bcf STATUS,RPZERO
movlw 01010001B ;01XXX001, three blank bits tell ADCON0 which analog input to check
movwf ADCON0
bsf ADCON0,1 ;start adc conversion
loopadc2:
clrwdt ;Pat the watchdog
btfsc ADCON0,1 ;check if conversion finished
goto loopadc2
movf ADRESH,w
movwf ADC2
return
;================================ INITIALISATION ===============================
;7 seg connections for PORTB,C,D: abcdefg0B - the LSB is not used
IOPORTA EQU 00000001B ;set the PORTA data direction. PORTA,0 = ADC.
IOPORTB EQU 00000001B ;set the PORTB data direction. PORTB,0 must be 1.
IOPORTC EQU 00000000B ;set the PORTC data direction
IOPORTD EQU 00000000B ;set the PORTD data direction
IOPORTE EQU 00001000B ;set the PORTE data direction. PORTE has only 4 usable bits.
;PORTB,0 is the default interrupt trigger - ensure this is set as 1 if used as such.
;PORTA,5 must ALWAYS be an input.
;PORTA are all usable as analog inputs.
;PORTE,3 must be an INPUT.
start:
;clrf PORTA
;clrf PORTB
;clrf PORTC
;clrf PORTD
;clrf PORTE
bsf STATUS,RPZERO ;change RP0 to 1 to select BANK1
movlw 01100000B ;set the clock speed to 4MHz https://docs.rs-online.com/a168/0900766b81382af8.pdf pg40
movwf OSCCON ;move the new clock speed to the clock controller.
clrf ANSEL ;disable adc
movlw IOPORTA ;call on the decided Inputs/outputs for PORTA
movwf TRISA
movlw IOPORTB ;call on the decided i/o for PORTB
movwf TRISB
movlw IOPORTC
movwf TRISC
movlw IOPORTD
movwf TRISD
movlw IOPORTE
movwf TRISE
movlw 00000000B ;Vref is power supply voltage & left justified
movwf ADCON1 ;configured ready to use readadc subroutines
bcf STATUS,RPZERO ;change RP0 to 0 to select BANK0
;uncomment the next lines to enable interrupt routines
;bsf INTCON,INTEN ;set the external interrupt enable
;bsf INTCON,GI ;enable all interruptions
main:
call readadc0
movf ADC0,w
;movlw 178
movwf BINARY_INPUT
bsf STATUS,0
clrf NUM_100s
clrf NUM_10s
clrf NUM_1s
dec_100_loop:
movlw 100
subwf BINARY_INPUT ;subtract 100 from value
btfss STATUS,0 ;check if is <0 - check carry flag in STATUS register
goto reset_value_100s ;if is <0, move on to test num 10s
incf NUM_100s ;else +1 to 100s counter
goto dec_100_loop ;repeat to test again
reset_value_100s:
movlw 100
addwf BINARY_INPUT
dec_10_loop:
movlw 10
subwf BINARY_INPUT ;subtract 10 from the remainder value after removing 100s
btfss STATUS,0 ;check if <0
goto reset_value_10s ;if <0, move on to get num 1s
incf NUM_10s ;else +1 to 10s counter
goto dec_10_loop ;repeat to test 10s again
reset_value_10s:
movlw 10
addwf BINARY_INPUT
units:
movf BINARY_INPUT,w ;put number of units into its own memory
movwf NUM_1s
check_100s_digit_is_2:
movf NUM_100s,w
sublw 2
btfss STATUS,2
goto check_100s_digit_is_1
movlw TWO
movwf PORTD
goto check_10s_digit_is_9
check_100s_digit_is_1:
movf NUM_100s,w
sublw 1
btfss STATUS,2
goto check_100s_digit_is_0
movlw ONE
movwf PORTD
goto check_10s_digit_is_9
check_100s_digit_is_0:
movf NUM_100s,w
sublw 0
btfss STATUS,2
goto error_occurred
movlw ZER0
movwf PORTD
goto check_10s_digit_is_9
check_10s_digit_is_9:
movf NUM_10s,w
sublw 9
btfss STATUS,2
goto check_10s_digit_is_8
movlw NINE
movwf PORTC
goto check_1s_digit_is_9
check_10s_digit_is_8:
movf NUM_10s,w
sublw 8
btfss STATUS,2
goto check_10s_digit_is_7
movlw EIGHT
movwf PORTC
goto check_1s_digit_is_9
check_10s_digit_is_7:
movf NUM_10s,w
sublw 7
btfss STATUS,2
goto check_10s_digit_is_6
movlw SEVEN
movwf PORTC
goto check_1s_digit_is_9
check_10s_digit_is_6:
movf NUM_10s,w
sublw 6
btfss STATUS,2
goto check_10s_digit_is_5
movlw SIX
movwf PORTC
goto check_1s_digit_is_9
check_10s_digit_is_5:
movf NUM_10s,w
sublw 5
btfss STATUS,2
goto check_10s_digit_is_4
movlw FIVE
movwf PORTC
goto check_1s_digit_is_9
check_10s_digit_is_4:
movf NUM_10s,w
sublw 4
btfss STATUS,2
goto check_10s_digit_is_3
movlw FOUR
movwf PORTC
goto check_1s_digit_is_9
check_10s_digit_is_3:
movf NUM_10s,w
sublw 3
btfss STATUS,2
goto check_10s_digit_is_2
movlw THREE
movwf PORTC
goto check_1s_digit_is_9
check_10s_digit_is_2:
movf NUM_10s,w
sublw 2
btfss STATUS,2
goto check_10s_digit_is_1
movlw TWO
movwf PORTC
goto check_1s_digit_is_9
check_10s_digit_is_1:
movf NUM_10s,w
sublw 1
btfss STATUS,2
goto check_10s_digit_is_0
movlw ONE
movwf PORTC
goto check_1s_digit_is_9
check_10s_digit_is_0:
movf NUM_10s,w
sublw 0
btfss STATUS,2
goto error_occurred
movlw ZER0
movwf PORTC
goto check_1s_digit_is_9
check_1s_digit_is_9:
movf NUM_1s,w
sublw 9
btfss STATUS,2
goto check_1s_digit_is_8
movlw NINE
movwf PORTA
goto finished
check_1s_digit_is_8:
movf NUM_1s,w
sublw 8
btfss STATUS,2
goto check_1s_digit_is_7
movlw EIGHT
movwf PORTA
goto finished
check_1s_digit_is_7:
movf NUM_1s,w
sublw 7
btfss STATUS,2
goto check_1s_digit_is_6
movlw SEVEN
movwf PORTA
goto finished
check_1s_digit_is_6:
movf NUM_1s,w
sublw 6
btfss STATUS,2
goto check_1s_digit_is_5
movlw SIX
movwf PORTA
goto finished
check_1s_digit_is_5:
movf NUM_1s,w
sublw 5
btfss STATUS,2
goto check_1s_digit_is_4
movlw FIVE
movwf PORTA
goto finished
check_1s_digit_is_4:
movf NUM_1s,w
sublw 4
btfss STATUS,2
goto check_1s_digit_is_3
movlw FOUR
movwf PORTA
goto finished
check_1s_digit_is_3:
movf NUM_10s,w
sublw 3
btfss STATUS,2
goto check_1s_digit_is_2
movlw THREE
movwf PORTA
goto finished
check_1s_digit_is_2:
movf NUM_1s,w
sublw 2
btfss STATUS,2
goto check_1s_digit_is_1
movlw TWO
movwf PORTA
goto finished
check_1s_digit_is_1:
movf NUM_1s,w
sublw 1
btfss STATUS,2
goto check_1s_digit_is_0
movlw ONE
movwf PORTA
goto finished
check_1s_digit_is_0:
movf NUM_1s,w
sublw 0
btfss STATUS,2
goto error_occurred
movlw ZER0
movwf PORTA
goto finished
finished:
goto main
error_occurred:
movlw 00000010B
movwf PORTA
movwf PORTC
movwf PORTD
call wait1000ms
goto main
END