PIC 18F4550 2x8 LCD Character Display Assistance

Status
Not open for further replies.

Micro9900

New Member
Hello, I recently purchased a Newhaven 2x8 Character LCD (Model: NHD‐0208BZ‐RN‐GBW). This is my first time programming for a character LCD, and I am having a bit of trouble getting this 2x8 LCD to work with my PIC18F4550. I am using MPLAB v8.76 with C18 Lite compiler (for programming in C).

I will be programming the LCD in 4-bits at a time. Here is the data sheet for the LCD I am using: https://www.electro-tech-online.com/custompdfs/2011/10/NHD-0208BZ-RN-GBW.pdf

Model: NHD-0208BZ-RN-GBW
(It is a 2x8 14pin (no backlight) character LCD display)

Updated:

Here is a diagram of the connections:

**broken link removed**


The data sheet provides me with the following code layout for the initialization:


Code:
4-bit Initialization: 
/**********************************************************/ 
void command(char i) 
{ 
      P1 = i;                       //put data on output Port 
      D_I =0;                       //D/I=LOW : send instruction 
      R_W =0;                       //R/W=LOW : Write      
      Nybble();                     //Send lower 4 bits 
      i = i<<4;                     //Shift over by 4 bits 
      P1 = i;                       //put data on output Port 
      Nybble();                     //Send upper 4 bits 
} 
/**********************************************************/ 
void write(char i) 
{ 
      P1 = i;                       //put data on output Port 
      D_I =1;                       //D/I=HIGH : send data 
      R_W =0;                       //R/W=LOW : Write     
      Nybble();                     //Clock lower 4 bits 
      i = i<<4;                     //Shift over by 4 bits 
      P1 = i;                       //put data on output Port 
      Nybble();                     //Clock upper 4 bits 
} 
/**********************************************************/ 
void Nybble() 
{ 
      E = 1; 
      Delay(1);                     //enable pulse width  >= 300ns 
      E = 0;                        //Clock enable: falling edge 
} 
/**********************************************************/ 
void init() 
{ 
      P1 = 0; 
      P3 = 0; 
      Delay(100);                   //Wait >15 msec after power is applied 
      P1 = 0x30;                    //put 0x30 on the output port 
      Delay(30);                    //must wait 5ms, busy flag not available 
      Nybble();                     //command 0x30 = Wake up  
      Delay(10);                    //must wait 160us, busy flag not available 
      Nybble();                     //command 0x30 = Wake up #2 
      Delay(10);                    //must wait 160us, busy flag not available 
      Nybble();                     //command 0x30 = Wake up #3 
      Delay(10);                    //can check busy flag now instead of delay 
      P1= 0x20;                     //put 0x20 on the output port 
      Nybble();                     //Function set: 4-bit interface 
      command(0x28);                //Function set: 4-bit/2-line 
      command(0x10);                //Set cursor 
      command(0x0F);                //Display ON; Blinking cursor 
      command(0x06);                //Entry Mode set 
} 
/**********************************************************/

Solved: Here is the code and a quick video.

Thank you everyone so much, I made a video to show a token of my appreciation:

https://www.youtube.com/watch?v=ZkrgRjbVZtQ

Here is the final code with the routine shown in the video:
(Note: This program uses the default clock of the 18F4550, which is 1MHz. Be sure to change the delays if you have it configured to operate at a different frequency).

Code:
//turns watch dog timer off, turn low voltage programming off
#pragma config WDT=OFF, LVP=OFF, DEBUG=ON, MCLRE = OFF
 
//Internal oscillator, port function on RA6, EC used by USB 
#pragma config FOSC = INTOSCIO_EC 
#include <p18f4550.h>
#include <delays.h>
 
//Power LED (PortA)
#define LEDPin LATAbits.LATA0 //Define LEDPin as PORT A Pin 1
 
//LCD (PortD)
#define  E LATDbits.LATD6
#define  R_W LATDbits.LATD5 
#define  RS  LATDbits.LATD4
#define LCDdata LATD
 
 
void command(unsigned char);
void write(unsigned char);
void Nybble(unsigned char);
void init(void);
void PutMessage(rom char *);
 
void main()
{
	while(!OSCCONbits.IOFS);      //wait for osc stable
   	ADCON1 = 0x0F;                //make RA0 digital
 
    //data direction registers all 0's mean that all pins are set to output
	//all 1's means that all of the pins are set to operate as inputs
	TRISA = 0x00;  
	TRISB = 0x00; 
	TRISD = 0x00;
        init();

		while(1)
		{
        	PutMessage("Thanks");
        	command(0xc0);
        	PutMessage("Pommie");
			Delay10KTCYx(50);

			command(0x01);      //Clear Display (Added)
			
			PutMessage("Thank");
       		command(0xc0);
        	PutMessage("You");
			Delay10KTCYx(50);

			command(0x01);      //Clear Display (Added)
			PutMessage("Electro");
        	command(0xc0);
        	PutMessage("tech");
			Delay10KTCYx(50);
	
			command(0x01);      //Clear Display (Added)

			PutMessage("Forum");
        	command(0xc0);
        	PutMessage("members");
			Delay10KTCYx(50);

			command(0x01);      //Clear Display (Added)
		}
        
}
 
//Write a string to the LCD
void PutMessage(rom char *Message){
rom char *Pos = Message;
	while(*Pos!=0)
	    write(*Pos++);
}
 
/**********************************************************/
//4-bit methods for LCD
/**********************************************************/
void command(unsigned char i)
{
	RS =0;
	R_W =0;          //R/W=LOW : Write
	Nybble(i>>4);    //Send upper 4 bits
	Nybble(i);       //Send lower 4 bits
	Delay1KTCYx(2);  //must wait at least 2mS (2*1000*4/1e6 = 8ms used)
}
 
void write(unsigned char i)
{
	RS =1;
	R_W =0;          //R/W=LOW : Write
	Nybble(i>>4);    //Send upper 4 bits
	Nybble(i);       //Send lower 4 bits
	Delay1KTCYx(2);  //must wait 2mS
}
 
/**********************************************************/
void Nybble(unsigned char dat)
{
    dat &= 0x0f;             //clear top bits of dat
    LCDdata &= 0xf0;         //clear bottom bits of port (interested only in DB7-DB4)
    LCDdata |= dat;          //or the two and store at port
    E = 1;
    Delay1TCY();             //enable pulse width >= 300ns (used 4uS)
    E = 0;                   //Clock enable: falling edge
}
 
