/* ===================================================================
24-hour CLOCK with time switch (switching times stored in EEPROM)
with LCD output (HD44780) with PIC 16F84A
(training program...:)
- nothing more, because 16F84A is already FULL :)
- 16F628/819 with 2048k/228 should be better choice but
i don't have a "normal" programmer still :(
by Peter Mervart - a501@seznam.cz (petr.mervart@vslib.cz)
(original text's are in Czech, so sorry for my English :)
========================================================
- This is my first a little bigger testing program in C2C Plus - It's a Great Compiler and IDE !!!
- The code isn't quite optimized, but I am learning still... :)
- PIC16F84A<->2x16 LCD displej (EL1602A-www.hw.cz) connection shown in picture 'lcd_pic.gif'
- LCD used in 4bit (6wire) configuration
- Tested and debugged on PVK BOARD v2 from WWW.ASIX.CZ
- Programed with PGM16F84 v.1.01 http://www.volny.cz/dj_dyk/
absolutely the simpliest programmer for 16F84 - But WORK's perfect !!!
Compiled by C2C Plus 5.0.6 with Maximal Optimization
FUSES: XT,WDT=Off,PWR=Off,CP=Off
-- ALL rutines listed here are FOR FREE using --
20.6.2003
Program function:
-----------------
After Power On time is 00:00 and running, you could setting time:
1.0 TL4 down - long press (1,5s) - setting time mode (HOURS):
- TL5/TL6 decrement/increment HOURS
1.1 TL4 press again - setting time mode (MINUTES):
- TL5/TL6 decrement/increment MINUTES
1.2 TL4 press again - save new time and return to home screen
2.0 TL4 down - short press - view switching times from EEPROM:
- after 5s return to home screen
*/
#pragma CLOCK_FREQ 3276800 // 3.2768Mhz Crystal
#include "display.h" // LCD rutines By: J. Winpenny (light modified)
#include "eeprom.h" // EEPROM rutines
#include <system.h>
#define PortAConfig 01100b // configure port A ( 1 = input )
#define PortBConfig 11110000b // configure port B
#define hours 0xC1 // hours position on LCD - 2line/2cell
#define minutes 0xC4 // minutes --"--- ---"-- - 2line/5cell
#define seconds 0xC7 // seconds --"--- ---"-- 2line/8cell (default seconds are off)
#define sp1 0xC3 // ':' between hours and minutes
#define sp2 0xC6 // ':' between minutes and seconds (default seconds are off)
#define TL4 4 // Button on RB4
#define TL5 5 // Button on RB5
#define TL6 6 // Button on RB6
#define OUT 4 // switching output on RA04
// variables
char timer@0x11,timer1@0x12,timer2@0x13,timer3@0x14; // all timers
char hod@0x15,min@0x16,sek@0x17; // time variables
char old_hod@0x20,old_min@0x21,old_sek@0x22;
char flag@0x35,set@0x18,state@0x19; // flags for buttons,clock
char hod_ON@0x30,min_ON@0x31,hod_OFF@0x32,min_OFF@0x33; // for loading from EEPROM
/* Name: Varibles Adress in EEPROM:
---------------------------------------
hod_ON.........................00
min_ON.........................01
hod_OFF........................02
min_OFF........................03
*/
/////// /////// /////// /////// /////// /////// /////// /////// ///////
/////// /////// /////// /////// /////// /////// /////// /////// ///////
void interrupt(); // interrupt rutines
void time(); // calculate time
/////// /////// /////// /////// /////// /////// /////// /////// ///////
void interrupt() // every 20ms (prescaler (1:64)*256=20ms
{
clear_bit(INTCON,T0IF); // flag from RTCC overflow = 0
if (state==1) timer++; // count only if clock are running (stav=1)
if (timer==50) time(); // 1s gone?
if (set==3) // flag for EEPROM data show
{
timer3++;
if (timer3==250) set=0; //250*20=5s show on LCD: ON TIME OFF TIME, then back
}
else timer3=0;
if (input_pin_port_b(TL4)==1) { flag=1; timer1=0; } // TL4 release
//TL4 press 1x - allow time change (long press) or ON TIME OFF TIME show from EEPROM (short press)
if (input_pin_port_b(TL4)==0 && (set==0 || set==3) && flag==1)
{
timer1++;
if (timer1==6) set=3; //short press of TL4-120ms - ON TIME OFF TIME show from EEPROM
if (timer1==75) // T4 - first long press TL4-1,5s - allow time change, clock stopped(state=0)
{
flag=0; // TL4 holding down
set=1; // allowed HOURS change by TL5/TL6
state=0; // clock stopped
sek=0; // seconds = 0 (for beter time setting)
}
}
if (input_pin_port_b(TL4)==0 && set==1 && flag==1) // TL4 - second press
{ // MINUTES change(set=1)
timer1++;
if (timer1==6) // short press of TL4-120ms
{
flag=0;
set=2; // allowed MINUTES change by TL5/TL6
}
}
if (input_pin_port_b(TL4)==0 && set==2 && flag==1) // TL4 press
{
timer1++;
if (timer1==6)
{
flag=0;
set=0; // ukonceni zmeny casu
state=1; // hodiny opet bezi
timer=0;
}
}
// TL5 and TL6 release (prepare for new count -> timer2=0 )
if ((input_pin_port_b(TL5) && input_pin_port_b(TL6))==1) timer2=0;
// TL6 press ->increment HOURS (set=1) or MINUTES (set=2)
if (input_pin_port_b(TL6)==0 && (set==1 || set==2))
{
timer2++;
if (timer2==6) // TL6 press 5*20ms=100ms ?
{
timer2=0;
if (set==2) // increment MINUTES
{
min++;
if(min==60) min=0;
}
else // increment HOURS
{
hod++;
if(hod==24) hod=0;
}
}
}
// TL5 press ->decrement HOURS (set=1) or MINUTES (set=2)
if (input_pin_port_b(TL5)==0 && (set==1 || set==2))
{
timer2++;
if (timer2==6) // TL5 press 5*20ms=100ms ?
{
timer2=0;
if (set==2) // decrement MINUTES
{
if(min==0) min=60;
min--;
}
else // increment HOURS
{
if(hod==0) hod=24;
hod--;
}
}
}
}
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
void time() // run after every 1s
{
timer=0; // prepare for another count
sek++; // SECONDS increment
if(sek==60) // 60s Gone :) -> 1 MINUTES
{
sek=0; // prepare for another count
min++; // MINUTES increment
if(min==60) // 60 MINUTES Gone -> 1 HOURS
{
hod++; // HOURS increment
min=0; // prepare for another count
}
if(hod==24) // 24 HOURS Gone -> reset all
{ hod=0;min=0;sek=0; }
/*---------------------------------------------------------*/
/*---Testing real time with data from EEPROM --*/
/*---------------------------------------------------------*/
hod_ON=EEPROM_READ(0); // ON Time-HOURS
min_ON=EEPROM_READ(1); // ON Time-MINUTES
hod_OFF=EEPROM_READ(2); // OFF Time-HOURS
min_OFF=EEPROM_READ(3); // OFF Time-MINUTES
if (hod==hod_ON && min==min_ON)
{
output_low_port_a(OUT); // switch OUT to NULL (f.e. SWITCH ON something...)
}
if (hod==hod_OFF && min==min_OFF)
{
output_high_port_a(OUT); // switch OUT to HIGH (f.e. SWITCH OFF something...)
}
}
}
////------------------------------------------------------------////
//---------------------------------------------------------------//
void main()
{
set_tris_a(PortAConfig); // Setup ports
set_tris_b(PortBConfig );
output_high_port_a(OUT); // OUT in log 1
OPTION_REG=10000101b; // RTCC from Fosc/4, prescaller 1:64 (INT every 20ms)
TMR0=0;
timer=0;
timer1=0;
timer2=0;
timer3=0;
set=0; // Actual time: on LCD
state=1; // Time is running
set_bit(INTCON,GIE); // global INT enabled (GIE = 1)
enable_interrupt(T0IE); // RTCC overflow INT enable (T0IE = 1)
clear_bit(INTCON,T0IF); // RTCC INT flag reset(T0IF = 0)(interrupt yes, but not yet)
LCD_Setup(); // Initialize the LCD device
hod=0;min=0;sek=0; // reset time
old_hod=70;old_min=70;old_sek=70;
/* Here you can write switching times to EEPROM
Note: I write it to EEPROM direct from my 16f84 programer (no more profram memory :)
EEPROM_WRITE(19); // ON Time-HOURS (f.e.19:30)
EEPROM_WRITE(30); // ON Time-MINUTES
EEPROM_WRITE(6); // OFF Time-HOURS (06:30)
EEPROM_WRITE(0); // OFF Time-MINUTES
*/
while( 1 ) // main LOOP
{
if(set==3) // EEPROM (ON time-OFF time) data on LCD
{
hod_ON=EEPROM_READ(0);
min_ON=EEPROM_READ(1);
hod_OFF=EEPROM_READ(2);
min_OFF=EEPROM_READ(3);
LCD_SetPos(set_dd_line1); // set cursor position
Lprintf("ON time-OFF time"); // show string on LCD
LCD_SetPos(set_dd_line2);
LCD_Write_4_Bit(' '); // show single byte on LCD
LCD_WriteInt(hod_ON);
LCD_Write_4_Bit(':');
LCD_WriteInt(min_ON);
LCD_Write_4_Bit(' ');
LCD_Write_4_Bit('-');
LCD_Write_4_Bit(' ');
LCD_WriteInt(hod_OFF);
LCD_Write_4_Bit(':');
LCD_WriteInt(min_OFF);
old_hod=80;
old_min=80;
old_sek=80;
}
else
{
if(set==0) // defalut LCD screen -> Actual time:
{
LCD_SetPos(set_dd_line1);
Lprintf("Actual time: ");
}
if(set==1) // changing HOURS
{
LCD_SetPos(set_dd_line1);
Lprintf("HOU: -/+ TL5/TL6");
}
if(set==2) // changing MINUTES
{
LCD_SetPos(set_dd_line1);
Lprintf("MIN");
}
if (old_hod!=hod) // redraw HOURS (any change) ?
{
old_hod=hod;
LCD_SetPos(hours); // move cursor on HOURS position
LCD_WriteInt(hod);
}
else LCD_SetPos(sp1); // move cursor on ':' position: between HOURS and MINUTES
LCD_Write_4_Bit(':');
if (old_min!=min) // redraw MINUTES (any change) ?
{
old_min=min;
LCD_SetPos(minutes);
LCD_WriteInt(min);
}
else LCD_SetPos(sp2); // kurzor na pozici dvojtecky min:sec
/*
LCD_Write_4_Bit(':');
if (old_sek!=sek) // redraw MINUTES (any change) ?
{ // REM because, no more PROGRAM MEMORY in 16F84A
old_sek=sek; // if all EEMPROM operation REM,it work it :)
LCD_SetPos(seconds); // move cursor on SECONDS position: (0xC3)
LCD_WriteInt(sek);
}
*/
LCD_Write_4_Bit(' ');
LCD_Write_4_Bit(' ');
LCD_Write_4_Bit(' ');
LCD_Write_4_Bit(' ');
LCD_Write_4_Bit(' ');
LCD_Write_4_Bit(' ');
LCD_Write_4_Bit(' ');
LCD_Write_4_Bit(' ');
}
}
}
Copyright © 2002-2006 SourceBoost Technologies