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.

16f877 timer problem

Status
Not open for further replies.

cobra1

New Member
Im trying to make the timer work on a 16f877, i have done this before without issues.

This time im using a ks0108 type LCD, and when i activate the timer in the program it jams up and scrambles all the data on the screen, (looks like i have typed the same thing over and over and over)

The program just locks up and has to be reset.

Without the timer active the program runs flawlessly. The LCD is using the entire port B for data, and most of port D for control lines.

Is there any reason why this should be happening???
 
Yes, it's called a bug. You need to post a lot more to get any help finding it. Like which timer? Are interrupts used etc. In fact, posting the code would be the best idea.

Mike.
 
The code is flocode generated code, might not be much use.

its timer0 im using (my only option) and all i have done is switched it on, i have since tried to make a new program with the same hardware setup having just a timer to turn an led on after 10 seconds.

(this is something ihave done many times) the timer doesnt start,

I will try disconnecting the LCD display shortly and see if it works
 
Last edited:
Update

Ok. Think im making progress...sort of.

I have now got the timer running, and i have found out why my program is hanging. If i have the timer ON and use the PRINT NUMBER macro for the LCD the timer doesnt work properly and the screen bocomes filled with numbers and then hangs up, (all this within 1 second or so)

If i use the PRINT NUMBER on its own then all is well and works as expected, if i use the timer and the PRINT STRING macro again everything works as expected.

This suggest that there is a clash of some kind when the timer and print number are used together... Now i am really stuck.

I have made a short piece of code, it initialises the LCD activates the timer then goes into a loop where every second it flashes an led, this works fine until i add in the print number function to show the seconds variable.

Here is the code. Can anyone help me as i dont really know what im looking for..


had to chop the top half off as it wouldnt all fit
 
