Jump to content

Recommended Posts

Please someone help me out. I've been trying for almost a week to get a 16F688 driving an LCD (4 Bit). I've tried EVERY language in the Source Boost system and I've scoured the darkest corners of the net for code. I have tried the samples that come with Source Boost and nothing works. I have tried to modify each and every bit and byte of code I have found. I am to the point where I am damn near ready to give up. Can anyone lend me a much needed hand?

 

Thanks 999 Trillion!

Link to post
Share on other sites

A bit more information might be needed:

LCD manufacturer

Data and Control line connections

 

If your writting your own functions for the LCD you will also need to know in what format it expects

the data/commands, MSB first or LSB first etc

 

Are you atleast getting any response on your LCD? and can you confirm your instructions via serial

dump or other method?

Link to post
Share on other sites

Well I am new to PIC's and obviously LCD's so, this is all uncharted territory for me. The LCD is

http://www.allelectronics.com/cgi-bin/item..._LINE_LCD_.html

 

The datasheet:

http://www.allelectronics.com/spec/LCD-113.pdf

 

I didn't write my own functions because I have no idea where to start.

Link to post
Share on other sites

You have this wired for four bit?

It has an option for both modes.

 

As well you have your contrast voltage wired or connected to a pot?

 

Pins -> lines would be helpful for me to to just make sure its not a logic or wiring issue.

The lack of commands is a bit troublesome, hopefully it uses one of the common sets.

 

... i dont suppose that you can read the manufacturer of the display chip? i expect it has

the nice black security goop on it.

Link to post
Share on other sites

Is there a trace I need to solder for 4 bit or something? I know it isn't a wiring problem, because I haven't even been able to get a working program compatible with a 16F688. As for the display driver, its gooped up and I am not seeing anything that is clearly the display driver model.

 

Oh and the contrast is on a pot (I have tested and confirmed that works).

Edited by Sarge
Link to post
Share on other sites
Is there a trace I need to solder for 4 bit or something? I know it isn't a wiring problem, because I haven't even been able to get a working program compatible with a 16F688. As for the display driver, its gooped up and I am not seeing anything that is clearly the display driver model.

 

Oh and the contrast is on a pot (I have tested and confirmed that works).

 

For Four bit you just need to have lines DB4-DB7 (physical pins 10-14) connected.(as well as 4,5,6)

After that you just need to give the command to the LCD to tell it to use four bit mode.

Link to post
Share on other sites
Sounds easy enough but how is that going to look in code compatible with the 16F688?

 

If you would like to provide your physical connections and maybe more details about how you were configuring the standard functions to talk to your LCD we can come up with a solution for you.

 

As for being compatible with your chip, thats not really an issue, its more about compatability with

the code your using to talk to it.

Edited by emte
Link to post
Share on other sites

I pretty much have nothing code wise or wiring wise, so I don't have anything to provide other then the fact that I want to use a 16F688 to control an LCD.

 

I contacted the LCD manufacturer for two things here is the response:

 

"The EW24210BFW uses the NT3881 chipset. All EDT character modules are 8

bit interface."

 

 

The NT3881 datasheet: http://www.datasheets.org.uk/datasheet.php?article=2582472

 

Thanks again.

Link to post
Share on other sites
I have been looking for code to control it and modify it to control it. It doesn't even compile, thats how I know if it works or not.

 

So the problem is compiling existing code with Sourceboost, why not post the code you have with details of the compile error then someone will be able to help you with the translation.

Link to post
Share on other sites

I played around with one and it compiled, but doesn't work. I'm 99% sure it isn't the wiring. It's probably the signals sent to the LCD, but I am not sure what ones are right for my LCD. I basically just slightly modified the lcd_driver.h file that comes with SB IDE.

 

Here is my project on my webserver, zipped: http://tekcube.ath.cx/lcd.zip

 

Thanks! :)

Link to post
Share on other sites

Well the problem now is I don't exactly know why it isn't working. Here is the code:

 

main_lcd.c

#include <system.h>
#include "lcd_drv.h"

#pragma CLOCK_FREQ 4000000
#pragma DATA 0x2007, _HS_OSC & _WDT_OFF

void main()
{	
lcd_setup();
porta = 0;
lprintf( "4Bit test :-)" );

while(1){
;
}
}

 

 

lcd_drv.h (Slightly modifed version of lcd_driver.h) I removed comments at start to shorten this post:

#define LCD_ARGS 	1,	/* Interface type: mode 0 = 8bit, 1 = 4bit(low nibble), 2 = 4bit(upper nibble) */ \
	1, 				/* Use busy signal: 1 = use busy, 0 = use time delays */\
	PORTC, TRISC, 	/* Data port and data port tris register */ \
	PORTA, TRISA, 	/* Control port and control port tris register */ \
	3,				/* Bit number of control port is connected to RS */ \
	2,				/* Bit number of control port is connected to RW */ \
	1 				/* Bit number of control port is connected to Enable */
////////////////////////////////////////////////////////////////////////////

char writeDelayType;

