PIC18F4550 countdown timer help

Thread Starter

messier

Joined Feb 2, 2013
3
I am able to get the timer to count down to 00:00:00 but I need an output to happen (buzzer or LED etc...). How do I set the condition for which to activate all of PORTB and PORTC?
**SKIP TO PART 2 BELOW. Part 1 is to initialize the LCD keypad and wait for user input, which I have no issues with. It's just here if anyone needs to refer to it.
My code is given as (PART 1, to initialize LCD keypad, wait for input, etc etc);


#include <p18F4550.h>
#include <delays.h>

// ***** begin *****************************************************************************
// function prototypes
void lcd_strobe(void);
unsigned char char_2_int (char char1);
char int_2_char (unsigned char int1);
void T2ISR(void);
// ***** end *****************************************************************************

// Include this when using Bootloader Program ================================
#pragma udata

extern void _startup (void); // See c018i.c in your C18 compiler dir

#pragma code _RESET_INTERRUPT_VECTOR = 0x000800
void _reset (void)
{
_asm goto _startup _endasm
}
#pragma code

// ***** begin *****************************************************************************
#pragma code _HIGH_INTERRUPT_VECTOR = 0x000808
void _high_ISR (void)
{
_asm goto T2ISR _endasm
}

#pragma code _LOW_INTERRUPT_VECTOR = 0x000818
void _low_ISR (void)
{
_asm goto T2ISR _endasm
}
// ***** end *****************************************************************************

#pragma code
#pragma code

// additional codes ends here ===============================================================

// Your program declarations start here:====

#define LCD_RS PORTDbits.RD6 // Register Select on LCD
#define LCD_EN PORTDbits.RD4 // Enable on LCD controller
#define LCD_WR PORTDbits.RD5 // Write on LCD controller

#define KEY_DA PORTBbits.RB5 // 74922 DA output
#define KEY_PORT PORTB // RB3 to RB0 has keypad data


//--- Function for writing a command byte to the LCD in 4 bit mode -------------
void lcd_write_cmd(signed char cmd)
{
unsigned char temp2;
LCD_RS = 0; // Select LCD for command mode
Delay10TCYx(4); // 40us delay for LCD to settle down
temp2 = cmd;
temp2 = temp2 >> 4; // Output upper 4 bits, by shifting out lower 4 bits
PORTD = temp2 & 0x0F; // Output to PORTD which is connected to LCD

Delay1KTCYx(10); // 10ms -Delay at least 1 ms before strobing
lcd_strobe();

Delay1KTCYx(10); // 10ms - Delay at least 1 ms after strobing

temp2 = cmd; // Re-initialise temp2
PORTD = temp2 & 0x0F; // Mask out upper 4 bits

Delay1KTCYx(10); // 10ms - Delay at least 1 ms before strobing
lcd_strobe();

Delay1KTCYx(10); // 10ms - Delay at least 1 ms before strobing

}

//---- Function to write a character data to the LCD ---------------------------
void lcd_write_data(char data)
{
char temp1;

LCD_RS = 1; // Select LCD for data mode
Delay10TCYx(4); // 40us delay for LCD to settle down

temp1 = data;
temp1 = temp1 >> 4;
PORTD = temp1 & 0x0F;
Delay1KTCYx(10);
LCD_RS = 1;
Delay1KTCYx(10); //_-_ strobe data in

lcd_strobe();
Delay1KTCYx(10);

temp1 = data;
PORTD = temp1 & 0x0F;
Delay1KTCYx(10);
LCD_RS = 1;
Delay1KTCYx(10); //_-_ strobe data in

lcd_strobe();
Delay1KTCYx(10);

}

//-- Function to generate the strobe signal for command and character----------
void lcd_strobe(void) // Generate the E pulse
{

LCD_EN = 1; // E = 0
Delay1KTCYx(1); // 1ms delay for LCD_EN to settle
LCD_EN = 0; // E = 1
Delay1KTCYx(1); // 1ms delay for LCD_EN to settle

}

