Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

LCD without using __delay library

Status
Not open for further replies.

Stas Mamaischi

Newbie level 6
Joined
Apr 24, 2014
Messages
11
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Activity points
60
Hi everyone. Can someone explain or show me example how i can interfacing LCd without using __delay library . Because __delays generate in my project the signal delay time that I do not need. I attach picture of the problem . Untitled1.png
 

As you seem to be using the 8-bit LCD interface mode, you can read the 'busy' signal back on DB7. It will tell you immediately whether it is safe to write to the LCD. Everything is explained in the LCD data sheet (or HD44780 data sheet).

Brian.
 

As you seem to be using the 8-bit LCD interface mode, you can read the 'busy' signal back on DB7. It will tell you immediately whether it is safe to write to the LCD. Everything is explained in the LCD data sheet (or HD44780 data sheet).

Brian.

Code:
void LCD_D7()
{
 
LCD_D7 = 1; //Make D7th bit of LCD as i/p
RA2 = 1; //EN
RA0 = 0; //RS
RA1 = 1; //RW
 
 while(LCD_D7){ //read busy flag again and again till it becomes 0
RA2 = 0; //Enable H->L
RA2 = 1;
 }
 
}

result it there



Untitled4.png
 

Code:
LCD_D7 = 1; //Make D7th bit of LCD as i/p
RA2 = 1; //EN
RA0 = 0; //RS
RA1 = 1; //RW
 
 while(LCD_D7){ //read busy flag again and again till it becomes 0
RA2 = 0; //Enable H->L
RA2 = 1;
This is essentially bad code and may cause unexpected behaviour. You'll always set the data, RS and RW pins first and then activate E, otherwise you may issue an unwanted command.

Secondly I don't understand how LCD_D7 = 1 will set D7 to input. Obviously you are working with a PIC processor, you should set the TRIS bit of the respective port pin.

Reading busy state should reduce command execution delays to the minimum. Some commands, eg. CLR will take considerable time though, refer to the datasheet for expectable duration.

I'm not sure if HD44780 timing is fully modelled by Proteus.
 

Code:
LCD_D7 = 1; //Make D7th bit of LCD as i/p
RA2 = 1; //EN
RA0 = 0; //RS
RA1 = 1; //RW
 
 while(LCD_D7){ //read busy flag again and again till it becomes 0
RA2 = 0; //Enable H->L
RA2 = 1;
This is essentially bad code and may cause unexpected behaviour. You'll always set the all data, RS and RW pins and then activate E, otherwise you may issue an unwanted command.

Secondly I don't understand how LCD_D7 = 1 will set D7 to input. Obviously you are working with a PIC processor, you should set the TRIS bit of the respective port pin.

Reading busy state should reduce command execution delays to the minimum. Some commands, eg. CLR will take considerable time though, refer to the datasheet for expectable duration.

I'm not sure if HD44780 timing is fully modelled by Proteus.

but this problem i sow on osciloscope in real time .


i use this library for interfacing LCD
Code:
void msdelay(unsigned int itime)
	{
		unsigned int i,j;
		for(i=0;i<itime;i++)
			for(j=0;j<2;j++);
	}

void command() //comand functie definita 
{

    RA0=0;
    RA1=0;
    RA2=1;
    msdelay(1);
    RA2=0;
}

void data()  //definite data functie
{

    RA0=1;
    RA1=0;
    RA2=1;
    msdelay(1);
    RA2=0;
}

void displayLCD()
{
    int i;
    PORTC = 0x01;
    command();
   msdelay(1);
    
    char a[10]={" rpm:"};
    if (rpm > 32000 || rpm < 10)
    {
        a[5] = 'O';
        a[6] = 'V';
        a[7] = 'F';
        a[8] = 'L';
    }
    else
    {
        a[5] = 48 + rpm / 100;  
        rpm = rpm - 100 * (rpm / 100);
        a[6] = 48 + rpm / 10;  
        rpm = rpm - 10 * (rpm / 10);
        a[7] = 48 + rpm;
    }
		    for(i=0;i<=8;i++)
		    {
		         PORTC = a[i];
		         data();
     
	msdelay(1);
		    }

}

- - - Updated - - -

Code:
TRISC=0X00; //PORTC ca port de iesire pentru Display
		
		    TRISA=0XA0; // PORTA ca port de iesire pentru E, RW, R
		    
            //LCD_busy();
		    msdelay(1);
		
		    PORTC=0X38; //8 bit 2 linii
		
		    command(); // chemam funcia ca sa aratam ca nu ese functie ci este comanda
		    //LCD_busy();
		    msdelay(1);
		
		    PORTC=0X38; // 8biti 2 linii
		
		    command(); // chemama comanda
		    //LCD_busy();
		    msdelay(1);
		
		    PORTC=0X06; // modul de intrare
		
		    command();
		    //LCD_busy();
		    msdelay(1);
		
		    PORTC=0X0F; 
		
		    command();
		    //LCD_busy();
			msdelay(1);
		    
			PORTC=0xC0;
		    
		    command();
 			//LCD_busy();
		   msdelay(1);
		
		    displayLCD();
		    
		     while(1);
 

Reading busy state should reduce command execution delays to the minimum. Some commands, eg. CLR will take considerable time though, refer to the datasheet for expectable duration.

I cannot agree with that as a general statement, at least not when using Asssembly. I have shamelessly used code from Mike Webb (screen name "Pommie") for controlling a 64X128 GLCD (NHD-12864MZ which uses two KS0108B controllers). His code includes a very nice subroutine, WaitNotBusy ("WNB") to test test E for both controllers. Here is his code:

Code:
WAIT NOT BUSY

WaitNotBusy	bsf	STATUS,RP0
		movlw	0xff
		movwf	TRISB
		bcf	STATUS,RP0
		bsf	b_LCD_RW
		bcf	b_LCD_RS  
		btfss	b_LCD_CS1
		goto	Skip_CS1
		bcf	b_CS2
		btfsc	b_LCD_CS2
		bsf	b_CS2
		bcf	b_LCD_CS2


WNB1_Loop	bsf	b_LCD_E
		btfsc	PORTB,7
		goto	WNB1_Loop
		bcf	b_LCD_E
		btfsc	b_CS2
		bsf	b_LCD_CS2
Skip_CS1	btfss	b_LCD_CS2
		goto	Skip_CS2
		bcf	b_CS1
		btfsc	b_LCD_CS1
		bsf	b_CS1
		bcf	b_LCD_CS1
WNB2_Loop	bsf	b_LCD_E
		btfsc	PORTB,7
		goto	WNB2_Loop
		bcf	b_LCD_E
		btfsc	b_CS1
		bsf	b_LCD_CS1
Skip_CS2
SetOutput	bsf	STATUS,RP0
		clrf	TRISB
		bcf	STATUS,RP0
		return

By actual testing using an MCU (PIC16F1519) at 4 MHz or 8MHz, a delay of one or two NOP's worked and was much faster for screen writing (I did not use CLR, so this might not apply to doing that.) A much faster clock speed or use of CLR may change that conclusion. In the latter case, however, one could include "WNB" only when using CLR.

Microchip forums and are replete with discussions of this topic. My conclusion is that if you do not want to use a delay for whatever reason, Mike's program does that efficiently. If you do not object to using a delay and are aware of the risks, a fixed delay of one or more NOP's will suffice.

John

Edit: Here is Pommie's code in C (Source: https://www.electro-tech-online.com/threads/ks0108-glcd-busy-reads.125826/#post-1043372 ). I tested it in Assembly, but not this version in C.

Code:
void Wait_Not_Busy(void){
    TRISD=0xff;
    b_GLCD_RS=0;
    b_GLCD_RW=1;
    if (b_GLCD_GCS1==1 && b_GLCD_GCS2==1){
        b_GLCD_GCS1=0;
        while (GLCD_Read()&0x80);
        b_GLCD_GCS1=1;
        b_GLCD_GCS2=0;
        while (GLCD_Read()&0x80);
        b_GLCD_GCS2=1;
    }
    else{
        while (GLCD_Read()&0x80);
    }
    TRISD=0x00;
}
 
Last edited:

My conclusion is that if you do not want to use a delay for whatever reason, Mike's program does that efficiently. If you do not object to using a delay and are aware of the risks, a fixed delay of one or more NOP's will suffice.
Do you say this related to HD44780 controllers, which is the topic of this post?

Hitachi specifies the maximum execution time of most instructions with 37 µs at nominal clock frequency, may be up to 50 µs for the clock frequencies considered in the datasheet. Without using busy check, you are required to assume the maximum execution time (at least when writing professional software).
 

I sow that when i put function display_LCD in interrupt , then i create this problem. I try to make a function delay in program .
Code:
void msdelay(unsigned int time)
	{
		unsigned int i,j;
		for(i=0;i<time;i++)
			for(j=0;j<2;j++);
	}

but problem has not disappeared

- - - Updated - - -

about busy flug is the first time when i heard about this. now i try to see how it work and how to adopt in my code

- - - Updated - - -

i forget to say i use LCD HD44780
 

I saw that when i put function display_LCD in interrupt , then i create this problem.
My general comment: You won't do that, neither using delay nor busy flag. Just a matter of well considered application layout.
 

when i use 7 segment display this problem disappear, because there i don't use delay library . Is a curiosity for me to solve this problem .
 

The method I use, which I am not going to show code for is to use a timer (usually TMR0) to trigger an interrupt, each time the ISR is entered, it checks the LCD status bit and if a data queue has anything in it, it sends a byte from the tail of the queue to the LCD. Any new data to be sent is placed at the head of the queue and a pointer to it is advanced. Essentially it is a data buffer which transfers bytes to the LCD as a background task. There is a small time penalty as the ISR does the check but it has two big advantages over the methods described earlier: 1. while waiting for the LCD to go 'not busy' the program isn't held up and 2. Whole strings can be written to the LCD in one step.

Brian.
 

The method I use, which I am not going to show code for is to use a timer (usually TMR0) to trigger an interrupt, each time the ISR is entered, it checks the LCD status bit and if a data queue has anything in it, it sends a byte from the tail of the queue to the LCD. Any new data to be sent is placed at the head of the queue and a pointer to it is advanced. Essentially it is a data buffer which transfers bytes to the LCD as a background task. There is a small time penalty as the ISR does the check but it has two big advantages over the methods described earlier: 1. while waiting for the LCD to go 'not busy' the program isn't held up and 2. Whole strings can be written to the LCD in one step.

Brian.


it's very interesting idea to use timer as a delay function
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top