////////////////////////////////////////////////////////////////////////////
// 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 WriteControlled	0

// Interface type
#define LCD_8_BIT_MODE 0
#define LCD_4_BIT_LO_NIB_MODE 1
#define LCD_4_BIT_HI_NIB_MODE 2

// These macros make susequent code more readable, but can seem a little confusing
#define _LCD_RawWriteNibble LCD_RawWriteNibble	<InterfaceType, UseBusy, DataPort, Data_PortTris, CtrlPort, Ctrl_PortTris, RS, RW, E>
#define _LCD_RawWriteNibbleInline  LCD_RawWriteNibbleInline	<InterfaceType, UseBusy, DataPort, Data_PortTris, CtrlPort, Ctrl_PortTris, RS, RW, E>
#define _LCD_Read			LCD_Read			<InterfaceType, UseBusy, DataPort, Data_PortTris, CtrlPort, Ctrl_PortTris, RS, RW, E>
#define _LCD_WaitForNotBusy	LCD_WaitForNotBusy	<InterfaceType, UseBusy, DataPort, Data_PortTris, CtrlPort, Ctrl_PortTris, RS, RW, E>
#define _LCD_Write			LCD_Write			<InterfaceType, UseBusy, DataPort, Data_PortTris, CtrlPort, Ctrl_PortTris, RS, RW, E>
#define _LCD_FunctionMode	LCD_FunctionMode	<InterfaceType, UseBusy, DataPort, Data_PortTris, CtrlPort, Ctrl_PortTris, RS, RW, E>
#define _LCD_DataMode		LCD_DataMode		<InterfaceType, UseBusy, DataPort, Data_PortTris, CtrlPort, Ctrl_PortTris, RS, RW, E>
#define _LCD_RawWrite		LCD_RawWrite		<InterfaceType, UseBusy, DataPort, Data_PortTris, CtrlPort, Ctrl_PortTris, RS, RW, E>
#define _LCD_ClockOut		LCD_ClockOut		<InterfaceType, UseBusy, DataPort, Data_PortTris, CtrlPort, Ctrl_PortTris, RS, RW, E>

#define _LCD_TEMPL		template <	unsigned char InterfaceType,\
								unsigned char UseBusy,\
								unsigned int DataPort, unsigned int Data_PortTris,\
								unsigned int CtrlPort, unsigned int Ctrl_PortTris,\
								unsigned char RS, unsigned char RW, unsigned char E>

_LCD_TEMPL
inline void LCD_FunctionMode( void )
{
volatile bit rs@CtrlPort.RS = 0;
}

_LCD_TEMPL
inline void LCD_DataMode( void )
{
volatile bit rs@CtrlPort.RS = 1;
}


inline void LCD_CycleMakeupDelay()
{
// Enable cycle time must be > 1000ns total for both reading and writing
// LCD_SetupDelay + LCD_EnablePulseDelay + LCD_HoldupDelay + LCD_CycleMakeupDelay >= 1000ns
//       200      +          500         +       100       +          200         >= 1000ns

// This delay is required to meet the Sharp data sheet total cycle time of > 1000ns
// @40MHz this is 2 instructions
asm nop 
asm nop	
}


inline void LCD_EnablePulseDelay()
{		
// PWEH > 460ns on Sharp data sheet
// @40MHz this is 5 instructions
asm nop 
asm nop
asm nop
asm nop
asm nop
}

inline void LCD_SetupDelay()
{
// tAS > 140ns min on Sharp data sheet
// @40MHz this is 2 instructions
asm nop 
asm nop
}

inline void LCD_HoldupDelay()
{
// tAS > 10ns min on Sharp data sheet
// @40MHz this is 1 instructions
asm nop
}



_LCD_TEMPL
char LCD_Read()
{		
char d; 
volatile unsigned char data@DataPort, tris@Data_PortTris;
volatile bit rw@CtrlPort.RW, e@CtrlPort.E;

if( InterfaceType == LCD_4_BIT_HI_NIB_MODE )
{
	// upper nibble input
	tris |= 0xF0;
	rw = 1; // set reading mode
	// first high nibble	
	LCD_SetupDelay();
	e = 1;
	LCD_EnablePulseDelay();
	d = data & 0xF0; // read data
	e = 0;
	LCD_HoldupDelay();
	LCD_CycleMakeupDelay();

	// then low nibble
	LCD_SetupDelay();
	e = 1;
	LCD_EnablePulseDelay();
	d |= data >> 4;
	e = 0;
	LCD_HoldupDelay();
	LCD_CycleMakeupDelay();
}


if( InterfaceType == LCD_4_BIT_LO_NIB_MODE )
{
	// lower nibble input	
	tris |= 0x0F;
	rw = 1; // set reading mode
	// first high nibble
	LCD_SetupDelay();
	e = 1;
	LCD_EnablePulseDelay();
	d = data << 4;
	e = 0;
	LCD_HoldupDelay();
	LCD_CycleMakeupDelay();

	// then low nibble
	LCD_SetupDelay();
	e = 1;
	LCD_EnablePulseDelay();	
	d |= data & 0x0F;
	e = 0;
	LCD_HoldupDelay();
	LCD_CycleMakeupDelay();
}


if( InterfaceType == LCD_8_BIT_MODE )
{
	// port input	
	tris = 0xFF;
	rw = 1; // set reading mode
	LCD_SetupDelay();
	e = 1;
	LCD_EnablePulseDelay();
	d = data;
	e = 0;
	LCD_HoldupDelay();
	LCD_CycleMakeupDelay();
}

return d;
}