/**********************************************************/
void init(void)
{
    LCDdata=0x00; 
    Delay1KTCYx(15);    //Wait >15 msec after power is applied (used 20mS)
    Nybble(0x3); 	//command 0x30 = Wake up
    Delay1KTCYx(5);     //must wait 160us, busy flag not available (used 160uS)
    Nybble(0x3); 	//command 0x30 = Wake up #2
    Delay1KTCYx(5); 	//must wait 160us, busy flag not available (used 160uS) 
 
    command(0x20);      //Function set: 4-bit/2-line
    command(0x2c);      //Function set: 4-bit/2-line
    command(0x10);      //Set cursor
    command(0x01);      //Clear Display (Added)
    command(0x06);      //Entry Mode set
    command(0x0c);
}
/**********************************************************/
//End methods for LCD
/**********************************************************/

Solved
 
Last edited:
Hi,

Your connection diagram looks a little odd i.e. both Vss and Vdd connected to 0V. But you do have black squares displayed so I guess it's just the drawing that is wrong, not the actual connections.

I'm too dim to decipher the code you posted but I have done a few routines for LCD's myself, maybe they can help, maybe not. **broken link removed**
 
Last edited:
I just get a black squares across the top row while the bottom row is completely blank.

That sounds like the contrast. Replace your 10k resistor with a pot, if you don't have a pot, try various values of resistor. Your characters could be there, but you can't see them.
 
I'm still getting a black row across the top. I think D_I refers to RS, no? So, I tried to include that as well. I have a break statement in the loop so it is only running the routine once. Additionally, I moved the connections over to port D, so now I am only using one port.

Code:
//turns watch dog timer off, turn low voltage programming off
#pragma config WDT=OFF, LVP=OFF, DEBUG=ON, MCLRE = OFF

//Internal oscillator, port function on RA6, EC used by USB 
#pragma config FOSC = INTOSCIO_EC 
#include <p18f4550.h>
#include <delays.h>

//Power LED (PortA)
#define LEDPin LATAbits.LATA0 //Define LEDPin as PORT D Pin 1

//LCD (Port B and 1 pin PortD)
#define  E	   LATDbits.LATD6 
#define  R_W       LATDbits.LATD5 
#define  RS        LATDbits.LATD4 
#define  DB7       LATDbits.LATD3
#define  DB6       LATDbits.LATD2 
#define  DB5       LATDbits.LATD1
#define  DB4       LATDbits.LATD0


void command(char);
void write(char);
void Nybble(void);
void init(void);

void main()
{
	unsigned int count=1;
	while(!OSCCONbits.IOFS);      //wait for osc stable
   	ADCON1 = 0x0F;                //make RA0 digital
  
    //data direction registers all 0's mean that all pins are set to output
	//all 1's means that all of the pins are set to operate as inputs
	TRISA = 0x00;  
	TRISB = 0x00; 
	TRISD = 0x00;
	while(1)
	{
		LEDPin=1;
		init();
		break;
	}

}

/**********************************************************/
//4-bit methods for LCD
/**********************************************************/
void command(char i)
{
//	P1 = i; //put data on output Port
//	D_I =0; //D/I=LOW : send instruction
	RS =0;

	DB7 = ((i>>3)&'1');
	DB6 = ((i>>2)&'1'); 
	DB5 = ((i>>1)&'1');
	DB4 = i&'1';

	R_W =0;   //R/W=LOW : Write
	Nybble(); //Send lower 4 bits
	
	DB7 = ((i>>7)&'1');
	DB6 = ((i>>6)&'1'); 
	DB5 = ((i>>5)&'1');
	DB4 = ((i>>4)&'1');

	Nybble(); //Send upper 4 bits
}

void write(char i)
{
	Delay1KTCYx(4);  //must wait 5ms, busy flag not available (used 5ms)
	//P1 = i; //put data on output Port
	//D_I =1; //D/I=HIGH : send data
	RS= 1;
	DB7 = ((i>>7)&'1');
	DB6 = ((i>>6)&'1'); 
	DB5 = ((i>>5)&'1');
	DB4 = ((i>>4)&'1');

	R_W =0; //R/W=LOW : Write
	Nybble(); //Clock lower 4 bits

//	P1 = i; //put data on output Port
	DB7 = ((i>>3)&'1');
	DB6 = ((i>>2)&'1'); 
	DB5 = ((i>>1)&'1');
	DB4 = i&'1';

	Nybble(); //Clock upper 4 bits
}

/**********************************************************/
void Nybble(void)
{
	E = 1;
	Delay1TCY(); //enable pulse width >= 300ns 
	E = 0; //Clock enable: falling edge
}

/**********************************************************/
void init(void)
{
	//P1 = 0;
	//P3 = 0;
		DB7 = 0;
		DB6 = 0; 
		DB5 = 0;
		DB4 = 0;

	Delay1KTCYx(1000); //Wait >15 msec after power is applied
	//P1 = 0x30; //put 0x30 on the output port

	//command(0x30);
	
		DB7 = 0;
		DB6 = 0; 
		DB5 = 1;
		DB4 = 1;

	
	Delay1KTCYx(4);  //must wait 5ms, busy flag not available 
	Nybble(); 			//command 0x30 = Wake up
	Delay10TCYx(20); 	//must wait 160us, busy flag not available
	Nybble(); 			//command 0x30 = Wake up #2
	Delay10TCYx(20); 	//must wait 160us, busy flag not available
	Nybble(); 			//command 0x30 = Wake up #3
	Delay10TCYx(20); 	//can check busy flag now instead of delay
	//P1= 0x20; 		//put 0x20 on the output port

	//command(0x20);
		DB7 = 0;
		DB6 = 0; 
		DB5 = 1;
		DB4 = 0;

	Nybble(); //Function set: 4-bit interface
	command(0x28); //Function set: 4-bit/2-line
	command(0x10); //Set cursor
	command(0x0F); //Display ON; Blinking cursor
	command(0x06); //Entry Mode set
}
/**********************************************************/
//End methods for LCD
/**********************************************************/

I played around with the delays bit, I'm sort of lost . I also put a 10K pot to adjust contrast going into V0 (Looks the same as if I had it going to ground at max darkness).

I also found the data sheet for the controllers:

SPLC80D
https://www.electro-tech-online.com/custompdfs/2011/10/SPLC780D.pdf
(Timing info for 4-bit operation on pg. 11)