Last edited:
Code:
//Internal Prototypes
    void MX_LCD_Enable (void);
    void MX_Write_Command(char cmd, char chip);
    void GotoXY(char x, char y);
    void MX_WriteData(char data);
    char MX_ReadData(void);


    //Internal Functions
    void MX_LCD_Enable (void)
    {
        set_bit(MX_CONTROL_PORT, MX_ENABLE);
        //delay_10us(1);                                //Min delay 450ns
        nop();
        nop();
        nop();
        nop();
        nop();

        clear_bit(MX_CONTROL_PORT, MX_ENABLE);
        //delay_10us(1);                                //Min delay 1.5us
        nop();
        nop();
        nop();
        nop();
        nop();
    }


    void MX_Write_Command(char cmd, char chip)
    {
        if(chip == MX_CHIP1)                        //Select Chip 1
        {
            clear_bit(MX_CONTROL_PORT, MX_CS2);
            set_bit(MX_CONTROL_PORT, MX_CS1);
        }
        else if(chip == MX_CHIP2)                    //Select Chip 2
        {
            clear_bit(MX_CONTROL_PORT, MX_CS1);
            set_bit(MX_CONTROL_PORT, MX_CS2);
        }
        clear_bit(MX_CONTROL_PORT, MX_READ_WRITE);    //Write Command
        clear_bit(MX_CONTROL_PORT, MX_DAT_INST);    //Instruction code
        MX_DATA_TRIS = 0x00;                        //Configure data port as output
        MX_DATA_PORT = cmd;
        MX_LCD_Enable();
        MX_DATA_PORT = 0x00;
    }


    void MX_GotoXY(char x, char y)
    {
        char chip = MX_CHIP1;
        char cmd;

        if(x > 127) x = 0;                            //Ensure that coordinates are legal
        if(y > 63)  y = 0;

        mx_currentx = x;
        mx_currenty = y;
        mx_page = y / 8;

        if(x >= 64)                                 //Select the right chip
        {
            x = x - 64;
            chip = MX_CHIP2;
        }

        cmd = MX_LCD_SET_PAGE | mx_page;            //Set y address on both chips
        MX_Write_Command(cmd, MX_CHIP1);
        MX_Write_Command(cmd, MX_CHIP2);

        cmd = MX_LCD_SET_ADD | x;                    //Set x address on active chip
        MX_Write_Command(cmd, chip);
    }



    void MX_WriteData(char data)
    {
        char displayData, yOffset, cmdPort;

        if(mx_currentx >= 128)
            return;

        if(mx_currentx < 64)
        {
            clear_bit(MX_CONTROL_PORT, MX_CS2);            //Select chip 1
            set_bit(MX_CONTROL_PORT, MX_CS1);
        }

        else if(mx_currentx >= 64)
        {
            clear_bit(MX_CONTROL_PORT, MX_CS1);            //Select chip 2
            set_bit(MX_CONTROL_PORT, MX_CS2);
        }

        if(mx_currentx == 64)                            //Chip 2 X Address = 0
            MX_Write_Command(MX_LCD_SET_ADD, MX_CHIP2);

        set_bit(MX_CONTROL_PORT, MX_DAT_INST);            //Configure to send data
        clear_bit(MX_CONTROL_PORT, MX_READ_WRITE);        //Configure to write data
        MX_DATA_TRIS = 0x00;                            //Configure data port to Output
        yOffset = mx_currenty % 8;

        if(yOffset != 0)                                 //First page?
        {
            cmdPort = MX_CONTROL_PORT;                    //Save command port
            displayData = MX_ReadData();
            MX_CONTROL_PORT = cmdPort;                    //Restore command port
            MX_DATA_TRIS = 0x00;                        //Data port is output
            displayData = displayData | (data << yOffset);
            MX_DATA_PORT = displayData;                    //Write data
            MX_LCD_Enable();                            //Enable

            // second page
            MX_GotoXY(mx_currentx, (mx_currenty + 8));
            displayData = MX_ReadData();
            MX_CONTROL_PORT = cmdPort;                    //Restore command port
            MX_DATA_TRIS = 0x00;                        //Data port is output
            displayData = displayData | (data >> (8-yOffset));
            MX_DATA_PORT = displayData;                    //Write data
            MX_LCD_Enable();                            //Enable
            MX_GotoXY(mx_currentx + 1, (mx_currenty - 8));
        }
        else
        {
            MX_DATA_PORT = data;                        //Write data
            MX_LCD_Enable();                            //Enable
            mx_currentx = mx_currentx + 1;
        }
        MX_DATA_PORT = 0x00;
    }


    char MX_ReadData(void)
    {
        char data, i;

        MX_DATA_PORT = 0x00;
        MX_DATA_TRIS = 0xFF;                            //Data port is input
        set_bit(MX_CONTROL_PORT, MX_READ_WRITE);        //Configure to read data
        set_bit(MX_CONTROL_PORT, MX_DAT_INST);            //Configure to send data

        if(mx_currentx < 64)
        {
            clear_bit(MX_CONTROL_PORT, MX_CS2);            //Select chip 1
            set_bit(MX_CONTROL_PORT, MX_CS1);
        }

        else if(mx_currentx >= 64)
        {
            clear_bit(MX_CONTROL_PORT, MX_CS1);            //Select chip 2
            set_bit(MX_CONTROL_PORT, MX_CS2);
        }

        set_bit(MX_CONTROL_PORT, MX_ENABLE);            //Set the enable bit
        for (i=0; i<3; i++);
        clear_bit(MX_CONTROL_PORT, MX_ENABLE);            //Clear the enable bit
        for (i=0; i<8; i++);                            //Min 1.5us delay
        set_bit(MX_CONTROL_PORT, MX_ENABLE);            //Set the enable bit
        for (i=0; i<15; i++);                            //Min 450ns delay

        data = MX_DATA_PORT;                            //Read Data
        clear_bit(MX_CONTROL_PORT, MX_ENABLE);            //Clear the enable bit
        MX_DATA_TRIS = 0x00;                            //Configure port as output
        MX_GotoXY(mx_currentx, mx_currenty);
        return data;
    }


    // Dummy function to close the defines section off
    void CUSTOM_Dummy_Function();
    void CUSTOM_Dummy_Function()
    {

}