//---- Function to initialise LCD module ----------------------------------------
void lcd_init(void)
{
TRISD = 0x00;
PORTD = 0x00; // PORTD is connected to LCD data pin
LCD_EN = 0;
LCD_RS = 0; // Select LCD for command mode
LCD_WR = 0; // Select LCD for write mode

Delay10KTCYx(250); // Delay a total of 1 s for LCD module to
Delay10KTCYx(250); //
Delay10KTCYx(250); //
Delay10KTCYx(250); // finish its own internal initialisation

/* The data sheets warn that the LCD module may fail to initialise properly when
power is first applied. This is particularly likely if the Vdd
supply does not rise to its correct operating voltage quickly enough.

It is recommended that after power is applied, a command sequence of
3 bytes of 3xh be sent to the module. This will ensure that the module is in
8-bit mode and is properly initialised. Following this, the LCD module can be
switched to 4-bit mode.
*/

lcd_write_cmd(0x33);
lcd_write_cmd(0x32);

lcd_write_cmd(0x28); // 001010xx – Function Set instruction
// DL=0 :4-bit interface,N=1 :2 lines,F=0 :5x7 dots

lcd_write_cmd(0x0E); // 00001110 – Display On/Off Control instruction
// D=1 : display on,C=1 :Cursor on,B=0 :Cursor Blink on

lcd_write_cmd(0x06); // 00000110 – Entry Mode Set instruction
// I/D=1 :Increment Cursor position
// S=0 : No display shift

lcd_write_cmd(0x01); // 00000001 Clear Display instruction

Delay10KTCYx(20); // 20 ms delay

}

//----- Function to obtained wait for key press and returns its ASCII value
char getkey(void)
{ char keycode;
const unsigned char lookup[] = "123F456E789DA0BC ";

while (KEY_DA==0); //wait for key to be pressed
keycode=KEY_PORT &0x0F; //read from encoder at portB,mask upper 4 bits

while (KEY_DA==1); //wait for key to be released
return(lookup[keycode]); //convert keycode to its ascii value for LCD
}
 
Last edited:

Thread Starter

messier

Joined Feb 2, 2013
3
PART 2 :



// ---- Main Program ---------------------------------------------------------------

unsigned char key,msgindex,outchar,lcdindex,msgindex2,outchar2,msgindex3,outchar3;

// ***** begin *****************************************************************************
char Message1 [ ] = "Set time hhmmss:"; // Defining a 16 char string
char Message2 [ ] = "Welcome User ";
char Message3 [ ] = "Buzzer activated ";
int h,m,s,i;
unsigned char hour, minute, second, hour10, hour1, minute10, minute1, second10, second1;
unsigned char key,p1,p2,p3,p4,p5,p6;// numbers
char ctemp; // temp character for reading from keypad, and writing to LCD
unsigned int tick_count; // tick_count increments by 1 every time timer interrupts, many ticks make one second
// ***** end *****************************************************************************


