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