16-Digits Elapsed Timer Using 7-Segment Displays
OMER YILDIZ
' June 2009 ' PIC 16F628A - 20Mhz
' This example shows how to drive 16-digits 7-Segment displays
' using 3 PIC pins only (via 74HC595)
' This example also shows DT's elapsed timer application from 1/100 second
'to 255 years (Byte variable should be good enough to hold year value !)
' This example also shows how to start/stop DT's elapsed timer application
' using RB0 Ext. Interrupt pin using DT's int routine within the same program.
' Anode segment arrangement.
EEPROM 0, [
$c0,
$F9,
$A4,
$B0,
$99,
$92,
$82,
$F8,
$80,
$90]
' Cathode segment arrangement.
EEPROM 100,[
$3F,
$06,
$5B,
$4F,
$66,
$6D,
$7D,
$07,
$7F,
$6F]
@ __config _HS_OSC & _WDT_OFF & _PWRTE_OFF & _MCLRE_OFF & _BODEN_ON & _LVP_OFF & _CP_ON & _DATA_CP_ON
PAUSE 100
DEFINE OSC
20
' Using 4Mhz osc is ok but may have some flickering
' on displays if all 16-digits are being used.
' Thus, 20Mhz osc is used in this application.
CMCON =
7 ' Disable Comps.
PAUSE 1
VRCON =
0 ' Turn off VRCON.
PAUSE 1
' RA4 Reset button, RA6-RA7 OSC.
TRISA =
%00010000
' RB0 Int. start/stop button.
TRISB =
%00000001
PORTA =
0
PORTB =
0
StStp
VAR T1CON.
0 ' Start/Stop bit. Start stop flag for Timer counter.
Digs
VAR BYTE ' Holds the common pin index for the displays.
DigLine
VAR WORD ' Common pins of the displays will be turned
'on/off by this variable via 74HC595.
Display
VAR BYTE ' Segment arrangement will be set by this variable via 74HC595.
DT
VAR Display.
7 ' Dot led on displays via 74HC595.
DTFlag
VAR BIT ' Holds the set/clear value for Dot led.
EEAdrs
VAR BYTE ' EEPROM address for anode / cathode displays are different.
'====== User changes dynamic settings here ===========
NumOfDigits
CON 16 ' How many digits are we driving?
DigTerm
CON NumOfDigits
' Add one more for coding pusposes.
' Select display type, anode or cathode?
DispType
VAR BIT ' This bit could be a jumper on a pic pin for external option.
Anode
CON 0
Cathode
CON 1
'RA0-RA3 not used.
Reset
VAR PORTA.
4 ' Reset button
'( This pin can also be used for TMR0 counter mode).
'RA5 not used.
'RA6-RA7 external Crystal.
' RB0-RB3 notused.
Dat
VAR PORTB.
4 ' 74HC595 DATA pin.
Strobe
VAR PORTB.
5 ' 74HC595 Latch pin.
'PORTB.6 '(This pin can also be used for TMR1 counter mode)
' Not used in this program.
Clk
VAR PORTB.
7 ' 74HC595 Clock pin.
PAUSE 100
INCLUDE "DT_INTS-14.bas"
INCLUDE "ReEnterPBP.bas"
; Modified Elapsed Timer Routines. This is not the same as DT's original routine.
INCLUDE "Elapsed_INTmod.bas"
ASM
INT_LIST macro ; IntSource, Label, Type, ResetFlag?
INT_Handler INT_INT, _ToggleFlag, PBP, yes
INT_Handler TMR1_INT, _ClockCount, PBP, yes
endm
INT_CREATE ; Creates the interrupt processor
ENDASM
@ INT_ENABLE INT_INT ; enable external (INT) interrupts
@ INT_ENABLE TMR1_INT ; Enable Timer 1 Interrupts
Begin:
StStp =
0 ' Make sure timer is off.
Digs =
0 ' Set the starting digit index to zero (from right to left).
' disptype = cathode ' Select a display type. I use Common Anode display.
DispType = Anode
GOSUB ResetTime
' Reset Timer.
Main:
' Reset only when Timer is not counting.
' If reset button accidentally pressed
' when the timer is ON, it won't work. Safety first! Don't smoke.
IF Reset + StStp =
0 THEN GOSUB resettime
SELECT CASE DispType
CASE Cathode
' We are driving Cathode diplay here, pull all pins high.
DigLine =
%1111111111111111
DigLine.
0[Digs] =
0 ' Leave the next digit low.
EEAdrs =
100 'Eprom address for cathode display segments
DTFlag =
1 ' Dot is set by 1 for cathode displays.
CASE Anode
' We are driving Anode diplay here, pull all pins low.
DigLine =
%0000000000000000
DigLine.
0[Digs] =
1 ' Leave the next digit high.
EEAdrs =
0 ' Eprom address for anode display segments
DTFlag =
0 ' Dot is set by 0 for anode displays.
END SELECT
' Read digit number in line, and assign segment arrangement to display variable.
READ ( (ary[Digs]) + EEAdrs),Display
'Ary[0],[1] = Milisecond Dig 0 and Dig1
'Ary[2],[3] = Second Dig 0 and Dig1
'Ary[4],[5] = Minute Dig 0 and Dig1
'Ary[6],[7] = Hour Dig 0 and Dig1
'Ary[8],[9],[10] = Day Dig 0,Dig1,Dig2
'Ary[11],[12],[13] = Years Dig 0,Dig1,Dig2
'Ary[14],[15] = None
' Turn dot ON/OFF for floating point purposes etc. Adjust as desired.
SELECT CASE Digs
CASE 2,
4,
6,
8,
11
DT = DTFlag
END SELECT
' ========== Drive the displays and the segments ===========
'Send digit index and segment arrangement at one shot.
SHIFTOUT Dat,Clk,
1,[DigLine\
16,Display\
8]
Strobe =
1 'Latch'em all.
Strobe =
0
'========Scan Frequency - Optional =======================
' Adjust the scan frequency using TMR0 interrupt.
'This way, PAUSE command is not used.
' Driving digits more then 8, does not require scan frequency;
' PIC's process time is good enough to provide a scan delay.
' IF flickering occurs on display, increase the scan frequency
' by reducing the TMR0 int time, OR use a higher osc speed.;
' TOIF = 0
' TMR0 = 0
' Delay: ' Should a RB0 interrupt or TMR1 interrupt
' occur here, we can catch it. Thus, no PAUSE.
' if TOIF = 0 then delay ' Scan delay.
Digs = Digs +
1
IF Digs = DigTerm
THEN Digs =
0
GOTO Main
'--- INT RB0 - interrupt handler, Start/Stop button pressed =>>
' Start or stop the timer. ---
ToggleFlag:
StStp = StStp ^
1 ' ON/OFF Timer.
T1CON.
1 =
0
T1CON.
3 =
0
@ INT_RETURN
END
by
Sayzer
Re: SOLVED - PIC seems to RESET unless I add a PAUSE in Mainloop
What is the duration of this reset, if it is reset?
Ioannis Today, 09:54You may add a PAUSE 1000 at the beggining of the program and see if this duration is increased. This will confirm that PIC is indeed reseting....