Bináris óra

Bináris óra leírás
vicsys által publikált kapcsolást építettem meg. Annyit hozzáfűznék, hogy az oszlopokat fel kell cserélni a helyes működéshez.
Bináris óra

Videó bináris óra

program ASM file:

; Binary LED Clock
; By Hein Ragas
; http://home.publishnet.nl/~hragas
; Version 1.0
; Clock functionality ONLY

title "Binary LED Clock"
list P = 16F628A
include "p16F628A.inc"
__CONFIG _CP_OFF & _XT_OSC & _WDT_OFF & _PWRTE_ON & _MCLRE_OFF & _BODEN_OFF & _LVP_OFF

; Variables for delay loop
teller EQU 070h
teller2 EQU 071h

; Variables for time-keeping
sece EQU 072h ; Second units
sect EQU 073h ; Second tens
mine EQU 07Bh ; Minute units
mint EQU 07Ch ; Minute tens
hre EQU 07Dh ; Hour units
hrt EQU 07Eh ; Hour tens

; Variables for the one second timer
bres_hi EQU 076h ; hi byte of our 24bit variable
bres_mid EQU 077h ; mid byte
bres_lo EQU 078h ; lo byte

; Variables to save register statusses during interrupt
temp_s EQU 079h
temp_w EQU 07Ah

; Variables for debouncing and inputs
bounce_timer EQU 07Fh ; Counter for the debounce routine
csa EQU 060h
cva EQU 061h
count_A EQU 062h
count_B EQU 063h
prev_val EQU 064h

GOTO init
ORG 0x4 ; Choose starting adress

; Interrupt routine. This is called every 256 instructions.
isr MOVWF temp_w ; save w register
MOVF STATUS, W ; W = STATUS
MOVWF temp_s ; save STATUS register

; First, see if we need to call the debouncing routine
; We don't call the debouncing routine every interrupt, but every 10
; interrupts. That's once every 2560 instructions. Because an input needs
; to be the same for 4 consecutive calls to the debouncing routine, it
; needs to be the same for roughly 0.01 seconds.
DECFSZ bounce_timer, f ; Decrement bounce_timer, see if it's 0
GOTO bookkeeping ; Not 0, skip the debouncing routine

MOVLW 009h ; Bounce_timer == 0
MOVWF bounce_timer ; Reset bounce_timer to 9

CALL read_inputs
CALL debounce
CALL process_inputs

; Here comes the bookkeeping for the timer routine
bookkeeping TSTF bres_mid ; first test for mid==0
SKPNZ ; nz = no underflow needed
DECF bres_hi,f ; z, so is underflow, so dec the msb

DECFSZ bres_mid,f ; dec the mid byte (subtract 256)
GOTO end_isr ; nz, so definitely not one second yet.

TSTF bres_hi ; test hi for zero too
SKPZ ; z = both hi and mid are zero, is one second!
GOTO end_isr ; nz, so not one second yet.

MOVLW 0x0F ; get msb value
MOVWF bres_hi ; load in msb
MOVLW 0x42 ; get mid value
MOVWF bres_mid ; load in mid
MOVLW 0x40 ; lsb value to add
ADDWF bres_lo,f ; add it to the remainder already in lsb
SKPNC ; nc = no overflow, so mid is still ok

INCF bres_mid,f ; c, so lsb overflowed, so inc mid

CALL continue ; A second has passed, increase the second count

; End of the interrupt routine
end_isr BCF INTCON, T0IF ; clear the TMR0 flag bit
MOVF temp_s, W ; Put STATUS and W back where they belong
MOVWF STATUS
SWAPF temp_w, F
SWAPF temp_w, W
RETFIE ; Return from interrupt