_LCD_TEMPL
void LCD_RawWriteNibble( char d )
{
// Note: this function is duplicate below, but declared inline.
// this is to reduce stack depth usage
// Note: this function is above, but declared inline.
// this is to reduce stack depth usage
volatile unsigned char data@DataPort, tris@Data_PortTris;
volatile bit rw@CtrlPort.RW, e@CtrlPort.E;

if( InterfaceType == LCD_4_BIT_HI_NIB_MODE )
{
	// port upper nibble output
	rw = 0; // set writing mode
	LCD_SetupDelay();
	tris &= 0x0F;
	data &= 0x0F;
	data |= d & 0xF0;
	e = 1;
	LCD_EnablePulseDelay();
	e = 0;
	LCD_HoldupDelay();
	LCD_CycleMakeupDelay();
}

if( InterfaceType == LCD_4_BIT_LO_NIB_MODE )
{
	// port upper nibble output
	rw = 0; // set writing mode
	LCD_SetupDelay();
	tris &= 0xF0;
	data &= 0xF0;
	data |= d >> 4;
	e = 1;
	LCD_EnablePulseDelay();
	e = 0;
	LCD_HoldupDelay();
	LCD_CycleMakeupDelay();
}	
}

_LCD_TEMPL
inline void LCD_RawWriteNibbleInline( char d )
{
// Note: this function is above, but declared inline.
// this is to reduce stack depth usage
volatile unsigned char data@DataPort, tris@Data_PortTris;
volatile bit rw@CtrlPort.RW, e@CtrlPort.E;

if( InterfaceType == LCD_4_BIT_HI_NIB_MODE )
{
	// port upper nibble output
	rw = 0; // set writing mode
	LCD_SetupDelay();
	tris &= 0x0F;
	data &= 0x0F;
	data |= d & 0xF0;
	e = 1;
	LCD_EnablePulseDelay();
	e = 0;
	LCD_HoldupDelay();
	LCD_CycleMakeupDelay();
}

if( InterfaceType == LCD_4_BIT_LO_NIB_MODE )
{
	// port upper nibble output
	rw = 0; // set writing mode
	LCD_SetupDelay();
	tris &= 0xF0;
	data &= 0xF0;
	data |= d >> 4;
	e = 1;
	LCD_EnablePulseDelay();
	e = 0;
	LCD_HoldupDelay();
	LCD_CycleMakeupDelay();
}	
}


_LCD_TEMPL
void LCD_RawWrite( char d )
{		
volatile unsigned char tris@Data_PortTris, data@DataPort;
volatile bit rw@CtrlPort.RW, e@CtrlPort.E;

if( InterfaceType == LCD_4_BIT_HI_NIB_MODE  )
{
	// output upper nibble, then lower nibble
	bit flag = 0;
	do
	{			
		_LCD_RawWriteNibbleInline( d );
		flag = !flag;
		d <<= 4;
	}
	while( flag );
}	

if( InterfaceType == LCD_4_BIT_LO_NIB_MODE )
{
	// output upper nibble, then lower nibble
	bit flag = 0;
	do
	{			
		_LCD_RawWriteNibbleInline( d );
		flag = !flag;
		d <<= 4;
	}
	while( flag );
}	


if( InterfaceType == LCD_8_BIT_MODE )
{
	// port b output
	rw = 0; // set writing mode
	tris = 0x00;		
	data = d;
	LCD_SetupDelay();
	e = 1;
	LCD_EnablePulseDelay();
	e = 0;
	LCD_HoldupDelay();
	LCD_CycleMakeupDelay();
}
}

_LCD_TEMPL
inline void LCD_WaitForNotBusy()
{
volatile bit rs@CtrlPort.RS; bit old_RS = rs;	
rs = 0;
while( _LCD_Read() & 0x80 ); // wait while busy set
rs = old_RS;
}

_LCD_TEMPL
void LCD_Write(char d )
{
volatile bit rs@CtrlPort.RS;

if( UseBusy == 1 )
{	
	// wait until display Not busy before sending next data
	if ( writeDelayType == WriteControlled )
		_LCD_WaitForNotBusy();

	_LCD_RawWrite( d );
}
else
{		
		_LCD_RawWrite( d );

	// give time to complete
	if ( writeDelayType == WriteControlled )
	{
		if( !rs && (d == return_home || d == clear_lcd) )
			delay_ms( 2 ); // return_home takes more time than other instructions to execute
		else
			delay_10us( 5 ); // 50us - enough time for normal command execution - clear and home need longer!!			
	}
}
}

