LCD HD44780 Generic Driver 4Bit mode (working)

Go To Last Post
33 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Dear All

I want share with you my 1st Generic LCD HD44780 (4 Bit mode) Driver for AVR micro controllers (write Pin of the LCD is connected to Ground),

 and it's tested and working.

 

I mean by Generic,

 It's independent of the hardware connection of the LCD to the AVR micro controller ,you can connect any pin of the LCD data line and control line to any pin on any port of the micro controller, it doesn't need to connect the 4 bit Data line of the LCD to the same port in sequence ,

for example you can connect LCD Pin 4 to (port C  Pin 0), LCD Pin 5 to (port D  Pin 2) , LCD Pin 6 to (port B  Pin 5) , LCD Pin 7 to (port C  Pin 4)

,and  the control lines RS,EN (W pin is tied to ground)

LCD EN Pin  to (port D  Pin 3)

LCD RS Pin  to (port B  Pin 2)

this just an example you can connect any LCD pin to any pin on the micro controller port .

 

and support many functions,

 

* displaying single character at any location on the lcd

* displaying string   at any location on the lcd

* displaying double,float,int numbers  at any location on the lcd

 

How to use

 

*-It's easy just open the header file "KH_AVR_LCD HD44780 Lib.h"

*- Go to the section "Hardware Data Lines Configuration" and change the values of the ports name and pin number as your hardware connections

*- Go to the section "Hardware Control Configuration" and change the values of the ports name and pin number as your hardware connections

*- Save the header file 

*- compile your application

That's all 

 

I'll appreciate any optimizations or modifications from you

 

Header File KH_AVR_LCD HD44780 Lib.h

#ifndef KH_LCD_H
#define KH_LCD_H

#include <inttypes.h>
#ifndef F_CPU						//if the frequency not explicitly defined
	#define	F_CPU 16000000UL		//then define it with the mentioned value
#endif

#ifndef _UTIL_DELAY_H_				//if the delay header is not included
	#include <util/delay.h>         //then include it
#endif

#define COMMAND_DELAY 2				//delay time between successive commands in millisecond								(Don't Change it)
#define PULSE_DELAY 1               //delay for the Enable pulse of the enable pin of the LCD in microsecond			(Don't Change it) 

#define DATA_VARIES_PORTS 1		    //defines if the data lines of the LCD connected to varies ports pins or to single port pins 0=single port   1= connected to varies ports	    (Don't Change it)
#define Control_VARIES_PORTS 1		//defines if the Control lines of the LCD connected to varies ports pins or to single port pins 0=single port   1= connected to varies ports	(Don't Change it)		

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
                                       //LCD connection to the micro controller (4Bit mode) (the write Pin W is tied to ground)
//HardWare Data Lines Configuration
#define DPORT			PORTD		//The Data Lines (of the LCD) Port (connected to single port)	(Change it as your needs)
#define DATA_DDR		DDRD		//Data lines Data Direction port (connected to single port)

#define DLINE_7P		PORTD       //Data line 7 Port of  the micro controller						(Change it as your needs)
#define DLINE_6P		PORTB	    //Data line 6 Port of  the micro controller						(Change it as your needs)
#define DLINE_5P		PORTD	    //Data line 5 Port of the micro controller						(Change it as your needs)
#define DLINE_4P		PORTC	    //Data line 4 Port of the micro controller						(Change it as your needs)

#define DLINE_7D		DDRD        //Data line 7 Data Direction Port of  the micro controller				(Change it as your needs)
#define DLINE_6D		DDRB	    //Data line 6 Data Direction Port of  the micro controller				(Change it as your needs)
#define DLINE_5D		DDRD	    //Data line 5 Data Direction Port of the micro controller				(Change it as your needs)
#define DLINE_4D		DDRC	    //Data line 4 Data Direction Port of the micro controller				(Change it as your needs)

#define DLINE_7		3				//Data line 7 of the LCD connection to the micro controller Pin number  (pin7 of LCD to Pin 3 Port D Micro controller) (Change it as your needs)
#define DLINE_6		2				//Data line 6 of the LCD connection to the micro controller Pin number			(Change it as your needs)
#define DLINE_5		7				//Data line 5 of the LCD connection to the micro controller Pin number			(Change it as your needs)
#define DLINE_4		3				//Data line 4 of the LCD connection to the micro controller Pin number			(Change it as your needs)

						/**********************************************************/

// Hardware Control Configuration
#define CPORT		PORTB			// The command Port which are RS and EN connected to (connected to single port)				(Change it as your needs)
#define CTRL_DDR	DDRB			// Control Lines Data Direction port (connected to single port)								(Change it as your needs)

#define RS_P		PORTC			//The port which control lines of the LCD connected to(RS)									(Change it as your needs)
#define EN_P		PORTB			//The port which control lines of the LCD connected to (EN)									(Change it as your needs)

#define RS_D		DDRC			//the Data Direction Register for RS pin													(Change it as your needs)
#define EN_D		DDRB			//the Data Direction Register for EN pin
									//If RS =1 Data register is selected, If RS=0 Instruction register(command register) is selected
									//to enable write or read a pulse High to Low must be send to this pin
#define RS			0				//Control Line of the LCD connection to the micro controller Pin number  (RS pin Connected to PORT C Pin 0)		(Change it as your needs)
#define EN			1				//Control Line of the LCD connection to the micro controller Pin number						(Change it as your needs)

/*------------------------------------------------------------------------------------------------------*/
			//D=Display		B=Blink Character		C=Cursor