; Initialisation routine
init BSF STATUS,5 ; Choose bank 1
CLRF TRISA ; All pins of port A are outputs
CLRF TRISB ; All pins of port B are outputs...
BSF TRISB, 6
BSF TRISB, 7 ; ...except for the last two
MOVLW b'10001000' ; Set the options (prescaler for watchdog timer)
MOVWF OPTION_REG
BCF STATUS,5 ; Choose bank 0

CALL initial_vals ; Set initial values

MOVLW 0x0F ; get msb value
MOVWF bres_hi ; put in hi
MOVLW 0x42 +1 ; get mid value (note we added 1 to it)
MOVWF bres_mid ; put in mid
MOVLW 0x40 ; get lsb value
MOVWF bres_lo ; put in mid

CLRF INTCON
BSF INTCON, T0IE
BSF INTCON, GIE ; Set Timer interrupt

; Routine to show the numbers on the display
shownumbers
MOVLW 000h
MOVWF PORTB ; All LEDs off
MOVF sece,w ; Load sece into W
MOVWF PORTA ; Set the LEDs
BSF PORTB, 0 ; Show the first row
CALL delay ; Call our delay routine

MOVLW 000h
MOVWF PORTB ; All LEDs off
MOVF sect,w ; Load sect in W
MOVWF PORTA ; Set the LEDs
BSF PORTB, 1 ; Show the second row
CALL delay

MOVLW 000h
MOVWF PORTB ; All LEDs off
MOVF mine,w ; Load mine into W
MOVWF PORTA ; Set the LEDs
BSF PORTB, 2 ; Show the third row
CALL delay

MOVLW 000h
MOVWF PORTB ; All LEDs off
MOVF mint,w ; Load mint into W
MOVWF PORTA ; Set the LEDs
BSF PORTB, 3 ; Show the fourth row
CALL delay

MOVLW 000h
MOVWF PORTB ; All LEDs off
MOVF hre,w ; Load hre into W
MOVWF PORTA ; Set the LEDs
BSF PORTB, 4 ; Show the fifth row
CALL delay

MOVLW 000h
MOVWF PORTB ; All LEDs off
MOVF hrt,w ; Load hrt into W
MOVWF PORTA ; Set the LEDs
BSF PORTB, 5 ; Show the sixth row
CALL delay

GOTO shownumbers ; Just keep on showing those numbers -- the
; rest of the functionality is called from the interrupt
; routine.

; This routine is called whenever a second has passed.
continue INCF sece, 1 ; Increase sece
MOVF sece, w
ADDLW 0F6h ; sece > 9?
SKPNC
GOTO overflow_sece ; sece == 10, so increment sect
RETURN

overflow_sece CLRF sece ; Set sece back to 0
INCF sect, 1 ; Increase sect with 1
MOVF sect, w
ADDLW 0FAh ; sect > 5?
SKPNC
GOTO overflow_sect ; sect == 5, so increment mine
RETURN

overflow_sect CLRF sect ; Set sect back to 0
CLRF sece
INCF mine, 1 ; Increase mine
MOVF mine, w
ADDLW 0F6h ; mine > 9?
SKPNC
GOTO overflow_mine ; mine == 10, so increment sect
RETURN

overflow_mine CLRF mine ; Set mine back to 0
INCF mint, 1 ; Increase mint
MOVF mint, w
ADDLW 0FAh ; mint > 5?
SKPNC
GOTO overflow_mint ; mint == 5, so increment hre
RETURN

overflow_mint CLRF mint ; Reset mint to 0
incr_hre INCF hre, 1 ; Increase hre
MOVF hre, w
ADDLW 0FCh ; hre > 4?
SKPNC
GOTO check_hre ; hre > 4, so we need to check whether we need
; to overflow hrt
RETURN

check_hre MOVF hrt, w
ADDLW 0FEh ; hrt > 1?
SKPNC
GOTO overflow_hre ; hrt == 2, hre == 5 -> overflow!
MOVF hre, w ; hrt == 1
ADDLW 0F6h ; hre > 9?
SKPNC
GOTO overflow_hre ; hrt == 1, hre == 10 -> overflow!
RETURN