_LCD_TEMPL
void LCD_Clear()
{
_LCD_FunctionMode();
_LCD_Write( clear_lcd ); // clear display
_LCD_Write( return_home );
}

_LCD_TEMPL
void LCD_Setup( void )
{
// set control port bits used to output
volatile bit trisRS@Ctrl_PortTris.RS, trisRW@Ctrl_PortTris.RW, trisE@Ctrl_PortTris.E;
trisRS = 0;
trisRW = 0;
trisE = 0;

writeDelayType = WriteNoDelay; // no delays in data writes

delay_ms(16); // Power up delay
_LCD_FunctionMode();

if( InterfaceType == LCD_4_BIT_HI_NIB_MODE )
{
	// Reset sequence as described in data sheets
	_LCD_RawWriteNibble( system_set_reset ); 
	delay_ms(5); // min delay here of 4.1 ms
	_LCD_RawWriteNibble( system_set_reset );
	delay_10us(100); // min delay here of 100us
	_LCD_RawWriteNibble( system_set_reset );
   
	// LCD busy flag is valid from this point onwards
	if( UseBusy == 1 )
		_LCD_WaitForNotBusy();
	else
		delay_10us( 5 ); // standard command delay time

	_LCD_RawWriteNibble( system_set_4_bit );

	if( UseBusy == 1 )
		_LCD_WaitForNotBusy();
	else
		delay_10us( 5 ); // standard command delay time

	writeDelayType = WriteControlled;
	_LCD_Write( system_set_4_bit );
}

if( InterfaceType == LCD_4_BIT_LO_NIB_MODE )
{
	// Reset sequence as described in data sheets
	_LCD_RawWriteNibble( system_set_reset ); 
	delay_ms(5); // min delay here of 4.1 ms
	_LCD_RawWriteNibble( system_set_reset );
	delay_10us(100); // min delay here of 100us
	_LCD_RawWriteNibble( system_set_reset );
   
	// LCD busy flag is valid from this point onwards
	if( UseBusy == 1 )
		_LCD_WaitForNotBusy();
	else
		delay_10us( 5 ); // standard command delay time

	_LCD_RawWriteNibble( system_set_4_bit );

	if( UseBusy == 1 )
		_LCD_WaitForNotBusy();
	else
		delay_10us( 5 ); // standard command delay time

	writeDelayType = WriteControlled;
	_LCD_Write( system_set_4_bit );
}

if( InterfaceType == LCD_8_BIT_MODE )
{
	// Reset sequence as described in data sheets
	_LCD_RawWrite( system_set_reset ); 
	delay_ms(5); // min delay here of 4.1 ms
	_LCD_RawWrite( system_set_reset );
	delay_10us(10); // min delay here of 100us
	_LCD_RawWrite( system_set_reset );
   
	// busy flag is valid from this point onwards
	if( UseBusy == 1 )
		_LCD_WaitForNotBusy();
	else
		delay_10us( 5 ); // standard command delay time

	_LCD_RawWrite( system_set_8_bit );	

	if( UseBusy == 1 )
		_LCD_WaitForNotBusy();
	else
		delay_10us( 5 ); // standard command delay time

	writeDelayType = WriteControlled; // use busy
}

_LCD_Write( entry_mode );
_LCD_Write( display_on );
_LCD_Write( set_dd_ram );
}

_LCD_TEMPL
void LCD_Printf( const char *lcdptr )
{
char pi = 0, c;
_LCD_DataMode();
   while( 1 )
   {
	c = lcdptr[pi++];
	if ( !c )
		return;
	if ( c == '\n' )
	{
		_LCD_FunctionMode();
		// move to start second line
		_LCD_Write( set_dd_ram + 0x40 );
		_LCD_DataMode();
	}
	else
		_LCD_Write( c );// Display on LCD
}
}

_LCD_TEMPL
void LCD_Printf( rom char *lcdptr )
{
char pi = 0, c;
_LCD_DataMode();
   while( 1 )
   {
	c = lcdptr[pi++];
	if ( !c )
		return;
	if ( c == '\n' )
	{
		_LCD_FunctionMode();
		// move to start second line
		_LCD_Write( set_dd_ram + 0x40 ); 
		_LCD_DataMode();
	}
	else
		_LCD_Write( c );// Display on LCD
}
}

