PIC18F4550 countdown timer help

Discussion in 'Homework Help' started by messier, Feb 2, 2013.

  1. messier

    Thread Starter New Member

    Feb 2, 2013
    3
    0
    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: Feb 2, 2013
  2. messier

    Thread Starter New Member

    Feb 2, 2013
    3
    0
    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: Feb 2, 2013
  3. WBahn

    Moderator

    Mar 31, 2012
    17,788
    4,807
    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.
     
  4. messier

    Thread Starter New Member

    Feb 2, 2013
    3
    0
    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 :)
     
Loading...