This project is devoted to a clock with time represented in the binary system. There is some display flickering on the video, which is not noticeable in reality.
Functionality |
![]() clip (AVI, ~1.6Mb) |
---|
Reading from left to right, the first 2 columns will display hours. The tens digit is in the first column and the ones will be in the next column. After that, the 3rd column, there will be a spacer column to provide a separator for the time. Next will follow minutes in the 4th and 5th column. Simular to hours, the tens digit will be in the 4th column and ones digit will be in the 5th column. The 6th column is another spacer to separate the data columns. Finally the last 2 columns will display the seconds. The 7th column will display the tens digit of the Seconds and the 8th, last, column will display the ones digit. The example above displays the time of 12:53:37.
Time encoding | Example | |
The 2 buttons on the left side allow the time to be set. The top button will add an hour on every push while the bottom button will add one minute on every push. Currently there is no control to change the seconds.
The heart of the project is PIC16F684 microcontroller that keeps, updates, and displays time. The PIC is running at 4 MHz from internal oscillator. The time keeping part is based on its timer TMR1 whose clock input is powered form a 32768 = 215 Hz oscillator. The timer is configured to divide this frequency into 215 times and, thus, its overflow occurs every second. The overflow event is captured and the corresponding Interrupt Service Routine (ISR) updates the clock.
Schematic | PCB Front | PCB Back | Board | |||
The time is displayed on a matrix LED column by column starting from hours down to minutes. To activate a column a DEMUX 74HC138 is used. The inputs A,B,C of DEMUX get a binary code of the column to activate. The causes one of the outputs get low and open the corresponding MOSFET. The column code is loaded to LED via PORTC. The resistors at its outputs provide 25mA through each dot, resulting in a very bright display even under a bright light.
The clock can be powered form a 9V DC. The board is designed for SMD components excluding buttons and LED. It is designed with Eagle software. The grid pitch on the picture is 0.05" (1.27mm) There are several wire bridges shown in a blue color. The 5-pin connector on the left photo above was used for programming and is removed from the final design.
Parts list: | |||
PART | QTY | PRICE | DESCRIPTION |
---|---|---|---|
LTP14158 | 1 | 1.75 | LED 5x8 matrix display |
ECX-39 | 1 | 0.96 | crystal 32,768 KHz |
PIC16F684 | 1 | 1.23 | microcontroller |
FDC6312P | 4 | 4x 0.34 | P-Channel MOSFET |
SN74HC138 | 1 | 0.50 | 3:8 demultiplexor |
The embedded software besides of configurating code consists of two parts: ISR and the main loop. The entire code is written in assembly language and formatted for compilation under MPLAB IDE. The ISR is called every second and increments the seconds counter. If needed, the minutes and hours counters are updated respectively. The new values of counters will be then used in the main loop to display time. Time values are stored in BCD representation in 6 variables, corresponding to tens and units of hours, minutes, and seconds. This way no conversion is needed for displaying them in binary.
ORG 4 ; ISR is called every second movwf w_save ; save Wreg swapf STATUS, w ; save stat reg without movwf stat_save ; changing flags movlw 128 ; set next timer interrupt event movwf TMR1H ; 1 sec apart incf s2, f ; increment units of seconds movlw 6 addwf s2, w btfss STATUS, DC ; is unit(seconds) < 10 ? goto ISR_end ; YES - return from INT clrf s2 ; clear the lower digit of seconds incf s1, f ; increment tens of seconds movlw 10 addwf s1, w btfss STATUS, DC ; check if seconds = 60 goto ISR_end ; NO - return clrf s1 ; reset seconds incf m2, f ; increment units of minutes movlw 6 addwf m2, w btfss STATUS, DC ; is units(minutes) < 10 ? goto ISR_end ; YES - return clrf m2 incf m1, f ; increment tens of minutes movlw 10 addwf m1, w btfss STATUS, DC ; check if minutes = 60 goto ISR_end ; NO - return clrf m1 ; reset minutes incf h2, f ; increment units of hours movlw 12 addwf h2, w btfss STATUS, DC ; is units(minutes) = 4 ? goto not24 ; NO - proceed to process hours btfss h1, 1 ; is h1=2, so hours = 24 ? goto not24 ; NO - proceed clrf h1 clrf h2 goto ISR_end not24 movlw 6 addwf h2, w btfss STATUS, DC ; if units(hours) < 10 ? goto ISR_end ; YES - return clrf h2 incf h1, f ; increment tens of hours ISR_end bcf PIR1, TMR1IF ; clear interrupt flag swapf stat_save, w ; get original flags in STATUS movwf STATUS swapf w_save, f ; restore Wreg swapf w_save, w retfie |
The main loop performs two tasks. The first task is to activate column by column by updating PORTA and load the corresponding binary value to PORTC for displaying. After loading a new column value the PIC executes a 3msec delay loop. This way all 6 display columns are updated in 18msec, which corresponds to 55Hz display refresh rate. This value can be easily increased to 83Hz by loading 2 into the variable delayCnt within the colDelay routine.
The second task of the mail loop is to check the buttons stati after refreshing the display. The debouncing routine integrated into this part of code provides a reliable reading of the button stati.
loop ; column display loop clrf colNo ; start with column 1 movlw 0x1F iorwf PORTC, f ; clear display column movf h1, w ; pass tens of hours movwf display call displayColumn movlw 0x1F iorwf PORTC, f ; clear display movf h2, w ; pass units of hours movwf display call displayColumn incf colNo, f ; skip column separator movlw 0x1F iorwf PORTC, f ; clear display column movf m1, w ; pass tens of minutes movwf display call displayColumn movlw 0x1F iorwf PORTC, f ; clear display movf m2, w ; pass units of minutes movwf display call displayColumn incf colNo, f ; skip column separator movlw 0x1F iorwf PORTC, f ; clear display column movf s1, w ; pass tens of seconds movwf display call displayColumn movlw 0x1F iorwf PORTC, f ; clear display movf s2, w ; pass units of seconds movwf display call displayColumn ; checking the button status and debouncing btfsc PORTC, 5 ; check the H button status goto hOff ; not pressed incf debounceHon, f ; update button on state counter movlw debounce subwf debounceHon, w btfss STATUS, C ; was H button ON for debounce times? goto checkMbut ; NO - check the other button clrf debounceHon clrf debounceHoff call incHours ; YES - update hours goto checkMbut hOff incf debounceHoff, f ; update button off state counter movlw debounce subwf debounceHoff, w btfss STATUS, C ; was H button OFF for debounce times ? goto checkMbut ; NO - check the other button clrf debounceHon ; YES - confirm its state clrf debounceHoff checkMbut btfsc PORTA, 3 ; check the M button status goto mOff ; not pressed incf debounceMon, f ; update button on state counter movlw debounce subwf debounceMon, w btfss STATUS, C ; was M button ON for debounce times? goto loop ; NO - proceed clrf debounceMon clrf debounceMoff call incMinutes ; YES - update minutes goto loop mOff incf debounceMoff, f ; update button off state counter movlw debounce subwf debounceMoff, w btfss STATUS C ; was M button OFF for debounce times ? goto loop ; NO - proceed clrf debounceMon ; YES - confirm its state clrf debounceMoff goto loop |
Last modified:Mon, Jan 23, 2023.