_LCD_TEMPL
void LCD_Printf( const char *lcdptr, unsigned int val ) // JS - Accept unsigned by default
{
unsigned char pi = 0, bi, c, fill, baseOrBits, sign, mask;
unsigned char buff[ 10 ]; // max length allow is 9
bit pad;

_LCD_DataMode();
   while( 1 )
   {
	c = lcdptr[pi++]; if ( !c ) return;

	switch( c )
	{
	case '\n':
		_LCD_FunctionMode();
		// move to start second line
		_LCD_Write( set_dd_ram + 0x40 );
		_LCD_DataMode();
		break;
	case '%':
		c = lcdptr[pi++]; if ( !c ) return;

		//Handle escape sequence that prints '%'
		if ( c == '%' )
		{
			_LCD_Write( c );// Display on LCD
			break;
		}

		// Next character if zero indicates that we should zero fill output
		if ( c == '0' )
		{
			fill = '0';
			c = lcdptr[pi++]; if ( !c ) return;
		}
		else
			fill = ' ';

		// Next character if valid digit indicates field width
		if( c > '0' && c <= '9' )
		{
			pad = 1;
			bi = c - 48;;				
			c = lcdptr[pi++]; if ( !c ) return;
		}
		else
		{
			pad = 0;
			bi = sizeof( buff ) - 1;
		}


		// Next character indicates the radix (number base)
		sign = 0;
		switch( c )
		{
		case 'd':
			if( val & 0x8000 )	// Negative values must be adjusted to be positive // JS
			{
				sign = '-';
				val ^= 0xFFFF; // 2s complement negate	// JS
				val++;
			}
		case 'u':
			baseOrBits = 10; // base ten, divide by ten per digit
			break;			
		case 'X':
			baseOrBits = 4; // base 16, requires a 4 bit shift per digit
			mask = 0x0F;
			break;
		case 'b':
			baseOrBits = 1; // base 16, requires a 1 bit shift per digit
			mask = 0x01;
			break;
		default:
			return; // no radix
		}

		// null terminate, then reverse fill string
		buff[ bi ] = '\0';

		bit first = true;				
		while( bi )
		{
			bi--;
			if( val || first )
			{
				first = false;

				if( baseOrBits == 10 )
				{
					c = (unsigned char)(val % 10);	// JS - Optimization, use absolute of 10
					val /= 10;	// JS - Optimization, use absolute of 10
				}
				else
				{
					c = val & mask;
					val = ((unsigned int)val) >> baseOrBits;						
				}

				if( c > 9 )
					c += 55; // convert to hex digits character A-F
				else
					c += 48; // convert to digit character 0-9

			}
			else
			{
				if( sign && (bi == 0 || fill != '0') )
				{
					c = sign;
					sign = 0;
				}
				else
					c = fill;
			}

			buff[ bi ] = c;

			if( pad == 0 && val == 0 && sign == 0 )
				break;
		}
		// output string to display
		while( 1 )
		{
			c = buff[ bi ];
			if( !c ) break;
			_LCD_Write( c );// Display on LCD
			bi++;
		}
		break;
	default:
		_LCD_Write( c );// Display on LCD
		break;
	}
}
}

_LCD_TEMPL
void LCD_GotoXy( char x, char y )
{
// displays memory mapping with two lines:
// line 1: 0x00
// line 2: 0x40

// display memory mapping with four lines:
// line 1: 0x00
// line 2: 0x40
// line 3: 0x14
// line 4: 0x54

_LCD_FunctionMode();
unsigned char offset = x;
if( y & 0x01 ) offset += 0x40;
if( y & 0x02 ) offset += 0x14;		
_LCD_Write( set_dd_ram + offset );
}


_LCD_TEMPL
void LCD_Function( char func )
{
_LCD_FunctionMode();
_LCD_Write( func );
}

////////////////////////////////////////////////////////////////////////////
// Helpers that hide template arguments
////////////////////////////////////////////////////////////////////////////
// low level functions
#define lcd_write		LCD_Write<LCD_ARGS>
#define lcd_waitfornotbusy LCD_WaitForNotBusy<LCD_ARGS>
#define lcd_read		LCD_Read<LCD_ARGS>
#define lcd_funcmode	LCD_FunctionMode<LCD_ARGS>
#define lcd_datamode	LCD_DataMode<LCD_ARGS>


// high level functions - these all set function or data mode as required
#define lcd_setup		LCD_Setup<LCD_ARGS>
#define lprintf			LCD_Printf<LCD_ARGS>
#define lcd_clear		LCD_Clear<LCD_ARGS>
#define lcd_gotoxy		LCD_GotoXy<LCD_ARGS>
#define lcd_function 	LCD_Function<LCD_ARGS>

Link to post
Share on other sites

Sarge,

 

You have got several problems going for you:

 

You selected PORT A for your control signals.

 

From your "lcd_drv.h" file the PORT A to LCD connections are:

RA3 <> RS, RA2 <> RW, RA1 <> E

 

Problem 1:

 

Using RA3 bit for the RS control line. For the 16F688 this is an INPUT ONLY bit.

 

The RA3 bit is shared with MCLR/VPP so connecting this to something else will make in circuit serial programming much more troublesome.

 

You should move this to RA0 and change your "lcd_drv.h" file.

 

---------------

 

You selected PORT C as the 4 bit nibble data interface to the LCD.

 

I'm guessing here but I assume that you are planning to use RC4 and RC5 as a serial interface to send strings to the LCD eventually.

 

This implies that PORT C to LCD connections are:

RC3 <> DB7, RC2 <> DB6, RC1 <> DB5, RC0 <> DB4

 

If your connections are like this it should be good.

 