#define LCD_RETURN_HOME 			0x02	//need 1.52ms to execute, Sets DDRAM address 0 in address counter. Also returns display from being shifted to original position.DDRAM contents remain unchanged.
#define LCD_CLEAR					0x01	//Clear the display and set DDRam address to 0 in the address counter AC
#define LCD_4Bit2Line				0x28	//Set the data length = 4 bit and number of display lines = 2 , font size 5x8 dot
#define LCD_4Bit1Line				0x20	//Set the data length = 4 bit and number of display lines = 1 , font size 5x8 dot
//Entry mode set
#define LCD_Dec_ShiftOff			0x04	//Entry mode set : Sets cursor move direction to Left (decrement) and specifies display shift Off
#define LCD_Dec_ShiftOn				0x05	//Entry mode set : Sets cursor move direction to Left (decrement) and specifies display shift On
#define LCD_Inc_ShiftOff			0x06    //Entry mode set : Sets cursor move direction to right (incrementing) and specifies display shift to non (Display is not shifted).These operations are performed during data write and read.
#define LCD_Inc_ShiftOn				0x07	//Entry mode set : Sets cursor move direction to right (incrementing) and specifies display shift on
//Display control
#define LCD_DOn_COff_BOff			0x0C	//Turn On the display, Cursor Off and blinking character off
#define LCD_DOn_COn_BOn		    	0x0F	//Turn On the display, Cursor On  and blinking character On
#define LCD_DOn_COff_BOn			0x0D	//Turn On the display, Cursor Off and blinking character On
#define LCD_DOn_COn_BOff			0x0E	//Turn On the display, Cursor On  and blinking character Off
//////////////
#define LCD_DOff_COff_BOff			0x08	//Turn Off the display, Cursor Off and blinking character off
#define LCD_DOff_COn_BOn		    0x0B	//Turn Off the display, Cursor On  and blinking character On
#define LCD_DOff_COff_BOn			0x09	//Turn Off the display, Cursor Off and blinking character On
#define LCD_DOff_COn_BOff			0x0A	//Turn Off the display, Cursor On  and blinking character Off
//Cursor or Display Shift
#define LCD_SHLFTCUR				0x10	//Shift Left Cursor	,Moves cursor and shifts display without changing DDRAM contents.
#define LCD_SHRGTCUR				0x14	//shift Right Cursor ,Moves cursor and shifts display without changing DDRAM contents
#define LCD_SHLFTDSP				0x18	//Shift Left Entire Display ,Moves cursor and shifts display without changing DDRAM contents
#define LCD_SHRGTDSP				0x1C    //Shift Right Entire Display ,,Moves cursor and shifts display without changing DDRAM contents
/*
The instruction to write a character at a certain location on the display in case of 16x2 display
by writing  the location  to DDRAM address crossponding to the required location

1st line
display position in DDRAM				  1	    2	3	4	5	6	7	8	9	10	11	12	13	14	15	16.........40
DDRAM address in HEX					  00	01	02	03	04	05	06	07	08	09	0A	0B	0C	0D	0E	0F		  	

2nd Line
display position in DDRAM		           41   42   43   44   45   46   47   48   49   50   51   52   53   54   55   56     --------------80
DDRAM address in HEX					   40   41   42   43   44   45   46   47   48   49   4A   4B   4C   4D   4E   4F   

The Instruction to Write to DDRAM
				RS	RW	D7	D6	D5	D6	D5	D4	D3	D2	D1	 D0
				0	0	1	....the address from tables above..
*/

Code File  KH_AVR_LCD HD44780 Lib.c

 

#include "KH_AVR_LCD HD44780 Lib.h"
#include <avr/io.h>
#include <stdio.h>
#include <stdlib.h>

#define buffer 20			//buffer size for double and float Functions
#ifndef precission
	#define precision 3		// define the Precision for the double Function
#endif

char str[buffer];			//Global storage buffer for double,float functions

//The address of display positions for LCD 16x2 (the total number of locations is 80--> 40x2)
char Line1_Address[]=
{     /*  1    2   3    4    5    6    7    8    9    10   11   12   13   14   15   16 ------------40 */
	    0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F
};

char Line2_Adress[]=
{  /*    41   42   43   44   45   46   47   48   49   50   51   52   53   54   55   56--------------80 */
        0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4A,0x4B,0x4C,0x4D,0x4E,0x4F
};

 void LCD_SetPosition(char charPosition,char charlineNumber)
{
 // line1 StartAddress = 0x00;		//from data sheet for 2 Line 8x2 character
 // line2 StartAddress = 0x40;     //from data sheet for 2 Line 8x2 character

//the total number of characters is 80 character ---> 40 char x 2 lines
 if(charPosition>=1 && charPosition <=16)   // i have used 16 character only from the 40 character in each line
	{

		if(charlineNumber==1)
			WriteCommand(Line1_Address[charPosition-1] | 0x80,0);	//To set the DDRAM address you must or logic the required address with 0x80(from the data sheet)

		else if(charlineNumber==2)
			WriteCommand(Line2_Adress[charPosition-1] | 0x80,0);	//To set the DDRAM address you must or logic the required address with 0x80(from the data sheet)
	}

}

void LCD_Initialize()
{
	#if (Control_VARIES_PORTS==1) //If the control lines of the LCD connected to many ports
	RS_D |= 1 << RS;
	EN_D |= 1 << EN;
	#endif

	#if (DATA_VARIES_PORTS==0)  //If the Data lines of the LCD connected to Single port with this sequence  LCD (D4-D5-D6-D7)  microController (Pin0-Pin1-Pin2-Pin3)
		DATA_DDR |= (1<<DLINE_7 | 1<<DLINE_6 | 1<< DLINE_5 | 1<< DLINE_4);			//configuring data lines port as Output
	#endif

	#if (DATA_VARIES_PORTS==1)
	{
		DLINE_7D |= 1 << DLINE_7;			//configure LCD data line 7 pin as output
		DLINE_6D |= 1 << DLINE_6;			//configure LCD data line 6 pin as output
		DLINE_5D |= 1 << DLINE_5;			//configure LCD data line 5 pin as output
		DLINE_4D |= 1 << DLINE_4;			//configure LCD data line 4 pin as output
	}
	#endif

	_delay_ms(20);				    				//wait until auto initialization of the LCD complete (more than 15ms)

	WriteCommand(0x30,0);
	_delay_ms(5);									    //wait more than 4.1ms

	WriteCommand(0x30,0);
	_delay_us(105);									  //wait more than 100us

	WriteCommand(0x30,0);
	_delay_ms(COMMAND_DELAY);

WriteCommand(LCD_4Bit1Line,0);						//Set Data length to 4 Bit with 1 Line and 5x8 font

	_delay_ms(COMMAND_DELAY);
WriteCommand(LCD_4Bit2Line,0);						//Set Data length to 4 Bit with 2 Line and 5x8 font

	_delay_ms(COMMAND_DELAY);
 WriteCommand(LCD_DOff_COff_BOff,0);				//Display Off

	_delay_ms(COMMAND_DELAY);
WriteCommand(LCD_CLEAR,0);							    //Display Clear

	_delay_ms(COMMAND_DELAY);
WriteCommand(LCD_Inc_ShiftOff,0);					  //set cursor to increment with no display shift

	_delay_ms(COMMAND_DELAY);

WriteCommand(LCD_DOn_COff_BOn,0);
	_delay_ms(COMMAND_DELAY);
}

