;----------------------------------------------------------------------; ; BINCLK4M.ASM A clock that displays in bcd numbers ; ;----------------------------------------------------------------------; ; .-----------. ; -|RA2 RA1|- V+ = 4.5 or 5 Volts ; -|RA3 RA0|- X = 4.096 MHz xtal ; -|RA4 OSC1|--|X|-||--- gnd 20 pf caps ; -{r}- = 470 ohm V+ ---|MCLR OSC2|--|X|-||--- gnd ; -|<- = LED gnd ---|Vss Vdd|--- V+ ; gnd ---|<--{r}--|RB0 RB7|- ; gnd ---|<--{r}--|RB1 RB6|- ; gnd ---|<--{r}--|RB2 RB5|---[PB]--- gnd <- SET PB ; gnd ---|<--{r}--|RB3 RB4|---[PB]--- gnd <- SHOW PB ; '-----------' ; PIC16F84 -[PB]- pushbutton LIST P=16F84 ; tells which processor is used INCLUDE "p16f84.inc" ; defines various registers etc. Look ERRORLEVEL -224 ; supress annoying message from tris __CONFIG _PWRTE_ON & _XT_OSC & _WDT_OFF ; config. switches CBLOCK 0CH sec ; seconds digit sec10 ; 10's of second digit mins ; minutes digit min10 ; 10's of minutes digit hr ; hours digit hr10 ; 10's of hours digit w_temp ; holds W during interrupt status_temp ; holds STATUS during interrupt fsr_temp ; holds FSR during interrupt digit ; holds digit position cntmsec ; used to count milliseconds counter ; used to stretch isr out to 1 sec flashcnt ; counter for flashing LED ENDC ;----------------------------------------------------------------------; ; Here are some DEFINEs which give 'names' to pushbutton port bits ; ;----------------------------------------------------------------------; #DEFINE SHOWPB PORTB, 4 #DEFINE SETPB PORTB, 5 ORG 0 ; start at location 0 goto main ; jump over to main routine ORG 4 goto isr ; jump to interrupt routine ;----------------------------------------------------------------------; ; High limit + 1 of digits at position W ; ;----------------------------------------------------------------------; sethi: addwf PCL, f dt H'A',H'6',H'A',H'6',H'A',H'3' ;----------------------------------------------------------------------; ; time delay routines ; ;----------------------------------------------------------------------; micro4 addlw H'FF' ; subtract 1 from 'W' btfss STATUS,Z ; skip when you reach zero goto micro4 ; more loops return msec250: movlw D'250' ; delay for 250 milliseconds ;*** N millisecond delay routine *** nmsec: movwf cntmsec ; delay for N (in W) millisec msecloop: movlw D'248' ; 1 usec for load call micro4 ; this instruction is 995 usec nop ; 1 usec decfsz cntmsec,f ; 1 usec, (2 if skip taken) goto msecloop ; 2 usec, loop = 995+5 = 1 msec return ;----------------------------------------------------------------------; ; Delay for one second ; ;----------------------------------------------------------------------; onesecond: ; a subroutine that delays for 1 seconds call msec250 call msec250 call msec250 call msec250 return ;----------------------------------------------------------------------; ; Put value in W on LEDs for 1 second ; ;----------------------------------------------------------------------; sendnbr: btfsc STATUS, Z ; skip if not zero movlw H'0F' ; else all on for a zero movwf PORTB ; light LEDs call onesecond ; wait 1 second clrf PORTB ; clear the LEDs movlw D'100' ; pause for 0.1 sec call nmsec return ;----------------------------------------------------------------------; ; Send the current time out LEDs ; ;----------------------------------------------------------------------; disptime: movf hr10, W call sendnbr movf hr, W call sendnbr movf min10, W call sendnbr movf mins, W call sendnbr return ;----------------------------------------------------------------------; ; Wait until set button is released ; ;----------------------------------------------------------------------; waitsetup: ; wait for set pushbutton up btfss SETPB ; skip if set button released goto waitsetup movlw D'10' call nmsec ; wait 10 msec for debounce btfss SETPB ; check again for release goto waitsetup ; false alarm, start over return ; yes, finished ;----------------------------------------------------------------------; ; Initialization Subroutine ; ;----------------------------------------------------------------------; init: movlw B'0000000' ; all outputs port A tris PORTA movlw B'00110000' ; RB4, RB5 inputs, others outputs tris PORTB ; on port B movlw H'0' ; all low (off) movwf PORTB movlw B'00000100' ; pull-ups enabled ; prescaler assigned to TMR0 ; prescaler set to 1:16 ; rolls over each 1/125 th second option movlw 0 movwf hr10 movlw H'9' ; initialize hrs, mins and secs movwf hr ; Do this before interrupts are movlw H'5' ; turned on because isr also acts movwf min10 ; on these registers movlw H'0' movwf mins movwf sec10 movwf sec movlw D'125' ; initialize isr counter movwf counter movlw B'10100000' ; GIE & T0IE set, T0IF cleared movwf INTCON return ;----------------------------------------------------------------------; ; Interrupt routine, increments time by one second (BCD) ; ;----------------------------------------------------------------------; isr: movwf w_temp ; save W swapf STATUS,W ; save status movwf status_temp ; without changing flags swapf FSR,W ; save FSR movwf fsr_temp ; without changing flags decfsz counter, f ; skip on 125th time thru goto restore ; else exit movlw D'125' ; reset interrupt counter movwf counter movlw sec ; point at sec register movwf FSR newdigit: incf INDF, f ; current digit up one movlw sec ; get difference sec and FSR subwf FSR, W call sethi ; use to get high limit + 1 subwf INDF, W ; reached that number yet? btfss STATUS, Z ; skip over if yes goto restore ; else exit isr clrf INDF ; set current digit to 0 incf FSR, f ; point at next digit btfss hr10, 1 ; has hr10 reached 2? goto newdigit ; no, increment the next digit btfss hr, 2 ; has hr reached 4? goto newdigit ; no clrf hr ; yes, set hour to 00 clrf hr10 ; and hour 10 restore: swapf status_temp,W ; get original status back movwf STATUS ; into status register swapf fsr_temp,W ; get original fsr back movwf FSR ; into status register swapf w_temp,f ; old no flags trick again swapf w_temp,W ; to restore W bcf INTCON,T0IF ; clear the TMR0 interrupt flag retfie ; finished reset GIE ;----------------------------------------------------------------------; ; Increment and display digit pointed to by FSR ; ;----------------------------------------------------------------------; updigit: incf INDF, f ; selected digit up one movlw mins ; set up to subtract mins address subwf FSR, W ; from address of current digit call sethi ; get maximum of digit + 1 into W subwf INDF, W ; is it = to current digit value? btfsc STATUS, Z ; gives zero if yes, skip if no clrf INDF ; reset value of digit to zero movf INDF, W ; get current value and .. movwf PORTB ; display it call onesecond ; pause for 1 second return ;----------------------------------------------------------------------; ; flash LED representing digit position ; ;----------------------------------------------------------------------; setnext: movwf digit ; save digit position flashloop: clrf PORTB ; all LEDs off movf digit, W ; restore digit position btfss flashcnt, 0 ; leave off on odd #'s of counter movwf PORTB ; flash digit on even #'s movlw 50 ; delay for 50 msec call nmsec incf flashcnt, f ; flip LSB of flashcnt btfss SHOWPB ; skip over if SHOW not pressed call updigit ; else increment current digit btfsc SETPB ; skip over if set pressed goto flashloop ; continue until pressed again incf FSR, f ; set up for next digit call waitsetup ; wait for release return ;----------------------------------------------------------------------; ; Increment and set digits ; ;----------------------------------------------------------------------; setdigits: bcf INTCON, GIE ; no interrupts while setting time movlw mins ; point at minutes register movwf FSR call waitsetup ; wait on set pushbutton up movlw B'00000001' ; light right LED (mins) call setnext movlw B'00000010' ; light min10 LED call setnext movlw B'00000100' ; light hr LED call setnext movlw B'00001000' ; hr10 LED on call setnext clrf PORTB ; clear LEDs bsf INTCON, GIE ; enable interrupts again return ;----------------------------------------------------------------------; ; The main routine ; ;----------------------------------------------------------------------; main: call init ; set up initial conditions loop: btfss SHOWPB ; check for show pushbutton call disptime ; display the time btfss SETPB ; check for setting of time call setdigits goto loop ; do forever end ; Note: A 4.096 MHz xtal is needed for accurate timing over long ; periods. You press the SHOW pushbutton to show the time, digit by ; digit. Zeros are shown as all lights on. To set the time you press ; SET. The right most digit will blink indicating minutes are to ; be set. Pressing SET again chooses tens of minutes etc. After tens ; of hours, the LEDs blank and the clock is timing again. While any ; LED is blinking, pressing SHOW will display that digit value and ; increment it every second. Release SHOW when the digit value is what ; you want.
file: /Techref/piclist/cheapic/binclk4m.asm, 13KB, , updated: 2000/12/8 11:59, local time: 2024/12/11 11:10,
18.97.9.173:LOG IN
|
©2024 These pages are served without commercial sponsorship. (No popup ads, etc...).Bandwidth abuse increases hosting cost forcing sponsorship or shutdown. This server aggressively defends against automated copying for any reason including offline viewing, duplication, etc... Please respect this requirement and DO NOT RIP THIS SITE. Questions? <A HREF="http://www.massmind.org/techref/piclist/cheapic/binclk4m.asm"> piclist cheapic binclk4m</A> |
Did you find what you needed? |
Welcome to massmind.org! |
Welcome to www.massmind.org! |
.