It's unclear from the LCD datasheets but you may need to connect DB3 through DB0 of the LCD to ground.

 

Problem 2:

 

Both ports have analog signals for the comparators and ADC function blocks associated with them.

 

This means that you need to tell the 16F688 what line to use for digital I/O to the LCD.

 

Your sample code does not do this initialization. So these line are stuck as analog inputs.

 

Problem 3:

 

The setting you used for the configuration word may not be what you want.

 

You selected the high speed external crystal oscillator mode. This is usually a good choice for oscillators in the 8MHz and up range. If you are not using an external crystal then you should select and internal oscillator mode.

 

A line like: #pragma DATA 0x2007, _MCLRE_ON & _INTOSCIO & _WDT_OFF

may be closer to what you need.

 

---------------

 

Here's what your main could look like if you are not using any analog inputs:

// target PIC16F688

#include <system.h>
#include "lcd_drv.h"

#pragma CLOCK_FREQ 4000000
#pragma DATA 0x2007, _MCLRE_ON & _INTOSCIO & _WDT_OFF

void main()
{
   // Turn off comparators and set pins for digital I/O
   cmcon0 = (0 << C2OUT)
          | (0 << C1OUT)
          | (0 << C2INV)
          | (0 << C1INV)
          | (0 << CIS)
          | (1 << CM2)
          | (1 << CM1)
          | (1 << CM0);
          
   // Turn off ADC and set pins for digital I/O
   adcon0 = 0;
   adcon1 = 0;
   ansel  = 0;
   
   lcd_setup();
   porta = 0;
   lprintf( "4Bit test :-)" );
   
   while(1){
     ;
   }
}

 

Remember to use some bit other than RA3 for an ouput to the RS input of the LCD.

Edited by cac001
Link to post
Share on other sites

There should have been a post above that said I think I fragged the LCD. I then asked what LCD's do when they die.

 

Well I'm not to sure it is dead anymore. I just think it isn't sending the necessary signals or something. Err now I am thinking I might have fragged it again. Ahh so confused.

 

 

EDIT:

 

Found broken solder joint. I am going to fix it then try again and see if luck is on my side. Broken connection is DB7.

 

EDIT:

 

...No luck. How can I see a flashing cursor when I first try cac001's code, not I see the top line all blocks...

 

EDIT: Pulled out all of the LCD connections out of my breadboard and rewired it very carefully. Still the same thing...

 

EDIT: Oh and RC4 & RC5; What do you mean by using them as serial interface. I don't have them hooked up to anything, should they be wired to something?

Edited by Sarge
Link to post
Share on other sites
There should have been a post above that said I think I fragged the LCD. I then asked what LCD's do when they die.

 

Well I'm not to sure it is dead anymore. I just think it isn't sending the necessary signals or something. Err now I am thinking I might have fragged it again. Ahh so confused.

 

 

EDIT:

 

Found broken solder joint. I am going to fix it then try again and see if luck is on my side. Broken connection is DB7.

 

EDIT:

 

...No luck. How can I see a flashing cursor when I first try cac001's code, not I see the top line all blocks...

 

EDIT: Pulled out all of the LCD connections out of my breadboard and rewired it very carefully. Still the same thing...

 

EDIT: Oh and RC4 & RC5; What do you mean by using them as serial interface. I don't have them hooked up to anything, should they be wired to something?

 

From your code I see that you choosed low nibble 4 bit interface:

#define LCD_ARGS     1,    /* Interface type: mode 0 = 8bit, 1 = 4bit(low nibble), 2 = 4bit(upper nibble) */ \
       1,                 /* Use busy signal: 1 = use busy, 0 = use time delays */\
       PORTC, TRISC,     /* Data port and data port tris register */ \
       PORTA, TRISA,     /* Control port and control port tris register */ \
       3,                /* Bit number of control port is connected to RS */ \
       2,                /* Bit number of control port is connected to RW */ \
       1                 /* Bit number of control port is connected to Enable */

So you have to connect the data signals to DB0...DB3 or if you have them already wired to DB4..DB7 you have to change the first LCD_ARGS to 2 (upper nibble).

Link to post
Share on other sites
From your code I see that you choosed low nibble 4 bit interface:

#define LCD_ARGS     1,    /* Interface type: mode 0 = 8bit, 1 = 4bit(low nibble), 2 = 4bit(upper nibble) */ \
       1,                 /* Use busy signal: 1 = use busy, 0 = use time delays */\
       PORTC, TRISC,     /* Data port and data port tris register */ \
       PORTA, TRISA,     /* Control port and control port tris register */ \
       3,                /* Bit number of control port is connected to RS */ \
       2,                /* Bit number of control port is connected to RW */ \
       1                 /* Bit number of control port is connected to Enable */

So you have to connect the data signals to DB0...DB3 or if you have them already wired to DB4..DB7 you have to change the first LCD_ARGS to 2 (upper nibble).

 

I was under the impression that that was referring to the upper or lower nibble of the port on the PIC. Just to see I tried hooking up DB0-DB3 to RC0-RC3 and there is no noticeable difference.

