Stas Mamaischi
Newbie level 6
- Joined
- Apr 24, 2014
- Messages
- 11
- Helped
- 0
- Reputation
- 0
- Reaction score
- 0
- Trophy points
- 1
- Activity points
- 60
Follow along with the video below to see how to install our site as a web app on your home screen.
Note: This feature may not be available in some browsers.
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.
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;
}
}
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.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;
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.
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);
}
}
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.
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
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;
}
Do you say this related to HD44780 controllers, which is the topic of this post?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.
void msdelay(unsigned int time)
{
unsigned int i,j;
for(i=0;i<time;i++)
for(j=0;j<2;j++);
}
My general comment: You won't do that, neither using delay nor busy flag. Just a matter of well considered application layout.I saw that when i put function display_LCD in interrupt , then i create 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.