;-------------------------------------------------------------------------------
;16F684
;
;24 uurs timer
;instelbaar van (hh:mm:ss) 00:00:01 tot 23:59:59
;wanneer de teller gestart wordt op '00:00:00'
;telt hij af vanaf '00:59:59'
;-------------------------------------------------------------------------------
include 16f684
pragma target clock 4_000_000 ;oscillator frequency
pragma target OSC XT ;4MHz xTal
pragma target WDT disabled ;no watchdog
pragma target MCLR internal ;reset internally
enable_digital_io() ;alle pinnen digitale IO
;LED is via voorschakelweerstand aangesloten op pin A0
alias led is pin_A0
pin_A0_direction = output
led = off
alias relais is pin_A2
pin_A2_direction = output
relais = off
alias switch is pin_A3
pin_A3_direction = input
var volatile byte ProgFlags
var volatile bit sw_vorige at ProgFlags : 0
var volatile bit sw_temp at ProgFlags : 1
var volatile bit adc_window at ProgFlags : 7
;schakelaar is laag-waar daarom uitgangspositie is high
sw_vorige = high
sw_temp = high
;trigger om nieuwe waarde in te stellen
adc_window = high
;-------------------------------------------------------------------------------
;instellingen voor de timer
;-------------------------------------------------------------------------------
include pic_data_eeprom
var volatile byte Hours
var volatile byte Minutes
var volatile byte Seconds
var volatile byte Tmp
const byte BuzzerTime = 3
var byte BuzzerTimer = BuzzerTime
procedure LoadTime is
;gegevens opgeslagen in de EEPROM om tijd te herzetten?
data_eeprom_read(0, Hours)
if(Hours > 23)then
Hours = 0
end if
data_eeprom_read(1, Minutes)
if(Minutes > 59)then
Minutes = 0
end if
data_eeprom_read(2, Seconds)
if(Seconds > 59)then
Seconds = 0
end if
end procedure
;voer procedure uit
LoadTime
;-------------------------------------------------------------------------------
;instellingen voor Timer2
;Prescaler= 16
;PostScaler = 5
;PR2 = 250 - 1 voor herlaadtijd
;Freq = 50 Hz
;Tijd = 0.02 seconden
;-------------------------------------------------------------------------------
T2CON_TOUTPS = 0b0100 ;postscaler
T2CON_T2CKPS = 0b11
PR2 = 249 ;herlaadwaarde
PIE1_TMR2IE = high ;Timer2 interrupt enable
INTCON_PEIE = high ;perifierie interrupt enable
PIR1_TMR2IF = low ;wis interrupt vlag
const byte TimerCounterReload = 50
var byte TimerCounter = TimerCounterReload
var volatile byte TimeFlags = 0
var volatile bit FlagTimePassed at TimeFlags : 0
var volatile bit Flag20msPassed at TimeFlags : 1
var volatile bit FlagBlink at TimeFlags : 2
var volatile bit FlagBlinkState at TimeFlags : 3
var volatile bit FlagClear at TimeFlags : 7
const byte BlinkTimerReload = 20
var byte BlinkTimer = BlinkTimerReload
;-------------------------------------------------------------------------------
;LCD declaratie en initialisatie
;-------------------------------------------------------------------------------
;Volgende constanten moeten gedeclareerd worden:
const byte LCD_ROWS = 1 -- 1, 2 or 4 lines
const byte LCD_CHARS = 8 -- 8, 16 or 20 chars per line
;Alisassen voor de handshake-lijnen:
alias lcd_rs is pin_c5 -- cmd/data select
alias lcd_en is pin_c4 -- trigger
pin_C5_direction = output
pin_C4_direction = output
;Aliassen voor de vier datalijnen:
alias lcd_dataport is portC_low -- 4 databits
pin_C0_direction = output
pin_C1_direction = output
pin_C2_direction = output
pin_C3_direction = output
const byte Blank[] = " "
;laad de eigenlijke bibliotheek
include lcd_hd44780_4
;en ionitialiseer het display
lcd_init() -- init the lcd controller
include print
;scherm wissen
lcd_clear_screen()
;-------------------------------------------------------------------------------
;ADC instellingen
;-------------------------------------------------------------------------------
const bit ADC_HIGH_RESOLUTION = true
const byte ADC_NVREF = 0
;de bibliotheek laden
include adc
;De ADC initialiseren
adc_init()
;en maak pen 12 (RA1/AN1) analoge ingang
set_analog_pin(1)
;-------------------------------------------------------------------------------
;INTERRUPT PROCEDURE
;-------------------------------------------------------------------------------
procedure TimerInterrupt is
pragma interrupt
if(PIR1_TMR2IF)then
PIR1_TMR2IF = low
;20ms
Flag20msPassed = true
;teller resetten?
if(FlagClear)then
FlagClear = false
TimerCounter = TimerCounterReload ;herlaad de teller
end if
;laat dit 50 keer gebeuren voor 1 seconde
TimerCounter = TimerCounter - 1
if(TimerCounter == 0)then
TimerCounter = TimerCounterReload ;herlaad de teller
FlagTimePassed = true ;tijd is verstreken
end if
;laat dit x keer gebeuren om te knipperen
BlinkTimer = BlinkTimer - 1
if(BlinkTimer == 0)then
BlinkTimer = BlinkTimerReload
FlagBlink = true
FlagBlinkState = !FlagBlinkState
end if
end if
end procedure
;-------------------------------------------------------------------------------
;status van de schakelaar
;-------------------------------------------------------------------------------
const byte STATE_NONE = 0x00
const byte STATE_HOURS = 0x01
const byte STATE_MINUTES = 0x02
const byte STATE_SECONDS = 0x03
const byte STATE_TIMER_READY = 0x10
const byte STATE_TIMER = 0x20
const byte STATE_TIMER_END = 0x40
const byte STATE_ABORT = 0x80
;initiele toestand
var volatile byte SwitchState = STATE_NONE
var byte SwitchCounter = 0
const byte MAX_TIME = 25
;-------------------------------------------------------------------------------
;procedure om te tijd weer te geven
;-------------------------------------------------------------------------------
procedure ShowTime is
;zet de tijd op het display en knipper de eventuele eenheden of de volledige
;tijd
lcd_cursor_position(0,0)
if((SwitchState == STATE_TIMER_READY) & !FlagBlinkState)then
;knipper volledig display
print_string(lcd, Blank)
lcd_write_char(":")
print_string(lcd, Blank)
lcd_write_char(":")
print_string(lcd, Blank)
else
;edit individueel
;uren / knipperen?
if(SwitchState == STATE_HOURS)then
;edit uren -> knipperen
if(FlagBlinkState)then
;toon de uren
if(Hours < 10)then
lcd_write_char("0")
end if
print_byte_dec(lcd, Hours)
else
;toon spaties
print_string(lcd, Blank)
end if
else
;uren 'gewoon' weergeven
if(Hours < 10)then
lcd_write_char("0")
end if
print_byte_dec(lcd, Hours)
end if
lcd_write_char(":")
;minuten / knipperen?
if(SwitchState == STATE_MINUTES)then
;edit minuten -> knipperen
if(FlagBlinkState)then
;toon de minuten
if(Minutes < 10)then
lcd_write_char("0")
end if
print_byte_dec(lcd, Minutes)
else
;toon spaties
print_string(lcd, Blank)
end if
else
;minuten 'gewoon' weergeven
if(Minutes < 10)then
lcd_write_char("0")
end if
print_byte_dec(lcd, Minutes)
end if
lcd_write_char(":")
;seconden / knipperen?
if(SwitchState == STATE_SECONDS)then
;edit seconden -> knipperen
if(FlagBlinkState)then
;toon de seconden
if(Seconds < 10)then
lcd_write_char("0")
end if
print_byte_dec(lcd, Seconds)
else
;toon spaties
print_string(lcd, Blank)
end if
else
;seconden 'gewoon' weergeven
if(Seconds < 10)then
lcd_write_char("0")
end if
print_byte_dec(lcd, Seconds)
end if
end if
end procedure
;tijd weergeven
ShowTime
var volatile word wOldValue = 0
function CalcADCValue (byte in Limit, byte in CurrentValue) return byte is
var volatile word wValue = 0
var volatile word wTemp = 0
var volatile byte Temp[2] at wTemp
wValue = adc_read(1)
;bereken de nieuwe waarde
wTemp = (wValue * Limit) / 1024
if(adc_window)then
;er moet een ruim verschil zijn tussen huidige en vorige meting om een
;nieuw resultaat te geven
if((wValue & 0xFF80) != (wOldValue & 0xFF80))then
adc_window = low
else
;geen ruim verschil, de vorige waarde wodt teruggekeerd
Temp[0] = CurrentValue
end if
end if
wOldValue = wValue
return Temp[0]
end function
;-------------------------------------------------------------------------------
T2CON_TMR2ON = high ;turn timer2 on;
INTCON_GIE = high ;enable interrupts
;-------------------------------------------------------------------------------
forever loop
;Lees de schakelaar en verwerk
sw_temp = switch
;debounce
_usec_delay(10)
if(sw_temp == switch)then
;stabiele toestand - ingedrukt?
if(!sw_temp)then
;toets ingedrukt - pas ingedrukt?
if(sw_temp != sw_vorige)then
;ja - start de teller
SwitchCounter = 0
sw_vorige = sw_temp
end if
else
;toets losgelaten - pas losgelaten?
if(sw_temp != sw_vorige)then
;ja - verwerk gegevens
if(SwitchCounter >= MAX_TIME)then
;GO! - ready of afbreken
if(SwitchState == STATE_TIMER_READY)then
SwitchState = STATE_NONE
adc_window = high
else
SwitchState = STATE_TIMER_READY
;sla de gegevens op
data_eeprom_write(0, Hours)
data_eeprom_write(1, Minutes)
data_eeprom_write(2, Seconds)
end if
else
if(SwitchState <= STATE_SECONDS)then
;verhoog teller - none - hours - minutes - seconds - none - ...
SwitchState = (SwitchState + 1) & STATE_SECONDS
;set de adc_window vlag - zo moet even aan de potmeter gedraaid
;worden om de huidige waarde te wijzigen
adc_window = high
;wOldValue = wValue
end if
if(SwitchState == STATE_TIMER)then
;Afbreken
SwitchState = STATE_ABORT
end if
if(SwitchState == STATE_TIMER_READY)then
;teller starten maar eerst zorgen dat de interruproutine de eerste
;seconde ook volledig telt
FlagClear = high
SwitchState = STATE_TIMER
end if
if(SwitchState == STATE_TIMER_END)then
;knipper resetten?
SwitchState = STATE_NONE
adc_window = high
end if
end if
sw_vorige = sw_temp
end if
end if
end if
;controlleer de status
if(SwitchState == STATE_NONE)then
Led = off
Relais = off
end if
;tijdseenheden alleen bewerken wanneer er een sereuze draai
;aan de potmeter werd gegeven en pas alle 20ms
if(Flag20msPassed)then
Flag20msPassed = low
;Geluid bij klikken langer aanhouden?
BuzzerTimer = BuzzerTimer - 1
if(BuzzerTimer == 0)then
BuzzerTimer = BuzzerTime
Led = off
end if
SwitchCounter = SwitchCounter + 1
if(SwitchState == STATE_HOURS)then
;0-23
Tmp = Hours
Hours = CalcADCValue(24, Tmp)
if(Tmp != Hours)then
;geef een signaal dat de instellingen veranderd zijn
BuzzerTimer = BuzzerTime
Led = on
end if
end if
if(SwitchState == STATE_MINUTES)then
;0-59
Tmp = Minutes
Minutes = CalcADCValue(24, Tmp)
if(Tmp != Minutes)then
;geef een signaal dat de instellingen veranderd zijn
BuzzerTimer = BuzzerTime
Led = on
end if
end if
if(SwitchState == STATE_SECONDS)then
;0-59
Tmp = Seconds
Seconds = CalcADCValue(24, Tmp)
if(Tmp != Seconds)then
;geef een signaal dat de instellingen veranderd zijn
BuzzerTimer = BuzzerTime
Led = on
end if
end if
end if
if(SwitchState == STATE_TIMER_READY)then
end if
if(SwitchState == STATE_TIMER)then
;start de timer
Relais = on
if(FlagTimePassed)then
;1 seconde is verstreken
FlagTimePassed = low ;wis de vlag
;Tijd aanpassen en weergeven
Seconds = Seconds - 1
if(Seconds > 59)then
Seconds = 59
Minutes = Minutes - 1
if(Minutes > 59)then
Minutes = 59
if(Hours > 0)then
Hours = Hours - 1
end if
end if
end if
end if
;volledige tijd afgelopen?
Tmp = Hours + Minutes + Seconds
if(Tmp == 0)then
SwitchState = STATE_TIMER_END
;relais af!
Relais = off
;gegevens opgeslagen in de EEPROM om tijd te herzetten?
LoadTime
end if
end if
if(SwitchState == STATE_TIMER_END)then
;geef een signaal dat de tijd verstreken is
Led = FlagBlinkState
end if
if(SwitchState == STATE_ABORT)then
;relais af!
Relais = off
;herbegin
SwitchState = STATE_NONE
end if
;display data
ShowTime
end loop
;-------------------------------------------------------------------------------