Edited by Sarge
Link to post
Share on other sites

There are no full 8-bit ports on the PIC16F688.

 

You must use the lower 4-bits of port C or A.

 

These bits must be connected to DB7-DB4 of the LCD.

 

Sarge,

 

Have you connected the RS line from LCD to a bit on port A that is not RA3?

Edited by cac001
Link to post
Share on other sites

I assume that when you moved RS from RA3 to RA0 you also changed your "lcd_drv.h" file too.

 

The Novatek NT3881D and the Hitachi HD44780A both use the same kind of interface.

 

This link is for a Hitachi controller and may be a little easier to read Hitachi HD44780A LCD controller

 

This is a link to a Sharp application note Dot-Matrix LCD Units (with built-in controllers) User's Manual

 

This document has a good description of the 4-bit interface.

 

Using the SourceBoost simulator you should be able to step through your program and see that the bits on PORT A and PORT C change the way the LCD datasheets require.

 

If you are convinced that your code is running correctly and the signals are all wired right then your LCD must be toast.

Edited by cac001
Link to post
Share on other sites

If your only seeing the top line as blocks you most likely have a powerup timing issue.

 

There are many slow modules, especially Hitachi types that need more than 30ms to settle.

Looking at the code provided your way under that value.

 

As a suggestion (in my experiance) be VERY generous with delays for non-timming critical

applications, and tweak them after.

 

inline void LCD_SetupDelay()

{

    // tAS > 140ns min on Sharp data sheet

    // @40MHz this is 2 instructions

    asm nop

    asm nop

}

Link to post
Share on other sites

Sarge,

 

I do not have a PIC16F688 handy but here the sample code running in a PICKit1 with a PIC16F676.

 

// target PIC16F676

#include <system.h>

/* Port pin assignments:

  RA0 - digital input  connected to a 10K pot LCD contrast  of LCD (pin 3)
  RA1 - digital input  not connected
  RA2 - digital output connected to RW (read/write in)      of LCD (pin 5)
  RA3 - digital input  connected to PICKit1 button
  RA4 - digital output connected to RS (register select in) of LCD (pin 4)
  RA5 - digital output connected to E (enable strobe in)    of LCD (pin 6)
  
  RC0 - digital I/O connected to DB4 of LCD (pin 11)
  RC1 - digital I/O connected to DB5 of LCD (pin 12)
  RC2 - digital I/O connected to DB6 of LCD (pin 13)
  RC3 - digital I/O connected to DB7 of LCD (pin 14)
  RC4 - digital output not connected
  RC5 - digital output not connected

*/

/* LCD display module is Sharp LM20A21 

pin  1 - VSS Ground
pin  2 - VDD +5
pin  3 - Vo  Contrast
pin  4 - RS  Register select
pin  5 - RW  Read/Write select
pin  6 - E   Enable acrive high strobe
pin  7 - DB0 Data bit 0
pin  8 - DB0 Data bit 1
pin  9 - DB0 Data bit 2
pin 10 - DB0 Data bit 3
pin 11 - DB0 Data bit 4
pin 12 - DB0 Data bit 5
pin 13 - DB0 Data bit 6
pin 14 - DB0 Data bit 7

*/

#include "lcd_drv.h"

#pragma CLOCK_FREQ 4000000
#pragma DATA 0x2007, _MCLRE_ON & _INTRC_OSC_NOCLKOUT & _WDT_OFF

void main()
{
   unsigned int count;
   // Turn off comparators and set pins for digital I/O
   cmcon  = (0 << CIS)
          | (1 << CM2)
          | (1 << CM1)
          | (1 << CM0);
          
   // Turn off ADC and set pins for digital I/O
   adcon0 = 0;
   adcon1 = 0;
   ansel  = 0;
   
   trisa  = 0x0B;
   porta  = 0x00;
   
   trisc  = 0x0F;
   portc  = 0x00;
   
   lcd_setup();
   porta = 0;
   lcd_clear();
   //        01234567890123456  01234567890123456789
   lprintf( "Line 0: 4Bit test\nLine 1: " );
   count = 0;    
   while(1){
       lcd_gotoxy(8,1);
       lprintf( "%u", count);
       if (count < 10000) lcd_write('_');
       if (count < 1000) lcd_write('_');
       if (count < 100) lcd_write('_');
       if (count < 10) lcd_write('_');
       count++;
       delay_ms(100);
   }
}

Here is just the setup from lcd_drv.h:

#define LCD_ARGS     1,   /* Interface type: mode 0 = 8bit, 1 = 4bit(low nibble), 2 = 4bit(upper nibble) */ \
       1,                /* Use busy signal: 1 = use busy, 0 = use time delays */\
       PORTC, TRISC,     /* Data port and data port tris register */ \
       PORTA, TRISA,     /* Control port and control port tris register */ \
       4,                /* Bit number of control port is connected to RS */ \
       2,                /* Bit number of control port is connected to RW */ \
       5                 /* Bit number of control port is connected to Enable */

 

