PIC 16f84 vs 16f628
Moderators: pedja089, stojke369, [eDo], trax
PIC 16f84 vs 16f628
Imam pic 16f628 i imam kod za 16f84, stvar je u tome da su pinovi na čipovima isti, samo nešto treba promjeniti u kodu, googlao sam ali mi i dalje nije jasno što dalje da napravim... Naime radim LED pov sat, nisam baš neki stručnjak sa mikrokontrolerima pa jel može neko pomoći?
Re: PIC 16f84 vs 16f628
Ajde postavi taj kod za 84-orku, neko će pomoći.
Ako kaniš pobijediti, ne smiješ izgubiti
Re: PIC 16f84 vs 16f628
;--------
; mclock8.asm
; "The Propeller" mechanically scanned LED clock
; some changes since last version -
; modified table etc for compatiblility with 8th LED
; watchdog timer used to ensure startup
; Bob Blick February 12, 1997
; Licensed under the terms of the GNU General Public License, www.gnu.org
; No warranties expredded or implied
; Bob Blick February 18, 2002
;--------
list p=16C84
radix hex
include "p16c84.inc"
;--------
; remember to set blast-time options: OSC=regular xtal, WDT=ON
; timings all based on 4 MHz crystal
;--------
; are these equates already in the include file? someday I'll look.
;--------
w equ 0
f equ 1
;--------
; Start of available RAM.
;--------
cblock 0x0C
safe_w ;not really temp, used by interrupt svc
safe_s ;not really temp, used by interrupt svc
period_count ;incremented each interrupt
period_dup ;copy of period_count safe from interrupt
period_calc ;stable period after hysteresis calc.
flags ;b2=int b1=minute b4=edge
dot_index ;which column is being displayed
digit_index ;which digit is being displayed
hours ;in display format, not hex(01-12)
minutes ;00 to 59
bigtick_dbl ;incremented each interrupt
bigtick_hi
bigtick_lo
keys ;key value
scratch ;scratch value
tick ;used by delay
endc
;--------
; Start of ROM
;--------
org 0x00 ;Start of code space
goto Start
;--------
; INTERRUPT SERVICE ROUTINE
;--------
org 0x04 ;interrupt vector
Intsvc movwf safe_w ;save w
swapf STATUS,w ;swap status, w
movwf safe_s ;save status(nibble swap, remember)
;--------
; done saving, now start working
;--------
; clear watchdog timer to ensure startup
clrwdt
;
; increment period count
incf period_count,f
btfsc STATUS,Z ;zero set means overflow
decf period_count,f
; 234375 interrupts every minute. Increment the bigtick each time.
incf bigtick_lo,f
btfsc STATUS,Z
incf bigtick_hi,f
btfsc STATUS,Z
incfsz bigtick_dbl,f
goto Bigtick_out
;--------
; here? bigtick has rolled over to zero and one minute has passed.
; reload bigtick and set a flag for the main counter
;--------
movlw 0xFC ;234375 = 0x039387
movwf bigtick_dbl ;0 - 0x039387 = 0xFC6C79
movlw 0x6C
movwf bigtick_hi
movlw 0x79
movwf bigtick_lo
bsf flags,1 ;notify Keep_time
Bigtick_out
;--------
; done working, start restoring
;--------
swapf safe_s,w ;fetch status, reswap nibbles
movwf STATUS ;restore status
swapf safe_w,f ;swap nibbles in preparation
swapf safe_w,w ;for the swap restoration of w
bcf INTCON,2 ;clear interrupt flag before return
retfie ;return from interrupt
;--------
; CHARACTER LOOKUP TABLE
; ignore high bit. set=LED off, clear=LED on, bit0=bottom LED, bit6=top LED
;--------
Char_tbl
addwf PCL,f
dt 0xC1,0xBE,0xBE,0xBE,0xC1 ;"O"
dt 0xFF,0xDE,0x80,0xFE,0xFF ;"1"
dt 0xDE,0xBC,0xBA,0xB6,0xCE ;"2"
dt 0xBD,0xBE,0xAE,0x96,0xB9 ;"3"
dt 0xF3,0xEB,0xDB,0x80,0xFB ;"4"
dt 0x8D,0xAE,0xAE,0xAE,0xB1 ;"5"
dt 0xE1,0xD6,0xB6,0xB6,0xF9 ;"6"
dt 0xBF,0xB8,0xB7,0xAF,0x9F ;"7"
dt 0xC9,0xB6,0xB6,0xB6,0xC9 ;"8"
dt 0xCF,0xB6,0xB6,0xB5,0xC3 ;"9"
dt 0xFF,0xC9,0xC9,0xFF,0xFF ;":"
Char_tbl_end
;--------
; SUBROUTINES STARTING HERE
;--------
; clear important bits of ram
;--------
Ram_init movlw 0x07
movwf keys
movlw 0x12 ;why do clocks always start
movwf hours ;at 12:00 ?
clrf minutes
clrf dot_index
clrf digit_index
movlw 0xFC
movwf bigtick_dbl
retlw 0
;--------
; unused pins I am setting to be outputs
;--------
Port_init movlw 0x00 ;all output, b7=unused
tris PORTB ;on port b attached to LEDs
movlw b'00010111' ;port a has 5 pins. I need 4 inputs
;b0=minutes, b1=10mins, b2=hours
;b3=unused, b4=rotation index
tris PORTA ;on port a
retlw 0
;--------
; get timer-based interrupts going
;--------
Timer_init bcf INTCON,2 ;clear TMR0 int flag
bsf INTCON,7 ;enable global interrupts
bsf INTCON,5 ;enable TMR0 int
clrf TMR0 ;clear timer
clrwdt ;why is this needed? just do it..
movlw b'11011000' ;set up timer. prescaler(bit3)bypassed
option ;send w to option. generate warning.
clrf TMR0 ;start timer
retlw 0
;--------
; test for index in rotation and store period in period_dup
;--------
Check_index movf PORTA,w ;get the state of port a
xorwf flags,w ;compare with saved state
andlw b'00010000' ;only interested in bit 4
btfsc STATUS,Z ;test for edge
retlw 0 ;not an edge, same as last
xorwf flags,f ;save for next time
btfsc flags,4 ;test for falling edge
retlw 0 ;must have been a rising edge
movf period_count,w ;make a working copy
movwf period_dup ;called period dup
clrf period_count ;a fresh start for next rotation
clrf digit_index ;set to first digit
clrf dot_index ;first column
; calculate a period that does not dither or jitter
; period will not be changed unless new period is really different
movf period_calc,w
subwf period_dup,w ;find difference
btfss STATUS,C ;carry flag set means no borrow
goto Calc_period_neg ;must be other way
sublw 2 ;allowable deviation = 3
btfss STATUS,C ;borrow won't skip
incf period_calc ;new value much larger than calc
retlw 0
Calc_period_neg addlw 2 ;allowable deviation = 3
btfss STATUS,C ;carry will skip
decf period_calc ;no carry means it must be changed
retlw 0
;--------
; change LED pattern based on state of digit_index and dot_index
;--------
Display_now movlw 0x05
xorwf dot_index,w ;test for end of digit
movlw 0xFF ;pattern for blank column
btfsc STATUS,Z
goto D_lookup_3 ;it needs a blank
bcf STATUS,C ;clear carry before a rotate
rlf digit_index,w ;double the index because each
addwf PCL,f ;takes two instructions
D_10hr swapf hours,w
goto D_lookup ;what a great rush of power
D_1hr movf hours,w ;I feel when modifying
goto D_lookup ;the program counter
D_colon movlw 0x0A
goto D_lookup
D_10min swapf minutes,w
goto D_lookup
D_1min movf minutes,w
goto D_lookup
D_nothing retlw 0
D_lookup andlw b'00001111' ;strip off hi bits
movwf scratch ;multiply this by 5 for lookup
addwf scratch,f ;table base position
addwf scratch,f ;is this cheating?
addwf scratch,f ;I think not.
addwf scratch,f ;I think it is conserving energy!
btfss STATUS,Z ;test for zero
goto D_lookup_2 ;not a zero
movf digit_index,f ;this is just to test/set flag
movlw 0xFF ;this makes a blank LED pattern
btfsc STATUS,Z ;test if it is 10 hrs digit
goto D_lookup_3 ;it's a leading zero
D_lookup_2 movf dot_index,w ;get column
addwf scratch,w ;add it to digit base
call Char_tbl ;get the dot pattern for this column
D_lookup_3 movwf PORTB ;send it to the LEDs
movlw 0x0C ;overhead value sub from period
subwf period_calc,w ;compensate for overhead and set
call Delay ;width of digits with this delay
incf dot_index,f ;increment to the next column
movlw 0x06 ;6 columns is a digit plus space
xorwf dot_index,w ;next digit test
btfss STATUS,Z
retlw 0 ;not a new digit
clrf dot_index ;new digit time
incf digit_index,f
retlw 0 ;Display_now done.
;--------
; a short delay routine
;--------
Delay movwf tick
Delay_loop decfsz tick,f
goto Delay_loop ;w is not damaged, so Delay can
return ;be recalled without reloading
;--------
; test for keypress and call time adjust if needed
;--------
Check_keys movf PORTA,w ;get port "a"
xorwf keys,w ;compare with previous
andlw b'00000111' ;only care about button pins
btfsc STATUS,Z ;zero set=no buttons
retlw 0 ;return
xorwf keys,f ;store key value
movlw 0x64 ;a fairly long delay will
movwf scratch ;prevent key bounces
Key_delay movlw 0xFF
call Delay
decfsz scratch
goto Key_delay
btfss keys,2 ;test "minutes" button
goto Inc_mins
btfss keys,1 ;test "tens" button
goto Inc_tens
btfss keys,0 ;test "hours" button
goto Inc_hours
retlw 0 ;must be a glitch. yeah, right!
;--------
; increment ten minutes
;--------
Inc_tens movlw 0x0A
movwf scratch ;scratch has ten
Inc_tens_loop call Inc_mins
decfsz scratch
goto Inc_tens_loop ;another minute added
retlw 0
;--------
; increment one hour
;--------
Inc_hours movlw 0x12
xorwf hours,w
btfsc STATUS,Z
goto Inc_hours_12
movlw 0x07 ;this part gets a little sloppy
addwf hours,w
movlw 0x07
btfss STATUS,DC
movlw 1
addwf hours,f
retlw 0
Inc_hours_12 movlw 0x01
movwf hours
retlw 0
;--------
; increment the time based on flags,1 as sent by interrupt routine
; Inc_mins loop also used by time-setting routine
;--------
Keep_time btfss flags,1 ;the minutes flag
retlw 0 ;not this time
bcf flags,1 ;clear the minutes flag
Inc_mins movlw 0x07 ;start incrementing time
addwf minutes,w ;add 7 minutes into w
btfsc STATUS,DC ;did adding 7 cause digit carry?
goto Sixty_mins ;then test for an hour change
incf minutes ;otherwise add 1 for real
retlw 0 ;and go back
Sixty_mins movwf minutes ;save the minutes
movlw 0x60 ;test for 60
xorwf minutes,w ;are minutes at 60?
btfss STATUS,Z
retlw 0 ;no? go back
clrf minutes ;otherwise zero minutes
goto Inc_hours ;and increment hours
;--------
; End of subroutines
; Program starts here
;--------
Start call Ram_init ;set variables to nice values
call Port_init ;set port directions
call Timer_init ;start timer based interrupt
;--------
; Done initializing, start the endless loop.
;--------
;
Circle ;begin the big loop
;
;--------
; detect falling edge on PORTA,4 to determine rotary index
; calculate rotation period and store in period_dup
; compare with working period(period_calc) and adjust if way different
;--------
call Check_index
;--------
; check display state and change if needed
;--------
call Display_now
;--------
; check keyboard and adjust time
;--------
call Check_keys
;--------
; check minute flag and increment time if a minute has passed
;--------
call Keep_time
;--------
; gentlemen, that's a clock, keep it rolling
;--------
goto Circle ;you heard the man, get going!
end
;--------
; end of file
;--------
; mclock8.asm
; "The Propeller" mechanically scanned LED clock
; some changes since last version -
; modified table etc for compatiblility with 8th LED
; watchdog timer used to ensure startup
; Bob Blick February 12, 1997
; Licensed under the terms of the GNU General Public License, www.gnu.org
; No warranties expredded or implied
; Bob Blick February 18, 2002
;--------
list p=16C84
radix hex
include "p16c84.inc"
;--------
; remember to set blast-time options: OSC=regular xtal, WDT=ON
; timings all based on 4 MHz crystal
;--------
; are these equates already in the include file? someday I'll look.
;--------
w equ 0
f equ 1
;--------
; Start of available RAM.
;--------
cblock 0x0C
safe_w ;not really temp, used by interrupt svc
safe_s ;not really temp, used by interrupt svc
period_count ;incremented each interrupt
period_dup ;copy of period_count safe from interrupt
period_calc ;stable period after hysteresis calc.
flags ;b2=int b1=minute b4=edge
dot_index ;which column is being displayed
digit_index ;which digit is being displayed
hours ;in display format, not hex(01-12)
minutes ;00 to 59
bigtick_dbl ;incremented each interrupt
bigtick_hi
bigtick_lo
keys ;key value
scratch ;scratch value
tick ;used by delay
endc
;--------
; Start of ROM
;--------
org 0x00 ;Start of code space
goto Start
;--------
; INTERRUPT SERVICE ROUTINE
;--------
org 0x04 ;interrupt vector
Intsvc movwf safe_w ;save w
swapf STATUS,w ;swap status, w
movwf safe_s ;save status(nibble swap, remember)
;--------
; done saving, now start working
;--------
; clear watchdog timer to ensure startup
clrwdt
;
; increment period count
incf period_count,f
btfsc STATUS,Z ;zero set means overflow
decf period_count,f
; 234375 interrupts every minute. Increment the bigtick each time.
incf bigtick_lo,f
btfsc STATUS,Z
incf bigtick_hi,f
btfsc STATUS,Z
incfsz bigtick_dbl,f
goto Bigtick_out
;--------
; here? bigtick has rolled over to zero and one minute has passed.
; reload bigtick and set a flag for the main counter
;--------
movlw 0xFC ;234375 = 0x039387
movwf bigtick_dbl ;0 - 0x039387 = 0xFC6C79
movlw 0x6C
movwf bigtick_hi
movlw 0x79
movwf bigtick_lo
bsf flags,1 ;notify Keep_time
Bigtick_out
;--------
; done working, start restoring
;--------
swapf safe_s,w ;fetch status, reswap nibbles
movwf STATUS ;restore status
swapf safe_w,f ;swap nibbles in preparation
swapf safe_w,w ;for the swap restoration of w
bcf INTCON,2 ;clear interrupt flag before return
retfie ;return from interrupt
;--------
; CHARACTER LOOKUP TABLE
; ignore high bit. set=LED off, clear=LED on, bit0=bottom LED, bit6=top LED
;--------
Char_tbl
addwf PCL,f
dt 0xC1,0xBE,0xBE,0xBE,0xC1 ;"O"
dt 0xFF,0xDE,0x80,0xFE,0xFF ;"1"
dt 0xDE,0xBC,0xBA,0xB6,0xCE ;"2"
dt 0xBD,0xBE,0xAE,0x96,0xB9 ;"3"
dt 0xF3,0xEB,0xDB,0x80,0xFB ;"4"
dt 0x8D,0xAE,0xAE,0xAE,0xB1 ;"5"
dt 0xE1,0xD6,0xB6,0xB6,0xF9 ;"6"
dt 0xBF,0xB8,0xB7,0xAF,0x9F ;"7"
dt 0xC9,0xB6,0xB6,0xB6,0xC9 ;"8"
dt 0xCF,0xB6,0xB6,0xB5,0xC3 ;"9"
dt 0xFF,0xC9,0xC9,0xFF,0xFF ;":"
Char_tbl_end
;--------
; SUBROUTINES STARTING HERE
;--------
; clear important bits of ram
;--------
Ram_init movlw 0x07
movwf keys
movlw 0x12 ;why do clocks always start
movwf hours ;at 12:00 ?
clrf minutes
clrf dot_index
clrf digit_index
movlw 0xFC
movwf bigtick_dbl
retlw 0
;--------
; unused pins I am setting to be outputs
;--------
Port_init movlw 0x00 ;all output, b7=unused
tris PORTB ;on port b attached to LEDs
movlw b'00010111' ;port a has 5 pins. I need 4 inputs
;b0=minutes, b1=10mins, b2=hours
;b3=unused, b4=rotation index
tris PORTA ;on port a
retlw 0
;--------
; get timer-based interrupts going
;--------
Timer_init bcf INTCON,2 ;clear TMR0 int flag
bsf INTCON,7 ;enable global interrupts
bsf INTCON,5 ;enable TMR0 int
clrf TMR0 ;clear timer
clrwdt ;why is this needed? just do it..
movlw b'11011000' ;set up timer. prescaler(bit3)bypassed
option ;send w to option. generate warning.
clrf TMR0 ;start timer
retlw 0
;--------
; test for index in rotation and store period in period_dup
;--------
Check_index movf PORTA,w ;get the state of port a
xorwf flags,w ;compare with saved state
andlw b'00010000' ;only interested in bit 4
btfsc STATUS,Z ;test for edge
retlw 0 ;not an edge, same as last
xorwf flags,f ;save for next time
btfsc flags,4 ;test for falling edge
retlw 0 ;must have been a rising edge
movf period_count,w ;make a working copy
movwf period_dup ;called period dup
clrf period_count ;a fresh start for next rotation
clrf digit_index ;set to first digit
clrf dot_index ;first column
; calculate a period that does not dither or jitter
; period will not be changed unless new period is really different
movf period_calc,w
subwf period_dup,w ;find difference
btfss STATUS,C ;carry flag set means no borrow
goto Calc_period_neg ;must be other way
sublw 2 ;allowable deviation = 3
btfss STATUS,C ;borrow won't skip
incf period_calc ;new value much larger than calc
retlw 0
Calc_period_neg addlw 2 ;allowable deviation = 3
btfss STATUS,C ;carry will skip
decf period_calc ;no carry means it must be changed
retlw 0
;--------
; change LED pattern based on state of digit_index and dot_index
;--------
Display_now movlw 0x05
xorwf dot_index,w ;test for end of digit
movlw 0xFF ;pattern for blank column
btfsc STATUS,Z
goto D_lookup_3 ;it needs a blank
bcf STATUS,C ;clear carry before a rotate
rlf digit_index,w ;double the index because each
addwf PCL,f ;takes two instructions
D_10hr swapf hours,w
goto D_lookup ;what a great rush of power
D_1hr movf hours,w ;I feel when modifying
goto D_lookup ;the program counter
D_colon movlw 0x0A
goto D_lookup
D_10min swapf minutes,w
goto D_lookup
D_1min movf minutes,w
goto D_lookup
D_nothing retlw 0
D_lookup andlw b'00001111' ;strip off hi bits
movwf scratch ;multiply this by 5 for lookup
addwf scratch,f ;table base position
addwf scratch,f ;is this cheating?
addwf scratch,f ;I think not.
addwf scratch,f ;I think it is conserving energy!
btfss STATUS,Z ;test for zero
goto D_lookup_2 ;not a zero
movf digit_index,f ;this is just to test/set flag
movlw 0xFF ;this makes a blank LED pattern
btfsc STATUS,Z ;test if it is 10 hrs digit
goto D_lookup_3 ;it's a leading zero
D_lookup_2 movf dot_index,w ;get column
addwf scratch,w ;add it to digit base
call Char_tbl ;get the dot pattern for this column
D_lookup_3 movwf PORTB ;send it to the LEDs
movlw 0x0C ;overhead value sub from period
subwf period_calc,w ;compensate for overhead and set
call Delay ;width of digits with this delay
incf dot_index,f ;increment to the next column
movlw 0x06 ;6 columns is a digit plus space
xorwf dot_index,w ;next digit test
btfss STATUS,Z
retlw 0 ;not a new digit
clrf dot_index ;new digit time
incf digit_index,f
retlw 0 ;Display_now done.
;--------
; a short delay routine
;--------
Delay movwf tick
Delay_loop decfsz tick,f
goto Delay_loop ;w is not damaged, so Delay can
return ;be recalled without reloading
;--------
; test for keypress and call time adjust if needed
;--------
Check_keys movf PORTA,w ;get port "a"
xorwf keys,w ;compare with previous
andlw b'00000111' ;only care about button pins
btfsc STATUS,Z ;zero set=no buttons
retlw 0 ;return
xorwf keys,f ;store key value
movlw 0x64 ;a fairly long delay will
movwf scratch ;prevent key bounces
Key_delay movlw 0xFF
call Delay
decfsz scratch
goto Key_delay
btfss keys,2 ;test "minutes" button
goto Inc_mins
btfss keys,1 ;test "tens" button
goto Inc_tens
btfss keys,0 ;test "hours" button
goto Inc_hours
retlw 0 ;must be a glitch. yeah, right!
;--------
; increment ten minutes
;--------
Inc_tens movlw 0x0A
movwf scratch ;scratch has ten
Inc_tens_loop call Inc_mins
decfsz scratch
goto Inc_tens_loop ;another minute added
retlw 0
;--------
; increment one hour
;--------
Inc_hours movlw 0x12
xorwf hours,w
btfsc STATUS,Z
goto Inc_hours_12
movlw 0x07 ;this part gets a little sloppy
addwf hours,w
movlw 0x07
btfss STATUS,DC
movlw 1
addwf hours,f
retlw 0
Inc_hours_12 movlw 0x01
movwf hours
retlw 0
;--------
; increment the time based on flags,1 as sent by interrupt routine
; Inc_mins loop also used by time-setting routine
;--------
Keep_time btfss flags,1 ;the minutes flag
retlw 0 ;not this time
bcf flags,1 ;clear the minutes flag
Inc_mins movlw 0x07 ;start incrementing time
addwf minutes,w ;add 7 minutes into w
btfsc STATUS,DC ;did adding 7 cause digit carry?
goto Sixty_mins ;then test for an hour change
incf minutes ;otherwise add 1 for real
retlw 0 ;and go back
Sixty_mins movwf minutes ;save the minutes
movlw 0x60 ;test for 60
xorwf minutes,w ;are minutes at 60?
btfss STATUS,Z
retlw 0 ;no? go back
clrf minutes ;otherwise zero minutes
goto Inc_hours ;and increment hours
;--------
; End of subroutines
; Program starts here
;--------
Start call Ram_init ;set variables to nice values
call Port_init ;set port directions
call Timer_init ;start timer based interrupt
;--------
; Done initializing, start the endless loop.
;--------
;
Circle ;begin the big loop
;
;--------
; detect falling edge on PORTA,4 to determine rotary index
; calculate rotation period and store in period_dup
; compare with working period(period_calc) and adjust if way different
;--------
call Check_index
;--------
; check display state and change if needed
;--------
call Display_now
;--------
; check keyboard and adjust time
;--------
call Check_keys
;--------
; check minute flag and increment time if a minute has passed
;--------
call Keep_time
;--------
; gentlemen, that's a clock, keep it rolling
;--------
goto Circle ;you heard the man, get going!
end
;--------
; end of file
;--------
Code: Select all
Re: PIC 16f84 vs 16f628
ako može neko presložiti kod za 16f628, može li mi to odmah pretvoriti u .hex format?
Re: PIC 16f84 vs 16f628
Trebalo bi možda samo izmjeniti 16F84 u 16F628, eventualna razlika je veća programska memorija i neovisnost o vanjskom oscilatoru.
Ne koristim ovo za programiranje pa nisam 100% siguran, ali izmjeni ove dvije linije:
U komentarima vidim da stvar radi na 4MHz oscilatoru, tako da se ne moraš zezati sa uključivanjem u softveru za 16F628, već postavi kristal i kondenzatore (ili rezonator ako imaš).
Ne koristim ovo za programiranje pa nisam 100% siguran, ali izmjeni ove dvije linije:
Code: Select all
list p=16C84
include "p16c84.inc"
Ne vjeruj u čuda - računaj na njih!
Re: PIC 16f84 vs 16f628
PIC16F628 ima i analogni komparator koji treba iskljuciti i prebaciti pinove za digitalnu upotrebu.
Isto tako RAM ne pocinje na 0x0C nego na 0x20. Znaci ovaj
cblock 0x0C
treba promjeniti na
cblock 0x20
...
Probaj ovaj kod asemblirati:
Ili ucitaj ovaj HEX u svoj PIC16F628 i probaj:
Isto tako RAM ne pocinje na 0x0C nego na 0x20. Znaci ovaj
cblock 0x0C
treba promjeniti na
cblock 0x20
...
Probaj ovaj kod asemblirati:
Code: Select all
;--------
; mclock8.asm
; "The Propeller" mechanically scanned LED clock
; some changes since last version -
; modified table etc for compatiblility with 8th LED
; watchdog timer used to ensure startup
; Bob Blick February 12, 1997
; Licensed under the terms of the GNU General Public License, www.gnu.org
; No warranties expredded or implied
; Bob Blick February 18, 2002
;--------
list p=16F628A
radix hex
include "p16f628A.inc"
;--------
; remember to set blast-time options: OSC=regular xtal, WDT=ON
; timings all based on 4 MHz crystal
;--------
; are these equates already in the include file? someday I'll look.
;--------
w equ 0
f equ 1
;--------
; Start of available RAM.
;--------
cblock 0x20
safe_w ;not really temp, used by interrupt svc
safe_s ;not really temp, used by interrupt svc
period_count ;incremented each interrupt
period_dup ;copy of period_count safe from interrupt
period_calc ;stable period after hysteresis calc.
flags ;b2=int b1=minute b4=edge
dot_index ;which column is being displayed
digit_index ;which digit is being displayed
hours ;in display format, not hex(01-12)
minutes ;00 to 59
bigtick_dbl ;incremented each interrupt
bigtick_hi
bigtick_lo
keys ;key value
scratch ;scratch value
tick ;used by delay
endc
;--------
; Start of ROM
;--------
org 0x00 ;Start of code space
goto Start
;--------
; INTERRUPT SERVICE ROUTINE
;--------
org 0x04 ;interrupt vector
Intsvc movwf safe_w ;save w
swapf STATUS,w ;swap status, w
movwf safe_s ;save status(nibble swap, remember)
;--------
; done saving, now start working
;--------
; clear watchdog timer to ensure startup
clrwdt
;
; increment period count
incf period_count,f
btfsc STATUS,Z ;zero set means overflow
decf period_count,f
; 234375 interrupts every minute. Increment the bigtick each time.
incf bigtick_lo,f
btfsc STATUS,Z
incf bigtick_hi,f
btfsc STATUS,Z
incfsz bigtick_dbl,f
goto Bigtick_out
;--------
; here? bigtick has rolled over to zero and one minute has passed.
; reload bigtick and set a flag for the main counter
;--------
movlw 0xFC ;234375 = 0x039387
movwf bigtick_dbl ;0 - 0x039387 = 0xFC6C79
movlw 0x6C
movwf bigtick_hi
movlw 0x79
movwf bigtick_lo
bsf flags,1 ;notify Keep_time
Bigtick_out
;--------
; done working, start restoring
;--------
swapf safe_s,w ;fetch status, reswap nibbles
movwf STATUS ;restore status
swapf safe_w,f ;swap nibbles in preparation
swapf safe_w,w ;for the swap restoration of w
bcf INTCON,2 ;clear interrupt flag before return
retfie ;return from interrupt
;--------
; CHARACTER LOOKUP TABLE
; ignore high bit. set=LED off, clear=LED on, bit0=bottom LED, bit6=top LED
;--------
Char_tbl
addwf PCL,f
dt 0xC1,0xBE,0xBE,0xBE,0xC1 ;"O"
dt 0xFF,0xDE,0x80,0xFE,0xFF ;"1"
dt 0xDE,0xBC,0xBA,0xB6,0xCE ;"2"
dt 0xBD,0xBE,0xAE,0x96,0xB9 ;"3"
dt 0xF3,0xEB,0xDB,0x80,0xFB ;"4"
dt 0x8D,0xAE,0xAE,0xAE,0xB1 ;"5"
dt 0xE1,0xD6,0xB6,0xB6,0xF9 ;"6"
dt 0xBF,0xB8,0xB7,0xAF,0x9F ;"7"
dt 0xC9,0xB6,0xB6,0xB6,0xC9 ;"8"
dt 0xCF,0xB6,0xB6,0xB5,0xC3 ;"9"
dt 0xFF,0xC9,0xC9,0xFF,0xFF ;":"
Char_tbl_end
;--------
; SUBROUTINES STARTING HERE
;--------
; clear important bits of ram
;--------
Ram_init movlw 0x07
movwf keys
movlw 0x12 ;why do clocks always start
movwf hours ;at 12:00 ?
clrf minutes
clrf dot_index
clrf digit_index
movlw 0xFC
movwf bigtick_dbl
retlw 0
;--------
; unused pins I am setting to be outputs
;--------
Port_init
; trax added
bcf STATUS, RP1 ; BANK 0
bcf STATUS, RP0
movlw b'00000111' ; Comparator off
movwf CMCON ; CMCON=W
clrf CCP1CON ; Capt/Comp/PWM off
; -- trax
movlw 0x00 ;all output, b7=unused
tris PORTB ;on port b attached to LEDs
movlw b'00010111' ;port a has 5 pins. I need 4 inputs
;b0=minutes, b1=10mins, b2=hours
;b3=unused, b4=rotation index
tris PORTA ;on port a
retlw 0
;--------
; get timer-based interrupts going
;--------
Timer_init bcf INTCON,2 ;clear TMR0 int flag
bsf INTCON,7 ;enable global interrupts
bsf INTCON,5 ;enable TMR0 int
clrf TMR0 ;clear timer
clrwdt ;why is this needed? just do it..
movlw b'11011000' ;set up timer. prescaler(bit3)bypassed
option ;send w to option. generate warning.
clrf TMR0 ;start timer
retlw 0
;--------
; test for index in rotation and store period in period_dup
;--------
Check_index movf PORTA,w ;get the state of port a
xorwf flags,w ;compare with saved state
andlw b'00010000' ;only interested in bit 4
btfsc STATUS,Z ;test for edge
retlw 0 ;not an edge, same as last
xorwf flags,f ;save for next time
btfsc flags,4 ;test for falling edge
retlw 0 ;must have been a rising edge
movf period_count,w ;make a working copy
movwf period_dup ;called period dup
clrf period_count ;a fresh start for next rotation
clrf digit_index ;set to first digit
clrf dot_index ;first column
; calculate a period that does not dither or jitter
; period will not be changed unless new period is really different
movf period_calc,w
subwf period_dup,w ;find difference
btfss STATUS,C ;carry flag set means no borrow
goto Calc_period_neg ;must be other way
sublw 2 ;allowable deviation = 3
btfss STATUS,C ;borrow won't skip
incf period_calc ;new value much larger than calc
retlw 0
Calc_period_neg addlw 2 ;allowable deviation = 3
btfss STATUS,C ;carry will skip
decf period_calc ;no carry means it must be changed
retlw 0
;--------
; change LED pattern based on state of digit_index and dot_index
;--------
Display_now movlw 0x05
xorwf dot_index,w ;test for end of digit
movlw 0xFF ;pattern for blank column
btfsc STATUS,Z
goto D_lookup_3 ;it needs a blank
bcf STATUS,C ;clear carry before a rotate
rlf digit_index,w ;double the index because each
addwf PCL,f ;takes two instructions
D_10hr swapf hours,w
goto D_lookup ;what a great rush of power
D_1hr movf hours,w ;I feel when modifying
goto D_lookup ;the program counter
D_colon movlw 0x0A
goto D_lookup
D_10min swapf minutes,w
goto D_lookup
D_1min movf minutes,w
goto D_lookup
D_nothing retlw 0
D_lookup andlw b'00001111' ;strip off hi bits
movwf scratch ;multiply this by 5 for lookup
addwf scratch,f ;table base position
addwf scratch,f ;is this cheating?
addwf scratch,f ;I think not.
addwf scratch,f ;I think it is conserving energy!
btfss STATUS,Z ;test for zero
goto D_lookup_2 ;not a zero
movf digit_index,f ;this is just to test/set flag
movlw 0xFF ;this makes a blank LED pattern
btfsc STATUS,Z ;test if it is 10 hrs digit
goto D_lookup_3 ;it's a leading zero
D_lookup_2 movf dot_index,w ;get column
addwf scratch,w ;add it to digit base
call Char_tbl ;get the dot pattern for this column
D_lookup_3 movwf PORTB ;send it to the LEDs
movlw 0x0C ;overhead value sub from period
subwf period_calc,w ;compensate for overhead and set
call Delay ;width of digits with this delay
incf dot_index,f ;increment to the next column
movlw 0x06 ;6 columns is a digit plus space
xorwf dot_index,w ;next digit test
btfss STATUS,Z
retlw 0 ;not a new digit
clrf dot_index ;new digit time
incf digit_index,f
retlw 0 ;Display_now done.
;--------
; a short delay routine
;--------
Delay movwf tick
Delay_loop decfsz tick,f
goto Delay_loop ;w is not damaged, so Delay can
return ;be recalled without reloading
;--------
; test for keypress and call time adjust if needed
;--------
Check_keys movf PORTA,w ;get port "a"
xorwf keys,w ;compare with previous
andlw b'00000111' ;only care about button pins
btfsc STATUS,Z ;zero set=no buttons
retlw 0 ;return
xorwf keys,f ;store key value
movlw 0x64 ;a fairly long delay will
movwf scratch ;prevent key bounces
Key_delay movlw 0xFF
call Delay
decfsz scratch
goto Key_delay
btfss keys,2 ;test "minutes" button
goto Inc_mins
btfss keys,1 ;test "tens" button
goto Inc_tens
btfss keys,0 ;test "hours" button
goto Inc_hours
retlw 0 ;must be a glitch. yeah, right!
;--------
; increment ten minutes
;--------
Inc_tens movlw 0x0A
movwf scratch ;scratch has ten
Inc_tens_loop call Inc_mins
decfsz scratch
goto Inc_tens_loop ;another minute added
retlw 0
;--------
; increment one hour
;--------
Inc_hours movlw 0x12
xorwf hours,w
btfsc STATUS,Z
goto Inc_hours_12
movlw 0x07 ;this part gets a little sloppy
addwf hours,w
movlw 0x07
btfss STATUS,DC
movlw 1
addwf hours,f
retlw 0
Inc_hours_12 movlw 0x01
movwf hours
retlw 0
;--------
; increment the time based on flags,1 as sent by interrupt routine
; Inc_mins loop also used by time-setting routine
;--------
Keep_time btfss flags,1 ;the minutes flag
retlw 0 ;not this time
bcf flags,1 ;clear the minutes flag
Inc_mins movlw 0x07 ;start incrementing time
addwf minutes,w ;add 7 minutes into w
btfsc STATUS,DC ;did adding 7 cause digit carry?
goto Sixty_mins ;then test for an hour change
incf minutes ;otherwise add 1 for real
retlw 0 ;and go back
Sixty_mins movwf minutes ;save the minutes
movlw 0x60 ;test for 60
xorwf minutes,w ;are minutes at 60?
btfss STATUS,Z
retlw 0 ;no? go back
clrf minutes ;otherwise zero minutes
goto Inc_hours ;and increment hours
;--------
; End of subroutines
; Program starts here
;--------
Start call Ram_init ;set variables to nice values
call Port_init ;set port directions
call Timer_init ;start timer based interrupt
;--------
; Done initializing, start the endless loop.
;--------
;
Circle ;begin the big loop
;
;--------
; detect falling edge on PORTA,4 to determine rotary index
; calculate rotation period and store in period_dup
; compare with working period(period_calc) and adjust if way different
;--------
call Check_index
;--------
; check display state and change if needed
;--------
call Display_now
;--------
; check keyboard and adjust time
;--------
call Check_keys
;--------
; check minute flag and increment time if a minute has passed
;--------
call Keep_time
;--------
; gentlemen, that's a clock, keep it rolling
;--------
goto Circle ;you heard the man, get going!
end
;--------
; end of file
;--------
Code: Select all
:020000040000FA
:02000000F528E1
:08000800A000030EA10064003A
:10001000A20A0319A203AC0A0319AB0A0319AA0F17
:100020001828FC30AA006C30AB007930AC00A51465
:10003000210E8300A00E200E0B1109008207C1348F
:10004000BE34BE34BE34C134FF34DE348034FE34BA
:10005000FF34DE34BC34BA34B634CE34BD34BE34AE
:10006000AE349634B934F334EB34DB348034FB34BF
:100070008D34AE34AE34AE34B134E134D634B6342B
:10008000B634F934BF34B834B734AF349F34C934DC
:10009000B634B634B634C934CF34B634B634B534E5
:1000A000C334FF34C934C934FF34FF340730AD00E2
:1000B0001230A800A901A601A701FC30AA00003453
:1000C0000313831207309F0097010030660017303A
:1000D000650000340B118B178B1681016400D8303A
:1000E0006200810100340508250610390319003427
:1000F000A506251A00342208A300A201A701A60123
:1001000024082302031C8828023C031CA40A003490
:10011000023E031CA403003405302606FF300319F9
:10012000AE280310270D8207280E9F2828089F2835
:100130000A309F28290E9F2829089F2800340F394C
:10014000AE00AE07AE07AE07AE07031DAB28A7088B
:10015000FF300319AE2826082E071E2086000C301B
:100160002402BA20A60A06302606031D0034A60182
:10017000A70A0034AF00AF0BBB28080005082D0606
:10018000073903190034AD066430AE00FF30BA20E1
:10019000AE0BC6282D1DE828AD1CD1282D1CD72854
:1001A00000340A30AE00E820AE0BD3280034123001
:1001B00028060319E228073028070730831C01307E
:1001C000A80700340130A8000034A51C0034A51095
:1001D000073029078318EE28A90A0034A9006030E7
:1001E0002906031D0034A901D728562060206A2063
:0A01F00073208C20BE20E520F828C3
:00000001FF