void FCD_Custom0_LCD_Init()
{
    
        mx_currentx = 0;
        mx_currenty = 0;
        mx_page = 0;

        MX_DATA_TRIS = 0x00;                                //Convert data port to output
        MX_DATA_PORT = 0x00;

        clear_bit(MX_CONTROL_TRIS, MX_ENABLE);                //Convert control pins to output
        clear_bit(MX_CONTROL_TRIS, MX_DAT_INST);
        clear_bit(MX_CONTROL_TRIS, MX_CS1);
        clear_bit(MX_CONTROL_TRIS, MX_CS2);
        clear_bit(MX_CONTROL_TRIS, MX_READ_WRITE);

        set_bit(MX_CONTROL_PORT, MX_ENABLE);
        clear_bit(MX_CONTROL_PORT, MX_READ_WRITE);            //Write Command
        clear_bit(MX_CONTROL_PORT, MX_DAT_INST);            //Instruction code
        set_bit(MX_CONTROL_PORT, MX_CS1);                    //Select Chip 1
        clear_bit(MX_CONTROL_PORT, MX_CS2);

        MX_Write_Command(MX_LCD_ON, MX_CHIP1);                //Switch on LCD controller chips
        MX_Write_Command(MX_LCD_ON, MX_CHIP2);

        MX_Write_Command(MX_LCD_DISP_START, MX_CHIP1);        //Configure the display start address
        MX_Write_Command(MX_LCD_DISP_START, MX_CHIP2);

        FCD_Custom0_LCD_Clear();
        MX_GotoXY(0,0);

}

void FCD_Custom0_LCD_Clear()
{
        FCD_Custom0_LCD_Draw_Rect(0, 0, 127, 63, MX_WHITE);
}

void FCD_Custom0_LCD_PlotPixel(char x, char y, char colour)
{
        char data, mod_y;

        mod_y = y%8;
        MX_GotoXY(x, y - mod_y);
        data = MX_ReadData();                            //Read 8 pixels from display
        if (colour)
            data = data | (0x01 << mod_y);                //Set Pixel
        else
            data = data & (~(0x01 << mod_y));            //Clear Pixel
        MX_WriteData(data);
}

void FCD_Custom0_LCD_Draw_Line(char x, char y, char x2, char y2, char colour)
{
        int C1, M1;
        signed int D1 = 0;
        signed int Pixelx = x2 - x;    //number of X-pixels;
        signed int Pixely = y2 - y;    //Number of Y-pixels
        signed char Xinc = 1;
        signed char Yinc = 1;

        if (Pixelx < 0)        //If negative X direction
        {
            Xinc = -1;
            Pixelx = Pixelx * -1;
        }
        if (Pixely < 0)        //If negative Y direction
        {
            Yinc = -1;
            Pixely = Pixely * -1;
        }
        if (Pixely <= Pixelx)
        {
            C1 = 2 * Pixelx;
            M1 = 2 * Pixely;
            while (x != x2)
            {
                FCD_Custom0_LCD_PlotPixel(x, y, colour);    //ForePlot line
                x = x + Xinc;
                D1 = D1 + M1;
                if (D1 > Pixelx)
                {
                    y = y + Yinc;
                    D1 = D1 - C1;
                }
            }
        }
        else
        {
            C1 = 2 * Pixely;
            M1 = 2 * Pixelx;
            while (y != y2)
            {
                FCD_Custom0_LCD_PlotPixel(x, y, colour);    //ForePlot Line
                y = y + Yinc;
                D1 = D1 + M1;
                if (D1 > Pixely)
                {
                    x = x + Xinc;
                    D1 = D1 - C1;
                }
            }
            FCD_Custom0_LCD_PlotPixel(x, y, colour);
        }
}

void FCD_Custom0_LCD_Draw_Rect(char x, char y, char width, char height, char colour)
{
        char mask, pageOffset, h, i, data;

        if(colour)
            colour = 255;

        height = height + 1;

        pageOffset = y % 8;
        y = y - pageOffset;
        mask = 0xFF;

        if(height < (8 - pageOffset))
        {
            mask = mask >> (8-height);
            h = height;
        }
        else
            h = (8 - pageOffset);

        mask = mask << pageOffset;

        MX_GotoXY(x, y);

        for(i=0; i<=width; i++)
        {
            data = MX_ReadData();
            if(colour)
                data = data | mask;
            else
                data = data & (~mask);

            MX_WriteData(data);
        }

        while((h + 8) <= height)
        {
            h = h + 8;
            y = y + 8;
            MX_GotoXY(x, y);

            for(i=0; i<=width; i++)
                MX_WriteData(colour);
        }

        if(h < height)
        {
            mask = ~(0xFF << (height - h));
            MX_GotoXY(x, (y + 8));

            for(i=0; i<=width; i++)
            {
                data = MX_ReadData();

                if(colour)
                    data = data | mask;
                else
                    data = data & (~mask);

                MX_WriteData(data);
            }
        }
}

