'******************************************************************************' PIC16F84A ALARM CLOCK'******************************************************************************'' feel free to use this code at your own risks'' target : PIC16F84A, 16 Mhz crystal' HS clock, no watchdog.'' Author : Bruno Gavand, September 2007' see more details on http://www.micro-examples.com/''******************************************************************************program alarmClock'' if you are using COMMON CATHODE LED display, uncomment this definition.' if you are using COMMON ANODE LED display, comment this definition.''#define CATHODE_COMMUNEsymbol LUNDI = 0 ' mondaysymbol MARDI = 1 ' thuesdaysymbol MERCREDI = 2 ' wednesdaysymbol JEUDI = 3 ' thursdaysymbol VENDREDI = 4 ' fridaysymbol SAMEDI = 5 ' saturdaysymbol DIMANCHE = 6 ' sundaysymbol LMMJV = 7 ' from monday to friday included'' alarm definitions, to be changed on your needs'symbol NBALARM = 16 ' number of programmed alarmsconst alarmTable as byte[NBALARM * 4] = (' JOUR HEURE MINUTE DUREE (secondes, 59 maxi)' DAY HOUR MINUTE DURATION (in seconds, max is 59) LUNDI, 8, 30, 10, LUNDI, 12, 30, 10, LUNDI, 14, 00, 10, LUNDI, 16, 30, 10, MARDI, 8, 30, 10, MARDI, 12, 30, 10, MARDI, 14, 00, 10, MARDI, 16, 30, 10, JEUDI, 8, 30, 10, JEUDI, 12, 30, 10, JEUDI, 14, 00, 10, JEUDI, 16, 30, 10, VENDREDI, 8, 30, 10, VENDREDI, 12, 30, 10, VENDREDI, 14, 00, 10, VENDREDI, 16, 30, 10 )dim maxcount as word ' number of TMR0 overflow per seconddim scaler as word ' RTC scalerdim jj as byte ' day of week, 0 is mondaydim hh as byte ' hourdim mn as byte ' mindim ss as byte ' secdim digiled as byte[4] ' 4 x 7 segment tabledim digit as byte ' number of current digit to be displayeddim dp as byte ' decimal pointdim key as byte ' key codedim alarm as byte ' alarm flag'' the ISR works as real time clock'sub procedure interrupt dim i as byte'' count time' scaler = scaler + 1 if scaler > maxcount then scaler = 0 inc(ss) if ss = 60 then ss = 0 inc(mn) if mn = 60 then mn = 0 inc(hh) if hh = 24 then hh = 0 inc(jj) if jj = 8 then jj = 1 end if end if end if end if end if'' LED display'#ifdef CATHODE_COMMUNE PORTA = PORTA and $f0 TRISA = $0f key = PORTA TRISA = 0 PORTB = 0#else PORTA = PORTA or $0f TRISA = $0f key = PORTA key = not(key) TRISA = 0 PORTB = $ff#endif key = key and $07 digit = digit + 1 if digit > 3 then digit = 0 i = $01 else i = $01 << digit end if#ifdef CATHODE_COMMUNE PORTB = digiled[digit] PORTA = PORTA or i#else PORTB = digiled[digit] PORTB = not(PORTB) PORTA = PORTA and not(i)#endif INTCON.T0IF = 0end sub'' converts digit to 7 segment'sub function intTo7seg(dim n as byte) as byte select case n case 0 result = $3F case 1 result = $06 case 2 result = $5B case 3 result = $4F case 4 result = $66 case 5 result = $6D case 6 result = $7D case 7 result = $07 case 8 result = $7F case 9 result = $6F end selectend sub'' select a value with keys' value is pointed to by v, display char s as header, maximum value is max'sub procedure setValue(dim v as ^byte, dim s as byte, dim max as byte) digiled[0] = s digiled[1] = 0 while 1 if key.0 then inc(v^) if(v^ > max) then v^ = 0 end if end if if key.1 then if(v^ = 0) then v^ = max else dec(v^) end if end if if key.2 then Delay_ms(50) while key.2 wend Delay_ms(50) scaler = 0 ss = 0 return end if digiled[2] = intTo7seg(v^ / 10) digiled[3] = intTo7seg(v^ mod 10) delay_ms(300) wendend sub'' program entry'main: dim i as byte'' init variables' dp = 0 hh = 0 mn = 0 ss = 0 jj = 0 maxcount = 15625'' init I/O' PORTA = %00010000 TRISA = %00000000 PORTB = 0 TRISB = $00'' init interrupts' INTCON = %10100000 OPTION_REG = %11011000 Delay_ms(50)'' clock adjustment' setValue(@hh, 116, 23) setValue(@mn, 55, 59) setValue(@jj, 14, 6)'' forever loop' while true if key then'' display day and seconds (what for ? don't remember !)' digiled[0] = intTo7seg(jj) digiled[1] = 0 digiled[2] = intTo7seg(ss / 10) digiled[3] = intTo7seg(ss mod 10) else'' display hours and minutes' if hh < 10 then digiled[0] = 0 digiled[1] = intTo7seg(hh) else digiled[0] = intTo7seg(hh / 10) digiled[1] = intTo7seg(hh mod 10) end if digiled[2] = intTo7seg(mn / 10) digiled[3] = intTo7seg(mn mod 10) end if'' blinks semicolon (or decimal point)' if scaler > maxcount / 2 then dp.1 = 1 else dp.1 = 0 end if'' set decimal points' digiled[0].7 = dp.0 digiled[1].7 = dp.1 digiled[2].7 = dp.2 digiled[3].7 = dp.3'' check for alarm condition' alarm = 0 for i = 0 to (NBALARM - 1) * 4 if ((alarmTable[i] = jj) or ((alarmTable[i] = LMMJV) and (jj < SAMEDI))) and (alarmTable[i + 1] = hh) and (alarmTable[i + 2] = mn) and (alarmTable[i + 3] > ss) then inc(alarm) end if next i if alarm then'' set alarm' dp.3 = 1 PORTA.4 = 0 else'' clear alarm' dp.3 = 0 PORTA.4 = 1 end if wendend.