clock.c

24-hour clock with switching times stored in EEPROM and LCD output (HD44780) for PIC16F84A (by Petr Mervart).



/*        ===================================================================
            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(' ');

       }
   }

}



http://www.sourceboost.com/home.html

Copyright © 2002-2006 SourceBoost Technologies