void ClearLCDPort()
{
	//Clear the data port of the micro controller
	DLINE_7P &= ~(1<<DLINE_7);
	DLINE_6P &= ~(1<<DLINE_6);
	DLINE_5P &= ~(1<<DLINE_5);
	DLINE_4P &= ~(1<<DLINE_4) ;
}

void WriteCommand(char cmd,char lcdreg)
{
#if (Control_VARIES_PORTS==1)					//if the data lines of the LCD connected to different ports with data line 7 connected to pin 7 of the port ---data line 4 connected to pin 4
    if(lcdreg==0)								//LCD command register
    RS_P &= ~(1<<RS);							//make RS =0 to write to command register of the LCD

    else if(lcdreg==1)							//LCD Data register
    RS_P |= (1<<RS);							//make RS=1  to write to Data register of the LCD
#endif

#if(DATA_VARIES_PORTS==1 )						//if the data lines of the LCD connected to varies pins of varies ports

	char mask=0x80; //10000000

	ClearLCDPort();

	//mask the command bit number 7 (10000000)
	// move it to location 0
	//move it to the location of the required data line bit number (pin number which LCD Line7 Connected to)
	//write it to the required port
	DLINE_7P |= (((cmd & mask) >> 7)<< DLINE_7);
	mask=0x40;//mask>>=1;                       //move to the next bit

	//mask the command bit number 6 (010000000)
	// move it to location 0
	//move it to the location of the required data line bit number (pin number which LCD Line 6 Connected to)
	//write it to the required port
	DLINE_6P |= (((cmd & mask) >> 6)<< DLINE_6);
	mask=0x20;//mask>>=1;

	//mask the command bit number 5 (00100000)
	// move it to location 0
	//move it to the location of the required data line bit number (pin number which LCD Line 5 Connected to)
	//write it to the required port
	DLINE_5P |=	(((cmd & mask) >> 5)<< DLINE_5);
	mask=0x10;//mask>>=1;

	//mask the command bit number 4 (00010000)
	// move it to location 0
	//move it to the location of the required data line bit number (pin number which LCD Line 4 Connected to)
	//write it to the required port
	DLINE_4P |=(((cmd & mask) >> 4) << DLINE_4)	;
	mask=0x08;//mask>>=1; ;

	EN_Pulse();									//send a pulse for send the upper nibble of the command to the LCD command register
	ClearLCDPort();								// clear all pins of the ports which LCD Data Lines connected to to prepare it for sending the lower nibble

	/*                             SENDING The LOWE NIBBLE      */

	//mask the command bit number 3 (00001000) and move it to location 0
	//move it to the location of the required data line bit number (pin number which LCD Line7 Connected to)
	//write it to the required port
	DLINE_7P |=(((cmd & mask) >> 3)<< DLINE_7);
	mask=0x04;//mask>>=1                        //move to the next bit

	//mask the command bit number 2 (00000100) and move it to location 0
	//move it to the location of the required data line bit number (pin number which LCD Line 6 Connected to)
	//write it to the required port
	DLINE_6P |=(((cmd & mask) >> 2)<< DLINE_6);
	mask = 0x02;//mask>>=1;

	//mask the command bit number 1 (00000010) and move it to location 0
	//move it to the location of the required data line bit number (pin number which LCD Line 5 Connected to)
	//write it to the required port
	DLINE_5P |=(((cmd & mask) >> 1)<< DLINE_5);
	mask = 0x01;//mask>>=1;

	//mask the command bit number 0 (0000001) and  move it to location 0 (already at location 0)
	//move it to the location of the required data line bit number (pin number which LCD Line 4 Connected to)
	//write it to the required port
	DLINE_4P |=((cmd & mask)<< DLINE_4);							

	EN_Pulse();									//send a pulse for send the lower nibble of the command to the LCD command register
	_delay_us(15);
#endif
}

void EN_Pulse()									//this function is used to send a pulse to the Enable pin of the LCD
{
	#if(Control_VARIES_PORTS==1)
	EN_P |= 1<<EN;
	_delay_us(PULSE_DELAY);
	EN_P &= ~(1<<EN);
	#endif
}

void LCD_Show(char data)
{
  WriteCommand(data,1);
}

void LCD_ShowAt(char x,char y,char data)
{
	LCD_SetPosition(x,y);
	LCD_Show(data);
}

void LCD_ShowString(char *ptr)
{
	while(*ptr != '\0')
	{
	 LCD_Show(*ptr++);
	}
}

void LCD_ShowStringAT(char x,char y,char *ptr)
{
	LCD_SetPosition(x,y);
	while(*ptr != '\0')
		{
			LCD_Show(*ptr++);
		}
		WriteCommand(LCD_DOn_COff_BOff,0);
}