ST7066U:
https://www.electro-tech-online.com/custompdfs/2011/10/ST7066U.pdf
(pg. 25/42 shows more timing information for 4-bit operation mode)

___________________________

@Angry Badger - I managed to modify your 4-bit character input example. The difference is that I am using portD instead of C. The black bars across the first row now turns into 2 rows of light gray after about a half a second (So, the LCD was initialized? I don't see a black square in the first row or anything that your pictures indicate). However, the character commands do not work. No matter what I send in, the squares remain blank.

Here is the modified code I used:
Code:
//turns watch dog timer off, turn low voltage programming off, MCLR off need for +5V
#pragma config WDT=OFF, LVP=OFF, DEBUG=ON, MCLRE = OFF

//Internal oscillator, port function on RA6, EC used by USB 
#pragma config FOSC = INTOSCIO_EC 
#include <p18f4550.h>
#include <delays.h>

//Power LED (PortA)
#define LEDPin LATAbits.LATA0 //Define LEDPin as PORT D Pin 1

//LCD_RS: 0 = select instruction register, 1 = select data register
#define LCD_RS          LATDbits.LATD4      // RS = Register Select [lcd pin 04] pic pin 15
#define LCD_RW          LATDbits.LATD5      // RW = Read / Write [lcd pin 05] pic pin 16
#define LCD_En          LATDbits.LATD6      // En = Enable [lcd pin 06] pic pin 17
#define LCD_BF          PORTDbits.RD3       // BF = Busy Flag [pic pin 14]
#define LCDdata2port    LATD

void LCD_init (void);                       // subroutine for initialising lcd
void LCD_E (void);                          // subroutine for toggling lcd enable pin
void LCD_busy (void);                       // subroutine for reading lcd busy flag
void write2LCD (void);                      // subroutine for sending data to lcd
void LCD_char(void);                        // subroutine sets lcd RS pin and calls 'write to lcd' routine
void delay_250mS (void);                    // subroutine for 0.25s second delay

unsigned char data2LCD;                     // 8 bit variable
unsigned char RS_flag;                      // 8 bit variable


//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#pragma code
void main (void)
{

	TRISA = 0x00;
    ADCON1 = 0xF;                       // sets all analog channels as digital inputs

    TRISDbits.TRISD0 = 0;               // PORTD bit 0 (LCD pin11 [DB4])
    TRISDbits.TRISD1 = 0;               // PORTD bit 1 (LCD pin12 [DB5])
    TRISDbits.TRISD2 = 0;               // PORTD bit 2 (LCD pin13 [DB6])
    TRISDbits.TRISD3 = 0;               // PORTD bit 3 (LCD pin14 [DB7])
    TRISDbits.TRISD4 = 0;               // PORTD bit 4 (LCD pin4 [RS])
    TRISDbits.TRISD5 = 0;               // PORTD bit 5 (LCD pin5 [RW])
    TRISDbits.TRISD6 = 0;               // PORTD bit 6 (LCD pin6 [E])
    TRISDbits.TRISD7 = 0;               // PORTD bit 7
	
	LEDPin=1;	

    LATD = 0;
    PORTD = 0;
    LCD_RS = 0;
    LCD_RW = 0;
    LCD_En = 0;
    RS_flag = 0;
    data2LCD = 0;

    LCD_init();                         //call initialise lcd routine

//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

    while(1)                            // main program 'start'
    {

    data2LCD = 'p';                     // 0b01001000;
    LCD_char();                         // display it on lcd
    delay_250mS();

    data2LCD = 'i';                     // 0b01100101;
    LCD_char();
    delay_250mS();

    data2LCD = 'c';                     // 0b01101100;
    LCD_char();
    delay_250mS();


    while (!LCD_En);                    // stop and wait here - everything is done

    }
}

void LCD_char (void)
{
    RS_flag = 1;                        // memory flag (set for writing to data register)
    write2LCD();                        // send data or instruction to lcd
    RS_flag = 0;
}
// ***** Start of LCD initialization *****


void LCD_init (void)

{   // See the HD47780 or ST7066 data sheets
    //8 bit_mode;
    //start software reset.


    Delay10KTCYx(3);                    // wait MINIMUM 15mS - allow Vcc to settle

    LCDdata2port = 0b00000011;          // put the data on portC
    LCD_E();
    Delay1KTCYx(2);                     // wait 4mS as per data sheet (4.1mS says data sheet)

    LCDdata2port = 0b00000011;
    LCD_E();
    Delay10TCYx(3);                    // wait 100uS as per data sheet

    LCDdata2port = 0b00000011;          // data sheet bit hazy as to when exactly
    LCD_E();                            // 'busy' flag can be read
    LCD_busy();

    LCDdata2port = 0b00000010;          // can wait for busy flag from here
    LCD_E();
    LCD_busy();

    // end of software reset


    // 4 bit mode from here

    // (1) function set

    // Data Length = 4 bits, 2 (or 4) line display, 5x8 font
    //
    data2LCD = 0b00101000;
    write2LCD();

    //(2) display on/off control
    // turn on display, no cursor and no cursor flash
    //
    data2LCD = 0b00001100;
    write2LCD();

    // (3) clear display
    //
    data2LCD = 0b00000001;
    write2LCD();

    // (4) entry mode set
    //  cursor moves to right
    //
    data2LCD = 0b00000110;
    write2LCD();

}
// ********* end of LCD initialization **********

void delay_250mS (void)
{
    Delay10KTCYx(6.25);                               // wait 0.25S

}
void write2LCD (void)
{
    LCDdata2port = ((data2LCD >> 4) & 0xf);         // swap nyybles, clear upper nyyble on port
    if (RS_flag)                                    // set indicates reading / writing data, not 'instructions'
        LCD_RS = 1;                                 // set RS
    LCD_E();                                        // latch data into lcd

    LCDdata2port = ((data2LCD) & 0xf);
    if (RS_flag)
        LCD_RS = 1;                                 // set RS again - was cleared when 'data2LCD' ANDED
    LCD_E();                                        // latch data into lcd
    LCD_busy();                                     // check busy flag after second four bit write.
}

void LCD_E (void)                                   // toggle the lcd enable bit

{
    LCD_En = 1;
    LCD_En = 0;                                     // data read into lcd on high to low transition of E

}

void LCD_busy (void)                                // read lcd 'busy' flag
{
    LCD_RS = 0;                                     // cannot read the busy flag if RS = 1!
    TRISDbits.TRISD3 = 1;                           // When TRIS = 0 it's DB7, Tris = 1 it's lcd busy flag.
    LCD_RW = 1;
    LCD_En = 1;
    while (LCD_BF);                                 // wait until 'busy' flag clear
    LCD_En = 0;
    LCD_RW = 0;
    TRISDbits.TRISD3 = 0;

}

If I can't get this to work could you guys maybe recommend a 2x16 LCD that you have used before so that it is easier to assist me? I would really appreciate it. Thanks.
 
Last edited:
I'm a little confused. In your first post you show the data pins connected to port B but in your later code you write to port D!

Can you confirm what is connected to where and post your latest code?

Mike.
 
I'm sorry for the confusion. I was trying out the other users code which required all of the LCD inputs to be on one port so I moved them over to port D. As a result the current connections are as follows:

E --> RD6
R_W --> RD5
RS --> RD4
DB7 --> RD3
DB6 --> RD2
DB5 --> RD1
DB4 --> RD0

I had V0 going to ground before, and now I have a 10k potentiometer going to it (Both produce dark enough boxes).

Latest code (following nehaven data sheet):

Code:
//turns watch dog timer off, turn low voltage programming off
#pragma config WDT=OFF, LVP=OFF, DEBUG=ON, MCLRE = OFF

//Internal oscillator, port function on RA6, EC used by USB 
#pragma config FOSC = INTOSCIO_EC 
#include <p18f4550.h>
#include <delays.h>

//Power LED (PortA)
#define LEDPin LATAbits.LATA0 //Define LEDPin as PORT D Pin 1

//LCD (Port B and 1 pin PortD)
#define  E	 LATDbits.LATD6 //Define LCD pinout E
#define  R_W LATDbits.LATD5 //Define LCD pinout R/W
#define  RS  LATDbits.LATD4 //Define LCD pinout RS
#define  DB7 LATDbits.LATD3 //Define LCD pinout DB7
#define  DB6 LATDbits.LATD2 //Define LCD pinout DB6
#define  DB5 LATDbits.LATD1 //Define LCD pinout DB5
#define  DB4 LATDbits.LATD0 //Define LCD pinout DB4


void command(char);
void write(char);
void Nybble(void);
void init(void);

void main()
{
	while(!OSCCONbits.IOFS);      //wait for osc stable
   	ADCON1 = 0x0F;                //make RA0 digital
  
    //data direction registers all 0's mean that all pins are set to output
	//all 1's means that all of the pins are set to operate as inputs
	TRISA = 0x00;  
	TRISB = 0x00; 
	TRISD = 0x00;
	while(1)
	{
		LEDPin=1;
		init();
		break;
	}
}

/**********************************************************/
//4-bit methods for LCD
/**********************************************************/
void command(char i)
{
//	P1 = i; //put data on output Port
//	D_I =0; //D/I=LOW : send instruction
	RS =0;

	DB7 = ((i>>3)&'1');
	DB6 = ((i>>2)&'1'); 
	DB5 = ((i>>1)&'1');
	DB4 = i&'1';

	R_W =0;   //R/W=LOW : Write
	Nybble(); //Send lower 4 bits
	
	DB7 = ((i>>7)&'1');
	DB6 = ((i>>6)&'1'); 
	DB5 = ((i>>5)&'1');
	DB4 = ((i>>4)&'1');


	Nybble(); //Send upper 4 bits
}

void write(char i)
{
	Delay1KTCYx(1.25);  //must wait 5ms, busy flag not available (used 5ms)
	//P1 = i; //put data on output Port
	//D_I =1; //D/I=HIGH : send data
	RS= 1;
	DB7 = ((i>>7)&'1');
	DB6 = ((i>>6)&'1'); 
	DB5 = ((i>>5)&'1');
	DB4 = ((i>>4)&'1');

	R_W =0; //R/W=LOW : Write
	Nybble(); //Clock lower 4 bits

//	P1 = i; //put data on output Port
	DB7 = ((i>>3)&'1');
	DB6 = ((i>>2)&'1'); 
	DB5 = ((i>>1)&'1');
	DB4 = i&'1';

	Nybble(); //Clock upper 4 bits
}

/**********************************************************/
void Nybble(void)
{
	E = 1;
	Delay1TCY(); //enable pulse width >= 300ns (used 4uS)
	E = 0; //Clock enable: falling edge
}

/**********************************************************/
void init(void)
{
	//P1 = 0;
	//P3 = 0;
		DB7 = 0;
		DB6 = 0; 
		DB5 = 0;
		DB4 = 0;

	Delay1KTCYx(5); //Wait >15 msec after power is applied (used 20mS)
	//P1 = 0x30; //put 0x30 on the output port

	//command(0x30);
	
		DB7 = 0;
		DB6 = 0; 
		DB5 = 1;
		DB4 = 1;

	
	Delay1KTCYx(1.25);  //must wait 5ms, busy flag not available (used 5ms)
	Nybble(); 			//command 0x30 = Wake up
	Delay10TCYx(5); 	//must wait 160us, busy flag not available (used 160uS)
	Nybble(); 			//command 0x30 = Wake up #2
	Delay10TCYx(5); 	//must wait 160us, busy flag not available (used 160uS)
	Nybble(); 			//command 0x30 = Wake up #3
	Delay10TCYx(5); 	//can check busy flag now instead of delay
	//P1= 0x20; 		//put 0x20 on the output port

	//command(0x20);
		DB7 = 0;
		DB6 = 0; 
		DB5 = 1;
		DB4 = 0;

	Nybble(); //Function set: 4-bit interface
	command(0x28); //Function set: 4-bit/2-line
	command(0x10); //Set cursor
	command(0x0F); //Display ON; Blinking cursor
	command(0x06); //Entry Mode set
}
/**********************************************************/
//End methods for LCD
/**********************************************************/

Also, in case anyone is confused the following lines are used to just shift and mask the upper and lower nibbles ( I tried playing with the order of lower and upper nibble I feed in first, but it doesn't seem to affect it):

Code:
       ...
       //Shift and mask upper nibble bits and send them out the corresponding pins
        DB7 = ((i>>7)&'1');
	DB6 = ((i>>6)&'1'); 
	DB5 = ((i>>5)&'1');
	DB4 = ((i>>4)&'1');
        ...
        //Shift and mask lower nibble bits and send them out the corresponding pins
	DB7 = ((i>>3)&'1');
	DB6 = ((i>>2)&'1'); 
	DB5 = ((i>>1)&'1');
	DB4 = i&'1';
I believe the default frequency of oscillation is 1MHz. I have tested this using the following code with the LED I have connected:

Code:
#define LEDPin LATAbits.LATA0 //Define LEDPin as PORT A Pin 1
...
while(1)
{
     //Delay 250K cycles (1 second at 1MHz since each instruction takes 4 cycles)
     Delay10KTCYx(25);
     LEDPin = ~LEDPin; //constantly inverts output
}
...
 
Last edited:
The write sequence of the nibbles is high nibble first. You have it the wrong way around in your command function. You also don't have a delay in your command function. After a command write you should wait at least 2mS, for data it only needs to be 50uS.

The other big error I spotted was the lines,
Code:
    DB7 = ((i>>7)&'1');
This is wrong as it will AND the bit with the ascii for 1 which is 0x31. Whilst it will actually work, it is a bad way to do things. So, simply change those lines to,
Code:
    DB7 = ((i>>7) & 1);


Or, you could make your Nybble routine take data,
Code:
#define LCDdata LATD

void Nybble(unsigned char dat)
{
    dat &= 0x0f;             //clear top bits of dat
    LCDdata &= 0xf0;         //clear bottom bits of port
    LCDdata |= dat;          //or the two and store at port
    E = 1;
    Delay1TCY();             //enable pulse width >= 300ns (used 4uS)
    E = 0;                   //Clock enable: falling edge
}

And now your Command routine can be,
Code:
void command(char i)
{
	RS =0;
	R_W =0;          //R/W=LOW : Write
	Nybble(i>>4);    //Send upper 4 bits
	Nybble(i);       //Send lower 4 bits
	Delay1KTCYx(2);  //must wait 2mS
}

You will of course have to change your init routine and note that to write 0x30 (wakeup) you will simply do Nybble(0x03).

Mike.
 
Last edited:
Thank you Pommie for the helpful response. I modified my code to include your simple yet more elegant solution, and I will keep in mind to use 1 instead of '1' when masking individual bits. However, I still see a black row of squares. The only difference is that I now see a blinking cursor (as the bottom of the init function indicates) right before the top row turns into black squares (so I think we are on the right track).

Here is my latest code with your revisions:

Code:
//turns watch dog timer off, turn low voltage programming off
#pragma config WDT=OFF, LVP=OFF, DEBUG=ON, MCLRE = OFF
 
//Internal oscillator, port function on RA6, EC used by USB 
#pragma config FOSC = INTOSCIO_EC 
#include <p18f4550.h>
#include <delays.h>
 
//Power LED (PortA)
#define LEDPin LATAbits.LATA0 //Define LEDPin as PORT A Pin 1
 
//LCD (PortD)
#define  E LATDbits.LATD6
#define  R_W LATDbits.LATD5 
#define  RS  LATDbits.LATD4
#define LCDdata LATD
 
 
void command(unsigned char);
void write(unsigned char);
void Nybble(unsigned char);
void init(void);
 
void main()
{
	while(!OSCCONbits.IOFS);      //wait for osc stable
   	ADCON1 = 0x0F;                //make RA0 digital
 
    //data direction registers all 0's mean that all pins are set to output
	//all 1's means that all of the pins are set to operate as inputs
	TRISA = 0x00;  
	TRISB = 0x00; 
	TRISD = 0x00;
	while(1)
	{
		LEDPin=1;
		init();
		break;
	}
}
 
/**********************************************************/
//4-bit methods for LCD
/**********************************************************/
void command(unsigned char i)
{
	RS =0;
	R_W =0;          //R/W=LOW : Write
	Nybble(i>>4);    //Send upper 4 bits
	Nybble(i);       //Send lower 4 bits
	Delay1KTCYx(2);  //must wait at least 2mS (2*1000*4/1e6 = 8ms used)
}
 
void write(unsigned char i)
{
	RS =0;
	R_W =0;          //R/W=LOW : Write
	Nybble(i>>4);    //Send upper 4 bits
	Nybble(i);       //Send lower 4 bits
	Delay1KTCYx(2);  //must wait 2mS
}
 
/**********************************************************/
void Nybble(unsigned char dat)
{
    dat &= 0x0f;             //clear top bits of dat
    LCDdata &= 0xf0;         //clear bottom bits of port (interested only in DB7-DB4)
    LCDdata |= dat;          //or the two and store at port
    E = 1;
    Delay1TCY();             //enable pulse width >= 300ns (used 4uS)
    E = 0;                   //Clock enable: falling edge
}
 
/**********************************************************/
void init(void)
{
	LCDdata=0x00;
 
	Delay1KTCYx(5); //Wait >15 msec after power is applied (used 20mS)
	//P1 = 0x30; //put 0x30 on the output port  
 
	Delay1KTCYx(1.25);  //must wait 5ms, busy flag not available (used 5ms)
	Nybble(0x30); 	       //command 0x30 = Wake up
	Delay10TCYx(5);        //must wait 160us, busy flag not available (used 160uS)
	Nybble(0x30); 	       //command 0x30 = Wake up #2
	Delay10TCYx(5); 	//must wait 160us, busy flag not available (used 160uS)
	Nybble(0x30); 	        //command 0x30 = Wake up #3
	Delay10TCYx(5); 	//can check busy flag now instead of delay

	//P1= 0x20; 		//put 0x20 on the output port

	Nybble(0x20); //Function set: 4-bit interface
	command(0x28); //Function set: 4-bit/2-line
	command(0x10); //Set cursor
	command(0x0F); //Display ON; Blinking cursor
	command(0x06); //Entry Mode set
	
	
}
/**********************************************************/
//End methods for LCD
/**********************************************************/

Should I use some commands to clear the screen ( I believe 0x01 clears the screen)? Maybe the initialization routine is missing some commands?

EDIT1:
_________

I tried using clear screen and changing Display command from 0x0F to 0x0B, but it didn't work. I still get a row of black squares after about a second of applying power.

Code:
//Bottom of initialization function
        Nybble(0x20); //Function set: 4-bit interface
	command(0x28); //Function set: 4-bit/2-line
	command(0x10); //Set cursor
	command(0x0B); //Display ON (Changed from 0x0F to 0x0B)
	command(0x01); //Clear Display (Added)
	command(0x06); //Entry Mode set

I also tried switching the nibble statements like you suggest above: nybble(0x03) and nybble(0x02) instead of 0x30 and 0x20

EDIT2:
_________

I adjusted the contrast so that the black boxes are barely visible and now I can see a blinking cursor fly by the screen. However, I still only see one row, and I am not sure if I can write a character to the display since I tried the line "write(0x30);" in main, which should put the number zero on the screen.

Here is a video showing how I adjusted the pot and what I currently see displayed on the character LCD:

https://www.youtube.com/watch?v=8OKNH_HdXA0
 
Last edited:
This has been bugging me and so I dug out my Unicorn board, put a 2*16 LCD on it and got it working.

I had to change the init routine and the write (RS=1). Plus I added a PutMessage routine.

Here's the result,

Code:
//turns watch dog timer off, turn low voltage programming off
#pragma config WDT=OFF, LVP=OFF, DEBUG=ON, MCLRE = OFF
 
//Internal oscillator, port function on RA6, EC used by USB 
#pragma config FOSC = INTOSCIO_EC 
#include <p18f4550.h>
#include <delays.h>
 
//Power LED (PortA)
#define LEDPin LATAbits.LATA0 //Define LEDPin as PORT A Pin 1
 
//LCD (PortD)
#define  E LATDbits.LATD6
#define  R_W LATDbits.LATD5 
#define  RS  LATDbits.LATD4
#define LCDdata LATD
 
 
void command(unsigned char);
void write(unsigned char);
void Nybble(unsigned char);
void init(void);
void PutMessage(rom char *);

void main()
{
	while(!OSCCONbits.IOFS);      //wait for osc stable
   	ADCON1 = 0x0F;                //make RA0 digital
 
    //data direction registers all 0's mean that all pins are set to output
	//all 1's means that all of the pins are set to operate as inputs
	TRISA = 0x00;  
	TRISB = 0x00; 
	TRISD = 0x00;
        init();
        PutMessage("Hello World!");
        command(0xc0);
        PutMessage("Second Line.");
        while(1);
}
 
//Write a string to the LCD
void PutMessage(rom char *Message){
rom char *Pos = Message;
	while(*Pos!=0)
	    write(*Pos++);
}
 
/**********************************************************/
//4-bit methods for LCD
/**********************************************************/
void command(unsigned char i)
{
	RS =0;
	R_W =0;          //R/W=LOW : Write
	Nybble(i>>4);    //Send upper 4 bits
	Nybble(i);       //Send lower 4 bits
	Delay1KTCYx(2);  //must wait at least 2mS (2*1000*4/1e6 = 8ms used)
}
 
void write(unsigned char i)
{
	RS =1;
	R_W =0;          //R/W=LOW : Write
	Nybble(i>>4);    //Send upper 4 bits
	Nybble(i);       //Send lower 4 bits
	Delay1KTCYx(2);  //must wait 2mS
}
 
/**********************************************************/
void Nybble(unsigned char dat)
{
    dat &= 0x0f;             //clear top bits of dat
    LCDdata &= 0xf0;         //clear bottom bits of port (interested only in DB7-DB4)
    LCDdata |= dat;          //or the two and store at port
    E = 1;
    Delay1TCY();             //enable pulse width >= 300ns (used 4uS)
    E = 0;                   //Clock enable: falling edge
}
 
/**********************************************************/
void init(void)
{
    LCDdata=0x00; 
    Delay1KTCYx(15);    //Wait >15 msec after power is applied (used 20mS)
    Nybble(0x3); 	//command 0x30 = Wake up
    Delay1KTCYx(5);     //must wait 160us, busy flag not available (used 160uS)
    Nybble(0x3); 	//command 0x30 = Wake up #2
    Delay1KTCYx(5); 	//must wait 160us, busy flag not available (used 160uS) 
	
    command(0x20);      //Function set: 4-bit/2-line
    command(0x2c);      //Function set: 4-bit/2-line
    command(0x10);      //Set cursor
    command(0x01);      //Clear Display (Added)
    command(0x06);      //Entry Mode set
    command(0x0c);
}
/**********************************************************/
//End methods for LCD
/**********************************************************/
Let me know if this works or not.

Mike.
 

Attachments

  • LCD.jpg
    128.5 KB · Views: 2,502
Last edited:
hey micro 9000
Code:
while(1)
	{
		LEDPin=1;
		init();
		break;
	}
in the main loop, there is nothing that redirects you to the display routine.. i think that is the problem..
 
@Pommie Thank you so much for your help, but there is still a problem. The newer bit of code that you added does appear to properly initialize the LCD, but I only see a blinking cursor. The only thing I modified was changing "Hello World! Second Line" to just "Hello world."

Code:
init();
        PutMessage("Hello");
        command(0xc0);
        PutMessage("World");

Here is a video demonstrating the problem.

https://www.youtube.com/watch?v=60lzKOm9_20

Even more perplexing is that if I remove the "put messages" or I change them in anyway the blinking cursor in the video is no longer be displayed. I'm guessing that it was just luck that I put in the correct amount of characters for the display to output that blinking cursor that is present in the video. However, I now see two rows of boxes instead of just a single row.

@magnatro Yeah, I didn't call to the display routine since I just wanted to see a blink cursor so I could tell if the LCD initialized correctly. I'm not sure if there is a requirement to call the write or command routine in order to see what I have shown in the video.
 
Last edited:
Again, I thank you for taking the time and for your assistance. The code is the same. The only line I changed is in main where the put messages reside.

Code:
//turns watch dog timer off, turn low voltage programming off
#pragma config WDT=OFF, LVP=OFF, DEBUG=ON, MCLRE = OFF
 
//Internal oscillator, port function on RA6, EC used by USB 
#pragma config FOSC = INTOSCIO_EC 
#include <p18f4550.h>
#include <delays.h>
 
//Power LED (PortA)
#define LEDPin LATAbits.LATA0 //Define LEDPin as PORT A Pin 1
 
//LCD (PortD)
#define  E LATDbits.LATD6
#define  R_W LATDbits.LATD5 
#define  RS  LATDbits.LATD4
#define LCDdata LATD
 
 
void command(unsigned char);
void write(unsigned char);
void Nybble(unsigned char);
void init(void);
void PutMessage(rom char *);
 
void main()
{
	while(!OSCCONbits.IOFS);      //wait for osc stable
   	ADCON1 = 0x0F;                //make RA0 digital
 
    //data direction registers all 0's mean that all pins are set to output
	//all 1's means that all of the pins are set to operate as inputs
	TRISA = 0x00;  
	TRISB = 0x00; 
	TRISD = 0x00;
        init();
        PutMessage("Hello");
        command(0xc0);
        PutMessage("World");
        while(1);
}
 
//Write a string to the LCD
void PutMessage(rom char *Message){
rom char *Pos = Message;
	while(*Pos!=0)
	    write(*Pos++);
}
 
/**********************************************************/
//4-bit methods for LCD
/**********************************************************/
void command(unsigned char i)
{
	RS =0;
	R_W =0;          //R/W=LOW : Write
	Nybble(i>>4);    //Send upper 4 bits
	Nybble(i);       //Send lower 4 bits
	Delay1KTCYx(2);  //must wait at least 2mS (2*1000*4/1e6 = 8ms used)
}
 
void write(unsigned char i)
{
	RS =1;
	R_W =0;          //R/W=LOW : Write
	Nybble(i>>4);    //Send upper 4 bits
	Nybble(i);       //Send lower 4 bits
	Delay1KTCYx(2);  //must wait 2mS
}
 
/**********************************************************/
void Nybble(unsigned char dat)
{
    dat &= 0x0f;             //clear top bits of dat
    LCDdata &= 0xf0;         //clear bottom bits of port (interested only in DB7-DB4)
    LCDdata |= dat;          //or the two and store at port
    E = 1;
    Delay1TCY();             //enable pulse width >= 300ns (used 4uS)
    E = 0;                   //Clock enable: falling edge
}
 
/**********************************************************/
void init(void)
{
    LCDdata=0x00; 
    Delay1KTCYx(15);    //Wait >15 msec after power is applied (used 20mS)
    Nybble(0x3); 	//command 0x30 = Wake up
    Delay1KTCYx(5);     //must wait 160us, busy flag not available (used 160uS)
    Nybble(0x3); 	//command 0x30 = Wake up #2
    Delay1KTCYx(5); 	//must wait 160us, busy flag not available (used 160uS) 
 
    command(0x20);      //Function set: 4-bit/2-line
    command(0x2c);      //Function set: 4-bit/2-line
    command(0x10);      //Set cursor
    command(0x01);      //Clear Display (Added)
    command(0x06);      //Entry Mode set
    command(0x0c);
}
/**********************************************************/
//End methods for LCD
/**********************************************************/
 
Last edited:
I'm not sure what to suggest as that code works fine on my setup. Have you double checked your wiring?

Mike.
 
I'll double check it again and I'll try a few things with the code as well.

EDIT:
Wiring was incorrect. The way that the uC is oriented with the ribbon cables the wires were mixed up. It was a bit hard too see, but I had the data lines mixed up. I'm sorry for not checking more carefully. I'm going to test it out right now.

EDIT2: That did the trick thank you so very much. I'll post video in a sec.
 
Last edited:
Thank you everyone so much, I made a video to show a token of my appreciation:

https://www.youtube.com/watch?v=ZkrgRjbVZtQ

Here is the final code with the routine shown in the video:

Code:
//turns watch dog timer off, turn low voltage programming off
#pragma config WDT=OFF, LVP=OFF, DEBUG=ON, MCLRE = OFF
 
//Internal oscillator, port function on RA6, EC used by USB 
#pragma config FOSC = INTOSCIO_EC 
#include <p18f4550.h>
#include <delays.h>
 
//Power LED (PortA)
#define LEDPin LATAbits.LATA0 //Define LEDPin as PORT A Pin 1
 
//LCD (PortD)
#define  E LATDbits.LATD6
#define  R_W LATDbits.LATD5 
#define  RS  LATDbits.LATD4
#define LCDdata LATD
 
 
void command(unsigned char);
void write(unsigned char);
void Nybble(unsigned char);
void init(void);
void PutMessage(rom char *);
 
void main()
{
	while(!OSCCONbits.IOFS);      //wait for osc stable
   	ADCON1 = 0x0F;                //make RA0 digital
 
    //data direction registers all 0's mean that all pins are set to output
	//all 1's means that all of the pins are set to operate as inputs
	TRISA = 0x00;  
	TRISB = 0x00; 
	TRISD = 0x00;
        init();

		while(1)
		{
        	PutMessage("Thanks");
        	command(0xc0);
        	PutMessage("Pommie");
			Delay10KTCYx(50);

			command(0x01);      //Clear Display (Added)
			
			PutMessage("Thank");
       		command(0xc0);
        	PutMessage("You");
			Delay10KTCYx(50);

			command(0x01);      //Clear Display (Added)
			PutMessage("Electro");
        	command(0xc0);
        	PutMessage("tech");
			Delay10KTCYx(50);
	
			command(0x01);      //Clear Display (Added)

			PutMessage("Forum");
        	command(0xc0);
        	PutMessage("members");
			Delay10KTCYx(50);

			command(0x01);      //Clear Display (Added)
		}
        
}
 
//Write a string to the LCD
void PutMessage(rom char *Message){
rom char *Pos = Message;
	while(*Pos!=0)
	    write(*Pos++);
}
 
/**********************************************************/
//4-bit methods for LCD
/**********************************************************/
void command(unsigned char i)
{
	RS =0;
	R_W =0;          //R/W=LOW : Write
	Nybble(i>>4);    //Send upper 4 bits
	Nybble(i);       //Send lower 4 bits
	Delay1KTCYx(2);  //must wait at least 2mS (2*1000*4/1e6 = 8ms used)
}
 
void write(unsigned char i)
{
	RS =1;
	R_W =0;          //R/W=LOW : Write
	Nybble(i>>4);    //Send upper 4 bits
	Nybble(i);       //Send lower 4 bits
	Delay1KTCYx(2);  //must wait 2mS
}
 
/**********************************************************/
void Nybble(unsigned char dat)
{
    dat &= 0x0f;             //clear top bits of dat
    LCDdata &= 0xf0;         //clear bottom bits of port (interested only in DB7-DB4)
    LCDdata |= dat;          //or the two and store at port
    E = 1;
    Delay1TCY();             //enable pulse width >= 300ns (used 4uS)
    E = 0;                   //Clock enable: falling edge
}
 
/**********************************************************/
void init(void)
{
    LCDdata=0x00; 
    Delay1KTCYx(15);    //Wait >15 msec after power is applied (used 20mS)
    Nybble(0x3); 	//command 0x30 = Wake up
    Delay1KTCYx(5);     //must wait 160us, busy flag not available (used 160uS)
    Nybble(0x3); 	//command 0x30 = Wake up #2
    Delay1KTCYx(5); 	//must wait 160us, busy flag not available (used 160uS) 
 
    command(0x20);      //Function set: 4-bit/2-line
    command(0x2c);      //Function set: 4-bit/2-line
    command(0x10);      //Set cursor
    command(0x01);      //Clear Display (Added)
    command(0x06);      //Entry Mode set
    command(0x0c);
}
/**********************************************************/
//End methods for LCD
/**********************************************************/

Solved
 
Congratulations. Now you can have some fun with the rest of your project.

Mike.
 
HI Micro9900 , I have problem with this code I am using MPLAB IDE V8.8 this is code is debagieng fine with using MPLAB but when i sent to simulation with software proteus the micro-controller pic18f4550 not work also the LCD doesn't display anything I will attach the circuit to show u the connection thanks for helping me


this is the code :
#pragma config PLLDIV = 5
#pragma config USBDIV =2
#pragma config FOSC = HSPLL_HS

// In the next two lines, comment out either the fast clock or the slow clock

#pragma config CPUDIV = OSC1_PLL2 // Fast Clock
//#pragma config CPUDIV = OSC4_PLL6 // Slow Clock

#pragma config WDT = OFF, LVP = OFF

#include <p18f4550.h>
#include <delays.h>
#include <adc.h>
#include <xlcd.h>
#include <stdlib.h>

#define UPPER;
#define DATA_PORT PORTB ;
#define TRIS_DATA_PORT TRISB ;


#define RW_PIN PORTBbits.RB1; /* PORT for RW */
#define TRIS_RW DDRBbits.RB1 ; /* TRIS for RW */
#define RS_PIN PORTBbits.RB2; /* PORT for RS */
#define TRIS_RS DDRBbits.RB2; /* TRIS for RS */
#define E_PIN PORTBbits.RB0; /* PORT for E */
#define TRIS_E DDRBbits.RB0; /* TRIS for E */


void Delay_1msX (unsigned int miliseconds);
void Delay_100msX (unsigned int msec);
void SetCGRamAddr( unsigned char addr );
void ClearXLCD(void);
void SetCurXLCD(unsigned char data);
unsigned int i, t;
void main ()
{
//set I/O input output
TRISB = 0b00000000; //Configure PORTB I/O direction
//Configure PORTD I/O direction
PORTB = 0;

OpenXLCD( FOUR_BIT & LINES_5X7 );



WriteCmdXLCD(0x01); //Clear display

SetCGRamAddr(0x40); //Goto CGRAM address #1


// 90 Degree Rotated 'RH'
putcXLCD(0b11111);
putcXLCD(0b00100);
putcXLCD(0b11111);
putcXLCD(0b00000);
putcXLCD(0b01001);
putcXLCD(0b10101);
putcXLCD(0b10110);
putcXLCD(0b11111);

// 90 Degree Rotated '2T'
putcXLCD(0b10000);
putcXLCD(0b11111);
putcXLCD(0b10000);
putcXLCD(0b00000);
putcXLCD(0b01001);
putcXLCD(0b10101);
putcXLCD(0b10011);
putcXLCD(0b01001);

// Battery 1
putcXLCD(0b01110);
putcXLCD(0b11011);
putcXLCD(0b10001);
putcXLCD(0b10001);
putcXLCD(0b10001);
putcXLCD(0b10011);
putcXLCD(0b10111);
putcXLCD(0b11111);

// Battery 2
putcXLCD(0b01110);
putcXLCD(0b11011);
putcXLCD(0b10001);
putcXLCD(0b10001);
putcXLCD(0b10011);
putcXLCD(0b10111);
putcXLCD(0b11111);
putcXLCD(0b11111);

// Battery 3
putcXLCD(0b01110);
putcXLCD(0b11011);
putcXLCD(0b10001);
putcXLCD(0b10011);
putcXLCD(0b10111);
putcXLCD(0b11111);
putcXLCD(0b11111);
putcXLCD(0b11111);

// Battery 4
putcXLCD(0b01110);
putcXLCD(0b11011);
putcXLCD(0b10011);
putcXLCD(0b10111);
putcXLCD(0b11111);
putcXLCD(0b11111);
putcXLCD(0b11111);
putcXLCD(0b11111);

// Battery 5
putcXLCD(0b01110);
putcXLCD(0b11011);
putcXLCD(0b10111);
putcXLCD(0b11111);
putcXLCD(0b11111);
putcXLCD(0b11111);
putcXLCD(0b11111);
putcXLCD(0b11111);

// Battery 6
putcXLCD(0b01110);
putcXLCD(0b11111);
putcXLCD(0b11111);
putcXLCD(0b11111);
putcXLCD(0b11111);
putcXLCD(0b11111);
putcXLCD(0b11111);
putcXLCD(0b11111);

WriteCmdXLCD(0x01); //Clear display

SetCurXLCD(0); //Set cursor to line 1, position 0
putcXLCD(1); //Display user-defined graphic 1
SetCurXLCD(20); //Set cursor to line 2, position 0
putcXLCD(0); //Display user-defined graphic 0

SetCurXLCD(2); //Set cursor to line 1, position 2
for(i=2;i<8;i++) //Display user-defined graphic 2 to 7
{
putcXLCD(i);
}
putrsXLCD(" SK40C"); //Display "SK40C"

while(1) //Loop the battery level graphics
{
for(i=0;i<6;i++) //Refresh battery level graphics
{ //continuously every 500ms

SetCurXLCD(22); //Set cursor to line 2, position 2
putcXLCD(i+2); //Display current user-defined graphic
Delay_100msX(5); //Delay 500ms
}
}
}

void Delay_1msX (unsigned int miliseconds)
{
t=0;
while(t<miliseconds)
{
Delay1KTCYx(11);
Delay10TCYx(96);
Nop();
Nop();
Nop();
Nop();
Nop();
t++;
}
}

void Delay_100msX (unsigned int msec)
{
t=0;
while(t<msec)
{
Delay10KTCYx(119);
Delay1KTCYx(9);
Delay10TCYx(96);
t++;
}
}

void SetCurXLCD(unsigned char data)
{
if(data<16)
{
SetDDRamAddr(0x80+data);
}
else
{
data=data-20;
SetDDRamAddr(0xc0+data);
}
}
void DelayPORXLCD (void)
{
Delay1KTCYx(60);
return;
}

void DelayFor18TCY (void)
{

Nop();
Nop();
Nop();
Nop();

}
 
Status
Not open for further replies.
Cookies are required to use this site. You must accept them to continue using the site. Learn more…