void main(void)
{
// Do not remove these as well=============
ADCON1 = 0x0F; // Configure PORTA to be digital I/O
CMCON = 0x07;
TRISC = 0b00000000;
TRISD = 0b00000000;

// ========================================

// Your MAIN program Starts here: =========

lcd_init(); // Initialise LCD module
LCD_RS = 1; // Select LCD for character data mode
Delay1KTCYx(1); // 1 ms delay



// ***** begin *****************************************************************************
// 1. prompt to set time upon power up
while(1)
{lcd_write_cmd(0x80); // Move cursor to line 1 position 1

for (msgindex2 = 0; msgindex2 < 16; msgindex2++) //for 16 char LCD module
{
outchar2 = Message2[msgindex2];
lcd_write_data(outchar2); // write character data to LCD
} //Introducion(Welcome User)

Delay10KTCYx(80000);
Delay10KTCYx(80000);
Delay10KTCYx(80000);
Delay10KTCYx(80000);
Delay10KTCYx(80000);
Delay10KTCYx(80000);
Delay10KTCYx(80000);
Delay10KTCYx(80000);
Delay10KTCYx(80000);
Delay10KTCYx(80000);
break;
}

lcd_write_cmd(0x80); // Move cursor to line 1 position 1

for (msgindex = 0; msgindex < 16; msgindex++) //for 16 char LCD module
{
outchar = Message1[msgindex];
lcd_write_data(outchar); // write character data to LCD
} // for

lcd_write_cmd(0xC0); // Move cursor to line 2 position 1

// hour10
ctemp=getkey (); // waits and get an ascii key number when pressed
p1=key;
lcd_write_data(ctemp); //display on LCD
hour10 = char_2_int (ctemp);

// hour1
ctemp=getkey ();
p2=key;
lcd_write_data(ctemp);
hour1 = char_2_int (ctemp);

// minute10
ctemp=getkey ();
p3=key;
lcd_write_data(ctemp);
minute10 = char_2_int (ctemp);

// minute1
ctemp=getkey ();
p4=key;
lcd_write_data(ctemp);
minute1 = char_2_int (ctemp);

// second10
ctemp=getkey ();
p5=key;
lcd_write_data(ctemp);
second10 = char_2_int (ctemp);

// second1
ctemp=getkey ();
p6=key;
lcd_write_data(ctemp);
second1 = char_2_int (ctemp);

hour = hour10 * 10 + hour1;
minute = minute10 * 10 + minute1;
second = second10 * 10 + second1;

Delay10KTCYx(250); // Delay for a short while before proceeding...
Delay10KTCYx(250);
lcd_write_cmd(0x01); // 0000 0001 Clear Display instruction

// 2. setting timer interrupt etc

if (tick_count = 0)
{PORTDbits.RD0=1;
PORTCbits.RC0=1;
}

T2CON = 0x04; // posS=1, preS=1, Timer 2 ON.
PR2 = 240; // Period = 240 x 1/12 us = 20 us, with 48 MHz crystal, Fosc/4 = 12 MHz

RCONbits.IPEN = 1; // Enable Priority Features
IPR1bits.TMR2IP = 1; // Timer 2 is High Priority
PIR1bits.TMR2IF = 0; // Clear Timer 2 Flag.
PIE1bits.TMR2IE = 1; // Enable Timer 2 Interrupt.
INTCONbits.GIEH = 1; // Enable Global Interrupt, High.

while(1)
{
// 3. timer interrupt enabled, time automatically updated by T2ISR -- Timer 2 Interrupt Service Routine, loop here forever

} // while
// ***** end *****************************************************************************

} // main


// ***** begin *****************************************************************************
// Timer 2 interrup service routine
#pragma code
#pragma interrupt T2ISR

