;******************************************************************
; 2-Digit Up/Dn Counter, Isochronous Loop Example *
;******************************************************************
processor PIC16F88
include "p16f88.inc"
errorlevel -302
__CONFIG _CONFIG1, _LVP_OFF&_PWRTE_ON&_WDT_OFF&_INTRC_IO
__CONFIG _CONFIG2, _IESO_OFF & _FCMEN_OFF
ones equ 0x20 ; 0..9
tens equ 0x21 ; 0..9
number equ 0x22 ; 00..99
swlatch equ 0x23 ; switch state latch variable
DelayHi equ 0x24 ; DelayCy() subsystem variable
#define DnSw 3 ; RA3
;******************************************************************
;
; K8LH DelayCy() subsystem macro generates four instructions
;
radix dec
clock equ 8 ; clock frequency in Megahertz
usecs equ clock/4 ; cycles/microsecond multiplier
msecs equ usecs*1000 ; cycles/millisecond multiplier
DelayCy macro delay ; 11..327690 cycle range
movlw high((delay-11)/5)+1
movwf DelayHi
movlw low ((delay-11)/5)
call uDelay-((delay-11)%5)
endm
;******************************************************************
;
; init hardware and program variables
;
org 0x000
Init
bsf STATUS,RP0 ; bank 1 |B1
movlw b'01110000' ; |B1
movwf OSCCON ; select 8-MHz INTOSC clock |B1
Stable btfss OSCCON,IOFS ; INTOSC Freq Stable bit set? |B1
goto Stable ; no, branch, else |B1
clrf ANSEL ; setup PORT A for digital I/O |B1
movlw b'00001100' ; |B1
movwf TRISA ; RA3-RA2 inputs, others outputs |B1
clrf TRISB ; portb all outputs |B1
bcf STATUS,RP0 ; bank 0 |B0
clrf PORTB ; clear portb output latches |B0
movlw b'00000001' ; digit select bits (RA1-RA0) |B0
movwf PORTA ; select the 'ones' display |B0
clrf swlatch ; clear switch state latch |B0
clrf ones ; clear 'ones' |B0
clrf tens ; clear 'tens' |B0
clrf number ; number = 00 |B0
;
; isochronous 8 msec main program loop (62.5 Hz refresh rate)
;
Main clrf PORTB ; blank the display |B0
movf PORTA,W ; |B0
xorlw b'00000011' ; flip digit select bits |B0
movwf PORTA ; |B0
movf tens,W ; WREG = tens, 0..9 |B0
btfss PORTA,1 ; display tens? yes, skip, else |B0
movf ones,W ; WREG = ones, 0..9 |B0
call segtbl ; get segment data |B0
movwf PORTB ; display new digit |B0
TstSw comf PORTA,W ; sample active low switches |B0
andlw b'00001100' ; on RA3 and RA2 pins |B0
xorwf swlatch,W ; changes (press or release) |B0
xorwf swlatch,F ; update switch state latch |B0
andwf swlatch,W ; filter out "new release" bits |B0
bnz Bump ; branch on a "new press", else |B0
DelayCy(8*msecs-23) ; precise 8 msec loop timing |B0
goto Main ; |B0
;
; bump 'number' up or down with limit checking
;
Bump andlw 1<<DnSw ; the "Dn" switch? |B0
skpz ; no, skip (WREG=0), else |B0
movlw -2 ; WREG = -2 (dn) |B0
addlw 1 ; WREG = 1 (up) or -1 (dn) |B0
addwf number,F ; number++ or number-- |B0
movf number,W ; WREG = number = -1..100 |B0
xorlw 100 ; test upper limit |B0
skpnz ; upper limit? no, skip, else |B0
decf number,F ; reset to 99 |B0
btfsc number,7 ; lower limit? no, skip, else |B0
incf number,F ; reset to 00 |B0
movf number,W ; WREG = number = 00..99 |B0
;
; setup 'tens' and 'ones' for next loop
;
clrf tens ; isochronous bin2bcd routine |B0
addlw -80 ; W = W - 80 |B0
rlf tens,F ; shift in 2^3*10 bit |B0
btfss tens,0 ; borrow? no, skip, else |B0
addlw 80 ; W = W + 80 |B0
addlw -40 ; W = W - 40 |B0
rlf tens,F ; shift in 2^2*10 bit |B0
btfss tens,0 ; borrow? no, skip, else |B0
addlw 40 ; W = W + 40 |B0
addlw -20 ; W = W - 20 |B0
rlf tens,F ; shift in 2^1*10 bit |B0
btfss tens,0 ; borrow? no, skip, else |B0
addlw 20 ; W = W + 20 |B0
addlw -10 ; W = W - 10, now W = "ones" |B0
rlf tens,F ; shift in 2^0*10 bit |B0
btfss tens,0 ; borrow? no, skip, else |B0
addlw 10 ; W = W + 10, now W = "ones" |B0
movwf ones ; save "ones" |B0
DelayCy(8*msecs-54) ; precise 8 msec loop timing |B0
goto Main ; |B0
;
; segment data table (caveat, non-boundary tolerant)
;
segtbl
addwf PCL,F ; |B0
dt b'00111111' ; "0" -|-|F|E|D|C|B|A |B0
dt b'00000110' ; "1" -|-|-|-|-|C|B|- |B0
dt b'01011011' ; "2" -|G|-|E|D|-|B|A |B0
dt b'01001111' ; "3" -|G|-|-|D|C|B|A |B0
dt b'01100110' ; "4" -|G|F|-|-|C|B|- |B0
dt b'01101101' ; "5" -|G|F|-|D|C|-|A |B0
dt b'01111101' ; "6" -|G|F|E|D|C|-|A |B0
dt b'00000111' ; "7" -|-|-|-|-|C|B|A |B0
dt b'01111111' ; "8" -|G|F|E|D|C|B|A |B0
dt b'01101111' ; "9" -|G|F|-|D|C|B|A |B0
;
; K8LH DelayCy() subsystem 16-bit timing subroutine
;
nop ; entry for (delay-11)%5 == 4 |B0
nop ; entry for (delay-11)%5 == 3 |B0
nop ; entry for (delay-11)%5 == 2 |B0
nop ; entry for (delay-11)%5 == 1 |B0
uDelay addlw -1 ; subtract "loop" cycle time |B0
skpc ; borrow? no, skip, else |B0
decfsz DelayHi,F ; done? yes, skip, else |B0
goto uDelay ; do another loop |B0
return ; |B0
end