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: SERIN2 Receiving Wrong Data
The sending device has the typical 18F4550 USB setup and it is set to "Define OSC 48". The receiving device is set to "DEFINE OSC 16".
rsocor01 Yesterday, 19:56