Making 24 hour clock

Thread Starter

FroceMaster

Joined Jan 28, 2012
702
have debug it to that lcd_puts(day_of_week_names[week_day]);
even if i write 0-6 in week_day, it still wont show.
it will simply not select from the const array of Mon-sunday
happens since i wrote the other thing with utoa(timestr.........
 

t06afre

Joined May 11, 2009
5,934
have debug it to that lcd_puts(day_of_week_names[week_day]);
even if i write 0-6 in week_day, it still wont show.
it will simply not select from the const array of Mon-sunday
happens since i wrote the other thing with utoa(timestr.........
I think it is a bug in the compiler:eek: Let me see if I can come up with a workaround;
 

t06afre

Joined May 11, 2009
5,934
try this
Rich (BB code):
//lcd_puts(day_of_week_names[week_day]);
       for (unsigned char i=0;i<6;i++) lcd_putch(day_of_week_names[week_day]);
 

Thread Starter

FroceMaster

Joined Jan 28, 2012
702
try this
Rich (BB code):
//lcd_puts(day_of_week_names[week_day]);
       for (unsigned char i=0;i<6;i++) lcd_putch(day_of_week_names[week_day]);


Thanz, works great.
work some more again
will try yo add the daily counter, and use timer for it. u say i should use it, cause it's allready on the chip
 

Thread Starter

FroceMaster

Joined Jan 28, 2012
702
Should this be possible ?
Rich (BB code):
#define LED RC0
#define set_hour RC4
#define set_minute RC5
#define set_week RC6
#define set_time RC3
and later in main
Rich (BB code):
if (!set_time)
{
stil_ur();
}
it seems it allways think that the switch is pressed.
do "!set_time" not mean "LOW" on RC3 ???
 

t06afre

Joined May 11, 2009
5,934
Should this be possible ?
Rich (BB code):
#define LED RC0
#define set_hour RC4
#define set_minute RC5
#define set_week RC6
#define set_time RC3
and later in main
Rich (BB code):
if (!set_time)
{
stil_ur();
}
it seems it allways think that the switch is pressed.
do "!set_time" not mean "LOW" on RC3 ???
In my last program. I use this #define setup
Rich (BB code):
#define LED RC0
#define set_time_button RC3
#define set_hours RC4
#define set_minutes RC5
#define set_day RC6
So you are correct I think.
The "if (!set_time)" is the same as writing "if (set_time==0)" But all uber cool programmers use the first notation. Read the first one as "if not set_time"
Remember in C
Rich (BB code):
 ==      equal to    
        !=      not equal to
       >       greater than
       <       less than
       >=      greater than or equal to
       <=      less than or equal to
 

Thread Starter

FroceMaster

Joined Jan 28, 2012
702
2 error found,
1. have connected RA3 and not RC3.
2. RC3 have LED on board, and will allways be LOW,
Removed resistor for that and now works.
need to make some kind of debouncing, so that i count only once when pressed,
and need to be released before next count, or to count by 1 sec at i time, but that will then give 1 minute to set the minutes in max,,,,,
 

t06afre

Joined May 11, 2009
5,934
This is how I did it
Rich (BB code):
void set_time(void)
{
 GIE = 0;  // Global interrupt disable as we are setting the time
 TMR1ON=0;       //timer1 off
 seconds=0;
 TMR1H=0x80;
 TMR1L=0;
 LED=1;
 set_time_flag=1;
  do
   { 
    if (!set_hours)
                 {
                         hours++;
                  if (hours==24) hours=0;
                   lcd_format_and_send();
                  __delay_ms(100); 
                } 
    if (!set_minutes)
               {
      minutes++;
      if (minutes==60) minutes=0;
      lcd_format_and_send();
                   __delay_ms(100); 
               }    
    if (!set_day)
               {
      week_day++;
                  if (week_day==7) week_day=0;
                  lcd_format_and_send();
                 __delay_ms(100); 
                }    
         
    } while (!set_time_button);
 GIE = 1;  // Global interrupt enable
 TMR1ON=1;       //timer1 on
    set_time_flag=0;
}
 

Thread Starter

FroceMaster

Joined Jan 28, 2012
702
works great, have changed the delays to 200 ms, and also changed this
for (unsigned char i=0;i<7;i++) lcd_putch(day_of_week_names[week_day]);
u have wrote 6 char, but 2 days have 7 char, so i changed to 7.

is it difficult to write and read from EEProm ?
 

Thread Starter

FroceMaster

Joined Jan 28, 2012
702
Rich (BB code):
///*// Config Register: CONFIG
//#define CONFIG 0x2007
//// Oscillator Selection bits
//// RC oscillator: CLKOUT function on RA4/OSC2/CLKOUT pin, RC on RA5/OSC1/CLKIN
//#define FOSC_EXTRCCLK 0xFFFF
//// RCIO oscillator: I/O function on RA4/OSC2/CLKOUT pin, RC on RA5/OSC1/CLKIN
//#define FOSC_EXTRCIO 0xFFFE
//// INTOSC oscillator: CLKOUT function on RA4/OSC2/CLKOUT pin, I/O function on RA5/OSC1/CLKIN
//#define FOSC_INTRCCLK 0xFFFD
//// INTOSCIO oscillator: I/O function on RA4/OSC2/CLKOUT pin, I/O function on RA5/OSC1/CLKIN
//#define FOSC_INTRCIO 0xFFFC
//// EC: I/O function on RA4/OSC2/CLKOUT pin, CLKIN on RA5/OSC1/CLKIN
//#define FOSC_EC 0xFFFB
//// HS oscillator: High-speed crystal/resonator on RA4/OSC2/CLKOUT and RA5/OSC1/CLKIN
//#define FOSC_HS 0xFFFA
//// XT oscillator: Crystal/resonator on RA4/OSC2/CLKOUT and RA5/OSC1/CLKIN
//#define FOSC_XT 0xFFF9
//// LP oscillator: Low-power crystal on RA4/OSC2/CLKOUT and RA5/OSC1/CLKIN
//#define FOSC_LP 0xFFF8
//// Watchdog Timer Enable bit
//// WDT enabled
//#define WDTE_ON 0xFFFF
//// WDT disabled and can be enabled by SWDTEN bit of the WDTCON register
//#define WDTE_OFF 0xFFF7
//// Power-up Timer Enable bit
//// PWRT disabled
//#define PWRTE_OFF 0xFFFF
//// PWRT enabled
//#define PWRTE_ON 0xFFEF
//// MCLR Pin Function Select bit
//// MCLR pin function is MCLR
//#define MCLRE_ON 0xFFFF
//// MCLR pin function is digital input, MCLR internally tied to VDD
//#define MCLRE_OFF 0xFFDF
//// Code Protection bit
//// Program memory code protection is disabled
//#define CP_OFF 0xFFFF
//// Program memory code protection is enabled
//#define CP_ON 0xFFBF
//// Data Code Protection bit
//// Data memory code protection is disabled
//#define CPD_OFF 0xFFFF
//// Data memory code protection is enabled
//#define CPD_ON 0xFF7F
//// Brown-out Reset Selection bits
//// BOR enabled
//#define BOREN_ON 0xFFFF
//// BOR enabled during operation and disabled in Sleep
//#define BOREN_NSLEEP 0xFEFF
//// BOR controlled by SBOREN bit of the PCON register
//#define BOREN_SBODEN 0xFDFF
//// BOR disabled
//#define BOREN_OFF 0xFCFF
//// Internal External Switchover bit
//// Internal External Switchover mode is enabled
//#define IESO_ON 0xFFFF
//// Internal External Switchover mode is disabled
//#define IESO_OFF 0xFBFF
//// Fail-Safe Clock Monitor Enabled bit
//// Fail-Safe Clock Monitor is enabled
//#define FCMEN_ON 0xFFFF
//// Fail-Safe Clock Monitor is disabled
//#define FCMEN_OFF 0xF7FF*/
#include <htc.h>
//#include <stdio.h>
#include <stdlib.h>
#include "lcd.h"
__CONFIG (FCMEN_ON & IESO_OFF & BOREN_OFF & CPD_OFF & CP_OFF & MCLRE_OFF & PWRTE_ON & WDTE_OFF & FOSC_INTRCIO);
#define LED RC0
#define set_hour RC4
#define set_minut RC5
#define set_week RC6
#define set_time RC3
#define _XTAL_FREQ 4000000
//global defs
volatile unsigned char week_day;
volatile unsigned char hour, minut, sec;
volatile bit timer_tick, minut_tick, set_time_flag;
volatile bit blink;
const char * const day_of_week_names[] = {"Mandag ",
"Tirsdag",
"Onsdag ",
"Torsdag",
"Fredag ",
"Lordag ",
"Sondag " 
};
 
char timestr[3];
static void interrupt
isr(void) // Here is interrupt function - the name is unimportant.
{
if(TMR1IF) 
{// Was this a timer overflow?
TMR1IF=0;//Clear interrupt flag, ready for next
TMR1H=0x80;
//If we set TMR1 to start at 0x8000 (32768), the TMR1 will overflow every 1 second
timer_tick=1;
blink=!blink;
LED=blink; 
 
sec++;
if (sec==1)
{
minut_tick=1;
sec=0;
}
}//we are done here
}
void setup(void)
{ TRISA0=0;
TRISC=0b01111000;//RC0-RC2 out,RC3-RC6 in,RC7 out
TRISB=0; //All port B output
GIE = 0; // Global interrupt disable just in case
ANSEL=0;
ANSELH=0;//turn off all analog functions
//timer1 settings
TMR1H=0x80;
TMR1L=0;
//T1CON=0b00000110;//used during debug
T1CON=0b00001110;
// See datasheet REGISTER 6-1: T1CON: TIMER 1 CONTROL REGISTER
// bit order T1GINV TMR1GE T1CKPS1 T1CKPS0 T1OSCEN !T1SYNC TMR1CS TMR1ON
//Timer1 Interrupt prepare
TMR1IE=1;// PIE1 register
PEIE=1; //INTCON register
PIR1=0; // Clear all bits PERIPHERAL INTERRUPT REQUEST REGISTER 1
//todo now in order to generate interrupt GEI=1 and TMR1ON=1
//setup LCD
lcd_init();
lcd_goto(0); // select first line
//set the globals
week_day=5;
minut=7;
sec=0;
hour=23;
timer_tick=0;
blink=0;
//other misc settings
timer_tick=0;//clear the tick
}
void lcd_format_and_send(void)
{ 
lcd_goto(0x08);
utoa(timestr, hour, 10);
if (hour<10)lcd_puts("0");
lcd_puts(timestr);
lcd_puts(":");
utoa(timestr, minut, 10);
if (minut<10)lcd_puts("0");
lcd_puts(timestr);
lcd_goto(0x47); // Select second line
 
for (unsigned char i=0;i<7;i++) lcd_putch(day_of_week_names[week_day]);
lcd_goto(0x00); 
 
}
 
void midnat (void)
{
week_day++;
if (week_day==7) week_day=0;
}
void ur (void)
{
 
minut++;
if (minut>=60)
{ minut=0;
hour++;
if (hour>=24)
{ hour=0;
 
midnat();
}
}
lcd_format_and_send();
}
void stil_ur (void)
{
GIE = 0; // Global interrupt disable as we are setting the time
TMR1ON=0; //timer1 off
sec=0;
TMR1H=0x80;
TMR1L=0;
LED=1;
set_time_flag=1;
do
{ 
if (!set_hour)
{
hour++;
if (hour==24) hour=0;
lcd_format_and_send();
__delay_ms(200); 
} 
if (!set_minut)
{
minut++;
if (minut==60) minut=0;
lcd_format_and_send();
__delay_ms(200); 
} 
if (!set_week)
{
week_day++;
if (week_day==7) week_day=0;
lcd_format_and_send();
__delay_ms(200); 
} 
 
} while (!set_time);
GIE = 1; // Global interrupt enable
TMR1ON=1; //timer1 on
set_time_flag=0;
}
 
void main (void) 
{ setup();
timestr[2]='\0';
ur();
GIE=1;
TMR1ON=1;
while (1)
{
if (minut_tick)
{ 
ur();
minut_tick=0; 
} // end if (minut_tick)
if (!set_time)
{
stil_ur();
}
// flere hvis.....
} //end while endless loop
}//End main
 

t06afre

Joined May 11, 2009
5,934
Your clock is bit on the fast side. But other than that it works Here is my. It may need some cleaning up. As it still has some code in the comments.
Rich (BB code):
///*// Config Register: CONFIG
//#define CONFIG               0x2007
//// Oscillator Selection bits
//// RC oscillator: CLKOUT function on RA4/OSC2/CLKOUT pin, RC on RA5/OSC1/CLKIN
//#define FOSC_EXTRCCLK        0xFFFF
//// RCIO oscillator: I/O function on RA4/OSC2/CLKOUT pin, RC on RA5/OSC1/CLKIN
//#define FOSC_EXTRCIO         0xFFFE
//// INTOSC oscillator: CLKOUT function on RA4/OSC2/CLKOUT pin, I/O function on RA5/OSC1/CLKIN
//#define FOSC_INTRCCLK        0xFFFD
//// INTOSCIO oscillator: I/O function on RA4/OSC2/CLKOUT pin, I/O function on RA5/OSC1/CLKIN
//#define FOSC_INTRCIO         0xFFFC
//// EC: I/O function on RA4/OSC2/CLKOUT pin, CLKIN on RA5/OSC1/CLKIN
//#define FOSC_EC              0xFFFB
//// HS oscillator: High-speed crystal/resonator on RA4/OSC2/CLKOUT and RA5/OSC1/CLKIN
//#define FOSC_HS              0xFFFA
//// XT oscillator: Crystal/resonator on RA4/OSC2/CLKOUT and RA5/OSC1/CLKIN
//#define FOSC_XT              0xFFF9
//// LP oscillator: Low-power crystal on RA4/OSC2/CLKOUT and RA5/OSC1/CLKIN
//#define FOSC_LP              0xFFF8
//// Watchdog Timer Enable bit
//// WDT enabled
//#define WDTE_ON              0xFFFF
//// WDT disabled and can be enabled by SWDTEN bit of the WDTCON register
//#define WDTE_OFF             0xFFF7
//// Power-up Timer Enable bit
//// PWRT disabled
//#define PWRTE_OFF            0xFFFF
//// PWRT enabled
//#define PWRTE_ON             0xFFEF
//// MCLR Pin Function Select bit
//// MCLR pin function is MCLR
//#define MCLRE_ON             0xFFFF
//// MCLR pin function is digital input, MCLR internally tied to VDD
//#define MCLRE_OFF            0xFFDF
//// Code Protection bit
//// Program memory code protection is disabled
//#define CP_OFF               0xFFFF
//// Program memory code protection is enabled
//#define CP_ON                0xFFBF
//// Data Code Protection bit
//// Data memory code protection is disabled
//#define CPD_OFF              0xFFFF
//// Data memory code protection is enabled
//#define CPD_ON               0xFF7F
//// Brown-out Reset Selection bits
//// BOR enabled
//#define BOREN_ON             0xFFFF
//// BOR enabled during operation and disabled in Sleep
//#define BOREN_NSLEEP         0xFEFF
//// BOR controlled by SBOREN bit of the PCON register
//#define BOREN_SBODEN         0xFDFF
//// BOR disabled
//#define BOREN_OFF            0xFCFF
//// Internal External Switchover bit
//// Internal External Switchover mode is enabled
//#define IESO_ON              0xFFFF
//// Internal External Switchover mode is disabled
//#define IESO_OFF             0xFBFF
//// Fail-Safe Clock Monitor Enabled bit
//// Fail-Safe Clock Monitor is enabled
//#define FCMEN_ON             0xFFFF
//// Fail-Safe Clock Monitor is disabled
//#define FCMEN_OFF            0xF7FF*/
#include <htc.h>
//#include <stdio.h>
#include <stdlib.h>
#include "lcd.h"
__CONFIG (FCMEN_ON & IESO_OFF & BOREN_OFF & CPD_OFF & CP_OFF & MCLRE_OFF & PWRTE_ON & WDTE_OFF & FOSC_INTRCIO);
#define LED RC0
#define set_time_button RC3
#define set_hours RC4
#define set_minutes RC5
#define set_day RC6
#define _XTAL_FREQ  4000000
//global defs
//char ascii_time[9];
unsigned char seconds;
unsigned char minutes;
unsigned char hours;
volatile unsigned char week_day;
bit timer_tick;
bit blink;
bit new_day_flag;
bit set_time_flag;
const char * const day_of_week_names[] = {"Monday feels so bad",
                                          "Tuesday feel better",
                                          "Wednesday don't go ",
                                          "Thursday goes slow ",
                                          "Friday on my mind  ",
                                          "Saturday Night Live",
                 "Sunday be sporty   " 
                                         };
//const char * const day_of_week_names[] = {"Monday   ",
//                                          "Tuesday  ",
//                                          "Wednesday",
//                                          "Thursday ",
//                                          "Friday   ",
//                                          "Saturday ",
//               "Sunday   " 
//                                         };
//union { 
//   double data;
//  char b[4];
//}lcd;
static void interrupt
isr(void)   // Here is interrupt function - the name is
    // unimportant.
{
 if(TMR1IF) 
  {// Was this a timer overflow?
      TMR1IF=0;//Clear interrupt flag, ready for next
   TMR1H=0x80;
//If we set TMR1 to start at 0x8000 (32768), the TMR1 will overflow every 1 second
     timer_tick=1;
  }//we are done here
}
void setup(void)
{   set_time_flag=0;
    TRISA0=0;
    TRISC=0b01111000;//RC0-RC2 out,RC3-RC6 in,RC7 out
    TRISB=0; //All port B output
 GIE = 0;  // Global interrupt disable just in case
 ANSEL=0;
 ANSELH=0;//turn off all analog functions
//timer1 settings
 TMR1H=0x80;
 TMR1L=0;
 T1CON=0b00000110;//used during debug
    //T1CON=0b00001110;
 // See datasheet REGISTER 6-1: T1CON: TIMER 1 CONTROL REGISTER
 // bit order T1GINV TMR1GE T1CKPS1 T1CKPS0 T1OSCEN !T1SYNC TMR1CS TMR1ON
  //Timer1 Interrupt prepare
   TMR1IE=1;// PIE1 register
   PEIE=1; //INTCON register
   PIR1=0; // Clear all bits PERIPHERAL INTERRUPT REQUEST REGISTER 1
   //todo now in order to generate interrupt GEI=1 and TMR1ON=1
 //setup LCD
    lcd_init();
 lcd_goto(0); // select first line
 //set the globals
     seconds=0;
     minutes=0;
     hours=0;
     week_day=4;
     timer_tick=0;
     blink=0;
     new_day_flag=0;
     set_time_flag=0;
      //other misc settings
//      timer_tick=0;//clear the tick
//      ascii_time[2]=58;
//      ascii_time[5]=58; // ascii 58=':"
//      ascii_time[8]=0;
}
void lcd_format_and_send(void)
{ //format the LCD string
 char ascii_time[3];
    ascii_time[2]=0;//null 
 utoa(ascii_time, hours, 10);
     if (hours<10) lcd_putch(48);// pad zero ascii 48='0'
          
 lcd_puts(ascii_time); //write the ascii_time string to LCD (hours)
    lcd_putch(58);// ascii 58=':'
    utoa(&ascii_time, minutes, 10);
          if (minutes<10) lcd_putch(48);// pad zero ascii 48='0' 
   lcd_puts(ascii_time);//write the ascii_time string to LCD (minutes)
   lcd_putch(58);// ascii 58=':'
  utoa(&ascii_time, seconds, 10);
           if (seconds<10) lcd_putch(48);// pad zero ascii 48='0'
lcd_puts(ascii_time);//write the ascii_time string to LCD (seconds)
//    ascii_time[2]=58;
//    ascii_time[5]=58; // ascii 58=':'
//    ascii_time[8]; 
//  //write the ascii_time string to LCD
//         lcd_puts(ascii_time);
   lcd_goto(0x40); // Select second line
         //if (set_time_flag) lcd_puts("Setting the time");
         //lcd_puts("day of week ");
         //lcd_putch(week_day+48);
         //lcd_puts(day_of_week_names[week_day]);
         for (unsigned char i=0;i<19;i++) lcd_putch(day_of_week_names[week_day]);
         lcd_goto(0x00);
}
void set_time(void)
{
 GIE = 0;  // Global interrupt disable as we are setting the time
 TMR1ON=0;       //timer1 off
 seconds=0;
 TMR1H=0x80;
 TMR1L=0;
 LED=1;
 set_time_flag=1;
  do
   { 
    if (!set_hours)
                 {
                         hours++;
                  if (hours==24) hours=0;
                   lcd_format_and_send();
                  __delay_ms(100); 
                } 
    if (!set_minutes)
               {
      minutes++;
      if (minutes==60) minutes=0;
      lcd_format_and_send();
                   __delay_ms(100); 
               }    
    if (!set_day)
               {
      week_day++;
                  if (week_day==7) week_day=0;
                  lcd_format_and_send();
                 __delay_ms(100); 
                }    
         
    } while (!set_time_button);
 GIE = 1;  // Global interrupt enable
 TMR1ON=1;       //timer1 on
    set_time_flag=0;
}
void main (void) 
{ 
 setup();
    GIE=1;
 TMR1ON=1;
  while (1)
        {
         if (timer_tick)
            {
              blink=(!blink);//just to show
              LED=blink;//   we are alive
              timer_tick=0;
              seconds++;
      if (seconds==60)
                 {
       seconds=0;
       minutes++;
                     if (minutes==60)
                         {
          minutes=0;
            hours++;
          if (hours==24)
                            {
            week_day++;
                      if (week_day==7) week_day=0;
            hours=0;
                             }  
          }//end if minutes=60 
                            }//end if (seconds==60)
              lcd_format_and_send();//send time to LCD
             }// end if (timer_tick) Memo to my self put all this in sub function           
               if (!set_time_button) set_time();
  }//end while endless loop
 }//End main     
 

Thread Starter

FroceMaster

Joined Jan 28, 2012
702
more to construct, would like to just use 4 switches, for it all,
reason, want to use a keypad or something, cause it should look fancy,
timer0 can run as the counter for rain.
should be any problem i think, only 1 switch is monitored normal, and set_hour and set_minute and set_day could be use to ex reset of total, and selecting rain from days before.
 

t06afre

Joined May 11, 2009
5,934
more to construct, would like to just use 4 switches, for it all,
reason, want to use a keypad or something, cause it should look fancy,
timer0 can run as the counter for rain.
should be any problem i think, only 1 switch is monitored normal, and set_hour and set_minute and set_day could be use to ex reset of total, and selecting rain from days before.
I think you can do with 4 switches. If you modify your time setting function. like this set hour->set minute->set day of week. Else you may need 5 buttons. As for timer0. Just go for it. I will help if you need that. Start with the datasheet and find out which register you must use. Then try to code that.
By the way the LCD of your kind assume info is ASCII code then then written to. They are quite simple but versatile for most micro projects
 

Thread Starter

FroceMaster

Joined Jan 28, 2012
702
If i use timer0, i will need to understand some things.
can i read out the value before interrupt ?
do i set it to caount with prescaller 1:2 or 1:256 ?
 

Thread Starter

FroceMaster

Joined Jan 28, 2012
702
i think this is the answer, but i do not work
this in the setup...

Rich (BB code):
 INTCON=0b10100111;
    TMR0=1;
T0IE=1;
GIE=1;
and this in the interrupt .

Rich (BB code):
static void interrupt
isr(void)   // Here is interrupt function - the name is unimportant.
   {
 if(TMR1IF) 
  {// Was this a timer overflow?
      TMR1IF=0;//Clear interrupt flag, ready for next
   TMR1H=0x80;
        //If we set TMR1 to start at 0x8000 (32768), the TMR1 will overflow every 1 second
     timer_tick=1;
 blink=!blink;
           LED=blink; 
          
  sec++;
  if (sec==60)
 {
 minut_tick=1;
sec=0;
}
  }//we are done here
if(T0IF)
{
T0IF=0;
regn_tick=1;
}
 }
 

t06afre

Joined May 11, 2009
5,934
I was thinking more in the path of using timer0 as counter. So every that every pulse from the rain meter. Would case the to counter increment. As a start at least. In the beginning we may not use any interrupt on timer0. Remember the KISS rule ;)
 
Top