void FCD_Custom0_LCD_Print_String(char* String, char MSZ_String, char X, char Y, char Font, char Transparent, char Colour)
{
        char xpix, ypix, pos_Str, count, xcount, ycount, height, width, i;
        char Fontwidth = 1;                //First we assume small font
        char Fontheight = 1;
        char inv_colour = 1;

        char temp[6];
        temp[5] = 0x00;                        //Spacing Line

        if (Colour)
            inv_colour = 0;

        if (Font == 1)                         //Double Height Sizes //Double Width
        {
            Fontwidth = 2;
        }
        if (Font == 2)                         //Double Height and Width Sizes
        {
            Fontwidth = 2;
            Fontheight = 2;
        }
        if (Font == 3)                         //Double Height Sizes
        {
            Fontheight = 2;
        }
        if (Font == 4)                         //Double Height and Width Sizes
        {
            Fontwidth = 3;
            Fontheight = 3;
        }
        if (Font == 5)                         //Double Height and Width Sizes
        {
            Fontwidth = 7;
            Fontheight = 7;
        }

        xcount = 0;
        for (i=0;i<MSZ_String;i++)         //Start at beginning of string and work along
        {
            if (String[i] == 0)
                return;
            pos_Str = String[i] - 32;      //Calculate place in ASCII memory

            for (count = 0; count < 5; count++)        //Use correct buffer location
            {
                if (pos_Str < 12)
                {
                    temp[count]=ASCII1[(pos_Str*5)+count];
                }
                else if (pos_Str < 24)
                {
                    temp[count]=ASCII2[((pos_Str - 12)*5)+count];
                }
                else if (pos_Str < 36)
                {
                    temp[count]=ASCII3[((pos_Str - 24)*5)+count];
                }
                else if (pos_Str < 48)
                {
                    temp[count]=ASCII4[((pos_Str - 36)*5)+count];
                }
                else if (pos_Str < 60)
                {
                    temp[count]=ASCII5[((pos_Str - 48)*5)+count];
                }
                else if (pos_Str < 72)
                {
                    temp[count]=ASCII6[((pos_Str - 60)*5)+count];
                }
                else if (pos_Str < 84)
                {
                    temp[count]=ASCII7[((pos_Str - 72)*5)+count];
                }
                else if (pos_Str < 95)
                {
                    temp[count]=ASCII8[((pos_Str - 84)*5)+count];
                }
            }
            for (xpix=0;xpix<6;xpix++)    //For 6 ASCII bytes 0 - 5
            {
                for (width=0;width<Fontwidth;width++)
                {
                    ycount = 0;
                    for (ypix=0;ypix<8;ypix++)    //For 8 data bits in bytes 0 - 7
                    {
                        for (height=0;height<Fontheight;height++)
                        {
                            if (test_bit(temp[xpix],ypix))
                            {
                                FCD_Custom0_LCD_PlotPixel(X + xcount, Y + ycount, Colour);
                            }
                            else if (Transparent == 0)
                            {
                                FCD_Custom0_LCD_PlotPixel(X+xcount, Y+ycount, inv_colour);
                            }
                            ycount++;
                        }
                    }
                    xcount++;
                }
            }
        }
}

void FCD_Custom0_LCD_Print_Number(short Number, char X, char Y, char Font, char Transparent, char Colour)
{
        char string_length;

        if (Number < -10000   &nbsp;)
            string_length = 6;

        else if(Number > 10000 || Number < -1000)
            string_length = 5;

        else if(Number > 1000 || Number < -100)
            string_length = 4;

        else if(Number > 100 || Number < -10)
            string_length = 3;

        else if(Number > 10 || Number < -1)
            string_length = 2;

        else
            string_length = 1;

        char temp_str[6];

        FCI_TOSTRING(Number,temp_str,string_length);                                    //Convert number to String
        FCD_Custom0_LCD_Print_String(temp_str, string_length, X, Y, Font, Transparent, Colour);        //Send string to Print function
}

