Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

Real-time clock in PIC18F4520 and PIC2Plus Demo Board

Status
Not open for further replies.

noobC

New Member
Hi frens, I am trying to set up an alarm clock using PIC18F4520 and PICDEM 2 Plus Demo Board. I have to display the time(hhmmss) in LCD and enable interrupt when the alarm sound or when the user pressed the button.

I like to ask how do I go about doing it? I had tried to use software delays in looping but I have trouble displaying the time in real-time and it affect the interrupt where interrupt does not response when I pressed the button. I started by counting every second, then show the number in display but the number is never on display and it will lag the whole system and interrupt will not work also.

Second question is that I had included a high priority interrupt using RB0, I like to ask if I am doing the right way of setting interrupt because I think the way I used is not a interrupt.

I had include part of my program and will apprepriate any help. Thanks in advance.


#include <p18F4520.h>
#include <delays.h>
#include <stdlib.h>

#define RB0 PORTBbits.RB0 //define, in my opinion can do without also
#define INT0IF INTCONbits.INT0IF //define, in my opinion can do without also
#define Lcd_VEE LATDbits.LATD7 //VEE - LCD Contrast
#define Lcd_EN LATDbits.LATD6 //Enable Signal
#define Lcd_RW LATDbits.LATD5 //read - write signal
#define Lcd_RS LATDbits.LATD4 //register select signal


void Lcd_Title (void);
void Lcd_Micro (void);
void Button (void);
void Write_Lcd (unsigned char ,unsigned char );
void DelayFor18TCY (void);
void Lcd_Time (void);
void Time_sec (void);

void init(void);
void high_ISR(void);

#pragma code high_vector = 0x08
void high_interrupt(void)
{
_asm
goto high_ISR
_endasm
}
unsigned char count;

#pragma code
#pragma interrupt high_ISR

void high_ISR(void) //interrupt subrountine to display LCD and //toggle LED
{
if (INT0IF==1) { // Check INT0 flag
PORTBbits.RB2=1;
Lcd_Micro ();
Delay10KTCYx(50);
PORTBbits.RB2=0;
Delay10KTCYx(50);
PORTBbits.RB2=1;
Delay10KTCYx(50);
PORTBbits.RB2=0;
INT0IF = 0; // Clear interrupt flag
}
}

void init(void) { //qns 1

ADCON1=0x0F;
RCONbits.IPEN=1;
TRISB=0b00000001; //only bit 0 and 1 is input the rest all output
PORTB=0x01;

INTCON2bits.INTEDG0 = 0;
INT0IF=0;
INTCONbits.INT0IE=1;
INTCONbits.GIEH = 1;

/* configure LCD pin */
TRISDbits.TRISD7 = 0; // VEE // PICDEM2 PLUS GREEN BOARD
TRISDbits.TRISD6 = 0; // EN
TRISDbits.TRISD5 = 0; // RW
TRISDbits.TRISD4 = 0; // RS

TRISDbits.TRISD0 = 0; // DB4
TRISDbits.TRISD1 = 0; // DB5
TRISDbits.TRISD2 = 0; // DB6
TRISDbits.TRISD3 = 0; // DB7

Lcd_VEE = 1;
Delay10KTCYx(15);
Write_Lcd (0x20,0); //B0010 0000
Write_Lcd (0x28,0); //B0010 1000
Write_Lcd (0x0c,0); //B0000 1100
Write_Lcd (0x01,0); //B0000 0001
Write_Lcd (0x02,0); //B0000 0010

if (!RB0) { //is by setting this a interrupt??
INT0IF=1;
}

}

void main (void)
{
init();
while(1) {
Lcd_Time();
if (!RB0) {
INT0IF=1; }
}
}

