rajesh279
Junior Member level 3
Dear All,
I have implemented multiplexing method to display HH:MM:SS (Hours, Mins & Secs) on 7 segment LED. I used RTC HT1380 (Holtek) with 32768 Hz crystal.
The AT89S52 controller is running with 11.0592 MHz crystal.
The problem I am facing is : Initially it runs and perfectly matches with the Time, but slowly the seconds is running slow. say, e.g. delay of approx 20 secs in a day (comparing time with my PC).
I tried changing the multiplexing time (ISR invoke period) and also, reading of RTC registers ( periodically each second using Timer delay); but still I am getting time mismatch.
Can someone please let me know how to rectify this problem? Is it a software issue or hardware issue?
Also, a strange thing I observed; I designed and implement the same with Atmega16 controller and there I got perfectly matching time.
I am computing the RTC values in main() -> while() loop , by disabling the Timer and once the RTC calculation is over, re-enabling the Timer.
Please find the below code:
Regards,
Rsj S.
I have implemented multiplexing method to display HH:MM:SS (Hours, Mins & Secs) on 7 segment LED. I used RTC HT1380 (Holtek) with 32768 Hz crystal.
The AT89S52 controller is running with 11.0592 MHz crystal.
The problem I am facing is : Initially it runs and perfectly matches with the Time, but slowly the seconds is running slow. say, e.g. delay of approx 20 secs in a day (comparing time with my PC).
I tried changing the multiplexing time (ISR invoke period) and also, reading of RTC registers ( periodically each second using Timer delay); but still I am getting time mismatch.
Can someone please let me know how to rectify this problem? Is it a software issue or hardware issue?
Also, a strange thing I observed; I designed and implement the same with Atmega16 controller and there I got perfectly matching time.
I am computing the RTC values in main() -> while() loop , by disabling the Timer and once the RTC calculation is over, re-enabling the Timer.
Please find the below code:
Code:
#include <AT89X52.H> // Header file for IO operations
#include "intrins.h"
#define SPI_DS P2_5 //data 26
#define SPI_SH P2_3//clock-24
#define SPI_ST P2_2 //latch-23
#define DS_low() SPI_DS = 0 //Data Low
#define DS_high() SPI_DS = 1 //Data High
#define SH_CP_low() SPI_SH = 0 //Clock Low
#define SH_CP_high() SPI_SH = 1 //Clock High
#define ST_CP_low() SPI_ST = 0 //Latch Low
#define ST_CP_high() SPI_ST = 1 //Latch High
/*Positive signals on Digit */
#define COL1 4 //P0.2
#define COL2 8 //P0.3
#define COL3 16 //P0.4
#define COL4 32 //P0.5
#define COL5 64 //P0.6
#define COL6 128 //P0.7
/* main() function starts here*/
int main (void)
{
/*-----------------------------------------------
Initializing the PORTS
-----------------------------------------------*/
InitPORTS();
Initialize_RTC();
InitTimer();
while (1)
{
TR0 = 0; // Disable the Timer
rtcGetDateTime(); //calculate the RTC date/time from Holtek HT1380
TR0 = 1; //Enable the Timer
delay_1sec(); //Delay of 1 sec
}
return 0;
}
/*-------------------------------------------------------------------*/
/*Send the values to shift register*/
void DisplayClock(unsigned char timeval1, unsigned char portval)
{
unsigned char dot1=0,dot2=0;
ST_CP_low();
shiftOut(Digit[timeval1]);
P0 = 0x00; //Switch off the P0 ports ( all the columns/LED)
ST_CP_high();
Delay(1);
ST_CP_low();
P0 = portval; //Enable one column/LED at a time
}
/*Select each LED at a time and send the values*/
void Display(unsigned char disp_count)
{
tens_hrs = hours/10; //hours, minutes & seconds are calculated from RTC rtcGetDateTime() function
unit_hrs = hours%10;
tens_min = minutes/10;
unit_min = minutes%10;
tens_sec = seconds/10;
unit_sec = seconds%10;
switch(disp_count)
{
case 1:
//switch on 1st column and send tens hr
DisplayClock(tens_hrs,COL1); // COL1
break;
case 2:
//switch on 2nd column and send unit hr
DisplayClock(unit_hrs,COL2); // COL1
break;
case 3:
//switch on 3rd column and send tens min
DisplayClock(tens_min,COL3); // COL3
break;
case 4:
//switch on 4th column and send unit min
DisplayClock(unit_min,COL4); // COL4
break;
case 5:
//switch on 5th column and send tens sec
DisplayClock(tens_sec,COL5); // COL5
break;
case 6:
//switch on 6th column and send unit sec
DisplayClock(unit_sec,COL6); // COL6
break;
}
}
/*Initialize the Ports*/
void InitPORTS(void)
{
ST_CP_low(); //latch low
SH_CP_low(); //clock low
P0 = 0x00;
clock_init();
}
/*shifting data to shift register*/
void shiftOut(unsigned char val)
{
unsigned char i;
for (i = 0; i < 8; i++)
{
if ( val & (1<<i)) // LSB first
{
DS_high();
}
else
{
DS_low();
}
SH_CP_high();
Delay(10);
SH_CP_low();
}
}
/*Timer 0*/
void InitTimer(void)
{
/*Total machine cycles required to generate 9.7usec ~= 10usec delay = 9
TH0 fixed value will be 0xFF-0x09 = 0xF6;
Using TH0= 0xF6; an overflow interrupt will generate after each 9 counts.
*/
EA=0;
TMOD = 0x02;
TH0 = 0xF6;
//TL0 = 0x66;
TR0 = 1;
ET0 = 1;
EA = 1; //Enable Global interrupt
}
/*Timer 0 ISR */
void timer_0 () interrupt 1
{
prev_sec++;
if(prev_sec == 8) //0.07 ms
{
while(seg_count<6) // Select each LED one by one
{
seg_count++;
Display(seg_count);
}
seg_count=0;//reset
}
prev_sec = 0;
}
}
/*Function to provide a time delay of approx. 1 second. using Timer 1. */
void delay_1sec(void)
{
int i;
for(i=0;i<20;i++) //=20 for 1 sec
{
TL1=0xFD;
TH1=0x4B;
TR1=1;
while(TF1==0);
TR1=0;
TF1=0;
}
}
/*End of Code*/
Regards,
Rsj S.