void LCD_ShowDouble(uint8_t xpos,uint8_t ypos,double val)
{
	//clear the buffer
	for(uint8_t x=0;x<=buffer;x++)
	{
		str[x]=0;
		x++;
	}
	dtostre(val,str,precision,DTOSTR_ALWAYS_SIGN | DTOSTR_UPPERCASE);         //note that precision is defined in the top of this file
	LCD_ShowStringAT(xpos,ypos,str);
	/*
	char* dtostre ( double __val, char * __s, unsigned char __prec, unsigned char __flags )

	The dtostre() function converts the double value passed in val into an ASCII representation that will be stored under s. The caller is responsible for providing
	sufficient storage in s.Conversion is done in the format "[-]d.ddde�dd" where there is one digit before the decimal-point character and the number of digits after
	it is equal to the precision prec; if the precision is zero, no decimal-point character appears. If flags has the DTOSTRE_UPPERCASE bit set, the letter 'E'
	(rather than 'e' ) will be used to introduce the exponent. The exponent always contains two digits; if the value is zero, the exponent is "00".
	  If flags has the DTOSTRE_ALWAYS_SIGN bit set, a space character will be placed into the leading position for positive numbers.
      If flags has the DTOSTRE_PLUS_SIGN bit set, a plus sign will be used instead of a space character in this case.
	The dtostre() function returns the pointer to the converted string s.
	*/
}

void LCD_ShowInt(uint8_t xpos,uint8_t ypos,int val)
{
	//clear the buffer
	for(uint8_t x=0;x<=buffer;x++)
	{
		str[x]=0;
		x++;
	}
	sprintf(str,"%d ",val);
	LCD_ShowStringAT(xpos,ypos,str);
}

void LCD_ShowFloat(double val,uint8_t xpos,uint8_t ypos)
{
	//clear the buffer
	for(uint8_t x=0;x<=buffer;x++)
	{
		str[x]=0;
		x++;
	}
//	sprintf(str,"%f",val); //not working will
	dtostrf(val,0,precision,str);
	LCD_ShowStringAT(xpos,ypos,str);
	/*
	Function dtostrf()
	char * dtostrf(
	double __val,
	signed char __width,
	unsigned char __prec,
	char * __s)
	The dtostrf() function converts the double value passed in val into an ASCII representationthat will be stored under s. The caller is responsible for providing sufficient storage in s.

	Conversion is done in the format "[-]d.ddd". The minimum field width of the output string (including the possible '.' and the possible sign for negative values) is given in width, and prec determines the number of digits after the decimal sign. width is signed value, negative for left adjustment.

	The dtostrf() function returns the pointer to the converted string s.
	*/
}

 

Last Edited: Sat. Jun 1, 2019 - 11:19 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

 Why the drive/password nonsense. Just post the code here.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
 Why the drive/password nonsense. Just post the code here.

Hi  clawson

I modified the original post as your recommendation.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Looks like you studied Peter Fleurys 4 bit library extensively. Lot of similarities if you compare them. Then again there's not much to the LCD interface to begin with.

Jim

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

That appears to be a well-placed feather in your cap & if it works error-free, can be very handy.  I used one several years ago, but found out there was some bug if certain assignments were made & of course I happened to pick one of those!  Luckily I found out about the problem before I spent too much time chasing down the  very "strange" results.

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

jgmdesign wrote:
Looks like you studied Peter Fleurys 4 bit library

 

Hi  jgmdesign

This is the 1st time i heard about it from you,

the whole design of the program is my own design and i relies on the data sheet for lcd initialization.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
void LCD_ShowInt(uint8_t xpos,uint8_t ypos,int val)
{
	//clear the buffer ****why do this???. not necessary ****
	for(uint8_t x=0;x<=buffer;x++)
	{
		str[x]=0;
		x++;
	}
	sprintf(str,"%d ",val);
	LCD_ShowStringAT(xpos,ypos,str);
}

As part of the 4 bit initialisation, you are not supposed to write in 4bit mode - but it looks like you do.

 

Rather than:

DLINE_7P |= (((cmd & mask) >> 7)<< DLINE_7);
	mask=0x40;//mask>>=1;                       //move to the next bit

you could do something like this:

if (cmd & (1<<7))
{
    DLINE_7P |= (1<<DLINE_7);
}
else
{
    DLINE_7P &= ~ (1<<DLINE_7);
}

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Kartman wrote:

//clear the buffer ****why do this???. not necessary ****

Hi  Kartman

I'm doing so to make sure that there's no content from the previous writing to the buffer

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Kartman wrote:

Rather than:

DLINE_7P |= (((cmd & mask) >> 7)<< DLINE_7);
	mask=0x40;//mask>>=1;                       //move to the next bit

you could do something like this:

if (cmd & (1<<7))
{
    DLINE_7P |= (1<<DLINE_7);
}
else
{
    DLINE_7P &= ~ (1<<DLINE_7);
}

Hi  Kartman

I appreciate your modification,

it appears faster in execution than my code, i will update my code with your and test my application

many thanks

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Sprintf() will take care of that.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

My 2 cents worth.

use plain char for the buffer, fine.

Everywhere else eg. the masks, position, line number etc. I would use unsigned char (or uint8_t).

 

Having arrays for Line1_Address and Line2_Address seems unnecessary when there is a simple mapping between position and cmd.

