 |
 |
| View previous topic :: View next topic |
| Author |
Message |
ktallevi
Joined: 17 Dec 2005 Posts: 58
|
|
Posted: Thu Jul 22, 2010 6:24 pm |
|
|
Has anyone modified this to count milliseconds as well?
thanks |
|
 |
princejude
Joined: 07 Aug 2010 Posts: 4
|
|
Posted: Wed Aug 11, 2010 7:08 am |
|
|
Hello everyone, I am a student and new in CCS and C language in general. I have worked with PIC MCUs using ASSEMBLY LANGUAGE. My School project is to design and construct a DIGITAL CLOCK using PIC MCU. I modified (Mr/Engr...) ckielstra's"Timer based Real Time Clock (RTC)" code posted since Tue Feb 28, 2006 shown below to get a digital clock. The digital clock worked on proteus but the problem I have is that the first three digits are flashing ON and OFF(though there timing is correct). It is only the last digit that is permanent ON.
PLSSSSS how will I make the four digits to be ON instead of flashing ?
I will also be happy if anyone can give me materials or links on how to learn CCS (PIC C).
Here is the code posted by ckielstra
| Code: |
///////////////////////////////////////////////////////////
// Zero Drift Real Time Clock
// Original code supplied by Neutone.
// Some small optimizations by C.Kielstra.
///////////////////////////////////////////////////////////
#include <18F458.h>
#use delay(clock=20000000)
#fuses HS,NOWDT,NOLVP
//RTC variables
#define XTAL_FREQUENCY 20000000
#define TIMER1_FREQUENCY (XTAL_FREQUENCY / 4) // 1 clock tick = 1 instr. cycle = crystal frequency / 4
int32 Ticker;
int8 Seconds=0;
//optional:
// int8 Year=0,Month=0,Days=0,Hours=0,Minutes=0;
////////////////////////////////////////////////////////////////////////////////
// Test whether a given year is a leap year.
// This optimized version only works for the period 2001 - 2099
////////////////////////////////////////////////////////////////////////////////
#define IS_LEAP(year) (year%4 == 0)
////////////////////////////////////////////////////////////////////////////////
// Initialize RTC
////////////////////////////////////////////////////////////////////////////////
void Initialize_RTC(void)
{
Ticker = TIMER1_FREQUENCY; // initialize clock counter to number of clocks per second
setup_timer_1( T1_INTERNAL | T1_DIV_BY_1 ); // initialize 16-bit Timer1 to interrupt
// exactly every 65536 clock cycles
// (about 76 times per second)
enable_interrupts( INT_TIMER1 ); // Start RTC
}
////////////////////////////////////////////////////////////////////////////////
// -=Process Zero Drift Real Time Clock Information=-
//
// Most algorithms configure the timer to generate an interrupt every 100ms, and
// then count the number of interrupts. The problem in that approach is that most
// clock frequencies can't be divided by 256 and you don't get an exact 100ms.
// The small errors will add up to an error of several seconds a day.
//
// The algorithm presented here is exact in the long run because it doesn't
// count the number of interrupts but counts the number of clock cycles.
////////////////////////////////////////////////////////////////////////////////
#int_TIMER1
void TIMER1_isr()
{
Ticker -= 65536; // Decrement ticker by clocks per interrupt
if ( Ticker < 65536 ) // If second has expired
{ Ticker += TIMER1_FREQUENCY; // Increment ticker by clocks per second
seconds++; // Increment number of seconds
}
/* --- Optional part start ---
if(Seconds == 60) {Minutes++; Seconds=0;
if(Minutes == 60) {Hours++; Minutes=0;
if(Hours == 24) {Days++; Hours=0;
if ( (Days == 29 && Month==2 && !IS_LEAP(Year))
|| (Days == 30 && Month==2)
|| (Days == 31 && (Month==4 || Month==6 || Month==9 || Month==11 ))
|| (Days == 32)
) {Month++;Days=0;}
if(Month == 13) {Year++; Month=0;}
}}}
--- Optional part end --- */
}
////////////////////////////////////////////////////////////////////////////////
// Example program for using the RTC
////////////////////////////////////////////////////////////////////////////////
void main()
{
int8 prev_second;
Initialize_RTC();
enable_interrupts( GLOBAL );
// loop forever
while(1)
{
// Toggle output every second
if (seconds != prev_second)
{
prev_second = seconds;
output_toggle(PIN_A1);
}
}
}
|
HERE IS MY MODIFIED CODE
I changed the crystal value to 25MHz (instead of 20MHz) because i did not see 20MHz in our market. Will this different crystal value affect the timing? Is my one second timing still correct?
| Code: |
#include <16F887.h>
#use delay(clock=25000000)
#FUSES NOWDT //No Watch Dog Timer
#FUSES HS //High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)
#FUSES PUT //No Power Up Timer
#FUSES NOPROTECT //Code not protected from reading
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD //No EE protection
#FUSES NOWRT //Program memory not write protected
#FUSES NODEBUG //No Debug mode for ICD
//RTC variables
#define XTAL_FREQUENCY 25000000
#define TIMER1_FREQUENCY (XTAL_FREQUENCY / 4) // 1 clock tick = 1 instr. cycle = crystal frequency / 4
int32 Ticker;
int8 Seconds=0;
//optional:
int8 Year=0,Month=0,Days=0,Hours=0,Minutes=0;
////////////////////////////////////////////////////////////////////////////////
// Test whether a given year is a leap year.
// This optimized version only works for the period 2001 - 2099
////////////////////////////////////////////////////////////////////////////////
#define IS_LEAP(year) (year%4 == 0)
////////////////////////////////////////////////////////////////////////////////
// Initialize RTC
////////////////////////////////////////////////////////////////////////////////
void Initialize_RTC(void)
{
Ticker = TIMER1_FREQUENCY; // initialize clock counter to number of clocks per second
setup_timer_1( T1_INTERNAL | T1_DIV_BY_1 ); // initialize 16-bit Timer1 to interrupt
// exactly every 65536 clock cycles
// (about 76 times per second)
enable_interrupts( INT_TIMER1 ); // Start RTC
}
////////////////////////////////////////////////////////////////////////////////
// Example program for using the RTC
////////////////////////////////////////////////////////////////////////////////
int decode(int8 Minutes)
{
int code;
switch(Minutes)
{
case 0: code = 0x40;break;
case 1: code = 0x79;break;
case 2: code = 0x24;break;
case 3: code = 0x30;break;
case 4: code = 0x19;break;
case 5: code = 0x12;break;
case 6: code = 0x02;break;
case 7: code = 0x78;break;
case 8: code = 0x00;break;
case 9: code = 0x10;break;
}
return code;
}
void main()
{
int8 prev_second;
int Sec_units, Min_units, Sec_tens, Min_tens;
int Result;
set_tris_b(0x00);
set_tris_a(0x00);
Initialize_RTC();
enable_interrupts( GLOBAL );
// loop forever
while(1)
{
// Toggle output every second
if (seconds != prev_second)
{
prev_second = seconds;
Sec_tens = Seconds/10;
Sec_units= Seconds%10;
Min_tens = Minutes/10;
Min_units= Minutes%10;
output_A(0x02);
Result = decode(Min_tens);
output_C(Result);
delay_ms(10);
output_A(0x01);
Result = decode(Min_units);
output_C(Result);
delay_ms(10);
output_A(0x08);
Result = decode(Sec_tens);
output_C(Result);
delay_ms(10);
output_A(0x04);
Result = decode(Sec_units);
output_C(Result);
delay_ms(10);
}
}
}
////////////////////////////////////////////////////////////////////////////////
// -=Process Zero Drift Real Time Clock Information=-
//
// Most algorithms configure the timer to generate an interrupt every 100ms, and
// then count the number of interrupts. The problem in that approach is that most
// clock frequencies can't be divided by 256 and you don't get an exact 100ms.
// The small errors will add up to an error of several seconds a day.
//
// The algorithm presented here is exact in the long run because it doesn't
// count the number of interrupts but counts the number of clock cycles.
////////////////////////////////////////////////////////////////////////////////
#int_TIMER1
void TIMER1_isr()
{
Ticker -= 65536; // Decrement ticker by clocks per interrupt
if ( Ticker < 65536 ) // If second has expired
{ Ticker += TIMER1_FREQUENCY; // Increment ticker by clocks per second
seconds++; // Increment number of seconds
}
// --- Optional part start ---
if(Seconds == 60) {Minutes++; Seconds=0;
if(Minutes == 60) {Hours++; Minutes=0;
if(Hours == 24) {Days++; Hours=0;
if ( (Days == 29 && Month==2 && !IS_LEAP(Year))
|| (Days == 30 && Month==2)
|| (Days == 31 && (Month==4 || Month==6 || Month==9 || Month==11 ))
|| (Days == 32)
) {Month++;Days=0;}
if(Month == 13) {Year++; Month=0;}
}}}
// --- Optional part end ---
}
|
|
|
 |
