0
\$\begingroup\$

I have written a code for the 'PIC18F4550' micro-controller (20MHz xtal) which shows "Speed = xxx RPMs" on an HD44780 LCD in 4-bit mode, where the xxx is the value contained in the variable called 'input'. The compiler used is xc8 and I'm programming using the PICKIT3. I have run the simulation in proteus and it all goes good until I reset the PIC using the MCLR pin. It really shows an anomalous output where I can't seem to understand which part is going wrong. I've also implemented this on hardware and it behaves exactly like it does in the simulation. I read something similar to this problem and people were suggesting that the enable pin must be messing up at reset but I don't see how that might be happening here so please try to help guys. I'm out of ideas here.

Behavior upon power up and reset

#include <p18F4550.h>
#include <stdio.h>
#include <stdlib.h>
#include <delays.h>
#include <string.h>
#define _XTAL_FREQ 20000000
#define LCD_out PORTD
#define rs PORTCbits.RC0
#define rw PORTCbits.RC1
#define en PORTCbits.RC2


//---------------------//

void lcd_cmd(unsigned char a);      //for LCD commands
void lcd_data(unsigned char b);     //for LCD data
void lcd_reset(void);               //to initialize 4-bit mode
void lcd_init(void);                //primary initialization instructions
void string_display(char *p);       //to display character strings/arrays
void shift_right(int a);            //right cursor shift
void shift_left(int b);             //left cursor shift
void delay_10ms(int t);             //delay in multiples of 10ms
void fragment (int x);              //fragments,processes & displays int data

//.....................//

void main(void)

{
    TRISC=0;
    TRISD=0;
    int input=0;
    char text1[] = "Speed = ";
    char text2[] = "RPMs ";

    lcd_init();
    string_display(text1);
    shift_right(4);

    string_display(text2);
    shift_left(9);

    while(1)
    {
        input++;
        fragment(input);
    }
}


void fragment (int x)
{
    int number[3];
    char final_num[4];
    int flag = 0;

    number[2]= (x/1)%10;
    number[1]= (x/10)%10;
    number[0]= (x/100)%10;

    if(number[0]==0)
        flag++;
    if(number[1]==0 && number[0]==0)
        flag++;

    int temp=0;
    for(int i=flag;i<=2;i++)
    {
        final_num[temp]='0' + number[i];
        temp++;
    }

    if(x<1000)
    {
        string_display(final_num);
        shift_left(temp);
    }

    else
    {
        char nul[]="NUL";
        string_display(nul);
        shift_left(3);
    }

}

void delay_10ms(int t)
{
    for(int i=0; i<t;i++)
    {
        __delay_ms(10);
    }
}

void shift_right(int a)
{
    for(int i=0; i<a;i++)
    {
        lcd_cmd(0x14);
    }
}

void shift_left(int b)
{
    for(int i=0; i<b;i++)
    {
        lcd_cmd(0x10);
    }

}

void string_display(char *p)
{
    while(*p!=0)
    {
        lcd_data(*p);
        p++;
    }
}

void lcd_init(void)
{
    TRISC=0;
    TRISD=0;
    en = 0;
    rw = 0;

    LCD_out = 0;
    lcd_reset();
    lcd_cmd(0x28);
    lcd_cmd(0x01);
    lcd_cmd(0x0C);
}

void lcd_reset(void)
{
    __delay_ms(20);
    LCD_out=0x03;
    en=1;
    __delay_ms(5);
    en=0;

    __delay_ms(10);
    LCD_out=0x03;
    en=1;
    __delay_ms(5);
    en=0;

    __delay_ms(1);
    LCD_out=0x03;
    en=1;
    __delay_ms(5);
    en=0;

    __delay_ms(1);
    LCD_out=0x02;
    en=1;
    __delay_ms(5);
    en=0;
    __delay_ms(5);
}

void lcd_cmd(unsigned char cmd)
{
    rs=0;
    unsigned char temp;
    temp=cmd;

    //sends the upper four bits
    temp=temp>>4;
    LCD_out=temp;
    en=1;
    __delay_ms(1);
    en=0;
    __delay_ms(1);

    //sends the lower 4 bits
    temp=cmd;
    LCD_out=temp;
    en=1;
    __delay_ms(1);
    en=0;
    __delay_ms(1);
}

void lcd_data(unsigned char data)
{
    rs=1;
    unsigned char temp;
    temp=data;

    //sends the upper four bits
    temp=temp>>4;
    LCD_out=temp;
    en=1;
    __delay_ms(1);
    en=0;
    __delay_ms(1);

    //sends the lower 4 bits
    temp=data;
    LCD_out=temp;
    en=1;
    __delay_ms(1);
    en=0;
    __delay_ms(1);
}
\$\endgroup\$
  • \$\begingroup\$ Try adding final_num[temp] = '\0' to insert a null terminator after the loop that sets up final_num and see what happens. I'm not sure whether XC8 clears RAM or not after a reset so maybe some junk is left behind. \$\endgroup\$ – PeterJ Feb 11 '15 at 12:19
  • \$\begingroup\$ Is it me, or does the power layout of that circuit look completely and utterly wrong? Maybe it's just how you have to do it in the sim, I don't know, but it looks like LCD VDD is connected to GND through 10K and a capacitor, and VEE is connected to VCC through a 10K, and GND isn't connected to anything much. The oscillator layout just looks bizarre, and I really don't know what's going on. \$\endgroup\$ – Majenko Feb 11 '15 at 13:55
  • \$\begingroup\$ True, I have stated that in my answer. \$\endgroup\$ – Triak Feb 11 '15 at 14:00
  • \$\begingroup\$ I am new programming pics and now I'm studying this code, but I have one question, how do you process the input signal? How do you calculate the rpm? I dont see the the pin where you get the signal in the code, I think that I have to use an interrupt with one timer. I'm thinking of use RA4 and TMR0 to count 4 pulses and get the time of the period but I dont know where to put that in the code, is in the part where you write the code for fragment? \$\endgroup\$ – user70462 Mar 20 '15 at 20:08
2
\$\begingroup\$

I will start with mistakes on the circuit:

  • The oscillator is not connected properly.
  • I think you should not limit the LCD current with resistor and capacitor. (R2,C1)
  • In Proteus, you do not have to simulate 5V, since the PIC pins are connected to Vcc(5v). You can replace all connection for 5V to Vcc, it is same.
  • Make sure you are supplying 7805 with enough Vin. (check datasheet)

Mistakes in the code:

If you are using XC8 compiler as you stated, you should not include all these:
If you are totally sure that you want to use the specified header, then include it.

#include <p18F4550.h>
#include <stdio.h>
#include <stdlib.h>
#include <delays.h>
#include <string.h>

Instead you should include only:

#include <xc8.h>

It will include all headers needed.

I also can not see the configuration bits in the code. Include them too.

It might be all this shifting left and right which makes your code not work properly. Instead of shifting right or left, I would print the whole screen at once. Example:

while(1)
{
    lcd_reset();

    input++;
    fragment(input);

    string_display(text1);
    char_display(number[0]);
    char_display(number[1]);
    char_display(number[2]);
    string_display(text2);
}
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.