void T2ISR(void)
{
PIR1bits.TMR2IF = 0; // Clear Timer 2 Flag.
tick_count++;

if (tick_count = 50000 )
{
// one second's up, so update second, minute, hour
tick_count = 0;
second = second - 1; // decrement second
if ( second > 59 )
{
second = 59; // roll over second
minute = minute - 1; // decrement minute

if ( minute > 59 )
{
minute = 59; // roll over minute
hour = hour - 1; // decrement hour
if ( hour > 23 )
hour = 59; // roll over hour
while(1)
{while ( second = 0 )//second condition//w1
{
second = 0; // roll over second
s=0;
PORTDbits.RD0=1;
PORTCbits.RC0=1;
while ( minute = 0 )
{
minute = 0; // roll over minute
m=0;
PORTDbits.RD0=1;
PORTCbits.RC0=1;
while ( hour =0 )
hour = 0; // roll over hour
h=0;
PORTDbits.RD0=1;
PORTCbits.RC0=1;

} // if minute..
} // if second..//second condition
} // if minute..
} // if second..
}//w1
}//w2


hour10 = hour / 10;
hour1 = hour - hour10 * 10;

minute10 = minute / 10;
minute1 = minute - minute10 * 10;

second10 = second / 10;
second1 = second - second10 * 10;

if (h==0)
{//w2
PORTDbits.RD0=1;
PORTDbits.RD1=1;
TRISCbits.TRISC0=1;
lcd_write_cmd(0xC0); // Move cursor to line 2 position 1

for (msgindex3 = 0; msgindex3 < 16; msgindex3++) //for 16 char LCD module
{
outchar3 = Message3[msgindex3];
lcd_write_data(outchar3); // write character data to LCD
} //Display Buzzer Activated)


// send "time = hh:mm:ss" to LCD display
lcd_write_cmd(0x80); // Move cursor to line 1 position 1
lcd_write_data('t');
lcd_write_data('i');
lcd_write_data('m');
lcd_write_data('e');
lcd_write_data(' ');
lcd_write_data('=');
lcd_write_data(' ');
lcd_write_data(int_2_char (hour10));
lcd_write_data(int_2_char (hour1));
Delay10KTCYx(120);
lcd_write_data(':');
lcd_write_data(int_2_char (minute10));
lcd_write_data(int_2_char (minute1));
Delay10KTCYx(120);
lcd_write_data(':');
lcd_write_data(int_2_char (second10));
lcd_write_data(int_2_char (second1));
Delay10KTCYx(120);
//tick_count = "LCD update time" in ticks;
tick_count = 10000;


if (tick_count = 0)
{ PORTDbits.RD0=1;
PORTCbits.RC0=1;
lcd_write_cmd(0xC0); // Move cursor to line 2 position 1

for (msgindex3 = 0; msgindex3 < 16; msgindex3++) //for 16 char LCD module
{
outchar3 = Message3[msgindex3];
lcd_write_data(outchar3); // write character data to LCD
} //Display Buzzer Activated)
} // if tick_count...
}
return;
}

// function to convert unsigned char to char (for display)
char int_2_char (unsigned char int1)
{
// can shorten by using "look up" array
char char1;
switch (int1)
{
case 0 : char1 = '0' ; break;
case 1 : char1 = '1' ; break;
case 2 : char1 = '2' ; break;
case 3 : char1 = '3' ; break;
case 4 : char1 = '4' ; break;
case 5 : char1 = '5' ; break;
case 6 : char1 = '6' ; break;
case 7 : char1 = '7' ; break;
case 8 : char1 = '8' ; break;
case 9 : char1 = '9' ; break;
default : char1 = '?' ;
}
return(char1);
}

// function to convert char (for display) to unsigned char
unsigned char char_2_int (char char1)
{
// can shorten by using "look up" array
unsigned char int1;
switch (char1)
{
case '0' : int1 = 0 ; break;
case '1' : int1 = 1 ; break;
case '2' : int1 = 2 ; break;
case '3' : int1 = 3 ; break;
case '4' : int1 = 4 ; break;
case '5' : int1 = 5 ; break;
case '6' : int1 = 6 ; break;
case '7' : int1 = 7 ; break;
case '8' : int1 = 8 ; break;
case '9' : int1 = 9 ; break;
default : int1 = 0 ;
}
return(int1);
}
// ***** end *****************************************************************************


My questions are :
1) What condition should I use to alarm the user when the time reaches 00:00:00?
2) What should the condition be? Do I set it as "if (condition=0) or while(condition=0) ?
3) Where should I place the condition?

Would appreciate some advise, thank you!
 
Last edited:

WBahn

Joined Mar 31, 2012
26,074
Good luck finding someone to wade through so much code that you had to break it into two posts to get the forum to accept it.

If you want free help on your homework from people who don't know you or owe you anything, then you need to make it easy for them to do so. In this case, think of a very simple problem that captures the essence of what is giving you trouble -- or perhaps several tiny problems each of which will let you learn one component of your overall solution -- so that the code you present is very minimal and very well commented.
 

Thread Starter

messier

Joined Feb 2, 2013
3
I think the first part of the code is just initializing the LCD and stuff and waiting for the input by the user. It displays fine and it counts down the timer fine, so there's no issues there.

The main program starts at part 2 of the code where I am unable to pinpoint where should I put the condition to alarm the buzzer exactly, as well as the condition to alarm the buzzer.

You are right, I should start removing the redundant points of the code. Thank you for the reply :)
 
Top