You could simply do something like (I'm also changing to 0 based rather than1 based, makes more sense to me, you might disagree, fair enough)

 


void LCD_SetPosition(unsigned char position, unsigned char line)
{
 // line1 StartAddress = 0x00;  //from data sheet for 2 Line 8x2 character
 // line2 StartAddress = 0x40;  //from data sheet for 2 Line 8x2 character

    if (position < 16)
    {
        if (line == 0)
        {
            WriteCommand(position | 0x00 | 0x80, 0);
        }
        else if (line == 1)
        {
            WriteCommand(position | 0x40 | 0x80, 0);
        }
    }
}

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

TheNightWhisper wrote:

jgmdesign wrote:
Looks like you studied Peter Fleurys 4 bit library

 

Hi  jgmdesign

This is the 1st time i heard about it from you,

the whole design of the program is my own design and i relies on the data sheet for lcd initialization.

Fair enough.

Jim

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

OK so far,  but  in displaying characters, strings, etc 'at any location on the lcd' does your 'Generic' driver correctly deal with:

  • the interleaved rows of characters on a 20x4 display
  • the different starting addresses of two of the rows on a 16x4 display
  • the 16x1 displays that use only one line of memory
  • the more common 16x1 displays that are configured as 8x2
  • displays that have been shifted

 

Don

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Boy it's confusing that "buffer" is not "BUFFER" to signify that it's just a defined int constant! (And surely "BUFFER_LEN" would be more descriptive?). Anyway apart from the fact that when dealing with strings you only need 0x00 in [0] to signify that the string is "empty", if you really want to reset it use memset().

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

floresta1212 wrote:

OK so far,  but  in displaying characters, strings, etc 'at any location on the lcd' does your 'Generic' driver correctly deal with:

  • the interleaved rows of characters on a 20x4 display
  • the different starting addresses of two of the rows on a 16x4 display
  • the 16x1 displays that use only one line of memory
  • the more common 16x1 displays that are configured as 8x2
  • displays that have been shifted

 

Don

Hi  floresta1212

Sorry, I've design it for 16x2 LCD,

when i be sure every thing is right, i may update it to support 20x4 display

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Kartman wrote:
Sprintf() will take care of that.

Hi  Kartman

thanks, i will remove the for loop from my code,

but does dtostre() and dtostrf() will take care of that too

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
Boy it's confusing that "buffer" is not "BUFFER" to signify that it's just a defined int constant!

 

Hi clawson

Thanks, i will apply your recommendation to my code 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

MrKendo wrote:

void LCD_SetPosition(unsigned char position, unsigned char line)
{
 // line1 StartAddress = 0x00;  //from data sheet for 2 Line 8x2 character
 // line2 StartAddress = 0x40;  //from data sheet for 2 Line 8x2 character

    if (position < 16)
    {
        if (line == 0)
        {
            WriteCommand(position | 0x00 | 0x80, 0);
        }
        else if (line == 1)
        {
            WriteCommand(position | 0x40 | 0x80, 0);
        }
    }
}

 

Thanks MrKendo

but How the WriteCommand() Fn get the right address for the required location by Logic OR operation,

any way i will test your code, it save Memory by cancelling the two arrays

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

TheNightWhisper wrote:

but How the WriteCommand() Fn get the right address for the required location by Logic OR operation,

You were already using | 0x80, it works the same way.

I could have written

WriteCommand(position | 0x80,  0) for line 0

WriteCommand(position | 0xC0,  0) for line 1

 

Alternatively, using bitwise or in this case is the same as add, so could also have written

WriteCommand(position + 0x80,  0) for line 0

WriteCommand(position + 0xC0,  0) for line 1

or

WriteCommand(position + 128,  0) for line 0

WriteCommand(position  + 192,  0) for line 1

or

WriteCommand(position + 0 + 128,  0) for line 0

WriteCommand(position + 64 + 128,  0) for line 1

etc.

It's all the same.

The main point was using the arrays to turn

0 -> 0,         1 -> 1       etc (for line 0)

0 -> 0x40,  1 -> 0x41 etc (for line 1)

is not really necessary since there is clearly a very simple relationship between the position value and the value obtained from the array (ie. it's either the same value, or the value plus 0x40).

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

MrKendo wrote:

void LCD_SetPosition(unsigned char position, unsigned char line)
{
 // line1 StartAddress = 0x00;  //from data sheet for 2 Line 8x2 character
 // line2 StartAddress = 0x40;  //from data sheet for 2 Line 8x2 character

    if (position < 16)
    {
        if (line == 0)
        {
            WriteCommand(position | 0x00 | 0x80, 0);
        }
        else if (line == 1)
        {
            WriteCommand(position | 0x40 | 0x80, 0);
        }
    }
}

there is an issue with your code it should be like this

 

WriteCommand((position + 0x00) | 0x80, 0);

WriteCommand((position + 0x40) | 0x80, 0);

 

I've did it and it working

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

For readability, I suggest having two functions - WriteCommand and WriteData. Makes the code a whole lot more readable than a 0 or 1 passed as a parameter.

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

TheNightWhisper wrote:

here is an issue with your code it should be like this

 

WriteCommand((position + 0x00) | 0x80, 0);

WriteCommand((position + 0x40) | 0x80, 0);

There are lots of different ways to write it that all give the same value.

Take your pick. Use whichever way you prefer.

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

this the updated

KH_AVR_LCD HD44780 Lib.C

and

KH_AVR_LCD HD44780 Lib.h

 

files as recommendations by Kartman , MrKendo and  clawson,I appreciate their Help.

It's the Final Update , I wish that I could help My friends whose want to use the LCD HD44780  in their applications

 

Header File

 

#ifndef KH_LCD_H
#define KH_LCD_H

#include <inttypes.h>
#ifndef F_CPU						//if the frequency not explicitly defined
	#define	F_CPU 16000000UL		//then define it with the mentioned value
#endif

#ifndef _UTIL_DELAY_H_				//if the delay header is not included
	#include <util/delay.h>         //then include it
#endif


#define COMMAND_DELAY 2				//delay time between successive commands in millisecond								(Don't Change it)
#define PULSE_DELAY 1               //delay for the Enable pulse of the enable pin of the LCD in microsecond			(Don't Change it)

#define DATA_VARIES_PORTS 1		    //defines if the data lines of the LCD connected to varies ports pins or to single port pins 0=single port   1= connected to varies ports	    (Don't Change it)
#define Control_VARIES_PORTS 1		//defines if the Control lines of the LCD connected to varies ports pins or to single port pins 0=single port   1= connected to varies ports	(Don't Change it)

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
                                       //LCD connection to the micro controller (4Bit mode) (the write Pin W is tied to ground)
//HardWare Data Lines Configuration
#define DPORT			PORTD		//The Data Lines (of the LCD) Port (connected to single port)	(Change it as your needs)
#define DATA_DDR		DDRD		//Data lines Data Direction port (connected to single port)

#define DLINE_7P		PORTD       //Data line 7 Port of  the micro controller						(Change it as your needs)
#define DLINE_6P		PORTB	    //Data line 6 Port of  the micro controller						(Change it as your needs)
#define DLINE_5P		PORTD	    //Data line 5 Port of the micro controller						(Change it as your needs)
#define DLINE_4P		PORTC	    //Data line 4 Port of the micro controller						(Change it as your needs)

#define DLINE_7D		DDRD        //Data line 7 Data Direction Port of  the micro controller				(Change it as your needs)
#define DLINE_6D		DDRB	    //Data line 6 Data Direction Port of  the micro controller				(Change it as your needs)
#define DLINE_5D		DDRD	    //Data line 5 Data Direction Port of the micro controller				(Change it as your needs)
#define DLINE_4D		DDRC	    //Data line 4 Data Direction Port of the micro controller				(Change it as your needs)

#define DLINE_7		3				//Data line 7 of the LCD connection to the micro controller Pin number  (pin7 of LCD to Pin 3 Port D Micro controller) (Change it as your needs)
#define DLINE_6		2				//Data line 6 of the LCD connection to the micro controller Pin number			(Change it as your needs)
#define DLINE_5		7				//Data line 5 of the LCD connection to the micro controller Pin number			(Change it as your needs)
#define DLINE_4		3				//Data line 4 of the LCD connection to the micro controller Pin number			(Change it as your needs)

						/**********************************************************/

// Hardware Control Configuration
#define CPORT		PORTB			// The command Port which are RS and EN connected to (connected to single port)				(Change it as your needs)
#define CTRL_DDR	DDRB			// Control Lines Data Direction port (connected to single port)								(Change it as your needs)

#define RS_P		PORTC			//The port which control lines of the LCD connected to(RS)									(Change it as your needs)
#define EN_P		PORTB			//The port which control lines of the LCD connected to (EN)									(Change it as your needs)

#define RS_D		DDRC			//the Data Direction Register for RS pin													(Change it as your needs)
#define EN_D		DDRB			//the Data Direction Register for EN pin
									//If RS =1 Data register is selected, If RS=0 Instruction register(command register) is selected
									//to enable write or read a pulse High to Low must be send to this pin
#define RS			0				//Control Line of the LCD connection to the micro controller Pin number  (RS pin Connected to PORT C Pin 0)		(Change it as your needs)
#define EN			1				//Control Line of the LCD connection to the micro controller Pin number						(Change it as your needs)

/*------------------------------------------------------------------------------------------------------*/
			//D=Display		B=Blink Character		C=Cursor
#define LCD_RETURN_HOME 			0x02	//need 1.52ms to execute, Sets DDRAM address 0 in address counter. Also returns display from being shifted to original position.DDRAM contents remain unchanged.
#define LCD_CLEAR					0x01	//Clear the display and set DDRam address to 0 in the address counter AC
#define LCD_4Bit2Line				0x28	//Set the data length = 4 bit and number of display lines = 2 , font size 5x8 dot
#define LCD_4Bit1Line				0x20	//Set the data length = 4 bit and number of display lines = 1 , font size 5x8 dot
//Entry mode set
#define LCD_Dec_ShiftOff			0x04	//Entry mode set : Sets cursor move direction to Left (decrement) and specifies display shift Off
#define LCD_Dec_ShiftOn				0x05	//Entry mode set : Sets cursor move direction to Left (decrement) and specifies display shift On
#define LCD_Inc_ShiftOff			0x06    //Entry mode set : Sets cursor move direction to right (incrementing) and specifies display shift to non (Display is not shifted).These operations are performed during data write and read.
#define LCD_Inc_ShiftOn				0x07	//Entry mode set : Sets cursor move direction to right (incrementing) and specifies display shift on
//Display control
#define LCD_DOn_COff_BOff			0x0C	//Turn On the display, Cursor Off and blinking character off
#define LCD_DOn_COn_BOn		    	0x0F	//Turn On the display, Cursor On  and blinking character On
#define LCD_DOn_COff_BOn			0x0D	//Turn On the display, Cursor Off and blinking character On
#define LCD_DOn_COn_BOff			0x0E	//Turn On the display, Cursor On  and blinking character Off
//////////////
#define LCD_DOff_COff_BOff			0x08	//Turn Off the display, Cursor Off and blinking character off
#define LCD_DOff_COn_BOn		    0x0B	//Turn Off the display, Cursor On  and blinking character On
#define LCD_DOff_COff_BOn			0x09	//Turn Off the display, Cursor Off and blinking character On
#define LCD_DOff_COn_BOff			0x0A	//Turn Off the display, Cursor On  and blinking character Off
//Cursor or Display Shift
#define LCD_SHLFTCUR				0x10	//Shift Left Cursor	,Moves cursor and shifts display without changing DDRAM contents.
#define LCD_SHRGTCUR				0x14	//shift Right Cursor ,Moves cursor and shifts display without changing DDRAM contents
#define LCD_SHLFTDSP				0x18	//Shift Left Entire Display ,Moves cursor and shifts display without changing DDRAM contents
#define LCD_SHRGTDSP				0x1C    //Shift Right Entire Display,Moves cursor and shifts display without changing DDRAM contents

void LCD_Initialize(void);
void LCD_ShowCharacter(char data);
void LCD_ShowCharacterAt(char x,char y,char data);

void LCD_ShowString(char * ptr);
void LCD_ShowStringAT(char x,char y,char *ptr);
void EN_Pulse();
void LCD_SetPosition(char charPosition,char lineNumber);

void LCD_ShowDouble(uint8_t xpos,uint8_t ypos,double val);
void LCD_ShowInt(uint8_t xpos,uint8_t ypos,int val);
//void LCD_ShowFloat(float val,uint8_t xpos,uint8_t ypos);
void LCD_ShowFloat(uint8_t xpos,uint8_t ypos,double val);

void ClearLCDPort();
void WriteCommand(char arguments);
void WriteData(char data);
void WriteLcd (char cmd);
#endif

 

Source File

 

#include "KH_AVR_LCD HD44780 Lib.h"
#include <avr/io.h>
#include <stdio.h>
#include <stdlib.h>

#define BUFFER_LENGTH 20			//buffer size for double and float Functions
#ifndef PRECISSION
	#define PRECISSION 1		// define the Precision for the double Function
#endif

char str[BUFFER_LENGTH];			//Global storage buffer for double,float functions

 void LCD_SetPosition(char charPosition,char charlineNumber)
{
 // line1 StartAddress = 0x00;		//from data sheet for 2 Line 8x2 character
 // line2 StartAddress = 0x40;     //from data sheet for 2 Line 8x2 character

//the total number of characters is 80 character ---> 40 char x 2 lines
 if(charPosition>=1 && charPosition <=16)   // i have used 16 character only from the 40 character in each line
	{

		if(charlineNumber==1)
			WriteCommand((0x00+charPosition-1) | 0x80);			//To set the DDRAM address you must or logic the required address with 0x80(from the data sheet)
		else if(charlineNumber==2)
			WriteCommand((0x40+charPosition-1) | 0x80);			//To set the DDRAM address you must or logic the required address with 0x80(from the data sheet)
	}

}


void LCD_Initialize()
{
	#if (Control_VARIES_PORTS==1) //If the control lines of the LCD connected to many ports
	RS_D |= 1 << RS;
	EN_D |= 1 << EN;
	#endif

	#if (DATA_VARIES_PORTS==0)  //If the Data lines of the LCD connected to Single port with this sequence  LCD (D4-D5-D6-D7)  microController (Pin0-Pin1-Pin2-Pin3)
		DATA_DDR |= (1<<DLINE_7 | 1<<DLINE_6 | 1<< DLINE_5 | 1<< DLINE_4);			//configuring data lines port as Output
	#endif

	#if (DATA_VARIES_PORTS==1)
	{
		DLINE_7D |= 1 << DLINE_7;			//configure LCD data line 7 pin as output
		DLINE_6D |= 1 << DLINE_6;			//configure LCD data line 6 pin as output
		DLINE_5D |= 1 << DLINE_5;			//configure LCD data line 5 pin as output
		DLINE_4D |= 1 << DLINE_4;			//configure LCD data line 4 pin as output
	}
	#endif

	_delay_ms(20);				    				//wait until auto initialization of the LCD complete (more than 15ms)

	WriteCommand(0x30);
	_delay_ms(5);									    //wait more than 4.1ms

	WriteCommand(0x30);
	_delay_us(105);									  //wait more than 100us

	WriteCommand(0x30);
	_delay_ms(COMMAND_DELAY);

WriteCommand(LCD_4Bit1Line);						//Set Data length to 4 Bit with 1 Line and 5x8 font

	_delay_ms(COMMAND_DELAY);
WriteCommand(LCD_4Bit2Line);						//Set Data length to 4 Bit with 2 Line and 5x8 font

	_delay_ms(COMMAND_DELAY);
 WriteCommand(LCD_DOff_COff_BOff);				//Display Off

	_delay_ms(COMMAND_DELAY);
WriteCommand(LCD_CLEAR);							    //Display Clear

	_delay_ms(COMMAND_DELAY);
WriteCommand(LCD_Inc_ShiftOff);					  //set cursor to increment with no display shift

	_delay_ms(COMMAND_DELAY);

WriteCommand(LCD_DOn_COff_BOn);
	_delay_ms(COMMAND_DELAY);
}

void ClearLCDPort()
{
	//Clear the data port of the micro controller
	DLINE_7P &= ~(1<<DLINE_7);
	DLINE_6P &= ~(1<<DLINE_6);
	DLINE_5P &= ~(1<<DLINE_5);
	DLINE_4P &= ~(1<<DLINE_4) ;
}

void WriteCommand(char cmd)
{
	#if (Control_VARIES_PORTS==1)					//if the data lines of the LCD connected to different ports with data line 7 connected to pin 7 of the port ---data line 4 connected to pin 4
	RS_P &= ~(1<<RS);							//make RS =0 to write to command register of the LCD
	WriteLcd(cmd);
	#endif
}

void WriteData(char data)
{	
	#if (Control_VARIES_PORTS==1)					//if the data lines of the LCD connected to different ports with data line 7 connected to pin 7 of the port ---data line 4 connected to pin 4
		RS_P |= (1<<RS);
		WriteLcd(data);
	#endif	   					//make RS=1  to write to Data register of the LCD
}


void WriteLcd (char argu)
{
  #if(DATA_VARIES_PORTS==1)						//if the data lines of the LCD connected to varies pins of varies ports

	ClearLCDPort();

	//check the command bit 7 if it is 1 or 0 and write it to the required port
	if(argu & (1 << 7))
	DLINE_7P |= 1<<DLINE_7;
	else
	DLINE_7P &= ~ (1<<DLINE_7);

	//check the command bit 6 if it is 1 or 0 and write it to the required port
	if(argu & (1 << 6))
	DLINE_6P |= 1<<DLINE_6;
	else
	DLINE_6P &= ~ (1<<DLINE_6);

	//check the command bit 5 if it is 1 or 0 and write it to the required port
	if(argu & (1 << 5))
	DLINE_5P |= 1<<DLINE_5;
	else
	DLINE_5P &= ~ (1<<DLINE_5);

	//check the command bit 4 if it is 1 or 0 and write it to the required port
	if(argu & (1 << 4))
	DLINE_4P |= 1<<DLINE_4;
	else
	DLINE_4P &= ~ (1<<DLINE_4);

	EN_Pulse();									//send a pulse for send the upper nibble of the command to the LCD command register
	ClearLCDPort();								// clear all pins of the ports which LCD Data Lines connected to to prepare it for sending the lower nibble


	/*                             SENDING The LOWE NIBBLE      */


	//check the command bit 3 if it is 1 or 0 and write it to the required port
	if(argu & (1 << 3))
	DLINE_7P |= 1<<DLINE_7;
	else
	DLINE_7P &= ~ (1<<DLINE_7);

	//check the command bit 2 if it is 1 or 0 and write it to the required port

	if(argu & (1 << 2))
	DLINE_6P |= 1<<DLINE_6;
	else
	DLINE_6P &= ~ (1<<DLINE_6);

	//check the command bit 1 if it is 1 or 0 and write it to the required port
	if(argu & (1 << 1))
	DLINE_5P |= 1<<DLINE_5;
	else
	DLINE_5P &= ~ (1<<DLINE_5);

	//check the command bit 0i f it is 1 or 0 and write it to the required port
	if(argu & 1 )
	DLINE_4P |= 1<<DLINE_4;
	else
	DLINE_4P &= ~ (1<<DLINE_4);

	EN_Pulse();									//send a pulse for send the lower nibble of the command to the LCD command register
	_delay_us(15);
  #endif
}

void EN_Pulse()									//this function is used to send a pulse to the Enable pin of the LCD
{
	#if(Control_VARIES_PORTS==1)
	EN_P |= 1<<EN;
	_delay_us(PULSE_DELAY);
	EN_P &= ~(1<<EN);
	#endif
}

void LCD_ShowCharacter(char data)
{
  WriteData(data);
}

void LCD_ShowCharacterAt(char x,char y,char data)
{
	LCD_SetPosition(x,y);
	LCD_ShowCharacter(data);
}

void LCD_ShowString(char *ptr)
{
	while(*ptr != '\0')
	{
	 WriteData(*ptr++);
	}
}

void LCD_ShowStringAT(char x,char y,char *ptr)
{
	LCD_SetPosition(x,y);
	while(*ptr != '\0')
		{
			WriteData(*ptr++);
		}
	WriteCommand(LCD_DOn_COff_BOff);
}

void LCD_ShowDouble(uint8_t xpos,uint8_t ypos,double val)
{

	dtostre(val,str,PRECISSION,DTOSTR_ALWAYS_SIGN | DTOSTR_UPPERCASE);         //note that precision is defined in the top of this file
	LCD_ShowStringAT(xpos,ypos,str);
	/*
	char* dtostre ( double __val, char * __s, unsigned char __prec, unsigned char __flags )

	The dtostre() function converts the double value passed in val into an ASCII representation that will be stored under s. The caller is responsible for providing
	sufficient storage in s.Conversion is done in the format "[-]d.ddde�dd" where there is one digit before the decimal-point character and the number of digits after
	it is equal to the precision prec; if the precision is zero, no decimal-point character appears. If flags has the DTOSTRE_UPPERCASE bit set, the letter 'E'
	(rather than 'e' ) will be used to introduce the exponent. The exponent always contains two digits; if the value is zero, the exponent is "00".
	  If flags has the DTOSTRE_ALWAYS_SIGN bit set, a space character will be placed into the leading position for positive numbers.
      If flags has the DTOSTRE_PLUS_SIGN bit set, a plus sign will be used instead of a space character in this case.
	The dtostre() function returns the pointer to the converted string s.
	*/
}

void LCD_ShowInt(uint8_t xpos,uint8_t ypos,int val)
{

	sprintf(str,"%d ",val);
	LCD_ShowStringAT(xpos,ypos,str);
}

void LCD_ShowFloat(uint8_t xpos,uint8_t ypos,double val)
{

//	sprintf(str,"%f",val); //not working will
	dtostrf(val,4,PRECISSION,str);
	LCD_ShowStringAT(xpos,ypos,str);
	/*
	Function dtostrf()
	char * dtostrf(
	double __val,
	signed char __width,
	unsigned char __prec,
	char * __s)
	The dtostrf() function converts the double value passed in val into an ASCII representationthat will be stored under s. The caller is responsible for providing sufficient storage in s.

	Conversion is done in the format "[-]d.ddd". The minimum field width of the output string (including the possible '.' and the possible sign for negative values) is given in width, and prec determines the number of digits after the decimal sign. width is signed value, negative for left adjustment.

	The dtostrf() function returns the pointer to the converted string s.
	*/
}

 

Last Edited: Sat. Jun 8, 2019 - 08:48 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Kartman wrote:
For readability, I suggest having two functions - WriteCommand and WriteData. Makes the code a whole lot more readable than a 0 or 1 passed as a parameter.

In the next update i will do it,

thanks

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

TheNightWhisper wrote:

Kartman wrote:

For readability, I suggest having two functions - WriteCommand and WriteData. Makes the code a whole lot more readable than a 0 or 1 passed as a parameter.

 

In the next update i will do it,

thanks

Hi Kartma

I've updated the code as i promised,

by editing my previous comment

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Your initialise code still is not correct. The data sheet is very specific on the sequence that must be followed. It might be working for you now, but may fail on another display.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Kartman wrote:
Your initialise code still is not correct. The data sheet is very specific on the sequence that must be followed. It might be working for you now, but may fail on another display.

Hi Kartman

I followed the data sheet instructions for initializing the LCD, If you have any suggestions,you'r welcome.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You need to put the lcd into 4bit mode before using WriteCommand. Where do you do this?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Kartman wrote:
You need to put the lcd into 4bit mode before using WriteCommand. Where do you do this?

 

Hi

This is done in LCD_Initialize() function, which must be called before any other commands or functions  belong to the LCD.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Precisely where do you do this?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

@TheNightWhisper

 

Perhaps you haven't read the phrase in question as carefully as you should have.  The key word is 'before'.

 

Don

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Kartman wrote:
Precisely where do you do this?

 

Inside the header file

#define LCD_4Bit2Line				0x28	//Set the data length = 4 bit and number of display lines = 2 , font size 5x8 dot

Inside LCD_Initialize Fn

 

WriteCommand(LCD_4Bit1Line);						//Set Data length to 4 Bit with 1 Line and 5x8 font

	_delay_ms(COMMAND_DELAY);
WriteCommand(LCD_4Bit2Line);						//Set Data length to 4 Bit with 2 Line and 5x8 font
Last Edited: Wed. Jun 19, 2019 - 09:40 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The datasheet specifically says to do an 8 bit write. You do two 4bit writes per transaction. That only works once its in 4bit mode. Read the datasheet carefully!