Is simple C or ASM LCD Busy Flag check function

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

I have written my own HD44780 display functions that do everything I want to do except it usees delays to compensate for the AVR being much faster than the LCD. Everything in my code so far seems to work solidly in both 8-bit and 4-bit mode.

I would like to replace the delays with a function that can be called that waits for the Busy Flag to clear and/or possibly returns the BF.

If it returned the reading of the BF and my own code would use it to delay the program until it clears or display the BF reading on a PORT Pin or something else with it.

All the code I have seen so far needs a lot of other code to set this up and execute. So long as the function knows the data port and the three control pins this should be a simple function.
I'm thinking this could be the simple function:
Change the data port DDRx from output to input.
Clear the LCD RS pin and Set R/W pin.
Set the LCD E pin .
Read the LCD data port, PINx.
Clear the LCD E pin.
Change the data port DDRx back to output.

(Changing back to DDR out could be done elsewhere. However. this is the only place I believe I would ever read from the LCD so by putting it back to output I would not have to make sure of the direction many other times in code.)

I have seen code before that I'm sure does this. I have gone over it but understanding it was beyond me.

Mike

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

Post what you have tried so far. If you have written everything you described above, then this one more routine should not be that difficult.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
#ifdef LCD_CHECK_BUSY
void waitForLcd(void) {
	// adapted form http://www.8051projects.net/lcd-interfacing/busyflag.php
	
	LCD_DATA_DDR = 0x00; // set data bus to input
	LCD_CTRL_PORT &= ~_BV(LCD_RS);  // clear rs
	LCD_CTRL_PORT |= _BV(LCD_RW); // set read 
	LCD_CTRL_PORT |= _BV(LCD_E); // set enable 	
	while (LCD_DATA_PIN & 0x80) {
		LCD_CTRL_PORT &= ~_BV(LCD_E);
		LCD_CTRL_PORT |= _BV(LCD_E);
	}
	LCD_CTRL_PORT &= ~_BV(LCD_E);
	LCD_CTRL_PORT &= ~_BV(LCD_RW); // clear write flag
	LCD_DATA_DDR = 0xFF; // set data bus to output
}

#else
void waitForLcd(void) {
	_delay_us(50);
}

#endif

link

i am a NOOO00B!!

Don’t let that undermine what I just said.

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

On my experience LCD output with delay cost no noticeable CPU-load.
So implementing busy test would only cost more code and wires, but has not advantages.

You should rethink your program flow, if you use the LCD 1000 times to often,
so the user was unable to read every new value and see only annoying flicker on the LCD.
A new value every 200-500ms was an ergonomic user friendly rate.

Peter

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

Regardless of if the only read you do is to check the busy flag it still makes sense to divide this into two separate pieces:

- A function that reads a byte from the LCD module, and
- A function that checks the busy flag.

Sketchy:

uint8_t LCD_ReadAddressBusy()
{
   //...
}

int LcdBusy()
{
   while (LcdReadAddressBusy & 0x80);
}

Do not worry about the extra level of function calls now. Care about efficiency of the code later. Get it to work first.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

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

This code works for me in 4-bit mode:

// 4-bit parallel interface
#define _DB_PORT PORTB
#define _DB_DDR DDRB
#define _DB7 PB3 // DB bits must be on same port, but not necessarily consecutive
#define _DB6 PB2
#define _DB5 PB1
#define _DB4 PB0
#define _DB_PIN PINB

#define _BF 7 // busy flag is bit 7
#define _DB_BITS (( 1 << _DB7 ) | ( 1 << _DB6 ) | ( 1 << _DB5 ) | ( 1 << _DB4 ))

#define tick() _delay_us(1)
#ifndef bitRead
#define bitRead(x,n) ((x>>n)&0x01) // returns value of bit x.n 0 or 1
#endif

// read the busy flag and address counter from the LCD
// returns 6 bit address plus busy flag (in bit 7)
static uint8_t lcd_readByte() {  // 58 uS at 1MHz
	uint8_t d,b;
	lcd_RW_high(); // RW = 1 to read
	tick();
	lcd_EN_high(); // EN = 1 to enable read
	tick();
	b = _DB_PIN; // read pins while EN is high
	lcd_EN_low();
	tick();
	d = 	( bitRead(b,_DB4) << 4 ); // high nibble
	d |=	( bitRead(b,_DB5) << 5 );
	d |=	( bitRead(b,_DB6) << 6 );
	d |=	( bitRead(b,_DB7) << 7 );
	lcd_EN_high();
	tick();
	b = _DB_PIN;  // read pins while EN is high
	lcd_EN_low();
	tick();
	d |=	( bitRead(b,_DB4) << 0 ); // low nibble
	d |=	( bitRead(b,_DB5) << 1 );
	d |=	( bitRead(b,_DB6) << 2 );
	d |=	( bitRead(b,_DB7) << 3 );
	lcd_RW_low(); // clear the RW flag
	return d; // contains a full byte read from the LCD
}

// waits until busy flag is cleared
static void lcd_waitBusy() {
	lcd_RS_low(); // RS = 0 for instruction register
	_DB_DDR &= ~_DB_BITS; 	// set DB pins for input
	tick();
	while( lcd_readByte() & (1<<_BF) ); // repeat until busy flag is cleared
}

Jim

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

This very recent thread has some discussion:
https://www.avrfreaks.net/index.p...

And the forum search uncovers similar past threads.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.