andrewg
Joined: 17 Aug 2005 Posts: 162 Location: Perth, Western Australia
|
|
Posted: Fri Aug 13, 2010 9:43 pm |
|
|
The reason your display is flickering is because you're only updating it when the seconds change. You need to update it all the time.
| Quote: | | I changed the crystal value to 25MHz |
Check the PIC datasheet. You'll find the maximum oscillator frequency (table 17-1) is 20MHz. While you're probably OK (PICs are pretty tough), you really should use a slower crystal. _________________ Andrew |
|
 |
princejude
Joined: 07 Aug 2010 Posts: 4
|
|
Posted: Tue Aug 17, 2010 7:15 am |
|
|
Thanks Mr Andrew, I have edited the code as follows:
1. I changed the crystal value to 4MHz.
| Code: | #use delay(clock=25000000) to #use delay(clock=4000000)
and #define XTAL_FREQUENCY 25000000 to #define XTAL_FREQUENCY 4000000 |
2. I also changed the switch variable from Minutes to Seconds
| Code: | | switch(Minutes) to switch(Seconds) |
3. I reduced the "delay_ms(10);" from 10ms to 1ms
| Code: | | delay_ms(10); to delay_ms(1); |
After all these changes the FLICKERING/FLASHING/BLINKING STOPPED
I AM STILL WORKING ON THE TIME SETTING FUNCTIONS (need help if any).
I will like to use 4 push button switches labeled SET,MODE,UP and DOWN
The expected operation is as follows:
If i press the SET button - the clock will display the current time, call the MODE function(by default the MODE function will select SET_Min function) and wait for the next button to be pressed.
If i press the MODE button - it will select SET_Hr function
When the SET_Min function is selected - if i press UP button the Minutes value will increase and if i press DOWN the Minutes value will decrease.
When the SET_Hr function is selected - if i press UP button the Hours value will increase and if i press DOWN the Hours value will decrease.
Pls i need some advice (or help) on how to achieve these.
HERE IS MY CODE (the time setting section is not yet complete)
| Code: | #include <16F887.h>
#use delay(clock=4000000)
#FUSES NOWDT //No Watch Dog Timer
#FUSES XT //High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)
#FUSES PUT //No Power Up Timer
#FUSES NOPROTECT //Code not protected from reading
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD //No EE protection
#FUSES NOWRT //Program memory not write protected
#FUSES NODEBUG //No Debug mode for ICD
#define XTAL_FREQUENCY 4000000
#define TIMER1_FREQUENCY (XTAL_FREQUENCY / 4) // 1 clock tick = 1 instr. cycle = crystal frequency / 4
#define IS_LEAP(year) (year%4 == 0)
#define D 1
#define SET PIN_D0
#define MODE PIN_D1
#define UP PIN_D2
#define DOWN PIN_D3
int32 Ticker;
int8 Seconds=0;
int8 Year=0,Month=0,Days=0,Hours=0,Minutes=0;
// int1 flg=false;
////////////////////////////////////////////////////////////////////////////////
// Initialize RTC
////////////////////////////////////////////////////////////////////////////////
void Initialize_RTC(void)
{
Ticker = TIMER1_FREQUENCY; // initialize clock counter to number of clocks per second
setup_timer_1( T1_INTERNAL | T1_DIV_BY_1 ); // initialize 16-bit Timer1 to interrupt
// exactly every 65536 clock cycles
// (about 76 times per second)
enable_interrupts(INT_TIMER1); // Start RTC
}
/////////////////////////////////////////////////////////////////////////////////
// Set Time
/////////////////////////////////////////////////////////////////////////////////
void set_Hr()
{
if(!input(UP)) {enable_interrupts(INT_TIMER1); Seconds++;}
else if(!input(DOWN)) {enable_interrupts(INT_TIMER1); Seconds--;}
}
void set_Min()
{
}
////////////////////////////////////////////////////////////////////////////////////
// Main Program Start Here
////////////////////////////////////////////////////////////////////////////////////
int decode(int8 Seconds)
{
int code;
switch(Seconds)
{
case 0: code = 0x40;break;
case 1: code = 0x79;break;
case 2: code = 0x24;break;
case 3: code = 0x30;break;
case 4: code = 0x19;break;
case 5: code = 0x12;break;
case 6: code = 0x02;break;
case 7: code = 0x78;break;
case 8: code = 0x00;break;
case 9: code = 0x10;break;
}
return code;
}
void main()
{
int8 prev_second;
int Sec_units, Min_units, Sec_tens, Min_tens, Hr_units, Hr_tens;
int Result;
Initialize_RTC();
enable_interrupts(GLOBAL);
while(true)
{
if(!input(SET)) {disable_interrupts(INT_TIMER1); SET_Hr();}
{
if (seconds != prev_second)
{ prev_second = seconds; }
{
Sec_tens = Seconds/10;
Sec_units= Seconds%10;
Min_tens = Minutes/10;
Min_units= Minutes%10;
Hr_tens = Hours/10;
Hr_units= Hours%10;
output_A(0x20);
Result = decode(Hr_tens);
output_C(Result);
delay_ms(D);
output_A(0x10);
Result = decode(Hr_units);
output_C(Result);
delay_ms(D);
output_A(0x02);
Result = decode(Min_tens);
output_C(Result);
delay_ms(D);
output_A(0x01);
Result = decode(Min_units);
output_C(Result);
delay_ms(D);
output_A(0x08);
Result = decode(Sec_tens);
output_C(Result);
delay_ms(D);
output_A(0x04);
Result = decode(Sec_units);
output_C(Result);
delay_ms(D);
}
}
// set_Hr();
}
}
////////////////////////////////////////////////////////////////////////////////
// -=Process Zero Drift Real Time Clock Information=-
//
// The algorithm presented here is exact in the long run because it doesn't
// count the number of interrupts but counts the number of clock cycles.
////////////////////////////////////////////////////////////////////////////////
#int_TIMER1
void TIMER1_isr()
{
Ticker -= 65536; // Decrement ticker by clocks per interrupt
if ( Ticker < 65536 ) // If second has expired
{ Ticker += TIMER1_FREQUENCY; // Increment ticker by clocks per second
seconds++; // Increment number of seconds
}
if(Seconds == 60)
{
Minutes++; Seconds=0;
if(Minutes == 60)
{
Hours++; Minutes=0;
if(Hours == 24)
{
Days++; Hours=0;
if((Days == 29 && Month==2 && !IS_LEAP(Year))|| (Days == 30 && Month==2)
|| (Days == 31 && (Month==4 || Month==6 || Month==9 || Month==11 ))||(Days == 32))
{Month++;Days=0;}
if(Month == 13)
{Year++; Month=0;}
}
}
}
}
| [/b] |
|
 |
andrewg
Joined: 17 Aug 2005 Posts: 162 Location: Perth, Western Australia
|
|
Posted: Tue Aug 17, 2010 8:26 am |
|
|
It's good to hear your display is working now.
Do you have any specific questions about handling your input switches? I suggest that you Google "switch debouncing" and have a read. _________________ Andrew |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|