7Segment

This little program shows how you can display a four digit number, using four 7 segment displays. The display is updated every 1ms or so. The program was tested on an EasyPIC 5 board with the data lines on PORTD and the enable lines from PORTA.0 to PORTA.3. All you need to do to set a display value is call Display(). Display doesn't actually update the LEDs (this is done in the interrupt routine) but prepares and loads a variable which is used by the OnUpdate() interrupt routine. For example,

Display(100)  
Display(1234)

Program Code

// set device and clock...
Device = 18F452
Clock = 20

// 7 segment display constants (0..9) and TMR1 reload constant...
Const 
   Segment() As Byte = ($3F, $06, $5B, $4F, $66, $6D, $7D, $07, $7F, $67),
   ReloadTimerValue As Word = 65536 - _clock * 250

// timer registers...
Dim 
   TMR1 As TMR1L.AsWord,
   TMR1IF As PIR1.0,
   TMR1IE As PIE1.0,
   TMR1ON As T1CON.0,
   TMR1IP As IPR1.0

// program variables...
Dim 
   SegValue As LongWord,
   SegState As Byte,
   Index As Word
{
****************************************************************************
* Name    : On Update                                                      *
* Purpose : This routine triggered every 1ms to update the 7 segment       *
*         : displays                                                       *
****************************************************************************
} 
Interrupt OnUpdate()
   Dim Index As Byte

   // reload timer value and clear TMR1 flag
   TMR1 = TMR1 + ReloadTimerValue  
   TMR1IF = 0

   // context save the table pointer and decide which of the four
   // 7 segment displays we are going to update...
   Save(TABLEPTR)
      If SegState.3 = 1 Then
         Index = SegValue.Byte3
      ElseIf SegState.2 = 1 Then
         Index = SegValue.Byte2
      ElseIf SegState.1 = 1 Then
         Index = SegValue.Byte1
      ElseIf SegState.0 = 1 Then
         Index = SegValue.Byte0
      EndIf

      // update segment...
      PORTA = PORTA And $F0 Or SegState
      PORTD = Segment(Index)

      // prepare for next...
      SegState = SegState >> 1
      If SegState = 0 Then
         SegState = $08
      EndIf  
   Restore    
End Interrupt
{
****************************************************************************
* Name    : Display                                                        *
* Purpose : Display a word value to 4 seven segment displays. This routine *
*         : just prepares the number that will be displayed. The actual    *
*         : display code is in the interrupt above                         *
****************************************************************************
} 
Sub Display(pValue As Word)
   Disable(OnUpdate)
   SegValue.Byte3 = pValue / 1000
   pValue = pValue Mod 1000
   SegValue.Byte2 = pValue / 100
   pValue = pValue Mod 100
   SegValue.Byte1 = pValue / 10  
   SegValue.Byte0 = pValue Mod 10
   Enable(OnUpdate)
End Sub   
{
****************************************************************************
* Name    : Initialise                                                     *
* Purpose : Initialise the program                                         *
****************************************************************************
} 
Public Sub Initialize()

   // TMR1 setup...
   TMR1 = ReloadTimerValue
   T1CON = 0 
   TMR1IF = 0
   TMR1IE = 1
   TMR1ON = 1

   // clear port...
   PORTA = $00
   PORTD = $00

   // set ports to output...
   TRISA = $F0
   TRISD = $00  

   // set the segment update state variable
   // and then enable the interrupt...
   SegState = $08 
   Enable(OnUpdate)
End Sub

// program start...
Initialize
While true
   Index = 0
   Repeat
      Display(Index)
      Inc(Index)
      DelayMS(100)
   Until Index > 9999
Wend