void Write_Lcd (unsigned char dat,unsigned char opn)
{
unsigned int delay,tempdata = 0,value =1;
tempdata = dat;
dat = dat >> 4;

LATD = (LATD & 0xF0) | (dat & 0x0F);

Lcd_RS = opn; // set RS
Lcd_RW = 0; // clear RW - write mode
DelayFor18TCY();
Lcd_EN = 1; // set Enable bit
DelayFor18TCY();
Lcd_EN = 0; // clear Enable bit

LATD = (LATD & 0xF0) | (tempdata & 0x0F);

DelayFor18TCY();
Lcd_EN = 1; // set Enable bit
DelayFor18TCY();
Lcd_EN = 0; // clear Enable bit

Delay1KTCYx(24); // alternate to check busy flag.. if lcd doesnt work properly, inc/dec this delay
return;
} //end of Write_Lcd

void Lcd_Title (void)
{
unsigned char a[13] = "abcdefghijklm", b[9] = "abcdefghi";

Write_Lcd (0x82,0);
for (count = 0; count < 13; count ++)
Write_Lcd(a[count],1);
Write_Lcd (0xC4,0);
for (count = 0; count < 9; count ++)
Write_Lcd(b[count],1);
return;
} //end of Lcd_PPMI_Title

/* write ford menu */
void Lcd_Micro (void)
{
unsigned char a[15] = "abcdefghijklmno", b[6] = "abcdef";

Write_Lcd (0x01,0);
Write_Lcd (0x81,0);
for (count = 0; count < 14; count ++)
Write_Lcd(a[count],1);

Write_Lcd (0xC5,0);
for (count = 0; count < 5; count ++)
Write_Lcd(b[count],1);
return;
} //end of Lcd_FordMenu
/* delay routine */
void DelayFor18TCY(void)
{
Delay10TCYx(0x2); //delays 20 cycles
return;
}

void Lcd_Time (void)
{
unsigned int sec,sec1;
unsigned char c;
unsigned char b[9] = "abcdefghi";
Write_Lcd (0x01,0);

Write_Lcd (0x81,0); //pointer to write

for (sec=0; sec<59; sec ++) {
Delay10KTCYx(0x500);
Time_sec ();
}

Write_Lcd (0xC5,0); //set pointer to 2nd line
for (count = 0; count < 8; count ++)
Write_Lcd(b[count],1);
return;
}

void Time_sec (void) {
unsigned char a[12] = "Time now is ";
unsigned char b[4] = " ";
unsigned int sec;

Write_Lcd (0x01,0);
Write_Lcd (0x81,0); //pointer to write
for (count = 0; count < 11; count ++) {
Write_Lcd (a[count],1);
}

Write_Lcd (0xC3,0);
for (count = 0; count < 6; count ++) {
itoa(sec,b);
Write_Lcd(b[count],1);
}

}
 
You can also use a little 32k watch xtal with timer 1.

Full details of hardware and software in the timer 1 section of the 4520 datasheet.
 
There is heaps of C source code examples here for generating 1 second periods from any xtal;
Zero-error 1 second timing algorithm

It's very simple. For example, with a PIC and 4MHz xtal;
Code:
	// C code for a 1 second period with a 1MHz timer (4MHz xtal);
	// uses 1 variable; unsigned long bres
	// gets here every TMR0 int (every 256 ticks)

	bres += 256;	// add 256 ticks to bresenham total

	if(bres >= 1000000)	// if reached 1 second!
	{
		bres -= 1000000;	// subtract 1 second, retain error
		do_1sec_event();	// update clock, etc
	}

Another example from that page, it's the same code but only needs a int variable, not a long;
Code:
	// Optimised C code for a 1 second period with a 1MHz timer (4MHz xtal);
	// uses 1 variable; unsigned int bres
	// gets here every TMR0 int (every 256 ticks)

	bres += 16;	// add (256/16) ticks to bresenham total

	if(bres >= 62500)	// if reached (1000000/16) 1 second!
	{
		bres -= 62500;	// subtract 1 second, retain error
		do_1sec_event();	// update clock, etc
	}
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top