Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

Convert serial LCD code into parallel LCD.. Help please..

Status
Not open for further replies.

AntRoFiZ

New Member
Hi, I am thinking of getting 'SRF05 Ultrasonic Sonar Sensor' and use it to display the distance measured onto LCD..
The sensor itself is easy to use as it performs ranging using only a single pin (I assume it means that only 1 pin is connected to the PIC16F877 which is RB0..

What the hard part is is understanding the code which is for LCD03 (**broken link removed**)
and convert it to a code that I can use for parallel LCD.

The code for 'SRF05 Ultrasonic Sonar Sensor' is https://www.robot-electronics.co.uk/files/srf05_lcd03.c (written in HITECH PIC16).

What I need is very simple. No need to display all the fancy stuff.. It just need to display the measurements in cm.. I assume that means that alot of code can be strip off as it is not needed..

Advice is very much needed and appriciated..
Thanks..
 
You did not specify if you know how to program.
If you do not know how to program you may be better off buying the LCD03 and using the code as is. If you want to learn to program start with tutorials.
Assuming that you do know how to program at some level. Drivers are specific to the controller used by the LCD display.

There are many examples of code to drive parallel LCDs on the web. I googled for "PIC LCD DRIVER" and found quite a few.

You will need to change all the code in print(), clrscn(), cursor(), and the LCD related code in setup().

Are you going to use the Hi-Tech Compiler ?
 
Last edited:
Thanks for your reply..
Well.. I have a sample code for LCD written in BoostC..
I am more familiar with BoostC and have used BoostC before.. As for HITECH C, i don't know how to use it.. I downloaded it but am lost as in how to use it.. I prefer to use BoostC if possible..
As for the LCD sample code, I have compiled it in BoostC and have simulated it with Proteus VSM and it worked..

To use the sensor with PIC, I just need to know the distance in cm, and then ask the LCD to print it out rite..? The distance would be a variable rite..?
For the LCD code, whatever inside the " lprintf(" "); " was printed.. Forexample, if the code was lprintf( "Hello World" ); then it will print out Hello World.. I tried it on Proteus and it worked.. I know that there are more to LCD but at least that is a start to using it..

So, if I am able to extract the distance in the sensor code then I can command the LCD to print it out by putting it into the lprintf( ) command.
If I don't use the I2C and LCD03 then it would clear away the unnecessary code..

By the way, here is the sample LCD code that I plan to use to display the distance.. Of course i need to modify it and cut out the unnecessary part..

Code:
////////////////////////////////////////////////////////////////////////////
// LCD with HD44780 drive chip
////////////////////////////////////////////////////////////////////////////
// Author(s): David Hobday
// Date 4 September 2003
//
// Designed and test for 16F84A
//
// Interface :   
// RS = RA01
// WR = RA02
// E  = RA00
//
// DB7 = RB07
// DB6 = RB06
// DB5 = RB05
// DB4 = RB04
//                                                                               
// Using 4 Bit interface
//

/////////////////////////////////////////////////////////////////////////////
// Program to test LCD plugin - with 4 bit interface
// Designed and test for 16F84A
// 
// **** Beware MPLABS assembler fails to report when program exceeds memory 
// upto 4 words - this can then cause the program to fail! 
// This program nearly totally fills the processor!

// 20MHz - frequency needs setting high for busy test,
// It write characters faster than they can be handled by the display and 
// so get missed. If clock frequency set lower this may not happen
// Remeber also that the simualtor must also be told the clock rate so the plugins
// can convert clock ticks to actual time.
#pragma CLOCK_FREQ 20000000

// comment out when running on actual hardware - different delays used
#define RUN_UNDER_SIM

#include <system.h>

void LCD_Setup(void);
void LCD_FunctionMode(void);
void LCD_DataMode(void);
void LCD_RawWriteNibble(char);
void LCD_Write(char);
void LCD_RawWrite(char);
char LCD_Read();
void lprintf( const char *lcdptr );   //write string 
void LCD_Clear();
void LCD_WaitForNotBusy();

char writeDelayType;

////////////////////////////////////////////////////////////////////////////
// Control signal bit definitions
////////////////////////////////////////////////////////////////////////////
#define LCD_E    0   
#define LCD_RW   2   
#define LCD_RS   1 

////////////////////////////////////////////////////////////////////////////
// LCD Commands ( Refer to LCD Data Sheet )
////////////////////////////////////////////////////////////////////////////
#define clear_lcd         0x01 // Clear Display
#define return_home       0x02 // Cursor to Home position
#define entry_mode        0x06 // Normal entry mode
#define entry_mode_rev    0x04 // Normal entry mode  -reverse direction
#define entry_mode_scroll 0x07 // - with shift
#define entry_mode_scroll_rev  0x05 // reverse direction

#define system_set_8_bit  0x38 //8 bit data mode 2 line ( 5x7 font )
#define system_set_4_bit  0x28 // 4 bit data mode 2 line ( 5x7 font )
#define system_set_reset  0x30 // Reset code
#define display_on        0x0C // Display ON - 2 line mode
#define display_off       0x08 // Display off
#define set_dd_line1      0x80 // Line 1 position 1
#define set_dd_line2      0xC0 // Line 2 position 1
#define set_dd_ram        0x80 // Line 1 position 1
#define write_data        0x00 // With RS = 1
#define cursor_on         0x0E // Switch Cursor ON
#define cursor_off        0x0C // Switch Cursor OFF
#define cursor_blink_on   0x0F // Cursor plus blink
#define cursor_shift_right 0x14 // Move cursor right
#define cursor_shift_left 0x10 // Move cursor left
#define display_shift_right 0x1C // Scroll display right
#define display_shift_left 0x18 // Scroll display left

#define WriteNoDelay 1
#define WriteDelayTime 0
#define WriteUseBusy 2

void TestDelay()
{
#ifdef RUN_UNDER_SIM
	delay_ms( 2 );
#else
	delay_s( 2 );
#endif
}

void TestDelayShort()
{
#ifdef RUN_UNDER_SIM
	delay_ms( 1 );
#else
	delay_ms( 100 );
#endif
}

void main()
{	

#ifdef RUN_UNDER_SIM
#else
	delay_s( 1 ); // power up delay
#endif

	trisa = 0x00; // port a output

while( 1 )
	{
		LCD_Setup();
		
		char i = 0;
		
		//////////////////////////////////////////////////
		// Test1 - wrap to line 2 test
		//////////////////////////////////////////////////
		lprintf( "4Bit" );
		for( i = 0; i < 36; i++ )
			lprintf( "x" );
		TestDelay();
		
		lprintf( "T1 L2?" );
		
		for( i = 0; i < 34; i++ )
			lprintf( "x" );
		lprintf( "T1 L1?" ); 
		TestDelay();
	
		
		//////////////////////////////////////////////////
		// Test2 - Display clearing
		//////////////////////////////////////////////////	
		LCD_Clear();
		lprintf( "T2-clr?" );
		TestDelay();
		
		//////////////////////////////////////////////////
		// Test3 - Return Home
		//////////////////////////////////////////////////	
		LCD_FunctionMode();
		LCD_Write( return_home );
		delay_ms(2);
		LCD_Write( cursor_on );
		LCD_DataMode();
		lprintf( "T3 home?" );
		TestDelay();
		
		//////////////////////////////////////////////////
		// Test4 - Reverse entry mode
		//////////////////////////////////////////////////	
		LCD_FunctionMode();
		LCD_Write( entry_mode_rev );
		LCD_DataMode();
		lprintf( "?  veR 4T" ); // reverse entry test
		
		// back to normal mode
		LCD_FunctionMode();
		LCD_Write( entry_mode );
		LCD_DataMode();
		TestDelay();
	
		//////////////////////////////////////////////////
		// Test5 - Setting dd ramAddr
		//////////////////////////////////////////////////	
		LCD_Clear();
		LCD_FunctionMode();
		LCD_Write( set_dd_ram + 0x06 ); // start text top line, col 7
		LCD_DataMode();
		lprintf( "T5L1C7?" );
		LCD_FunctionMode();
		LCD_Write( set_dd_ram + 0x46 ); // start text bottom line 6, col 7
		LCD_DataMode();
		lprintf( "T5L2C7?" );
		TestDelay();
	
		//////////////////////////////////////////////////
		// Test6 - Scrolling
		//////////////////////////////////////////////////	
	test6:
		int j;
		LCD_FunctionMode();
		LCD_Write( set_dd_ram + 0x46 ); // line 2 start, col 7
		LCD_DataMode();	
		lprintf( "T6L2" );
	
		LCD_FunctionMode();
		LCD_Write( set_dd_ram + 0x06 ); // line 1 start, col 7
		LCD_DataMode();	
		lprintf( "T6L1" );
		
	
		LCD_FunctionMode();
		LCD_Write( entry_mode_scroll );
		LCD_DataMode();
		
		TestDelay();
		for ( i = 0; i < 30; i++ )
		{
			lprintf( "<" );
			TestDelayShort();
		}
		lprintf( "End L2?" );
		TestDelay();
	
		//////////////////////////////////////////////////
		// Test7 - Cursor
		//////////////////////////////////////////////////			
		LCD_Clear();
		LCD_FunctionMode();
		LCD_Write( entry_mode ); // scroll off
		LCD_Write( return_home );
		delay_ms( 2 );
		LCD_Write( cursor_on );
		LCD_DataMode();
		lprintf( "T7aCurOn?" );
	
		TestDelay();
		LCD_FunctionMode();
		LCD_Write( cursor_off );
		LCD_DataMode();
		
	
		//////////////////////////////////////////////////
		// Test8 - Scroll with no data being written
		//////////////////////////////////////////////////			
		LCD_Clear();
		LCD_FunctionMode();
		LCD_Write( entry_mode ); // scroll off
		LCD_Write( return_home );
		delay_ms( 2 );
		LCD_DataMode();
		lprintf( "T8-scroll Left cursor static?" );
		
		LCD_FunctionMode();
		LCD_Write( set_dd_ram + 15 ); // position cursor at position 4
		LCD_Write( cursor_on ); // show cursor
		LCD_DataMode();
	
		TestDelayShort();
		
		LCD_FunctionMode();
		for( i = 0; i < 20; i++ )
		{
			LCD_Write( display_shift_left );
			TestDelayShort();
			TestDelayShort();
		}
	
		for( i = 0; i < 20; i++ )
		{
			LCD_Write( display_shift_right );
			TestDelayShort();
			TestDelayShort();
		}
	
		LCD_DataMode();
	
	
	
		//////////////////////////////////////////////////
		// Test9 - Scroll with cursor moving to
		//////////////////////////////////////////////////			
	test9:
		LCD_Clear();
		LCD_FunctionMode();
		LCD_Write( entry_mode ); // scroll off
		LCD_Write( return_home );
		delay_ms( 2 );
		LCD_DataMode();
		lprintf( "T9-cursor" );
		
		LCD_FunctionMode();
		LCD_Write( set_dd_ram ); // position cursor at position 0
		LCD_Write( cursor_blink_on ); // show cursor
		LCD_DataMode();
		TestDelayShort();
		
		LCD_FunctionMode();
		for( i = 0; i < 20; i++ )
		{
			LCD_Write( cursor_shift_right );
			TestDelayShort();
		}
		
		for( i = 0; i < 20; i++ )
		{
			LCD_Write( cursor_shift_left );
			TestDelayShort();
		}
	
		LCD_DataMode();
		TestDelay();
		
		//////////////////////////////////////////////////
		// Test10 - busy bit usage
		//////////////////////////////////////////////////			
		LCD_Clear();
		lprintf( "T10 " );
		writeDelayType = WriteNoDelay; // no delay
		// some of these will be missing
		LCD_Write( 'A' );
		LCD_Write( 'A' );
		LCD_Write( 'A' );
		
		writeDelayType = WriteUseBusy;
		// This character may not be displayed, depends on timing! as there may be 
		// a nibble left over from uncontrolled writes
		LCD_Write( 'X' ); 
		
		LCD_Write( 'B' );
		LCD_Write( 'B' );	
		LCD_Write( 'B' );
		
		lprintf( "\nNo AAA just BBB ?" );
		TestDelay();
	
		//////////////////////////////////////////////////
		// Test11 - display read back
		//////////////////////////////////////////////////			
		// Should cause AB to change to YZ by reading back
		// and re-writing incremented values
		LCD_FunctionMode();
		LCD_Write( cursor_blink_on ); // show cursor
		LCD_Clear();	
		lprintf( "T11 AB" );
		
		char a,b;
		for ( i = 0; i < 24; i++ )
		{
			LCD_FunctionMode();
			LCD_Write( cursor_shift_left );
			LCD_Write( cursor_shift_left );
			LCD_DataMode();
			
			LCD_WaitForNotBusy();
			a = LCD_Read() + 1;
			LCD_WaitForNotBusy();
			b = LCD_Read() + 1;		
	
			LCD_FunctionMode();
			LCD_Write( cursor_shift_left );
			LCD_Write( cursor_shift_left );
			LCD_DataMode();
			
			LCD_Write( a );	
			LCD_Write( b );
		}
		TestDelay();
	
		//////////////////////////////////////////////////
		// Test12 - display on/off
		//////////////////////////////////////////////////			
		// should never see display off message on its own
		LCD_FunctionMode();
		LCD_Clear();
		lprintf( "T12 on/off?" );
		LCD_FunctionMode();
		
		for( i = 0; i < 5; i++ )
		{		
			LCD_Write( display_off ); // display off
			TestDelay();
			LCD_Write( display_on ); // display on
			TestDelay();
		}
	}
}

void LCD_Clear()
{
	LCD_FunctionMode();
	LCD_Write( clear_lcd ); // clear display
	LCD_Write( return_home );
	delay_ms( 2 );
	LCD_DataMode();
}

void LCD_Setup(void)
{
	writeDelayType = WriteNoDelay; // no delays in data writes
	
	delay_ms(16); // Power up delay
	LCD_FunctionMode();

	// Reset sequence as described in data sheets
	LCD_RawWriteNibble( system_set_reset >> 4 ); 
	delay_ms(5); // min delay here of 4.1 ms
	LCD_RawWriteNibble( system_set_reset >> 4 );
	delay_us(100); // min delay here of 100us
	LCD_RawWriteNibble( system_set_reset >> 4 );
   
	// busy flag is valid from this point onwards
	LCD_WaitForNotBusy();
	LCD_RawWriteNibble( system_set_4_bit >> 4 );
	
	writeDelayType = WriteUseBusy; // use busy
	LCD_Write( system_set_4_bit );
		
	LCD_Write( display_off );
	LCD_Write( entry_mode );
	LCD_Write( display_on );
	LCD_Write( set_dd_ram );
	
	LCD_DataMode();
}

void LCD_FunctionMode(void)
{
	clear_bit( porta, LCD_RS );
}

void LCD_DataMode(void)
{
	set_bit( porta, LCD_RS );
}

void LCD_Write(char d )
{
	if ( writeDelayType == WriteUseBusy )
		LCD_WaitForNotBusy();
		
	LCD_RawWrite( d );
	
	if ( writeDelayType == WriteDelayTime )
		delay_us( 50 ); // enough time for normal command execution - clear and home need longer!!	
}

void LCD_RawWrite( char d )
{		
	clear_bit( porta, LCD_RW ); // set writing mode
	// set port b lower bits to output
	trisb &= 0x0F; 
			
	// output upper nibble
	LCD_RawWriteNibble( d >> 4 );
	
	// output lower nibble
	LCD_RawWriteNibble( d );
}


void LCD_RawWriteNibble(char d )
{
	clear_bit( porta, LCD_RW ); // set writing mode
	// port b upper nibble output
	trisb &= 0x0F;
		
	portb &= 0x0F;
	portb |= d << 4;

	// Clock data
   	asm NOP // setup time
	asm NOP // setup time
	asm NOP // setup time
	set_bit( porta, LCD_E );
	clear_bit( porta, LCD_E );   
	asm NOP ;// holdup time
}

char LCD_Read()
{		
	char d;
	
	// portb upper nibble input	
	trisb |= 0xF0;
	set_bit( porta, LCD_RW ); // set reading mode
		
	// data valid while EN high - 
	
	// first high nibble
	set_bit( porta, LCD_E );
	asm NOP // setup time
	asm NOP // setup time
	asm NOP // setup time
	
	d = portb & 0xF0 ;
	clear_bit( porta, LCD_E );   
		
	// then low nibble
	set_bit( porta, LCD_E );
	asm NOP // setup time
	asm NOP // setup time
	asm NOP // setup time

	d |= portb >> 4;
	clear_bit( porta, LCD_E );   
	
	return d;
}

void LCD_WaitForNotBusy()
{
	char old_RS;
	// save RS current state
	old_RS = porta & ( 1 << LCD_RS );
	
	clear_bit( porta, LCD_RS );
	while( LCD_Read() & 0x80 ); // wait while busy set
	
	if ( old_RS ) // restore RS if necessary
		set_bit( porta, LCD_RS );
}

void lprintf( const char *lcdptr )
{
	char pi;
	char c;
	pi = 0;
                                          
    while( 1 )
    {
		c = lcdptr[pi++];
		if ( c + 1 == 1 ) // funny code here as c == 0 fails with compiler V5.1
			break;
		if ( c == '\n' )
		{
			LCD_FunctionMode();
			LCD_Write( set_dd_ram + 0x40 );
			LCD_DataMode();
		}
		else
			LCD_Write( c );// Display on LCD
	}
}
 
If you are more familiar with BoostC stick with it.

Yes you are on the correct track.

Start by removing all the tests from the above code.
Maybe just have it print Hello World on the LCD to be sure it still works.

The add the code that does the initialization of the sensor.
Then add the code that does the measurement and print the results.
Please try to understand what the code does there is a good chance it will not work.
 
Thanks for your input..
Umm.. when I have time, I will remove the LCD03 and I2C code from the sensor code as well as simplify the BoostC LCD code.. Its 3am at my place now and i am too tired to chew on the code..
Just wondering, if I want to test whether the sensor code is working or not after filtering out the LCD03 code, can I test it in Proteus..? Instead of attaching a sensor to the PIC pin, can I apply a high frequency to that pin to simulate the transmitting and receiving of the ultrasonic signal and after that, by calculation, verify to see if the distance shown in the LCD is correct or not..?
Do you think it will work..?
 
AntRoFiZ said:
Instead of attaching a sensor to the PIC pin, can I apply a high frequency to that pin to simulate the transmitting and receiving of the ultrasonic signal and after that, by calculation, verify to see if the distance shown in the LCD is correct or not..?
Do you think it will work..?

I don't think so. After the trigger pulse, you have to wait for a single pulse, whose width is proportional to the distance.
 
hmm.. in another words, it is not possible to test the code without using the sensor..? not even by using another PIC to generate a pulse trying to imitate the sensor..? At the moment, my C language is very limited and because of that, i don't know how to generate a pulse.. if i understand the code then i will know what to expect and know what to do... i will try to look up on the code to try to understand it when i have time....
 
AntRoFiZ said:
hmm.. in another words, it is not possible to test the code without using the sensor..? not even by using another PIC to generate a pulse trying to imitate the sensor..?

This is possible, of course.
Have you read the technical specification of the srf05? It helps understanding the code.
 
Last edited:
You should be able to test it in Proteus.

Proteus should have some means to specify the input signal over time for any given in pin. In mplab you do this with a file you create. Check the docs for Proteus to figure out how to create the pulses. Then check the sensor doc to see how far apart and long they need to be.

You could setup a 2nd pic and do the test with actual hardware. But since you have Proteus which is a very nice tool it would be easier to use it.
 
Questions about LCD

Hi..
Here is a question about LCD..

The code below written in BoostC will display "Hello World". The PIC is PIC16F84A.
If I want it to display a variable that keeps on changing forexample DutyCycle (variable name) and it changes between 50% to 60%.. How should I do it..?
Can somebody please advice.. Thanks..


Code:
#pragma CLOCK_FREQ 4000000

#define RUN_UNDER_SIM

#include <system.h>

void LCD_Setup(void);
void LCD_FunctionMode(void);
void LCD_DataMode(void);
void LCD_RawWriteNibble(char);
void LCD_Write(char);
void LCD_RawWrite(char);
char LCD_Read();
void lprintf( const char *lcdptr );   //write string 
void LCD_Clear();
void LCD_WaitForNotBusy();

char writeDelayType;

////////////////////////////////////////////////////////////////////////////
// Control signal bit definitions
////////////////////////////////////////////////////////////////////////////
#define LCD_E    0   
#define LCD_RW   2   
#define LCD_RS   1 

////////////////////////////////////////////////////////////////////////////
// LCD Commands ( Refer to LCD Data Sheet )
////////////////////////////////////////////////////////////////////////////
#define clear_lcd         0x01 // Clear Display
#define return_home       0x02 // Cursor to Home position
#define entry_mode        0x06 // Normal entry mode
#define entry_mode_rev    0x04 // Normal entry mode  -reverse direction
#define entry_mode_scroll 0x07 // - with shift
#define entry_mode_scroll_rev  0x05 // reverse direction

#define system_set_8_bit  0x38 //8 bit data mode 2 line ( 5x7 font )
#define system_set_4_bit  0x28 // 4 bit data mode 2 line ( 5x7 font )
#define system_set_reset  0x30 // Reset code
#define display_on        0x0C // Display ON - 2 line mode
#define display_off       0x08 // Display off
#define set_dd_line1      0x80 // Line 1 position 1
#define set_dd_line2      0xC0 // Line 2 position 1
#define set_dd_ram        0x80 // Line 1 position 1
#define write_data        0x00 // With RS = 1
#define cursor_on         0x0E // Switch Cursor ON
#define cursor_off        0x0C // Switch Cursor OFF
#define cursor_blink_on   0x0F // Cursor plus blink
#define cursor_shift_right 0x14 // Move cursor right
#define cursor_shift_left 0x10 // Move cursor left
#define display_shift_right 0x1C // Scroll display right
#define display_shift_left 0x18 // Scroll display left

#define WriteNoDelay 1
#define WriteDelayTime 0
#define WriteUseBusy 2

void main()
{	

#ifdef RUN_UNDER_SIM
#else
	delay_s( 1 ); // power up delay
#endif

	trisa = 0x00; // port a output

while( 1 )
	{
		LCD_Setup();
		
		char i = 0;
		
		//////////////////////////////////////////////////
		// Test1 - wrap to line 2 test
		//////////////////////////////////////////////////
		lprintf("Hello World" );
	}
}

void LCD_Clear()
{
	LCD_FunctionMode();
	LCD_Write( clear_lcd ); // clear display
	LCD_Write( return_home );
	delay_ms( 2 );
	LCD_DataMode();
}

void LCD_Setup(void)
{
	writeDelayType = WriteNoDelay; // no delays in data writes
	
	delay_ms(16); // Power up delay
	LCD_FunctionMode();

	// Reset sequence as described in data sheets
	LCD_RawWriteNibble( system_set_reset >> 4 ); 
	delay_ms(5); // min delay here of 4.1 ms
	LCD_RawWriteNibble( system_set_reset >> 4 );
	delay_10us(10); // min delay here of 100us
	LCD_RawWriteNibble( system_set_reset >> 4 );
   
	// busy flag is valid from this point onwards
	LCD_WaitForNotBusy();
	LCD_RawWriteNibble( system_set_4_bit >> 4 );
	
	writeDelayType = WriteUseBusy; // use busy
	LCD_Write( system_set_4_bit );
		
	LCD_Write( display_off );
	LCD_Write( entry_mode );
	LCD_Write( display_on );
	LCD_Write( set_dd_ram );
	
	LCD_DataMode();
}

void LCD_FunctionMode(void)
{
	clear_bit( porta, LCD_RS );
}

void LCD_DataMode(void)
{
	set_bit( porta, LCD_RS );
}

void LCD_Write(char d )
{
	if ( writeDelayType == WriteUseBusy )
		LCD_WaitForNotBusy();
		
	LCD_RawWrite( d );
	
	if ( writeDelayType == WriteDelayTime )
		delay_10us( 5 ); // enough time for normal command execution - clear and home need longer!!	
}

void LCD_RawWrite( char d )
{		
	clear_bit( porta, LCD_RW ); // set writing mode
	// set port b lower bits to output
	trisb &= 0x0F; 
			
	// output upper nibble
	LCD_RawWriteNibble( d >> 4 );
	
	// output lower nibble
	LCD_RawWriteNibble( d );
}


void LCD_RawWriteNibble(char d )
{
	clear_bit( porta, LCD_RW ); // set writing mode
	// port b upper nibble output
	trisb &= 0x0F;
		
	portb &= 0x0F;
	portb |= d << 4;

	// Clock data
   	asm NOP // setup time
	asm NOP // setup time
	asm NOP // setup time
	set_bit( porta, LCD_E );
	clear_bit( porta, LCD_E );   
	asm NOP ;// holdup time
}

char LCD_Read()
{		
	char d;
	
	// portb upper nibble input	
	trisb |= 0xF0;
	set_bit( porta, LCD_RW ); // set reading mode
		
	// data valid while EN high - 
	
	// first high nibble
	set_bit( porta, LCD_E );
	asm NOP // setup time
	asm NOP // setup time
	asm NOP // setup time
	
	d = portb & 0xF0 ;
	clear_bit( porta, LCD_E );   
		
	// then low nibble
	set_bit( porta, LCD_E );
	asm NOP // setup time
	asm NOP // setup time
	asm NOP // setup time

	d |= portb >> 4;
	clear_bit( porta, LCD_E );   
	
	return d;
}

void LCD_WaitForNotBusy()
{
	char old_RS;
	// save RS current state
	old_RS = porta & ( 1 << LCD_RS );
	
	clear_bit( porta, LCD_RS );
	while( LCD_Read() & 0x80 ); // wait while busy set
	
	if ( old_RS ) // restore RS if necessary
		set_bit( porta, LCD_RS );
}

void lprintf( const char *lcdptr )
{
	char pi;
	char c;
	pi = 0;
                                          
    while( 1 )
    {
		c = lcdptr[pi++];
		if ( c + 1 == 1 ) // funny code here as c == 0 fails with compiler V5.1
			break;
		if ( c == '\n' )
		{
			LCD_FunctionMode();
			LCD_Write( set_dd_ram + 0x40 );
			LCD_DataMode();
		}
		else
			LCD_Write( c );// Display on LCD
	}
}
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top