;************************************************************************** ; ; MODIFIED BY JON STANLEY FOR 12-HOUR CLOCK MODE ; ; Displays time on a single 7-segment display. The timing source ; can be an NTSC colour burst crystal (3.579454 MHz) or a 4 MHz ; crystal. ; ; A common anode 7-segment LED display is attached as follows: ; ; RA0 segment a ; RA1 segment b ; RA2 segment c ; RA3 segment d ; RA4 segment e ; RB4 segment f ; RB5 segment g ; ; Each segment is connected via a 470 ohm resistor. The common anode ; is connected directly to VDD. The strange allocation of port bits ; to segments allows RB6 and RB7 to be dedicated to in-circuit serial ; programming. ; ; The time is displayed digit by digit over a four second period ; every 15 seconds and the display is blank otherwise. Four LEDs are ; connected from RB3-RB0 to GND via 470 ohm resistors; these are used ; to indicate the significance of the displayed digit: 10s of hours - ; hours - 10s of minutes - minutes. ; ; A normally open switch is connected from RB7 to GND via a 470 ohm ; resistor; no pull-up resistor is needed as an internal weak pull-up ; is enabled by the program. To set the clock press the switch when ; the appropriate digit is displayed; the digit can then be incremented ; by pressing the switch repeatedly. If the switch is open for about ; 2 seconds the clock display is restarted allowing another digit to be ; changed. It is up to the user to put in sensible times as no checking ; is done by the program. ; ; To permit the PIC to be programmed in-circuit the /MCLR pin is ; connected to VDD via a 1k resistor in series with a signal diode ; (e.g. 1N4148) with anode connected to VDD. ; ; ; Copyright (C) 1998 David Tait (david.tait@man.ac.uk) ; ;************************************************************************** LIST P=16F84 ; no need to change this for the 16C84 ERRORLEVEL -302 ; suppress bank selection messages __CONFIG 3FF9H ; XT oscillator (and PWRTE if 16C84) #DEFINE _3_58MHZ ; choose clock speed ;#DEFINE _4_00MHZ PCL EQU 2 ; registers are defined here to make this STATUS EQU 3 ; program self contained. PORTA EQU 5 PORTB EQU 6 INTCON EQU 0BH TRISA EQU 85H TRISB EQU 86H OPTREG EQU 81H C EQU 0 ; bits in STATUS Z EQU 2 RP0 EQU 5 T0IF EQU 2 ; bit in INTCON #IFDEF _3_58MHZ ; number of ticks per second for 3.58 MHz: TCK0 EQU .109 ; nominal TCK1 EQU .111 ; every 10 secs TCK2 EQU .113 ; every min TCK3 EQU .115 ; every 10 mins TCK4 EQU .114 ; every hour TCK5 EQU .110 ; every 10 hours TCK6 EQU .111 ; every 24 hours #ENDIF #IFDEF _4_00MHZ ; as above but for 4 MHz TCK0 EQU .122 TCK1 EQU .123 TCK2 EQU .121 TCK3 EQU .123 TCK4 EQU .124 TCK5 EQU .125 TCK6 EQU .125 #ENDIF CBLOCK 0CH ; define variables required TICKS ; decremented every tick (9.15 ms or 8.19 ms) SEGS ; one bit per segment: "-gfedcba" SEC SEC10 MIN MIN10 HOUR HOUR10 FRAME ; used to decide when to display time HHMM ; one bit per digit displayed COUNT ; scratch register DIGIT ; last digit displayed ENDC ;*********************************; ; Initialisation ; ;*********************************; ORG 0 INIT CLRF SEC CLRF SEC10 CLRF MIN CLRF MIN10 movlw D'2' ; 12:00 initialized here! movwf HOUR movlw D'1' movwf HOUR10 CLRF FRAME CLRF PORTA CLRF PORTB BSF STATUS,RP0 ; select register bank 1 CLRF TRISA MOVLW 80H MOVWF TRISB ; only RB7 is an input MOVLW 4 MOVWF OPTREG ; assign prescaler (1:32) to TMR0 BCF STATUS,RP0 ; reselect bank 0 BTFSS PORTB,7 ; switch open? GOTO TEST ; no, go to test mode ;*********************************; ; Main Program ; ;*********************************; MAIN CALL CLOCK ; real-time clock algo called every second CALL SHOW ; display the time WAIT BTFSS INTCON,T0IF ; wait for TMR0 to roll over GOTO WAIT CLRF INTCON CALL CHKSW ; check for button press MOVF TICKS,W XORLW D'20' ; Check for 20 ticks BTFSS STATUS,Z GOTO J1 MOVLW 30 ; Turn off Display at 100/120 ticks MOVWF PORTB MOVLW 1F MOVWF PORTA J1 DECFSZ TICKS,F GOTO WAIT GOTO MAIN ; get here every second ;*********************************; ; Convert digit to segment form ; ;*********************************; SEGTAB ANDLW 0FH ADDWF PCL,F DT 40,79,24,30,19,12,02,78,00,10 DT 7F,7F,7F,7F,7F,7F ;*********************************; ; Real-time clock algorithm ; ;*********************************; CLOCK MOVLW TCK0 ; increment digits as appropriate MOVWF TICKS ; and define number of ticks per INCF SEC,F ; second for next second MOVF SEC,W SUBLW 9 BTFSC STATUS,C RETURN MOVLW TCK1 MOVWF TICKS CLRF SEC INCF SEC10,F MOVF SEC10,W SUBLW 5 BTFSC STATUS,C RETURN MOVLW TCK2 MOVWF TICKS CLRF SEC10 INCF MIN,F MOVF MIN,W SUBLW 9 BTFSC STATUS,C RETURN MOVLW TCK3 MOVWF TICKS CLRF MIN INCF MIN10,F MOVF MIN10,W SUBLW 5 BTFSC STATUS,C RETURN MOVLW TCK4 MOVWF TICKS CLRF MIN10 MOVF HOUR10,W SUBLW 0 BTFSC STATUS,C GOTO INCHR INCF HOUR,F MOVF HOUR,W SUBLW 2 BTFSC STATUS,C RETURN MOVLW TCK6 MOVWF TICKS CLRF HOUR INCF HOUR,F CLRF HOUR10 RETURN INCHR INCF HOUR,F MOVF HOUR,W SUBLW 9 BTFSC STATUS,C RETURN MOVLW TCK5 MOVWF TICKS CLRF HOUR INCF HOUR10,F RETURN ;*********************************; ; Displays the time digit by digit; ;*********************************; SHOW CLRF HHMM INCF FRAME,F ; increment place in frame MOVF FRAME,W SUBLW D'08' ; Display cycle time BTFSS STATUS,C CLRF FRAME MOVF FRAME,W XORLW 1 BTFSC STATUS,Z GOTO DHOUR10 ; display 10s of hours when frame is 1 XORLW 1^2 BTFSC STATUS,Z GOTO DHOUR ; display hour when frame is 2 XORLW 2^3 BTFSC STATUS,Z GOTO DMIN10 ; display 10s of mins when frame is 3 XORLW 3^4 BTFSC STATUS,Z GOTO DMIN ; display mins when frame is 4 MOVLW 30 ; otherwise blank display MOVWF PORTB MOVLW 1F MOVWF PORTA RETURN DHOUR10 BSF HHMM,3 MOVF HOUR10,W BTFSS STATUS,Z ; check for leading zero GOTO DISPLAY RETURN ; skip display of leading zero DHOUR BSF HHMM,2 MOVF HOUR,W GOTO DISPLAY DMIN10 BSF HHMM,1 MOVF MIN10,W GOTO DISPLAY DMIN BSF HHMM,0 MOVF MIN,W ; falls through to DISPLAY ;*********************************; ; Displays digit in W ; ;*********************************; DISPLAY MOVWF DIGIT ; save number to be displayed in DIGIT CALL SEGTAB ; convert to segment form MOVWF SEGS ; and store ANDLW 1FH ; extract PORTA segments MOVWF PORTA ; and display RRF SEGS,W ANDLW 30H ; extract PORTB segments IORWF HHMM,W MOVWF PORTB ; and display RETURN ;*********************************; ; Checks for a switch press and ; ; updates digit if displayed ; ;*********************************; CHKSW BTFSC PORTB,7 ; switch closed? RETURN ; no MOVF HHMM,F BTFSC STATUS,Z ; digit displayed? RETURN ; no INCDIG INCF DIGIT,F ; DIGIT is the currently displayed number MOVF DIGIT,W SUBLW 9 BTFSS STATUS,C CLRF DIGIT ; If DIGIT incremented over 9 MOVF DIGIT,W CALL DISPLAY CALL DELAY ; wait for switch to settle CHKSW0 BTFSS PORTB,7 ; switch open? GOTO CHKSW0 ; no CALL DELAY BTFSS PORTB,7 ; still open? GOTO CHKSW0 ; no MOVLW D'20' MOVWF COUNT CHKSW1 BTFSS PORTB,7 ; switch open? GOTO INCDIG ; no CALL DELAY DECFSZ COUNT,F GOTO CHKSW1 MOVF DIGIT,W ; switch was open for around 2 secs CLRF FRAME CLRF SEC10 CLRF SEC BTFSC HHMM,3 ; update correct digit MOVWF HOUR10 BTFSC HHMM,2 MOVWF HOUR BTFSC HHMM,1 MOVWF MIN10 BTFSC HHMM,0 MOVWF MIN GOTO MAIN ; restart the program ;*********************************; ; Delay used by switch routine ; ;*********************************; DELAY MOVLW D'12' ; roughly 100ms delay MOVWF TICKS DEL1 BTFSS INTCON,T0IF ; wait for TMR0 to roll over GOTO DEL1 CLRF INTCON DECFSZ TICKS,F GOTO DEL1 RETURN TEST CLRF COUNT ; exercise Numitron by cycling through MOVF COUNT,W ; all numbers CALL DISPLAY CALL DELAY CALL DELAY ; 1 second delay INCF COUNT,F MOVF COUNT,W XORLW D'10' ; Test for 10 BTFSS STATUS,Z GOTO TEST+1 GOTO TEST ; Reset COUNT to 0 END