Follow along with the video below to see how to install our site as a web app on your home screen.
Note: This feature may not be available in some browsers.
Which microcontroller are you using?
Always start your files at 20h so the program can be ported to another PIC chip.
You have already been shown how to multiplex two 7-segment displays so that no other chips are needed.
Don't keep going backwards all the time. PIC84's are out of date and expensive. PIC16F628A's are less than $2.00.
Here is a circuit diagram and code using very simple instructions that you be able to understand:
**broken link removed**
**broken link removed**
Here's the prototype. It took 1 hour to put together and a few hours to write the program:
**broken link removed**
;******************************************************************
; (C) K8LH 2-Digit Up/Dn Counter, Isochronous Loop Example v2 *
;******************************************************************
processor PIC16F88
include "p16f88.inc"
errorlevel -302
__CONFIG _CONFIG1, _LVP_OFF&_WDT_OFF&_INTRC_IO&_MCLR_OFF
__CONFIG _CONFIG2, _IESO_OFF & _FCMEN_OFF
number equ 0x20 ; packed BCD, 0x00..0x99
swlatch equ 0x21 ; switch state latch variable
swflags equ 0x22 ; switch flag bits
DelayHi equ 0x23 ; DelayCy() subsystem variable
#define Dn 3 ; RA3
#define Up 2 ; RA2
;******************************************************************
;
; K8LH DelayCy() subsystem macro generates four instructions
;
radix dec
clock equ 8 ; clock frequency in Megahertz
usecs equ clock/4 ; cycles/microsecond multiplier
msecs equ usecs*1000 ; cycles/millisecond multiplier
DelayCy macro delay ; 11..327690 cycle range
movlw high((delay-11)/5)+1
movwf DelayHi
movlw low ((delay-11)/5)
call uDelay-((delay-11)%5)
endm
;******************************************************************
;
; init hardware and program variables
;
org 0x000
Init
bsf STATUS,RP0 ; bank 1 |B1
movlw b'01110000' ; |B1
movwf OSCCON ; select 8-MHz INTOSC clock |B1
Stable btfss OSCCON,IOFS ; INTOSC Freq Stable bit set? |B1
goto Stable ; no, branch, else |B1
clrf ANSEL ; setup PORT A for digital I/O |B1
movlw b'00001100' ; |B1
movwf TRISA ; RA3-RA2 inputs, others outputs |B1
clrf TRISB ; portb all outputs |B1
bcf STATUS,RP0 ; bank 0 |B0
clrf PORTB ; clear portb output latches |B0
movlw b'00000001' ; digit select bits (RA1-RA0) |B0
movwf PORTA ; select the 'ones' display |B0
clrf swlatch ; clear switch state latch |B0
clrf swflags ; clear switch flags |B0
clrf number ; number = 00 |B0
;
; isochronous 8 msec program loop (62.5 Hz display refresh rate)
;
Display
clrf PORTB ; blank the display |B0
movf PORTA,W ; |B0
xorlw b'00000011' ; flip digit select bits |B0
movwf PORTA ; |B0
swapf number,W ; W = tens in right nybble |B0
btfss PORTA,1 ; 10's display? yes, skip, else |B0
movf number,W ; W = ones in right nybble |B0
call segtbl ; get segment data |B0
movwf PORTB ; display new digit |B0
Buttons
comf PORTA,W ; sample active low switches |B0
andlw b'00001100' ; on RA3 and RA2 pins |B0
xorwf swlatch,W ; changes (press or release) |B0
xorwf swlatch,F ; update switch state latch |B0
andwf swlatch,W ; filter out "new release" bits |B0
movwf swflags ; save any "new press" bits |B0
CountUp
movf number,W ; |B0
addlw 7 ; increment + bcd adjust? |B0
skpdc ; yes, skip, else |B0
addlw -6 ; increment only |B0
btfsc swflags,Up ; Up press? no, skip, else |B0
movwf number ; update 'number' |B0
movf number,W ; |B0
xorlw 0xA0 ; upper limit 99? |B0
skpnz ; no, skip, else |B0
clrf number ; reset to 00 (rollover mode) |B0 <-
CountDn
movf number,W ; lower limit 00? |B0
skpnz ; no, skip, else |B0
movlw 0xA0 ; reset to 99 (rollover mode) |B0 <-
addlw -1 ; decrement only? |B0
skpdc ; yes, skip, else |B0
addlw -6 ; decrement + bcd adjust |B0
btfsc swflags,Dn ; Dn press? no, skip, else |B0
movwf number ; update 'number' |B0
DelayCy(8*msecs-41) ; precise 8 msec loop timing |B0
goto Display ; loop |B0
;
; segment data table (caveat, non-boundary tolerant)
;
segtbl
andlw 0x0F ; strip off upper nybble |B0
addwf PCL,F ; |B0
retlw b'00111111' ; "0" -|-|F|E|D|C|B|A |B0
retlw b'00000110' ; "1" -|-|-|-|-|C|B|- |B0
retlw b'01011011' ; "2" -|G|-|E|D|-|B|A |B0
retlw b'01001111' ; "3" -|G|-|-|D|C|B|A |B0
retlw b'01100110' ; "4" -|G|F|-|-|C|B|- |B0
retlw b'01101101' ; "5" -|G|F|-|D|C|-|A |B0
retlw b'01111101' ; "6" -|G|F|E|D|C|-|A |B0
retlw b'00000111' ; "7" -|-|-|-|-|C|B|A |B0
retlw b'01111111' ; "8" -|G|F|E|D|C|B|A |B0
retlw b'01101111' ; "9" -|G|F|-|D|C|B|A |B0
;
; K8LH DelayCy() subsystem 16-bit timing subroutine
;
nop ; entry for (delay-11)%5 == 4 |B0
nop ; entry for (delay-11)%5 == 3 |B0
nop ; entry for (delay-11)%5 == 2 |B0
nop ; entry for (delay-11)%5 == 1 |B0
uDelay addlw -1 ; subtract "loop" cycle time |B0
skpc ; borrow? no, skip, else |B0
decfsz DelayHi,F ; done? yes, skip, else |B0
goto uDelay ; do another loop |B0
return ; |B0
end
I have a 16f54 PCB which includes 2 buttons, a 2-way DIL switch,
it's on ebay right now (link is on my website)
not a very good design, indeed one of my first PCBs,
but it works, good brightness, and source code for
hex up/down counter, and random numbers is included.
I could even give the source code seperately if interested (just it is explicitely customized to specific PORT bits).
I use plain 2n3904, and no resistors, one 74hc595 buffer.
yes the 16f54 does not have A/D, and also otherwise is limited, only 512 words.
PS. i do not really intend to sell large numbers of this design, it was just an experimental prototype. Indeed, i have made a new design recently.
still have a few unpopulated PCBs around.
money i made out of each PCB was $2 or $3.