SegTemperature

This little program shows how you can display the current temperature 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. The DS18B20 was connected to PORTE.2. The OneWire (OW) routines are bit banged, so can be a little sensitive to timing when an interrupt fires.

Program Code

Device = 18F452
Clock = 20

// import modules...
#option OW_PIN = PORTE.2
Include "DS18B20.bas"
Include "convert.bas"
include "utils.bas"

// 7 segment display constants (0..9, degree sym and C) and TMR1 reload constant...
Const Segment() As Byte = ($3F, $06, $5B, $4F, $66, $6D, $7D, $07, $7F, $67, $39, $63) 
Const 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 Word,
   SegState As Byte,
   TempA As ShortInt,
   TempB 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.Byte1
      ElseIf SegState.2 = 1 Then
         Index = SegValue.Byte0
      ElseIf SegState.1 = 1 Then
         Index = 11
      ElseIf SegState.0 = 1 Then
         Index = 10
      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 byte 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 Byte)
   Disable(OnUpdate)
   SegValue.Byte0 = pValue Mod 10
   SegValue.Byte1 = pValue / 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...
   SegValue = 0
   SegState = $08 
End Sub

// program start...
Initialize
SetAllDigital     

// the Find() routine using lots of bit banging, so don't enable
// interrupts until the 18B20 has been found. A call to Display()
// will enable the OnUpdate() interrupt...
If Find Then
   SetResolution(cr10bit)
   While true
      Convert
      GetTemp(TempA, TempB)
      Display(TempA)
   Wend
EndIf