overflow_hre CLRF hre ; Reset hre to 0
INCF hrt, 1 ; Increase hrt
MOVF hrt, w
ADDLW 0FDh ; hrt > 2?
SKPNC
GOTO overflow_hrt ; hrt == 2; overflow hrt (it's midnight!)
RETURN

overflow_hrt CLRF sece ; Midnight, reset everything to 0!
CLRF sect
CLRF mine
CLRF mint
CLRF hre
CLRF hrt
RETURN

; Sets the initial values. We start 9 seconds before midnight!
initial_vals MOVLW 001h
MOVWF sece
CLRF sect
CLRF mine
CLRF mint
CLRF hre
CLRF hrt
MOVLW 005h
MOVWF sect
MOVLW 009h
MOVWF mine
MOVLW 005h
MOVWF mint
MOVLW 003h
MOVWF hre
MOVLW 002h
MOVWF hrt
; Also, set the variables for the counters etc.
MOVLW 009h
MOVWF bounce_timer
CLRF csa
CLRF cva
CLRF count_A
CLRF count_B
CLRF prev_val
RETURN

; Our delay loop. Waits roughly 1000 instructions, that's 1 msec
delay
MOVLW 00Ah ;10 times...
MOVWF teller
outerloop MOVLW 064h ;100 times...
MOVWF teller2
innerloop DECFSZ teller2, 1
GOTO innerloop
DECFSZ teller, 1
GOTO outerloop
RETURN

; Read the inputs
read_inputs
; Check minute pin, sets the appropriate bit in the csa variable
BTFSC PORTB, 6
GOTO minute_een
minute_nul BCF csa, 0
GOTO einde_minute
minute_een BSF csa, 0
einde_minute

; Check hour pin, sets the appropriate bit in the csa variable
BTFSC PORTB, 7
GOTO hour_een
hour_nul BCF csa, 1
GOTO einde_hour
hour_een BSF csa, 1
einde_hour RETURN

; Debounce routine
debounce
;Increment the vertical counter
MOVF count_B,W
XORWF count_A,F
COMF count_B,F

;See if any changes occurred
MOVF csa,W
XORWF cva,W

;Reset the counter if no change has occurred
ANDWF count_B,F
ANDWF count_A,F

;Determine the counter's state
MOVF count_B,W
IORWF count_A,W

;Clear all bits that are filtered-or more accurately, save
;the state of those that are being filtered
ANDWF cva,F
XORLW 0xff

;Re-write the bits that haven't changed.
ANDWF csa,W
IORWF cva,F

RETURN

; Process the debounced inputs
; We have two variables to work with: prev_val, which contains the previous (debounced) states of the inputs;
; and cva, the debounced current state of the inputs.
; Each input is set as a bit in both the variables.
process_inputs
; Check the previous value of the minute-input
BTFSS prev_val, 0
GOTO minute_was_zero
minute_was_one BTFSS cva, 0
BCF prev_val, 0 ; from 1 to 0 -> reset prev_val to 0
GOTO check_hour
minute_was_zero BTFSC cva, 0
GOTO minute_press
GOTO check_hour
minute_press BSF prev_val, 0
CALL overflow_sect ; from 0 to 1 -> tick!
check_hour ; Check the previous value of the hour input
BTFSS prev_val, 1
GOTO hour_was_zero
hour_was_one BTFSS cva, 1
BCF prev_val, 1 ; from 1 to 0 -> reset prev_val to 0
RETURN
hour_was_zero BTFSC cva, 1
GOTO hour_press
RETURN
hour_press BSF prev_val, 1
CALL incr_hre ; from 0 to 1 -> tick!
RETURN

END

program HEX file: Valamiért nem tudom feltölteni, de elküldöm, aki kéri.

MINDEN VÉLEMÉNY SZÁMÍT!