This is not the exact same hardware that you are using but it's as close as I can manage.

 

The contrast control input for my LCD module needs to be set to a voltage near 0.5 volts, if it's greater than 1.5 volts the characters fade out completely.

 

The source code you have works fine for me.

 

If you are still stuck your problems may still be with your hardware.

 

Please check your wiring again carefully.

 

Be sure that voltage on the LCD contrast control is in a good range.

 

Good luck.

Edited by cac001
Link to post
Share on other sites
  • 3 years later...

Hi,

 

I m new to this all, i try to connect as per you mention bt in that RA3 where to connect PICKit1 Button means where to connect I bring 16 x 1 LCD screen and also have PIC now i dont know how to complie and make hex to lod PIC pls...... help me.....

 

Thanking you,

 

 

Sarge,

 

I do not have a PIC16F688 handy but here the sample code running in a PICKit1 with a PIC16F676.

 

// target PIC16F676

#include <system.h>

/* Port pin assignments:

  RA0 - digital input  connected to a 10K pot LCD contrast  of LCD (pin 3)
  RA1 - digital input  not connected
  RA2 - digital output connected to RW (read/write in)      of LCD (pin 5)
  RA3 - digital input  connected to PICKit1 button
  RA4 - digital output connected to RS (register select in) of LCD (pin 4)
  RA5 - digital output connected to E (enable strobe in)    of LCD (pin 6)
  
  RC0 - digital I/O connected to DB4 of LCD (pin 11)
  RC1 - digital I/O connected to DB5 of LCD (pin 12)
  RC2 - digital I/O connected to DB6 of LCD (pin 13)
  RC3 - digital I/O connected to DB7 of LCD (pin 14)
  RC4 - digital output not connected
  RC5 - digital output not connected

*/

/* LCD display module is Sharp LM20A21 

pin  1 - VSS Ground
pin  2 - VDD +5
pin  3 - Vo  Contrast
pin  4 - RS  Register select
pin  5 - RW  Read/Write select
pin  6 - E   Enable acrive high strobe
pin  7 - DB0 Data bit 0
pin  8 - DB0 Data bit 1
pin  9 - DB0 Data bit 2
pin 10 - DB0 Data bit 3
pin 11 - DB0 Data bit 4
pin 12 - DB0 Data bit 5
pin 13 - DB0 Data bit 6
pin 14 - DB0 Data bit 7

*/

#include "lcd_drv.h"

#pragma CLOCK_FREQ 4000000
#pragma DATA 0x2007, _MCLRE_ON & _INTRC_OSC_NOCLKOUT & _WDT_OFF

void main()
{
   unsigned int count;
   // Turn off comparators and set pins for digital I/O
   cmcon  = (0 << CIS)
          | (1 << CM2)
          | (1 << CM1)
          | (1 << CM0);
          
   // Turn off ADC and set pins for digital I/O
   adcon0 = 0;
   adcon1 = 0;
   ansel  = 0;
   
   trisa  = 0x0B;
   porta  = 0x00;
   
   trisc  = 0x0F;
   portc  = 0x00;
   
   lcd_setup();
   porta = 0;
   lcd_clear();
   //        01234567890123456  01234567890123456789
   lprintf( "Line 0: 4Bit test\nLine 1: " );
   count = 0;    
   while(1){
       lcd_gotoxy(8,1);
       lprintf( "%u", count);
       if (count < 10000) lcd_write('_');
       if (count < 1000) lcd_write('_');
       if (count < 100) lcd_write('_');
       if (count < 10) lcd_write('_');
       count++;
       delay_ms(100);
   }
}

Here is just the setup from lcd_drv.h:

#define LCD_ARGS     1,   /* Interface type: mode 0 = 8bit, 1 = 4bit(low nibble), 2 = 4bit(upper nibble) */ \
       1,                /* Use busy signal: 1 = use busy, 0 = use time delays */\
       PORTC, TRISC,     /* Data port and data port tris register */ \
       PORTA, TRISA,     /* Control port and control port tris register */ \
       4,                /* Bit number of control port is connected to RS */ \
       2,                /* Bit number of control port is connected to RW */ \
       5                 /* Bit number of control port is connected to Enable */

Here is a photo of this sample code working: Photo1

 

This is not the exact same hardware that you are using but it's as close as I can manage.

 

The contrast control input for my LCD module needs to be set to a voltage near 0.5 volts, if it's greater than 1.5 volts the characters fade out completely.

 

The source code you have works fine for me.

 

If you are still stuck your problems may still be with your hardware.

 

Please check your wiring again carefully.

 

Be sure that voltage on the LCD contrast control is in a good range.

 

Good luck.

Link to post
Share on other sites
i dont know how to complie and make hex to lod PIC pls...... help me.....

Asking for this kind of help means this LCD project is too complex for your level of experience.

 

Use a very simple project to gain understanding of how to use the SourceBoost tools.

Link to post
Share on other sites

Join the conversation

You are posting as a guest. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
×
×
  • Create New...