void FCD_Custom0_LCD_Invert_Rect(char x, char y, char width, char height)
{
        char mask, pageOffset, h, i, data, tmpData;
        height++;

        pageOffset = y % 8;
        y = y - pageOffset;
        mask = 0xFF;
        if(height < (8 - pageOffset))
        {
            mask = mask >> (8-height);
            h = height;
        }
        else
        {
            h = 8 - pageOffset;
        }
        mask = mask << pageOffset;

        MX_GotoXY(x, y);
        for(i=0; i<=width; i++)
        {
            data = MX_ReadData();
            tmpData = ~data;
            data = (tmpData & mask) | (data & ~mask);
            MX_WriteData(data);
        }

        while((h + 8) <= height)
        {
            h = h + 8;
            y = y + 8;
            MX_GotoXY(x, y);

            for(i=0; i<=width; i++)
            {
                data = MX_ReadData();
                MX_WriteData(~data);
            }
        }

        if(h < height)
        {
            mask = ~(0xFF << (height-h));
            MX_GotoXY(x, y+8);

            for(i=0; i<=width; i++)
            {
                data = MX_ReadData();
                tmpData = ~data;
                data = (tmpData & mask) | (data & ~mask);
                MX_WriteData(data);
            }
        }
}

//Macro implementations

void FCM_TIMER_SERVICE()
{
    
    //Decision
    //Decision: INT < 75?
    if (FCV_INT < 75)
    {
        //Calculation
        //Calculation:
        //  INT = INT + 1
        FCV_INT = FCV_INT + 1;
        

    } else {
        //Calculation
        //Calculation:
        //  INT = 0
        FCV_INT = 0;
        

        //Calculation
        //Calculation:
        //  SECONDS = SECONDS + 1
        FCV_SECONDS = FCV_SECONDS + 1;
        

    }


}

//Supplementary implementations


void main()
{
    
    //Initialisation
    adcon1 = 0x07;


    //Interrupt initialisation code
    option_reg = 0xC0;


    //Call Component Macro
    //Call Component Macro: Custom(0)::LCD_Init
    FCD_Custom0_LCD_Init();


    //Interrupt
    //Interrupt: Enable TMR0 Overflow
    option_reg.T0CS=0;
    option_reg.T0SE=1;
    option_reg = (option_reg & 0xF0) | 0x07;
    intcon.GIE=1;
    intcon.T0IE=1;


    //Output
    //Output: 1 -> C2
    trisc = trisc & 0xfb;
    if (1)
        portc = (portc & 0xfb) | 0x04;
    else
        portc = portc & 0xfb;


    //Loop
    //Loop: While 1
    while (1)
    {
        //Decision
        //Decision: SECONDS = 1?
        if (FCV_SECONDS == 1)
        {
            //Output
            //Output: 1 -> D1
            trisd = trisd & 0xfd;
            if (1)
                portd = (portd & 0xfd) | 0x02;
            else
                portd = portd & 0xfd;


            //Delay
            //Delay: 100 ms
            delay_ms(100);


            //Output
            //Output: 0 -> D1
            trisd = trisd & 0xfd;
            if (0)
                portd = (portd & 0xfd) | 0x02;
            else
                portd = portd & 0xfd;


            //Calculation
            //Calculation:
            //  SECONDS = 0
            FCV_SECONDS = 0;
            

        }


        //Delay
        //Delay: 50 ms
        delay_ms(50);


        //
        //Call Component Macro: Custom(0)::LCD_Print_Number(SECONDS, 40, 30, 0, 0, 1)
        FCD_Custom0_LCD_Print_Number(FCV_SECONDS, 40, 30, 0, 0, 1);


    }


    mainendloop: goto mainendloop;
}

void interrupt(void)
{
    if (intcon & (1 << T0IF))
    {
        FCM_TIMER_SERVICE();
        clear_bit(intcon, T0IF);
    }


}
 
Last edited by a moderator:
Status
Not open for further replies.

Latest threads

Back
Top